Skip to content

Avoid duplicate core module builds#11721

Draft
jkwak-work wants to merge 1 commit into
masterfrom
build-each-module
Draft

Avoid duplicate core module builds#11721
jkwak-work wants to merge 1 commit into
masterfrom
build-each-module

Conversation

@jkwak-work

@jkwak-work jkwak-work commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator

Fixes #11717

Motivation

When SLANG_EMBED_CORE_MODULE=OFF, a debug build was compiling the core module multiple times. The dedicated core module generation step produced embedded headers, but downstream module and example build rules still invoked compiler paths that had no prebuilt core archive, so slang-bootstrap or slangc compiled core again while generating GLSL, neural, and examples/cpu-shader-llvm/shader.o artifacts.

Proposed solution

Make the generated core module archive a first-class build output. Downstream module compilation now consumes it through -load-core-module, and saved built-in module outputs are deferred so a command such as slang-bootstrap -load-core-module <archive> -save-glsl-module-bin-source ... compiles only the requested non-core built-in module. This keeps the dependency at CMake rule boundaries instead of relying on each downstream compiler invocation to rebuild core independently.

Change summary

  • source/slang-core-module/CMakeLists.txt now writes slang-core-module.bin and the core header from one rule, exposes them through one generate_core_module target, and generates the GLSL header from a second rule that loads that archive.
  • cmake/RunIfOutdated.cmake wraps build-time generation commands so repeated Visual Studio target traversal skips commands whose declared outputs are newer than their inputs.
  • source/slang/slang-options.cpp defers save requests until after -compile-core-module, and compiles a requested built-in module on demand when a save request targets a module that has not been loaded yet.
  • source/standard-modules/neural/CMakeLists.txt uses slang-bootstrap and loads the generated core archive, avoiding a build-time dependency on slangc.
  • examples/cpu-shader-llvm/CMakeLists.txt passes the generated core archive to its slangc shader-object command, avoiding a second core compile during full builds.
  • source/slang-glsl-module/CMakeLists.txt depends on the GLSL generation target instead of the aggregate core-module header target.

Concepts and vocabulary

  • Core module archive: the generated slang-core-module.bin artifact loaded by -load-core-module when embedded core is off.
  • Bin-source header: a generated C++ header containing a serialized built-in module for embedding into the corresponding library target.
  • Bootstrap compiler: slang-bootstrap, the standalone generator tool used during the build before the full slangc executable is required.

Process report

The root cause was not that CMake had too few dependencies; it was that some consumers only depended on generated headers while invoking compiler commands without an explicit core archive. The first fix in source/slang-core-module/CMakeLists.txt separates core archive generation from GLSL header generation: the core rule runs slang-bootstrap -compile-core-module -save-core-module ..., and the GLSL rule runs slang-bootstrap -load-core-module ... -save-glsl-module-bin-source .... This makes the core archive the single source of truth for downstream generator commands.

The compiler option handling previously saved built-in module outputs as each option was parsed. That ordering forced combined command lines such as -compile-core-module -save-core-module-bin-source to depend on parse order and made it hard to save a non-core module after loading an existing core archive. OptionsParser::addPendingBuiltinModuleSave and OptionsParser::writePendingBuiltinModuleSaves record save requests, run them after the optional core compile, and call compileBuiltinModule only for the named module when saveBuiltinModule reports that it is missing. A request to save GLSL after -load-core-module is therefore a valid input shape: the core module is already loaded, and only the requested dependent module needs to be built.

Neural was using the full compiler for build-time module generation. That was the wrong layer for this build rule because neural only needs a standalone generator plus the prebuilt core archive. source/standard-modules/neural/CMakeLists.txt now selects slang-bootstrap and depends on generate_core_module, so building neural does not require slangc.exe and does not trigger core compilation.

The remaining full-build duplication came from examples/cpu-shader-llvm/CMakeLists.txt. Its slangc invocation for shader.o had no -load-core-module, so slangc had to compile core internally even after the dedicated archive rule had completed. Adding -load-core-module ${core_module_archive} and the corresponding dependency makes that example consume the same build artifact as the module-generation rules.

cmake/RunIfOutdated.cmake addresses repeated generator-rule traversal from Visual Studio builds. The CMake targets may still be visited more than once through different dependencies, but the wrapper checks declared outputs against explicit inputs and skips the command when the generated artifacts are up to date. This keeps the build graph behavior deterministic without relying on undocumented command-side side effects.

@jkwak-work jkwak-work added pr: non-breaking PRs without breaking changes CoPilot labels Jun 24, 2026
@jkwak-work jkwak-work self-assigned this Jun 24, 2026
@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds cmake/RunIfOutdated.cmake, a script that skips code-generation commands when outputs are up-to-date. Splits the single slang-bootstrap invocation that produced both core-module and GLSL-module headers into two separate RunIfOutdated-guarded steps sharing a serialized core_module_archive. Updates neural and cpu-shader-llvm build rules to load that archive. Defers slangc built-in module save operations until after core-module compilation.

