Register dependencies between `all` targets

Hi,

my project has the following hierarchy:

toplevel
 +-foo # added with add_subdirectory(... EXCLUDE_FROM_ALL)
 +-bar # added with add_subdirectory(...)
    +-quux # added with add_subdirectory(... EXCLUDE_FROM_ALL)

Apparently, there is an all target both in toplevel/foo and toplevel/bar/quux; due to the EXCLUDE_FROM_ALL these all targets are just not registered as dependencies in the all targets of the corresponding parent folders.

Is it possible to have the toplevel/bar/quux/all target depend on toplevel/foo/all? Alternatively, is there another way to build all in foo whenever all in bar/quux is built?

I tried the obvious add_dependencies(toplevel/bar/quux/all toplevel/foo/all), but CMake won’t let me use toplevel/bar/quux/all in this context.

Kind regards

Use CMake targets rather than internal CMake artifacts:

add_dependencies(quux foo)

@marc.chevrier where would I place this add_dependencies(...) instruction? Neither bar/CMakeLists.txt nor bar/quux/CMakeLists.txt seems to be the right place:

CMake Error at bar/CMakeLists.txt:2 (add_dependencies):
Cannot add target-level dependencies to non-existent target “quux”.

CMake Error at bar/quux/CMakeLists.txt:2 (add_dependencies):
Cannot add target-level dependencies to non-existent target “quux”.

At a level where both targets are already defined.

@marc.chevrier, thanks for your recommendations. I’m sorry, but I still don’t get it right:

toplevel/CMakeLists.txt reads:

add_subdirectory(foo EXCLUDE_FROM_ALL)
add_subdirectory(bar)

toplevel/foo/CMakeLists.txt:

add_executable(hello main.c)
# possibly more targets to be defined here...

toplevel/bar/CMakeLists.txt:

add_subdirectory(quux EXCLUDE_FROM_ALL)
add_dependencies(quux foo) # both foo and quux folders have been visited by now

toplevel/bar/quux/CMakeLists.txt:

add_executable(world main.c)
# possibly more targets to be defined here...

CMake still reports

CMake Error at bar/CMakeLists.txt:2 (add_dependencies):
Cannot add target-level dependencies to non-existent target “quux”.

Moving the add_dependencies() instruction to the end of the toplevel CMakeLists.txt does not work either. Neither does changing quux to bar/quux in the moved add_dependencies().

Kind regards

You cannot use directories as targets. So foo or quux cannot be specified as arguments to add_dependencies().

In your case, you can specify, for example, add_dependencies(world hello)

Thank you very much, @marc.chevrier.

This is what I was afraid of. In my real-life case, the situation is a little more complex: there is not just one hello and one world target, so with the suggested approach, I would have to manually enumerate several targets.

What I was searching for is a solution for the following situation:

  • whenever I make all in the toplevel folder, foo and bar/quux shall not be built
  • foo (and all targets within and below that folder) shall be built
    • when I make all in the foo folder
    • when I make all in the bar/quux folder

All targets within foo are already dependency of the (already existing) foo/all target (or artifact or whatever that all is). Similarly for bar/quux/all. As manual enumeration of the targets in parallel to the already existing all targets is error prone, I am searching for some easy way to have bar/quux/all depend on foo/all (or a semantically equivalent solution).

Kind regards

What you want is not possible and don’t think in terms of targets generated by CMake. They are internal and private to achieve correct build. Local all targets are for building targets included in ALL.

In your case, I suggest the creation of a custom target and, for each created target not in ALL, add a dependency to this custom target. So by launching this custom target you will achieve what you want.

# in toplevel/foo
add_custom_target(foo)
add_executable(hello main.c)
add_dependency(foo hello)
# you can create a function to wrap these actions

# in toplevel/bar/quux
add_custom_target(quux)
# do same as in foo

# in top level
add_dependency(foo quux)

After CMake generation, make foo will build all targets in fooand dependencies.

Thanks a lot for your support, @marc.chevrier.

Cheers
Ingolf