as far as I understand, when using the FetchContent module and populating the fetched package, all the cache variables are combined together with the top level project into a single CMakeCache.txt file.
Are in practice any major issues with this and cache variable often collide?
What would be a way to solve such issue when wanting to add many packages with FetchContent?
I’m thinking here about issues like this:
# Top level project checks for getcwd symbol:
check_symbol_exists(getcwd "unistd.h" HAVE_GETCWD)
# The fetched project checks for something else and stores the result to a
# variable with the same name HAVE_GETCWD:
check_source_compiles(C "..." HAVE_GETCWD)
Is there perhaps some rule of a thumb regarding using FetchContent?
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.
I really think the bar for packages out there is too high. I still unfortunately haven’t encountered a single CMake project that is able to fully follow these conventions. Yes, otherwise, theoretically, following very very very strict conventions goes through ok. But in reality, this is not the case yet.
Issues are mostly related not so much to targets but to cache variables. Also, for example build types are clashing heavily. At some point I thought some new CMake integrated ASAN build type and ASAN compile options by default and then I saw that the dependency did that.