Skip to content

Spurious rebuilds in some circunstances #20907

@pcanal

Description

@pcanal

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.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions