From af2e05263445ffcb9ce9e968cf47099c64ece694 Mon Sep 17 00:00:00 2001 From: Unknown-Findout Date: Tue, 25 Aug 2026 15:45:34 -0500 Subject: [PATCH 1/2] build(cuda): NVCC_ALLOW_UNSUPPORTED, so a newer host compiler is reachable CUDA 13.1's crt/host_config.h accepts only Visual Studio 2019-2022 and refuses anything newer outright. On a box with VS Build Tools 18 (MSVC 19.50) every nvcc target dies at the first #include: host_config.h(164): fatal error C1189: #error: -- unsupported Microsoft Visual Studio version! Only the versions between 2019 and 2022 (inclusive) are supported! That is cuda-test, cuda-dll, all of it. nvcc ships -allow-unsupported-compiler for exactly this, but there was no way to get one flag into the command: NVCCFLAGS is the only handle and replacing it wholesale discards $(CUDA_GENCODE), the -ccbin set above it, and the -Xcompiler warning form Windows specifically needs. That is the same argument the NVCC_STD comment already makes a few lines up, so this follows it rather than inventing a new shape. Defaults to 0. nvcc's own wording is "may cause compilation failure or incorrect run time execution", so running on an unsupported host compiler stays an explicit decision by the builder, and any result produced with it set should say so. Verified on Windows, RTX 3090 (sm_86), CUDA 13.1, MSVC 19.50.35725: unset : "nvcc" -O3 -std=c++17 -ftz=false -arch=sm_86 -Xcompiler=-W3 ... -> C1189, no binary =1 : same line plus -allow-unsupported-compiler -> compiles, exit 0, backend_cuda_test.exe produced Co-Authored-By: Claude Opus 5 --- c/Makefile | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/c/Makefile b/c/Makefile index 80c151cf6..00fbfa887 100644 --- a/c/Makefile +++ b/c/Makefile @@ -296,6 +296,23 @@ ifneq ($(LINUX),) NVCCFLAGS += -Xcompiler=-include,$(CURDIR)/glibc_c23_math_compat.h endif endif +# CUDA 13.1 host_config.h accepts only Visual Studio 2019-2022 and refuses +# anything newer outright, so on a box with VS Build Tools 18 (MSVC 19.50) +# EVERY nvcc target fails at the first #include with C1189 -- cuda-test, +# cuda-dll, all of it. nvcc offers -allow-unsupported-compiler to override the +# check, but there was no way to get one flag in: NVCCFLAGS is the only handle +# and replacing it wholesale discards $(CUDA_GENCODE), the -ccbin set above and +# the -Xcompiler warning form that Windows specifically needs -- the same +# argument that made NVCC_STD a variable rather than a rewrite. +# +# Defaults to 0: nvcc's own wording is "may cause compilation failure or +# incorrect run time execution", so an unsupported host compiler is the +# builder's decision to make explicitly, not a default this Makefile makes for +# them. Any result produced with it set should say so. +NVCC_ALLOW_UNSUPPORTED ?= 0 +ifeq ($(NVCC_ALLOW_UNSUPPORTED),1) +NVCCFLAGS += -allow-unsupported-compiler +endif # HIP=1 builds the SAME backend for AMD GPUs via ROCm: backend_cuda.cu is # compiled unchanged through backend_gpu_compat.h (one source, two vendors, # like compat.h does for Windows). HIP_ARCH=native targets the GPU in this From afb07727195859ebb22bf7970101b902593184fd Mon Sep 17 00:00:00 2001 From: Unknown-Findout Date: Tue, 25 Aug 2026 15:45:34 -0500 Subject: [PATCH 2/2] test(cuda): pin NVCC_ALLOW_UNSUPPORTED off by default and non-destructive Three assertions in the file that already owns this recipe's build contract. The load-bearing one is test_allow_unsupported_compiler_preserves_the_other_flags. Appending must not do what a wholesale NVCCFLAGS override does, which is silently drop the gencode and lose -ftz=false - and -ftz is a correctness flag on this recipe, not a tuning knob: the comment beside it says the fmt=8 kernels are cross-tier parity instruments and a flushed scale*subnormal contribution diverges from the CPU reference. A build that lost it would still compile and still pass, and only the parity numbers would quietly move. nvcc_compile_line() skips the `command -v "nvcc"` guard line, which a naive search for "nvcc" matches first and which contains none of the flags under test. Negative control run rather than assumed: reverting the Makefile alone fails test_allow_unsupported_compiler_is_reachable and passes the other two, which is the correct split - off-by-default and flag-preservation are both already true without the change. Full python suite: 661 tests, OK, skipped=50. Co-Authored-By: Claude Opus 5 --- c/tests/test_cuda_test_makefile.py | 39 ++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/c/tests/test_cuda_test_makefile.py b/c/tests/test_cuda_test_makefile.py index 9abf054e2..a79a96a4e 100644 --- a/c/tests/test_cuda_test_makefile.py +++ b/c/tests/test_cuda_test_makefile.py @@ -15,6 +15,15 @@ def cuda_test_recipe(*variables): return result.stdout + result.stderr +def nvcc_compile_line(recipe): + """First real nvcc invocation, skipping the `command -v "nvcc"` guard line + that a naive grep for "nvcc" matches first.""" + return next( + (line for line in recipe.splitlines() + if "backend_cuda.cu" in line and " -o " in line and "command -v" not in line), + "") + + def mxfp4_link_line(recipe): return next( (line for line in recipe.splitlines() @@ -53,6 +62,36 @@ def test_hipcc_does_not_link_an_openmp_runtime_for_the_oracle(self): self.assertTrue(line, "no MXFP4 HIP link command in dry-run recipe") self.assertNotIn("-fopenmp", line) + def test_allow_unsupported_compiler_is_off_by_default(self): + """nvcc's own wording for this flag is "may cause compilation failure or + incorrect run time execution", so it is never a default.""" + line = nvcc_compile_line(cuda_test_recipe("CUDA=1", "NVCC=nvcc")) + self.assertTrue(line, "no nvcc compile command in dry-run recipe") + self.assertNotIn("-allow-unsupported-compiler", line) + + def test_allow_unsupported_compiler_is_reachable(self): + """CUDA 13.1's host_config.h rejects any MSVC newer than VS2022, which + fails every nvcc target at the first #include with C1189. Before this + variable the only handle was NVCCFLAGS, and overriding that wholesale + drops the gencode, the -ccbin and the platform warning form.""" + line = nvcc_compile_line( + cuda_test_recipe("CUDA=1", "NVCC=nvcc", "NVCC_ALLOW_UNSUPPORTED=1")) + self.assertTrue(line, "no nvcc compile command in dry-run recipe") + self.assertIn("-allow-unsupported-compiler", line) + + def test_allow_unsupported_compiler_preserves_the_other_flags(self): + """The load-bearing one. Appending must not do what a wholesale + NVCCFLAGS override does, which is silently drop the arch and lose + -ftz=false -- and -ftz is a correctness flag here, not a tuning knob: + the fmt=8 kernels are cross-tier parity instruments and a flushed + subnormal diverges from the CPU reference.""" + line = nvcc_compile_line( + cuda_test_recipe("CUDA=1", "NVCC=nvcc", "CUDA_ARCH=sm_86", + "NVCC_ALLOW_UNSUPPORTED=1")) + self.assertTrue(line, "no nvcc compile command in dry-run recipe") + for flag in ("-ftz=false", "-std=c++17", "sm_86"): + self.assertIn(flag, line, f"{flag} lost when the override is set") + def test_setup_openmp_probe_does_not_require_tmp(self): setup = (HERE / "setup.sh").read_text(encoding="utf-8") self.assertNotIn("/tmp/_omp", setup)