[CMake] add_custom_command and generated true

Michael Hertling mhertling at online.de
Tue Jan 25 09:34:27 EST 2011


On 01/25/2011 10:17 AM, Micha Renner wrote:
> Recently, I learned that ADD_CUSTOM_COMMAND generated the property
> GENERATED TRUE for the generated file.
> 
> Somehow I have trouble in this situation:
> 
> In a top level CMakeLists file a source file, blue.c, is generated. This
> file should be used in a subdirectory with its own CMakeLists file.
> 
> Running CMake generates the message: "cannot find blue.c etc..."
> 
> Okay, the information, that this is a generated sourcefile is, maybe,
> lost on the transition to the subdirectory.

The documentation of SET_SOURCE_FILES_PROPERTIES() states

"Source file properties are visible only to targets added in the same
directory (CMakeLists.txt)."

and GENERATED is a source file property, so it's not amazing that the
subdirectory's CMakeLists.txt doesn't recognize blue.c as generated,
even if the property is imposed by ADD_CUSTOM_COMMAND(OUTPUT ...).

> So, I inserted in the CMakeLists file of subdirectory the line:
> 	SET_SOURCE_FILES_PROPERTIES(blue.c PROPERTIES GENERATED TRUE)
> which generates the make message
> 	No rule to build target subdirectory/blue.c

Explicitly setting the GENERATED property here quiets CMake, but the
subdirectory's Makefile won't have a rule to generate blue.c because
the custom command is defined in the top-level CMakeLists.txt; from
the documentation of ADD_CUSTOM_COMMAND():

"A target created in the same directory (CMakeLists.txt file)
that specifies any output of the custom command as a source file
is given a rule to generate the file using the command at build time."

So, the build will fail with the mentioned error message from make.

> I changed the inserted line (see above) to...
> 	SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_SOURCE_DIR}/blue.c
> 		 PROPERTIES GENERATED TRUE) 
> ... which is okay.

AFAICS from your example, this works by accident: The custom target is
processed before make descends to the subdirectory, so blue.c already
exists when the cTest target gets built, and CMake is happy because
blue.c is marked as GENERATED in that *directory's* CMakeLists.txt.
Remove the ALL flag from the ADD_CUSTOM_TARGET() command, and you
will probably see your example fail, regardless if and how the
GENERATED property is set.

> => Two question
> 
> - Is it general true, that properties are lost on transition to a
>   subdirectory?

This is true for the source file properties and for some directory
properties like EXCLUDE_FROM_ALL; the latter is not inherited by sub-
directories, but the COMPILE_DEFINITIONS directory property, e.g., is.

> - In which cases is it absolute necessary to work with absolute paths
>   and SET_SOURCE_FILES?

IMO, the rule of thumb is: Use absolute paths where the behavior
for relative paths is not specified or not appropriate. E.g.,

ADD_CUSTOM_COMMAND(OUTPUT blue.c ...)

will generate ${CMAKE_CURRENT_BINARY_DIR}/blue.c, but which directory

SET_SOURCE_FILES_PROPERTIES(blue.c PROPERTIES ...)

bases on? For the GENERATED property, CMAKE_CURRENT_BINARY_DIR would be
reasonable, but for the LANGUAGE property, CMAKE_CURRENT_SOURCE_DIR
might suit better. Thus, SET_SOURCE_FILES_PROPERTIES() should be
invoked with absolute paths only.

BTW, you shouldn't do in-source builds, and do not write to the source
directories; it's bad style, doesn't play nicely with version control
systems and might be the reason for some quite subtle problems.

Regards,

Michael


More information about the CMake mailing list