Skip to content

Add CI guard rejecting CMAKE_BINARY_DIR in first-party CMake files - #12793

Merged
jvepsalainen-nv merged 2 commits into
shader-slang:masterfrom
slang-coworkers:fix/issue-12790
Aug 31, 2026
Merged

Add CI guard rejecting CMAKE_BINARY_DIR in first-party CMake files#12793
jvepsalainen-nv merged 2 commits into
shader-slang:masterfrom
slang-coworkers:fix/issue-12790

Conversation

@nv-slang-bot

@nv-slang-bot nv-slang-bot Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Motivation

Slang's first-party CMake should use the project-scoped slang_BINARY_DIR (equivalent to PROJECT_BINARY_DIR within Slang's scope) for its own build outputs, not CMAKE_BINARY_DIR. CMAKE_BINARY_DIR resolves to the top-level build directory; when Slang is consumed via add_subdirectory (as a submodule/subproject of a larger build), that is the superproject's build tree, so Slang's outputs land outside its own tree and can collide with the consumer's (see #5871, #5896).

PR #12570 migrated the existing first-party uses to slang_BINARY_DIR. But nothing keeps the fix in place: no CI job builds Slang as a subproject, so a reintroduced ${CMAKE_BINARY_DIR} is invisible to every existing check. This PR adds a cheap textual guard so the invariant is enforced at PR time.

This is the "cheap grep guard" that #12790 requests. (The heavier add_subdirectory consumer smoke test the issue also mentions is intentionally left as a separate follow-up, per the reporter.)

Proposed solution

A lightweight lint job (intended to be configured as a non-required check) that asserts zero occurrences of CMAKE_BINARY_DIR in first-party CMake files, with a message pointing at the slang_BINARY_DIR remedy.

The check uses git grep (tracked files only). This is load-bearing: git grep does not descend into submodule working trees, so vendored third-party CMake (mimalloc, glm, spirv-tools, …) that legitimately uses CMAKE_BINARY_DIR is excluded automatically — while external/CMakeLists.txt, which is first-party (tracked, not a submodule), is still covered. A plain grep -r/rg over a checkout would false-positive on the vendored trees, and --exclude-dir=external would wrongly skip a first-party file. Scope is therefore the tracked-vs-submodule boundary, not the external/ path prefix.

The match is whole-word (git grep -w), so a larger identifier such as MY_CMAKE_BINARY_DIR would not be flagged. (CMAKE_CURRENT_BINARY_DIR — the subproject-safe variable used legitimately elsewhere in the tree — is a different string and is not matched.)

Change summary

  • extras/check-no-cmake-binary-dir.sh — new. Runs git grep -wn 'CMAKE_BINARY_DIR' -- '*.cmake' '*.cmake.in' '*CMakeLists.txt', captures the exit status (0 = matches, 1 = clean, >1 = a real grep error that fails the guard loudly), and on any match exits non-zero listing the offending lines plus the slang_BINARY_DIR remedy.
  • .github/workflows/check-cmake-binary-dir.yml — new. Modeled on check-submodules.yml: path-filtered pull_request, if: draft != true, permissions: contents: read, submodules: false, intended as a non-required check; a lightweight job.
  • .github/workflows/README.md — adds the new workflow to the PR-gates table.

Concepts and vocabulary

  • CMAKE_BINARY_DIR — the top-level (superproject) build directory. Differs from Slang's own build dir only when Slang is included via add_subdirectory.
  • slang_BINARY_DIR / PROJECT_BINARY_DIR — CMake's per-project() binary dir; always points at Slang's own build directory regardless of how Slang is included. The correct variable for Slang's outputs.
  • first-party CMake — CMake files tracked in this repository (including external/CMakeLists.txt), as opposed to CMake inside submodule working trees, which are third-party and out of scope.

Process report

  • Why a textual guard rather than a behavioral one? The behavioral regression (outputs escaping Slang's tree) only manifests under an add_subdirectory consumer build, which no PR-time CI job performs (cmake-options.yml's find_package consumer test is workflow_dispatch/weekly-cron only). A git grep assertion is essentially free and catches the reintroduction at the source line. The full consumer smoke test covers a broader class but is heavier/brittle and is deliberately deferred to a separate follow-up, as the issue requests.
  • Why git grep and -w, verified: at origin/master (c1cffad) git grep -wn 'CMAKE_BINARY_DIR' -- '*.cmake' '*.cmake.in' '*CMakeLists.txt' finds 22 lines across 8 files; a raw rg over a populated checkout finds many more, all under build/_deps/ (untracked artifacts) and external/<submodule>/ working trees — exactly what must be excluded.
  • Scope decision: the guard reads tracked-file text, the canonical surface — it does not special-case any accidental shape. The one non-obvious scope decision (first-party = tracked, not !external/) is dictated by the submodule boundary and stated in the script header.

