I have a project using ANTLR4 with an executable in a top level CMakeLists.txt, and one of the subfolders is “testrig” which I want to just produce a Bash script that issues Java commandlines to run the ANTLR4 testrig on my grammar. (The reason it can’t be a static script file is there are substitutions for the name of the grammar and path of the CMake build output for compiled artifacts produced from the grammar file.)
Previously I had written CMake code to run those Java commands during configuration step, but that required re-running configuration for that target. I changed things so that testrig builds a tool with add_executable, but that program just used a process-start C++ library to run commands based on settings written to an .ini file generated during CMake configuration. I thought, well, this is kinda pointless pulling in a library and building an executable to do what could be just a Bash script (run by MSys2 in my case).
It seems like my “testrig/CMakeLists.txt” file could be very simple, but I’m finding it surprisingly difficult to search the web for an example of this specific use-case and only this. Everything I’ve found is either relevant to generating a file but not having a file as a target, or else does other things like add_executable.
The problem I have with the example in this link is it uses add_executable and thus isn’t different from the intermediate way I’ve already done it with a process-starting executable:
https://cmake.org/cmake/help/latest/guide/tutorial/Adding%20a%20Custom%20Command%20and%20Generated%20File.html
The problem I have with this next example (add_custom_target) is it says the custom target will be considered always out of date. Does that mean it will rebuild the script every time even if it’s not needed to be rebuilt?
https://cmake.org/cmake/help/v3.0/command/add_custom_target.html
I am sure that somehow add_custom_command and add_custom_target will be involved in the solution; I’m just not quite seeing things clearly. I’m using CMake “file(WRITE …” to create the Bash script, so I’m not understanding what there is for add_custom_command to do here. Do I have to change from “file(WRITE …” to “echo” commands so I can write the .sh file at build time, or can I have add_custom_target with DEPENDS on the output of “file(WRITE …” with no add_custom_command?
Actually that’s not entirely true; I would still have “add_custom_command” to generate the Java .class files needed by the testrig script target. Previously I had problems I never fully figured out with those custom commands getting run more times than I expected. I assume either it was because if I had multiple outputs from the command it was re-running the command for each output (instead of understanding that one command produced two files), and/or the always-out-of-date thing I am worried about for add_custom_target.
So to recap, first attempt looked like this:
add_custom_command → .class file
add_custom_command → runs ANTLR4 testrig
add_custom_target ← depends on both custom commands
Second attempt:
add_custom_command → .class file
file(WRITE …) → .ini file
add_executable(testrig_runner) ← depends on outputs above
Third attempt:
add_custom_command → .class file
file(WRITE …) → .sh file
<<< what goes here? >>>