Changes

Avoid redundant core module builds

Layer / File(s) Summary
RunIfOutdated.cmake utility
cmake/RunIfOutdated.cmake
New script validates required variables, checks whether outputs are missing or inputs are newer than outputs, skips execution with a status log when up-to-date, and runs the configured command via execute_process with fatal-error handling.
Deferred built-in module saves
source/slang/slang-options.cpp
Introduces PendingBuiltinModuleSave struct and m_pendingBuiltinModuleSaves queue; replaces immediate save+write for -save-core-module, -save-core-module-bin-source, -save-glsl-module-bin-source with addPendingBuiltinModuleSave; adds writePendingBuiltinModuleSaves (with compile-on-fail retry and binary/hex-dump output); calls it after compileCoreModule.
Core-module CMake target restructuring
source/slang-core-module/CMakeLists.txt, source/slang-glsl-module/CMakeLists.txt
Defines and propagates core_module_archive; replaces the single slang-bootstrap invocation with two RunIfOutdated.cmake-driven steps producing generate_core_module_archive+generate_core_module_header (core) and generate_glsl_module_header (GLSL); updates slang-glsl-module REQUIRES to generate_glsl_module_header; narrows slang-embedded-core-module dependency to generate_core_module_header only.
Consumer build rules updated
source/standard-modules/neural/CMakeLists.txt, examples/cpu-shader-llvm/CMakeLists.txt
Neural module switches non-cross-compilation branch to slang-bootstrap with -load-core-module ${core_module_archive} and generate_core_module_archive dependency. cpu-shader-llvm adds generate_core_module_archive to its link-shader dependency list.

Suggested reviewers

  • bmillsNV
  • kaizhangNV
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Avoid duplicate core module builds' directly and concisely describes the main change: eliminating redundant core module compilation during the build process.
Linked Issues check ✅ Passed All code changes address the requirements in #11717: core archive is generated as a reusable artifact, GLSL module generation loads it, neural module uses slang-bootstrap with the archive, and RunIfOutdated prevents rerunning commands when outputs are newer than inputs.
Out of Scope Changes check ✅ Passed All changes are directly related to the core objective of eliminating duplicate core module builds: core archive generation separation, deferred compiler save handling, neural module build restructuring, example shader compilation with archive loading, and build deduplication logic.
Description check ✅ Passed The pull request description is directly related to the changeset, providing clear motivation, proposed solution, and detailed change summary aligned with the file modifications.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@jkwak-work

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 87c6bffe-f69c-47e9-8f05-d07cbd6f73d5

📥 Commits

Reviewing files that changed from the base of the PR and between f114261 and 33693ba.

📒 Files selected for processing (6)
  • cmake/RunIfOutdated.cmake
  • examples/cpu-shader-llvm/CMakeLists.txt
  • source/slang-core-module/CMakeLists.txt
  • source/slang-glsl-module/CMakeLists.txt
  • source/slang/slang-options.cpp
  • source/standard-modules/neural/CMakeLists.txt

Comment thread cmake/RunIfOutdated.cmake
Comment on lines +16 to +22
foreach(input IN LISTS SLANG_RUN_IF_OUTDATED_INPUTS)
foreach(output IN LISTS SLANG_RUN_IF_OUTDATED_OUTPUTS)
if("${input}" IS_NEWER_THAN "${output}")
set(SLANG_RUN_IF_OUTDATED_NEEDED TRUE)
endif()
endforeach()
endforeach()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Fail fast when a declared staleness input is missing.

On Line 16, inputs are compared with IS_NEWER_THAN, but there is no existence check for each input path first. If an input path is wrong/missing, this can silently evaluate as up-to-date and skip regeneration incorrectly.

🔧 Proposed fix
 if(NOT SLANG_RUN_IF_OUTDATED_NEEDED)
     foreach(input IN LISTS SLANG_RUN_IF_OUTDATED_INPUTS)
+        if(NOT EXISTS "${input}")
+            message(FATAL_ERROR "SLANG_RUN_IF_OUTDATED_INPUTS entry does not exist: ${input}")
+        endif()
         foreach(output IN LISTS SLANG_RUN_IF_OUTDATED_OUTPUTS)
             if("${input}" IS_NEWER_THAN "${output}")
                 set(SLANG_RUN_IF_OUTDATED_NEEDED TRUE)
             endif()
         endforeach()
     endforeach()
 endif()

As per path instructions, "cmake/**: Build system changes. Verify cross-platform compatibility (Windows/Linux/macOS). Check for proper target dependency declarations and generator expressions."

Source: Path instructions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CoPilot pr: non-breaking PRs without breaking changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Avoid redundant core module builds when SLANG_EMBED_CORE_MODULE=OFF

1 participant