Mechanisms for grouping targets, labels or otherwise?

Greetings CMake users— I’m a long-time CMake user via the ROS (Robot Operating System) community. It’s been interesting to watch over time as certain features which were initially implemented in the ROS 1 buildsystem are now available natively, but this has resulted in some confusion as we map from one to the other.

One area like this is around the building of executables needed for tests. In ROS 1, we had CMake macros which would connect up all test executables as dependencies of a master tests target, so that you could easily make tests, and build only the tests and their dependencies, or conversely, avoid/defer building them as part of ALL (and similarly a run_tests target for actually invoking the tests). In the next generation system, this has all been removed, and so now the baseline behaviour is that the test executables need to build as part of ALL, and either be built on every make, or excluded from being configured at all using a define if you know won’t need to build them later (for example, when doing a build for packaging purposes).

What I am wondering about is whether it would be possible/recommended to use target labels as a way of getting back the ability to exclude these (and potentially other) auxiliary executables from ALL. It looks like labels have been a long time feature of CMake (going back to at least 3.0), but seem to be mostly used internally by CTest, with the ominous line “Target label semantics are currently unspecified” as most of what’s documented about them.

Is there other documentation or a tutorial I could refer to which would help understand what the behaviour and capability of the labels feature is? For example, can I set_target_properties(<target_name> LABELS test), and then have some way elsewhere of iterating all the targets and their labels in order to gather a specific set of them in a similar way to how ctest -L works? Alternatively, is there some other CMake feature capable of grouping targets in this manner which would be helpful to know about?

Thanks in advance!

I think you’ll need add_custom_target with add_dependencies for this. I think you could probably use the BUILDSYSTEM_TARGETS property on directories (traversing using the SUBDIRECTORIES property on directories) to find all of the targets in the current build.

Easier, I find, is to have a wrapper for add_executable (and friends) that stashes the names into a global property that you can retrieve later. You can use a custom property on targets (like _build_group) to make the custom targets to group them together.

Thanks for the reply. I think what you’re describing is pretty much what we had in the previous ROS buildsystem, called catkin— basically we ended up with a bunch of wrappers like catkin_add_gtest, catkin_add_nosetests, add_rostest_gtest, etc. These would be mostly pass-thrus to the underlying CMake functionality, but were a maintenance and documentation/support headache, as well as needlessly diverging the ROS community from the larger CMake world. I think the function-wrapping approach is fine for use within a single large project, but is not ideal for use across a large federated ecosystem (ROS has thousands of these CMake packages).

Given all the mechanisms which modern CMake seems to have for managing little bits of metadata about entities that it knows about like targets, I had hoped there might be a way to leverage some of it tag/group these targets in a way that didn’t require function wrapping.

Then I recommend traversing the tree and querying properties. I agree that wrappers are tough to maintain, but it also makes it easier to only use the bits for certain parts of the tree (like VTK’s APIs sometimes end up).