Search code examples
cmakenamespacessemantics

Do CMake namespaces actually mean anything?


In modern CMake, it is customary to export targets within namespaces, e.g. have your foo project export foo::foo and perhaps also foo::bar etc.

My question is: Do these namespace actually mean anything by themselves, or are they just parts of a single name, without CMake separating the ::-separated name components?

And if the former is true, can you say things like "all targets in a namespace" or otherwise use the namespace as such?


Solution

  • I did not see any CMake functionality (yet) that would allow handling the name components of namespaced export targets separately. But I found that CMake namespaces still have one meaning, in the sense that they influence the behavior of CMake:

    Namespaced targets are never filenames

    Using target names containing :: in a target_link_libraries(…) call will ensure that CMake resolves this only to so-called IMPORTED targets that are found via find_package(…). It prevents the usual fallback mechanism to also try resolving this as a library filename on disk (like where -lName would look for libName.so on disk).

    That behaviour is documented in CMake Policy 0028. It is not necessarily enabled everywhere, but CMake ≥3.0.2 will warn if not.

    It's also useful. I just had a confusing issue caused by CMake's fallback behavior (see). As a consequence, I'll strictly use namespaced target names with :: in target_link_libraries(…).

    Sadly, from another piece of CMake documentation, it appears that this feature of identifying IMPORTED targets is probably the one and only meaning of CMake namespaces:

    A NAMESPACE with double-colons is specified when exporting the targets for installation. This convention of double-colons gives CMake a hint that the name is an IMPORTED target when it is used by downstreams with the target_link_libraries() command. This way, CMake can issue a diagnostic if the package providing it has not yet been found.

    Package components are a different thing

    At first glance, it seemed to me that there is one namespace per CMake package and one target name in that namespace per package component. So that after a find_package(noms COMPONENTS fruit veg) you'd have noms::fruit and noms::veg available for target_link_libraries(…). But that is only a widespread (and useful) current practice. Technically, package components do not necessarily map to one target though (details).