FetchContent and cache variables collisions

If a project wants to be consumable via FetchContent (or via add_subdirectory() as a git submodule, it’s effectively the same use case), that project should avoid using names for things that are too generic. Some strategies to help with that:

  • Use CMake target names that incorporate the project name, such as MyProj_Thing. This will avoid name collisions when absorbing the project into a larger project’s build.
  • Use exported target names like MyProj::Thing, creating an ALIAS target with that exported name so that consumers can just use MyProj::Thing everywhere and not care whether the project is brought in using FetchContent, or via an installed package.
  • Follow recommended naming conventions for cache variables used as result variables of find_...() commands. For example, for executables, use names like THING_EXECUTABLE. The Standard Variable Names section of the developer docs lays out the recommended naming conventions (it’s for Find modules, but projects should ideally follow the same conventions).
  • For other cache variables, prefix them with the project name, capitalised. This will also have the handy benefit of collecting all project-specific variables together in GUI applications that show the cache variables in a list, or grouped by prefix (CMake GUI does this). For example, I typically name all boolean option variables following the form MYPROJ_ENABLE_THING.

If a dependency doesn’t follow guidelines like those mentioned above, you’re at the mercy of what they define. Some projects simply can’t be used with FetchContent because they do things that cause name clashes with other projects (target names like documentation, or use of variables like CMAKE_SOURCE_DIR and CMAKE_BINARY_DIR are common problems).

You may also be interested in this issue, which proposes a namespace feature for projects. If implemented, it would address a large chunk of problems related to name clashes.

1 Like