If I include non-existent files in DEPENDS
section of add_custom_command
, it fails. Is there a way to specify the dependency may not exist, but if it's created the command should be rerun?
Specifically, I am using Coco/R, which requires Parser.frame
and Scanner.frame
file to exist either in the same directory as the grammar file or one specified by a command line argument, and Copyright.frame
which can exist or not. So I do this:
foreach(FRAME_DIR IN ITEMS ${GRAMMAR_DIR} ${ARG_FRAME_DIR})
foreach(FRAME_FILE_NAME IN ITEMS Copyright Scanner Parser)
set(FULL_FRAME_FILE ${FRAME_DIR}/${FRAME_FILE_NAME}.frame)
if(EXISTS ${FULL_FRAME_FILE})
list(APPEND FRAME_FILES ${FULL_FRAME_FILE})
endif()
endforeach()
endforeach()
...
set(GEN_SOURCES ${ARG_OUTPUT_DIR}/Scanner.h ${ARG_OUTPUT_DIR}/Parser.h ${ARG_OUTPUT_DIR}/Scanner.cpp ${ARG_OUTPUT_DIR}/Parser.cpp)
add_custom_command(OUTPUT ${GEN_SOURCES}
COMMAND ${COCOCPP} ${COCOCPP_ARGS}
MAIN_DEPENDENCY ${ARG_GRAMMAR}
DEPENDS ${FRAME_FILES}
VERBATIM)
add_library(${ARG_TARGET} ${GEN_SOURCES})
If I comment out if
inside foreach
, I get
ninja: error: '../verification/debug/config/Copyright.frame', needed by 'verification/gen/config/Parser.h', missing and no known rule to make it
at build time. With this if
, the files are generated but if I create Copyright.frame
later, of course the build program will not know about it.
For common generators, you can use DEPFILE to generate Make-ish dependency just like gcc -MT -MD
does with include files. You have to write a wrapper that will detect if the file exists or if not, and then generate the file.
The depfile looks generally like this:
output: source1 source2
And output
has to be relative to CMAKE_BINARY_DIR (this took me sooooooo long to find out) and source1
let be absolute. And you have to also escape spaces and tabs and newlines and #
(!) in names. Generally:
# CMakeLists.txt
# Example for one file
set(output ${ARG_OUTPUT_DIR}/Scanner.h)
# Relative to BINARY_DIR!
file(RELATIVE_PATH outputbinrela "${CMAKE_BINARY_DIR}" "${output}")
set(depfile "${CMAKE_CURRENT_BINARY_DIR}/Scanner.h.d" ABSOLUTE)
add_custom_command(
OUTPUT ${someoutput}
DEPFILE ${depfile}
# TODO: write it in cmake, to be portable
COMMAND sh ./thescript.sh
"${outputbinrela}" "${depfile}" "${input}"
${FRAME_DIR}/Copyright.frame
DEPENDS ${input}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
VERBATIM
)
# ./thescript.sh
outputbinrela="$1"
depfile="$2"
input="$3"
copyright="$4"
# Check if the file exists - if it does, add it to depfile
if [[ -e "$copyright" ]]; then
copyright=$(readlink -f "$copyright") # absolute!
echo "$outputbinrela: $copyright" > "$depfile"
else
echo "$outputbinrela:" > "$depfile"
fi
# Run the command to generate output.
yourcommand "$copyright" > "$input"
I once wrote such system for m4
preprocessor, you can check out this script that runs m4 preprocessor and grabs m4 included files and generates depfile, and this script that calls add_custom_command( ${CMAKE_COMMAND} -Pthe_other_script.cmake DEPFILE ...)
.
Still, if you add Copyright.frame
file, cmake will not pick it up on the first run, but if you modify something else, then depfile will be regenerated and the depdency will be picked. Or you could just re-generate depfile for example on each build.