Cleaning external_project / fetch_content SUBBUILD_DIR directories?

Hey all,

I’m encountering an issue that I don’t know how to solve. With CMake 3.24, --fresh was added as an option that is super helpful when writing iterations of a CMake build.

Even with that option, I’m seeing that SUBBUILD_DIRs keep their same initial state. This has been a particular problem for me. I have a CI job that checks out your branch and runs some checks on it. If I happen to change one of my external_project / fetch_content dependencies to/from URL and GIT_REPOSITORY, I’ll get this error:

  Failed to get the hash for HEAD:

  fatal: not a git repository: '.git'

It looks like some of this update logic is sticky. I end up having to clean build on the CI whenever these events happen. Is there any way to get around this issue?

Strange, I would expect that switching the download strategy would reset the source directory (like I’ve seen changing from one URL to another does). Maybe there’s a hole somewhere? Can you provide a minimal example with instructions to reproduce so that the behavior can be tracked down in detail?

Cc: @craig.scott

1 Like

Thanks for the quick reply @ben.boeckel ,

Here’s a minimal example with instructions to reproduce:

I just walked through those steps to reproduce myself:

~/git/cmake-subbuild-dir-bug main* ❯ cmake -B build                                                                                             09:15:11 PM
-- CPM: Adding package rapidjson@0 (6089180ecb704cb2b136777798fa1be303618975)
[ 11%] Performing download step (git clone) for 'rapidjson-populate'
-- Avoiding repeated git clone, stamp file is up to date: '/Users/anthony.alayo/git/cmake-subbuild-dir-bug/build/_deps/rapidjson-subbuild/rapidjson-populate-prefix/src/rapidjson-populate-stamp/rapidjson-populate-gitclone-lastrun.txt'
[ 22%] Performing update step for 'rapidjson-populate'
CMake Error at /Users/anthony.alayo/git/cmake-subbuild-dir-bug/build/_deps/rapidjson-subbuild/rapidjson-populate-prefix/tmp/rapidjson-populate-gitupdate.cmake:34 (message):
  Failed to get the hash for HEAD:

  fatal: not a git repository: '.git'

It looks like going from GIT_REPO to URL is no problem, but going from URL to GIT_REPO causes the error.

There are definitely some robustness holes in FetchContent and ExternalProject not properly handling when some details change. I had many of those fixed at one point, but had to revert them because of regressions in the main feature they were included with. I haven’t had a chance to go back and reapply at least the robustness fixes. I don’t know when I’ll get another chance to do that, sadly.

The --fresh option shouldn’t need to apply for anything to do with FetchContent. If the content you want to download is already present, then there’s nothing that should need to be repeated. The only reason it came up in this discussion is because of the robustness problems in FetchContent’s detection of changing arguments. Making --fresh try to somehow help with that is the wrong solution. The right fix is to address the bugs in the FetchContent detection logic. Those are definitely solvable, as mentioned above.

1 Like

Great to hear from you @craig.scott . Would this past attempt exist in a branch somewhere? Perhaps I can take it over?