Skip to content

build: preserve sysconfig extras in LDCXXSHARED - #2973

Merged
juenglin merged 11 commits into
NVIDIA:mainfrom
juenglin:build-hooks-refactor
Oct 1, 2026
Merged

juenglin merged 11 commits into
NVIDIA:mainfrom
juenglin:build-hooks-refactor

Conversation

@juenglin

@juenglin juenglin commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Description

closes #2970

Follow-up to #2903 (leofang): an explicit CUDA_PYTHON_TOOLCHAIN no longer replaces the linker command with {cxx} -shared.

These are C++ extensions, so the backend now sets LDCXXSHARED by swapping only the compiler in the existing command and keeping its extras (-shared/-bundle, rpath, -B, hardening flags). An LDCXXSHARED already exported in the environment is used as the base; otherwise sysconfig's LDCXXSHARED (falling back to LDSHARED). LDSHARED is left unset so distutils can rewrite it from CC. CC/CXX sccache 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-major and build/cython/cu12 / cu13 after #2903 switched to ABI-scoped .build-config.* stamps (cu13-{gnu|llvm}-{debug|opt}).

Checklist

  • New or existing tests cover these changes.
  • The documentation is up to date with these changes.

@copy-pr-bot

copy-pr-bot Bot commented Sep 30, 2026

Copy link
Copy Markdown
Contributor

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@github-actions github-actions Bot added cuda.bindings Everything related to the cuda.bindings module cuda.core Everything related to the cuda.core module labels Sep 30, 2026
@leofang

leofang commented Sep 30, 2026

Copy link
Copy Markdown
Member

btw I am consolidating all compiler/linker flags in #2965 so it'd be really great to sort out a review/merge order 😛

@juenglin
juenglin force-pushed the build-hooks-refactor branch from 7656d97 to a00f514 Compare September 30, 2026 17:32
@github-actions github-actions Bot added the CI/CD CI/CD infrastructure label Sep 30, 2026
@juenglin
juenglin force-pushed the build-hooks-refactor branch from b91c1a1 to 6fd5fdd Compare September 30, 2026 17:44
@juenglin

Copy link
Copy Markdown
Contributor Author

/ok to test e5ecafd

@juenglin
juenglin requested review from leofang and rwgk September 30, 2026 19:22
@juenglin juenglin self-assigned this Sep 30, 2026
@juenglin juenglin added this to the cuda.bindings next milestone Sep 30, 2026
@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor
Doc Preview CI
Preview removed because the pull request was closed or merged.

@juenglin

Copy link
Copy Markdown
Contributor Author

/ok to test 4002c6d

@juenglin
juenglin marked this pull request as ready for review September 30, 2026 20:11

@rwgk rwgk 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.

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

  1. P2 — An exported linker wrapper can be lost. _with_compiler drops every token before the first flag, not just the old compiler; the core copy does the same. An exported LDCXXSHARED="env LIBRARY_PATH=/custom/lib g++ -shared" becomes clang++ -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.

  2. 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.

  3. 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_so to start with sccache 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.

@juenglin

juenglin commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

@rwgk the changed nightly round-trip job was exercised with a manual workflow_dispatch on this PR's head at the time (e5ecafd) and passed:

https://github.com/NVIDIA/cuda-python/actions/runs/36766403261/job/110067451890

(The run's overall status shows "cancelled" only because the GPU pixi run test job was cancelled by the re-run of the first, stuck round-trip attempt; the cu13 -> cu12 -> cu13 round trip and build smoke jobs both succeeded.)

@juenglin

juenglin commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

/ok to test bb3898e

@juenglin
juenglin requested a review from rwgk October 1, 2026 16:06

@mdboom mdboom 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.

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 rwgk 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.

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:

  1. P1 — New tests fail in CI. The link-command helpers patch compiler.spawn, but setuptools 84 calls compiler.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.
  2. P3 — An uncommon exported linker command breaks. With LDCXXSHARED='env --unset=LD_LIBRARY_PATH g++ -shared', the compiler replacement moves clang++ ahead of --unset and leaves g++ 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.
@juenglin

juenglin commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

/ok to test 5867eea

@rwgk rwgk 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, based reviewing with codex GPT-6-Sol ultra.

@rwgk

rwgk commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

It looks like you need to merge main, to get #2982, to resolve the Test win-64 CI failures.

@juenglin

juenglin commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

/ok to test 75b0465

@juenglin

juenglin commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

pre-commit.ci run

@juenglin
juenglin merged commit a1c413f into NVIDIA:main Oct 1, 2026
119 checks passed
github-actions Bot pushed a commit that referenced this pull request Oct 2, 2026
Removed preview folders for the following PRs:
- PR #2920
- PR #2957
- PR #2973
- PR #2982
- PR #2983
- PR #2990
- PR #2991
- PR #2992
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CI/CD CI/CD infrastructure cuda.bindings Everything related to the cuda.bindings module cuda.core Everything related to the cuda.core module

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CI failure] CI: pixi run test (source build) scheduled runs

4 participants