0.2.2: a rule takes the extensions it claims, not every device source - #6
Merged
Merged
Conversation
`mcpp::device_sources()` is the package's WHOLE device set, and every rule in a
build program reads the same variable. All four rules took all of it, which is
right for exactly as long as a build has one rule in it.
A project with two backends puts a `.cu` and a `.comp` in that one list.
Measured on the unfixed rules, with both imported:
cuda:scale clang -x cuda shaders/scale.comp -o scale.cu.o
mcpp.rules.spirv: src/kernels/saxpy.cu has no shader stage.
Two failures, and the quieter one is the worse. The CUDA rule did not refuse
the shader -- it compiled it, and produced an object. The shader rule then
failed on the `.cu`, with a message about stages that points at a file it was
never meant to see. Neither names the actual condition, which is that two rules
were handed each other's inputs.
So each rule now selects the extensions it claims -- `.cu`, `.hip`, `.sycl`,
and the shader stages -- and leaves the rest to whoever claims those. A file no
rule claims is not silently dropped either: mcpp 2026.9.6.5 refuses a device
source that reached no action, which is the one place that can see every rule's
share at once. `rules-spirv` deliberately claims `.glsl` and `.hlsl` too,
though it refuses them, because "rename it to one of these stages" is a better
message than "nothing compiled this".
Second half: a rule whose backend this build does not name now returns
immediately instead of warning. A build program with several rules calls them
all, and the ones whose backend is absent have nothing to do -- which is not a
mistake and must not be reported as one. That is what makes `--no-accel` work
with two rules present.
tests/multi-rule-consumer is the fixture the change exists for: one package
with a `.cu` and a `.comp`, both rules in one build program, both products
asserted, and `test ! -f scale.cu.o` for the shader that must not have been
compiled as CUDA. Verified on a real device as well -- the artifact prints the
SPIR-V magic number and the kernel's result from one binary.
Every fixture also moves its rule dependency from `[dependencies]` to
`[build-dependencies]`. A rule package's library must never reach the target
while its rule is still wanted, which is what that section is for; the old
spelling works, which is why the distinction has to be stated rather than left
to a failure to teach.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this fixes
mcpp::device_sources()is the package's whole device set, and every rulein a build program reads the same variable. All four rules took all of it,
which is right for exactly as long as a build has one rule in it.
A project with two backends puts a
.cuand a.compin that one list.Measured on the unfixed rules with both imported:
Two failures, and the quieter one is worse: the CUDA rule did not refuse the
shader, it compiled it and produced an object. The shader rule then failed
on the
.cuwith a message about stages, pointing at a file it was never meantto see. Neither names the actual condition.
The change
Each rule selects the extensions it claims and leaves the rest:
rules-cuda.curules-hip.hiprules-sycl.syclrules-spirv.glsl/.hlslso a stage-less name is refused by nameA file no rule claims is not silently dropped either — mcpp 2026.9.6.5
refuses a device source that reached no action, which is the one place that can
see every rule's share at once.
Second half: a rule whose backend this build does not name now returns
immediately instead of warning. A build program with several rules calls them
all, and the ones whose backend is absent have nothing to do. That is what
makes
--no-accelwork with two rules present.Verification
tests/multi-rule-consumeris the fixture the change exists for: one packagewith a
.cuand a.comp, both rules in one build program, both productsasserted, and
test ! -f scale.cu.ofor the shader that must not have beencompiled as CUDA. Run on a real device as well — one binary prints the SPIR-V
magic number and the kernel's result:
All five existing fixtures re-run green, on the CI-pinned 2026.9.6.1 as well as
on the development engine.
Also
Every fixture moves its rule dependency from
[dependencies]to[build-dependencies]: a rule package's library must never reach the targetwhile its rule is still wanted. The old spelling works, which is why the
distinction has to be stated rather than left to a failure to teach.