FetchContent population reuse semantics when re-entering a superbuild from a different directory scope
0 reputation · 19 Nov 2021, 12:31 UTC
0 reputation · 19 Nov 2021, 12:31 UTC
FetchContent is documented to populate external sources once per build tree, caching the result under the build directory and reusing it on subsequent configures unless the declared URL, URL_HASH, or content changes. This contract works predictably for a single top-level configure run.
When a superbuild re-enters its own CMake logic from a different directory scope — for example, a nested add_subdirectory that re-invokes FetchContent_MakeAvailable for the same declared dependency — the cache invalidation rules become unclear. The populated source directory exists, but the module may re-evaluate the declare step in a new scope, potentially triggering a second population or skipping it silently depending on CMake version and policy settings (e.g., CMP0145). Multi-config generators and partial build-tree cleans add further variance.
Determine whether FetchContent guarantees idempotent reuse across re-configure entry points in different directory scopes, or whether the population step can run again and under what exact conditions.
34275 reputation · 19 Nov 2021, 22:03 UTC
When a superbuild re‑enters its own CMake logic from a different directory scope—e.g., a nested add_subdirectory that calls FetchContent_MakeAvailable again—the source and binary directories that were populated the first time are reused. CMake stores the state of every FetchContent_Declare in global properties keyed only by the lower‑cased name. The first declaration for a given name wins; subsequent declares from any scope are ignored unless a policy or variable forces a different outcome.
name and the URL, URL_HASH, GIT_TAG, etc., stored in global properties.CMP0145 (since CMake 3.12) dictates whether a second FetchContent_Declare for the same name is ignored.CMP0168 and CMP0169 (CMake 3.30+) deprecate direct FetchContent_Populate(name) and promote MakeAvailable as the sole public API.FETCHCONTENT_UPDATES_DISCONNECTED – skip the update step for VCS content.FETCHCONTENT_FULLY_DISCONNECTED – assume the source is already populated and skip any download or update.UPDATE_DISCONNECTED – same effect but scoped to a single dependency._deps/<name>-subbuild directory or the stamp files will cause the next configure to re‑run the population step, even though the source cache still exists.cmake -S . -B build
get_property(_src GLOBAL PROPERTY _FetchContent__SOURCE_DIR)
message("Source dir: ${_src}")
add_subdirectory that also calls FetchContent_MakeAvailable().FETCHCONTENT_FULLY_DISCONNECTED=ON before the second configure and observe that no download occurs._deps/<name>-subbuild or the stamp file?Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.