Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions c/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
39 changes: 39 additions & 0 deletions c/tests/test_cuda_test_makefile.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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)
Expand Down
Loading