⚠ Sequencing: depends on #12570 — held as draft until it merges

Today's master still has the 22 first-party occurrences; PR #12570 (OPEN, non-draft, head 1754931a0c, branch feature/fix-build-output-directory) is what makes the count zero — its changed-file set is identical to the 8 files with hits. If this guard ran as a green-required check against today's master it would fail on those 22 lines. This branch fails the guard today, by design, until #12570 lands.

This PR is therefore held as a draft: the workflow's if: github.event.pull_request.draft != true means the check does not run while the PR is draft, so there is no false red. Do not mark ready / merge until #12570 has landed on master; after it lands, a rebase makes the check pass (verified: the script exits 0 against #12570's head 1754931a0c, which has zero matches).

Closes #12790.

🤖 Generated by an automated Slang coworker — may be inaccurate. A human maintainer should verify.

Slang's first-party CMake must use the project-scoped slang_BINARY_DIR
rather than CMAKE_BINARY_DIR, so that build outputs land under Slang's own
build tree when Slang is consumed via add_subdirectory. No existing CI job
builds Slang as a subproject, so a reintroduced CMAKE_BINARY_DIR is
otherwise invisible.

Add extras/check-no-cmake-binary-dir.sh (git grep over tracked files, so
vendored submodule CMake is excluded) and a path-filtered, non-required
workflow that runs it on pull_request. Depends on shader-slang#12570, which removes the
existing 22 first-party occurrences.

Closes shader-slang#12790.
@nv-slang-bot nv-slang-bot Bot added the pr: non-breaking PRs without breaking changes label Aug 27, 2026
@jhelferty-nv

Copy link
Copy Markdown
Contributor

Automated notice (PR board sync) — do not reply to this comment.

Auto-assigned @jvepsalainen-nv as shepherd for this Bot PR.

FYI for maintainers: committer signal on the changed files is highest for jkiviluoto-nv among collaborators other than the assignee. They were not auto-requested; a human may optionally add them as a reviewer.

@jvepsalainen-nv
jvepsalainen-nv marked this pull request as ready for review August 28, 2026 08:11
@jvepsalainen-nv
jvepsalainen-nv requested a review from a team as a code owner August 28, 2026 08:11
@jvepsalainen-nv
jvepsalainen-nv requested review from bmillsNV and removed request for a team August 28, 2026 08:11
@jvepsalainen-nv

Copy link
Copy Markdown
Contributor

@nv-slang-bot review this PR

@nv-slang-bot

nv-slang-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

👋 @jvepsalainen-nv — thanks for merging #12570 and un-drafting this. Review complete.

Review checklist:

Outcome — WOULD_APPROVE @ 777942ff:

  • Changed CMake configuration for compiling Slang as a submodule #12570 dependency resolved: merged as cc5f4d7f5c (2026-08-27); master now has 0 first-party CMAKE_BINARY_DIR occurrences (was 22). The ordering hold this PR was held draft for has cleared.
  • Guard verified live: ran extras/check-no-cmake-binary-dir.sh at this PR's head and at master — both PASS (exit 0).
  • Its own CI workflow behaved exactly as designed: check-cmake-binary-dir was skipped while draft (the if: draft != true gate), and succeeded once un-drafted at both 3d587119 and the current 777942ff.
  • Diff is minimal and unchanged: net vs master is the 3 intended files (+72); the guard script and workflow are byte-identical to the reviewed versions.

No blocking findings. This is a maintainer-owned merge decision — flagging that the change touches .github/workflows/**, which is a maintainer-merge surface for bot-authored PRs.

(Last updated: 2026-08-28T08:50Z)

🤖 Generated by an automated Slang coworker — may be inaccurate. A human maintainer should verify.

@jvepsalainen-nv jvepsalainen-nv 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.

LGTM

@jvepsalainen-nv
jvepsalainen-nv added this pull request to the merge queue Aug 31, 2026
Merged via the queue into shader-slang:master with commit 19e4c90 Aug 31, 2026
64 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr: non-breaking PRs without breaking changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Guard against CMAKE_BINARY_DIR regressing the submodule build

2 participants