build: preserve sysconfig extras in LDCXXSHARED - #2973
Conversation
|
btw I am consolidating all compiler/linker flags in #2965 so it'd be really great to sort out a review/merge order 😛 |
7656d97 to
a00f514
Compare
b91c1a1 to
6fd5fdd
Compare
Keep LDCXXSHARED sysconfig extras; NVIDIA#2969 sccache prefix is already in this branch.
|
/ok to test e5ecafd |
|
|
/ok to test 4002c6d |
rwgk
left a comment
There was a problem hiding this comment.
GPT-6-Sol ultra
PR 2973 fixes how an explicit CUDA_PYTHON_TOOLCHAIN configures C++ linking. Previously, the build hooks replaced LDSHARED with {CXX} -shared, discarding linker flags supplied by Python or Conda. Both hooks now set LDCXXSHARED, taking an exported value first, then Python’s configuration, and replacing its compiler while retaining the remaining arguments. The default toolchain path is unchanged. The PR adds matching tests in both packages and updates the nightly pixi round-trip check to use the ABI-scoped build stamp and Cython directories.
Findings
-
P2 — An exported linker wrapper can be lost.
_with_compilerdrops every token before the first flag, not just the old compiler; the core copy does the same. An exportedLDCXXSHARED="env LIBRARY_PATH=/custom/lib g++ -shared"becomesclang++ -shared, losing a library search path. A captured setuptools 84 C++ link command retained that prefix with the base code and lost it with this PR. The replacement should identify the compiler while preserving required command prefixes. -
P2 — The new integration test can fail when the linker is correct. The bindings assertion and core assertion discard non-flag arguments from the expected command. For Conda’s
-B /path/to/python_compiler_compat, they discard the path while the actual linker correctly keeps it. Compare the complete argument tail. -
P3 — The sccache tests also assert an unrelated C-linker property. Both packages build C++ extensions, but the bindings test and core test require
linker_soto start withsccache clang. Setuptools need not rewrite that C linker for every valid Python configuration, even when the C++ link is correct.
Verification: Using TestVenv, the bindings hook suite had 53 passed, 1 skipped; core had 90 passed, 1 skipped. The current interpreter has no split -B operand, so those passes do not cover finding 2. git diff --check and the shared-helper sync check passed. PR CI ran the new tests, but the changed nightly round-trip job is skipped on pull requests; that workflow fix remains unverified on the PR head. No tracked files were changed during this review.
|
@rwgk the changed nightly round-trip job was exercised with a manual https://github.com/NVIDIA/cuda-python/actions/runs/36766403261/job/110067451890 (The run's overall status shows "cancelled" only because the GPU |
|
/ok to test bb3898e |
mdboom
left a comment
There was a problem hiding this comment.
I continue to have skepticism about adding complexity to the compiler support in our own build_hooks.py vs. evaluating a more full-featured build backend that may handle many of these things correctly already. But no strong opposition in the meantime, I guess.
rwgk
left a comment
There was a problem hiding this comment.
I switched up to codex GPT-6-Sol ultra for the re-review:
I re-reviewed PR #2973 at head bb3898e. My three earlier findings are fixed. Two issues remain:
- P1 — New tests fail in CI. The link-command helpers patch
compiler.spawn, but setuptools 84 callscompiler.call. Both packages then attempt real links; I reproduced two failures in each focused hook suite. The helpers in bindings and core need to capture the method setuptools actually uses. A Linux CI job shows the same failure. - P3 — An uncommon exported linker command breaks. With
LDCXXSHARED='env --unset=LD_LIBRARY_PATH g++ -shared', the compiler replacement movesclang++ahead of--unsetand leavesg++as an argument. I verified the resulting setuptools command; the core hook has the same code.
test_link_command_keeps_env_prefix and test_sccache_launches_the_cxx_link_command_once called compiler.link(), which spawns the real linker subprocess. On wheel-test runners without clang++ installed this raised CalledProcessError (exit 127). Replace both with assertions on compiler.linker_so_cxx, consistent with the other integration tests. The same properties (env prefix kept, clang++ not duplicated) are verified without requiring the compiler to be installed.
env --unset=LD_LIBRARY_PATH g++ -shared is a valid LDCXXSHARED value.
_with_compiler was stopping the env-prefix scan at --unset=LD_LIBRARY_PATH
(because it starts with -), leaving g++ in the output alongside clang++.
Drop the startswith("-") guard so any token containing = is treated as an
env operand, matching what setuptools' _split_env does.
|
/ok to test 5867eea |
rwgk
left a comment
There was a problem hiding this comment.
LGTM, based reviewing with codex GPT-6-Sol ultra.
|
It looks like you need to merge main, to get #2982, to resolve the Test win-64 CI failures. |
|
/ok to test 75b0465 |
|
pre-commit.ci run |
Description
closes #2970
Follow-up to #2903 (leofang): an explicit
CUDA_PYTHON_TOOLCHAINno longer replaces the linker command with{cxx} -shared.These are C++ extensions, so the backend now sets
LDCXXSHAREDby swapping only the compiler in the existing command and keeping its extras (-shared/-bundle, rpath,-B, hardening flags). AnLDCXXSHAREDalready exported in the environment is used as the base; otherwise sysconfig'sLDCXXSHARED(falling back toLDSHARED).LDSHAREDis left unset so distutils can rewrite it fromCC.CC/CXXsccache handling from #2969 is unchanged. The default path still does not touch the env.New tests also check the linker commands setuptools' distutils derives from the resulting environment (
linker_so_cxx,compiler_cxx,linker_so), not just the environment variables.Also updates the pixi source-build round-trip check, which still looked for
.build-cuda-majorandbuild/cython/cu12/cu13after #2903 switched to ABI-scoped.build-config.*stamps (cu13-{gnu|llvm}-{debug|opt}).Checklist