Is there DEPENDS property for custom targets?

add_custom_target() has syntax like this:

add_custom_target(Name [ALL] [command1 [args1...]]
                  [COMMAND command2 [args2...] ...]
                  [DEPENDS depend depend depend ... ]

The Docs say:

DEPENDS
    Reference files and outputs of custom commands created with add_custom_command() command calls in the same directory (CMakeLists.txt file). They will be brought up to date when the target is built.

Is there a property corresponding to this parameter? So I could do something like:

add_custom_target(foo)
...
set_property(TARGET foo
  APPEND PROPERTY
    DEPENDS
    "${some_files}"
)

Hi,

You could use add_dependencies(…) to add dependencies to any type of target. Including custom ones. Like:

add_custom_target(foo)
add_dependencies(foo bar)

However… Usually dependencies like this one are set up between targets. If you want to create a custom target that operates on files, and if those files change then the custom target’s command needs to be re-run, then the robust way of setting this up is:

add_custom_command(
   OUTPUT "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/foo.bar"
   COMMAND super_processing_script.sh input1.txt input2.h
   DEPENDS input1.txt input2.h )
add_custom_target( foo_bar
   DEPENDS "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/foo.bar" )

It may not seem obvious at first why you would want to do this, but generating files using “custom commands” instead of with “custom targets” results in much more flexible code usually.

Cheers,
Attila

Thanks for the reply! Yes, I am aware that add_dependencies() works with targets, and that the usual approach is to pair add_custom_command() with add_custom_target(). However, I was asking specifically about the editable property.

The usecase I am after is to create a single target codegen at the beginning of CMakeLists that could be built via cmake --build . --target codegen , and then later in subfolders declare codegeneration add_custom_command()s and mark their output as a dependency for a single codegen target. I was hoping to achieve this without creating excessive targets, one per file / group of files.

The need for separate codegeneration target, in turn, is to be able to quickly run the codegeneration, acquire “missing” source files, and then run static code analysis tools without building the whole project.

Ahh… :smiley:

I have no idea if this is the most ideal way of doing this or not, but I’ve implemented something like this in my own projects like:

add_custom_target( InstallFiles ALL SOURCES
   $<TARGET_PROPERTY:InstallFiles,INSTALLED_FILES> )
add_custom_command(
   OUTPUT "foo/bar"
   COMMAND ... )
set_property( TARGET InstallFiles APPEND PROPERTY
   INSTALLED_FILES "foo/bar" )

The actual code is a bit more elaborate than this (creating some stamp files “in the middle”), but the logic is something like this. So I just introduced my own property on top of a custom target, and then used a generator expression to make the custom target depend on the files set up in that custom property.

Cheers,
Attila

1 Like

I marked this as a solution, since it indeed works on a test project - but unfortunately it is not the case with more complex file structures in older cmake :frowning:

Specifically, if add_custom_target() happens at one directory (say, main CMakeLists.txt), and the property is appended in another (included via add_subdirectory()), then configuration will fail:

CMake Error at CMakeLists.txt:5 (add_custom_target):
  Cannot find source file:
    /tmp/cm/sub/foo/bar

This doc hints that Changed in version 3.20: The GENERATED source file property is now visible in all directories, so this might be the culprit.

In any case, for the solution above to actually work, one also needs cmake_minimum_required(VERSION 3.20), and I am currently stuck with 3.14 :pensive:

…on a related note: since it only works in 3.20+ anyway, it is probably a better idea to use target_sources() directly, instead of juggling with properties and generator expressions:

New in version 3.20: <target> can be a custom target.

Weird… With absolute path names this setup has worked for me ever since CMake 3.11. :confused: (It probably should work with older versions as well, it’s just that that’s the first version that we used “for production”.)

Thanks for the info about target_sources(...)! That could indeed be a good replacement for my implementation in the future.

Weird indeed! My only wild guess at the moment - is that in those cases set_property() is called in the same directory as add_custom_target(). But if that is not so, then perhaps I am missing some point and it could actually work for me too.