-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
As seen indirectly in the build https://github.com/root-project/root/actions/runs/20936367154/job/60253171091?pr=20861 and the tests https://github.com/root-project/root/pull/20861/checks?check_run_id=60259379743, there are scenarios when running make twice in a row in a ROOT build leads to spurious rebuilds.
This is has been seen on Debian and Ubuntu build, i.e. likely for OS where the file timestamp is granular enough to 'matter' for this.
The following reproduces the problem using the registry.cern.ch/root-ci/rawhide:buildready image (Debian),
# Download and setup a ROOT build as usual (eg. see step `To replicate this build locally` in link above)
cd root_build_dir
# Step (1) build ROOT
make
# Step (2) Ensure that core/CMakeFiles/G__Core.dir/compiler_depend.make is empty
cmake .
# Step (3) Ensure that G__Core.cxx (and Core.pcm) will be regenerated
touch include/RConfigure.h
# Step (4) After this Core.pcm is ‘older’ than ‘G__Core.cxx’ where the opposite is expected
make RIO
# (5) See that G__Core.cxx is not regenerated but G__RIO.cxx is regenerated (when it should not)
make RIO
The mechanics:
On step (3), because of step (2), core/CMakeFiles/G__Core.dir/compiler_depend.make is empty
and thus G__Core.cxx is depends on the explicit dependencies until that file is regenerated.
Inside step 4, one of the sub step (4.1) is:
- run /usr/sbin/gmake -s -f core/CMakeFiles/G__Core.dir/build.make core/CMakeFiles/G__Core.dir/depend
- - Checks both Core.cpm and G__Core.cxx
- - - No need to remake target 'core/G__Core.cxx'
- - - Prerequisite 'core/G__Core.cxx' is older than target 'lib/Core.pcm'
which generates core/CMakeFiles/G__Core.dir/compiler_depend.make.
This steps 4.1 is also the step responsible for updating the timestamp of Core.pcm to be newer than
G__Core. This is not needed/executed in this iteration.
Then inside 4, the next sub step (4.2) is:
- run /usr/sbin/gmake -s -f core/CMakeFiles/G__Core.dir/build.make core/CMakeFiles/G__Core.dir/build
- - Must remake target 'core/G__Core.cxx'.
- - core/CMakeFiles/G__Core.dir/build.make:479: update target 'core/G__Core.cxx' due to: include/RConfigure.h
- *BUT* Core.pcm is not check (it is not a dependency of `build`).
which loads the generated dependency file and thus notice that G__Core.cxx needs to be
regenerated. The generation produces Core.pcm first and the G__Core.cxx. So
after this step Core.pcm is older than G__Core.cxx. The updating is of the timestamp of Core.pcm
is not run (it is not part of the dependency tree of core/CMakeFiles/G__Core.dir/build.
Now on step 5, we run the same sub-step (5.1):
- run /usr/sbin/gmake -s -f core/CMakeFiles/G__Core.dir/build.make core/CMakeFiles/G__Core.dir/depend
this time make notices that:
- G__Core.cxx does not need updating
- Core.pcm needs to have its time stamp updated.
This then leads to the rebuild of libRIO and all the dictionaries (which should not be needed since nothing
actually changes since the last run).
It is not clear whether this is a bug in CMake's use of Makefiles or in the way the ROOT CMakeLists.txt are setup.