Skip to content

[CMake] Make dictionary module dependencies independent of config order#22648

Merged
guitargeek merged 1 commit into
root-project:masterfrom
guitargeek:issue-21673
Jun 18, 2026
Merged

[CMake] Make dictionary module dependencies independent of config order#22648
guitargeek merged 1 commit into
root-project:masterfrom
guitargeek:issue-21673

Conversation

@guitargeek

Copy link
Copy Markdown
Contributor

For each entry in DEPENDENCIES, ROOT_GENERATE_DICTIONARY passes rootcling a -m <dep>.pcm flag and a dependency on the dependency's module file, so that the prebuilt module is loaded instead of being built implicitly. This was wired up by inspecting the target graph while the macro runs (if(NOT TARGET G__${dep}) / get_target_property(... ROOT_PCM_FILENAME)), which only works if is configured before the dictionaries using it.

That breaks for core/multiproc: libMultiProc depends on Net (via TSocket), but it lives under core/, configured long before net/. So when G__MultiProc is generated, G__Net does not exist yet, the dependency is silently dropped, and rootcling can build Net implicitly, failing with "Building module 'Net' implicitly ... 'G__MultiProc.cxx' depends on 'Net'". The same shape affects every dictionary depending on a module configured later (Tree -> Net, ...).

Decide this at generation time instead, when all targets exist: guard the flag and the module-file dependency with $<TARGET_EXISTS:G__>. They are emitted whenever provides a dictionary and expand to nothing otherwise (e.g. a plain library such as TBB::tbb), regardless of configuration order.

Closes #21673.

🤖 Problem identified by AI, then the human guided the AI to write the solution that the human wanted to apply.

For each entry in DEPENDENCIES, ROOT_GENERATE_DICTIONARY passes rootcling
a `-m <dep>.pcm` flag and a dependency on the dependency's module file, so
that the prebuilt module is loaded instead of being built implicitly. This
was wired up by inspecting the target graph while the macro runs
(`if(NOT TARGET G__${dep})` / `get_target_property(... ROOT_PCM_FILENAME)`),
which only works if <dep> is configured before the dictionaries using it.

That breaks for core/multiproc: libMultiProc depends on Net (via TSocket),
but it lives under core/, configured long before net/. So when G__MultiProc
is generated, G__Net does not exist yet, the dependency is silently dropped,
and rootcling can build Net implicitly, failing with "Building module 'Net'
implicitly ... 'G__MultiProc.cxx' depends on 'Net'". The same shape affects
every dictionary depending on a module configured later (Tree -> Net, ...).

Decide this at generation time instead, when all targets exist: guard the
flag and the module-file dependency with $<TARGET_EXISTS:G__<dep>>. They are
emitted whenever <dep> provides a dictionary and expand to nothing otherwise
(e.g. a plain library such as TBB::tbb), regardless of configuration order.

Closes root-project#21673.

🤖 Problem identified by AI, then the human guided the AI to write the
solution that the human wanted to apply.
@github-actions

Copy link
Copy Markdown

Test Results

    22 files      22 suites   3d 12h 24m 33s ⏱️
 3 866 tests  3 866 ✅ 0 💤 0 ❌
76 384 runs  76 384 ✅ 0 💤 0 ❌

Results for commit 3706630.

@hageboeck hageboeck left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That looks quite nice. I have a small idea to save us an expansion.

Comment thread cmake/modules/RootMacros.cmake
@guitargeek guitargeek merged commit 9916067 into root-project:master Jun 18, 2026
40 of 45 checks passed
@guitargeek guitargeek deleted the issue-21673 branch June 18, 2026 09:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🤖AI-Assisted bug clean build Ask CI to do non-incremental build on PR in:Build System

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Issue with incremental builds

2 participants