Skip to content

clang-tidy as part of the actual build - #3272

Open
mdboom wants to merge 8 commits into
NVIDIA:mainfrom
mdboom:clang-tidy2
Open

mdboom wants to merge 8 commits into
NVIDIA:mainfrom
mdboom:clang-tidy2

Conversation

@mdboom

@mdboom mdboom commented Oct 28, 2026

Copy link
Copy Markdown
Contributor

This is an alternative to #3250.

Rather than running clang-tidy as part of the pre-commit hook (which requires replicating a whole build environment and tool), this runs clang-tidy as a side effect of building cuda-core. It therefore will raise its lint errors on compiling (which should be as noisy as a commit hook) and should always run in exactly the same configuration as the build.

This also helps for macOS support (where there are no nvidia-cuda-* Python wheels).

The other change from #3250 is to revert the "fix" for not leaking when an exception is raised inside of create_graph_handle. Two different coding agents were confused by it (especially seeing how GraphBox() can raise on Windows), but that's a separate issue from getting clang-tidy working well and we can separately try to get agents to be less alarmed (probably simply with the right comment).

@mdboom
mdboom requested a review from Andy-Jost October 28, 2026 21:55
@github-actions github-actions Bot added the cuda.core Everything related to the cuda.core module label Oct 28, 2026
@mdboom mdboom self-assigned this Oct 28, 2026
@mdboom mdboom added the CI/CD CI/CD infrastructure label Oct 28, 2026
@mdboom mdboom added this to the cuda.core 1.3.0 milestone Oct 28, 2026
@coderabbitai

coderabbitai Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

📝 Summary

Summary by CodeRabbit

  • Chores
    • Added automated checks for native C++ code during builds. Findings are reported as errors, and checks are skipped when the analysis tool is unavailable.
    • Included the analysis configuration and tooling in supported build environments.
  • Refactor
    • Updated internal error-message buffer sizing and clarified declarations and synchronization patterns. No user-facing runtime behavior changes are described.
    • These changes affect build and maintenance workflows; no new end-user features are included.

The C++ package adds a clang-tidy configuration and runs checks on handwritten C++ compile commands during builds. Runtime code adopts shared buffer-size constants and includes changes to declarations, locking, handle types, and lint annotations.

Changes: Clang-tidy build checks

Layer / File(s) Summary
Define clang-tidy policy
cuda_core/.clang-tidy, cuda_core/MANIFEST.in, cuda_core/pyproject.toml, cuda_core/pixi.toml
Adds clang-tidy check selections and exclusions, warning settings, build dependencies, and source-distribution inclusion.
Run clang-tidy during compilation
cuda_core/build_hooks.py, cuda_core/setup.py
Locates clang-tidy and checks handwritten C++ compile commands through the build extension wrapper.
Centralize runtime buffer sizes
cuda_core/cuda/core/_cpp/rt/error.hpp, cuda_core/cuda/core/_cpp/rt/error.cpp, cuda_core/cuda/core/_cpp/rt/context_scope.hpp, cuda_core/cuda/core/_cpp/rt/internal.hpp, cuda_core/cuda/core/_cpp/rt/memory.cpp, cuda_core/cuda/core/_cpp/rt/py_driver_fns.cpp, cuda_core/cuda/core/_cpp/rt/py_report.cpp, cuda_core/cuda/core/_cpp/rt/virtual_memory.cpp
Defines shared operation-name and error-message buffer sizes and uses them in runtime reporting paths.
Update runtime C++ declarations and operations
cuda_core/cuda/core/_cpp/rt/*
Updates declarations, locking, handle types, and lint annotations across runtime C++ code. The described error-reporting and IPC paths retain their existing behavior.

Possibly related PRs

  • NVIDIA/cuda-python#3250: Adds the clang-tidy configuration and C++ fixes that this PR packages and runs during the build.
  • NVIDIA/cuda-python#3133: Establishes the C++ formatting configuration and identifies clang-tidy as a follow-up.
  • NVIDIA/cuda-python#3274: Adds a build dependency group that must stay synchronized with build-system.requires.

Priority: Low

Change: Feature

Merge Risk: Low · up to 03c6b

Build-time linting is added and works in fresh builds. A failed lint check can be skipped on a retry in a reused build directory. The pinned Pixi lockfile does not yet include the new clang-tools dependency. Both are bounded and worth fixing, but neither should block merge.

Finishing Touches: 💡 1
🛠️ Fix failing CI checks: 💡
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4


Review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between d649075 and 30f1ad1.

Files selected for processing: 24
  • cuda_core/.clang-tidy
  • cuda_core/MANIFEST.in
  • cuda_core/build_hooks.py
  • cuda_core/cuda/core/_cpp/rt/context.cpp
  • cuda_core/cuda/core/_cpp/rt/context_scope.hpp
  • cuda_core/cuda/core/_cpp/rt/driver_api.cpp
  • cuda_core/cuda/core/_cpp/rt/driver_api.hpp
  • cuda_core/cuda/core/_cpp/rt/error.cpp
  • cuda_core/cuda/core/_cpp/rt/error.hpp
  • cuda_core/cuda/core/_cpp/rt/graph.cpp
  • cuda_core/cuda/core/_cpp/rt/graph_exec.cpp
  • cuda_core/cuda/core/_cpp/rt/internal.hpp
  • cuda_core/cuda/core/_cpp/rt/memory.cpp
  • cuda_core/cuda/core/_cpp/rt/program.cpp
  • cuda_core/cuda/core/_cpp/rt/py.hpp
  • cuda_core/cuda/core/_cpp/rt/py_deferred_cleanup.cpp
  • cuda_core/cuda/core/_cpp/rt/py_driver_fns.cpp
  • cuda_core/cuda/core/_cpp/rt/py_report.cpp
  • cuda_core/cuda/core/_cpp/rt/stream.cpp
  • cuda_core/cuda/core/_cpp/rt/texture.cpp
  • cuda_core/cuda/core/_cpp/rt/types.hpp
  • cuda_core/cuda/core/_cpp/rt/virtual_memory.cpp
  • cuda_core/pyproject.toml
  • cuda_core/setup.py

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 11 remain after this review.

Comment thread cuda_core/build_hooks.py Outdated
Comment thread cuda_core/build_hooks.py Outdated
Comment thread cuda_core/pyproject.toml Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review continued from previous batch...

Comment thread cuda_core/.clang-tidy Outdated

// See REGISTRY_DESIGN.md (Level 1: Driver Handle -> Resource Handle)
static HandleRegistry<CUcontext, ContextHandle> context_registry;
HandleRegistry<CUcontext, ContextHandle> context_registry;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having 'static' or removing it has not effected on the generated binary. However I would like the source code to consistently include static or consistently not include them. Is there a clang-tidy rule or equivalent that we can enable to ensure that is the case?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason the static is removed here is because it's inside an anonymous namespace (where everything always has internal linkage so that static is redundant). This is enforced by the readability-static-definition-in-anonymous-namespace. We could exclude that rule, which would make static allowed here, but wouldn't enforce that it is always there. My agent (and I) think that no such rule exists.

Outside of anonymous namespaces, static has actual semantic meaning and just needs to be applied correctly, but it wouldn't make sense to always have it or not have it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's basically what I was saying. I don't really care if static is always there or always not there -- as long as we are consistently applying that across the code base.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3


Review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between 30f1ad1 and 8ad4030.

Files selected for processing: 5
  • cuda_core/.clang-tidy
  • cuda_core/build_hooks.py
  • cuda_core/cuda/core/_cpp/rt/py.hpp
  • cuda_core/pixi.toml
  • cuda_core/pyproject.toml

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 11 remain after this review.

Comment thread cuda_core/build_hooks.py Outdated
return
config = Path(__file__).resolve().parent / ".clang-tidy"
implicit_includes: list[str] = []
for include_dir in _get_implicit_include_dirs(compile_command[0]):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Major · Stability & Availability · Quick win

Supported by static analysis

Script executed:

rg -n 'sccache|CC=|CXX=' .github/workflows/build-wheel.yml ci cuda_core/setup.py cuda_core/build_hooks.py cuda_core/pyproject.toml
sed -n '80,115p' cuda_core/setup.py
sed -n '760,835p' cuda_core/build_hooks.py

Repository: NVIDIA/cuda-python

Length of output: 7687


Script executed:

set -eu
printf '%s\n' '--- workflow cuda.core wheel block ---'
nl -ba .github/workflows/build-wheel.yml | sed -n '320,375p'
printf '%s\n' '--- CI compiler environment references ---'
rg -n -F --glob '*.yml' --glob '*.yaml' --glob '*.sh' --glob '*.py' -e 'CC=' -e 'CXX=' -e 'SCCACHE_PATH' ci .github cuda_core
printf '%s\n' '--- setup wrapper and its call site ---'
nl -ba cuda_core/setup.py | sed -n '90,135p'
rg -n -F -- 'clang_tidy_before_compile' cuda_core/setup.py
printf '%s\n' '--- relevant build hook declarations ---'
nl -ba cuda_core/build_hooks.py | sed -n '790,850p'
printf '%s\n' '--- compiler command construction references ---'
rg -n -F --glob '*.py' -e 'customize_compiler' -e 'compiler_so' -e 'self.spawn(' -e 'self.call(' cuda_core ci .github
printf '%s\n' '--- installed setuptools compiler implementation, if available ---'
python3 - <<'PY'
import inspect
try:
    from setuptools._distutils import sysconfig as sc
    from setuptools._distutils.unixccompiler import UnixCCompiler
    print('setuptools._distutils.compiler_source=', inspect.getsourcefile(UnixCCompiler))
    print(inspect.getsource(UnixCCompiler._compile))
    print('sysconfig.customize_compiler_source=', inspect.getsourcefile(sc))
    print(inspect.getsource(sc.customize_compiler))
except Exception as exc:
    print(type(exc).__name__ + ': ' + str(exc))
PY

Repository: NVIDIA/cuda-python

Length of output: 11091


Script executed:

set -u
python3 - <<'PY'
import inspect
try:
    from setuptools._distutils import sysconfig as sc
    from setuptools._distutils.unixccompiler import UnixCCompiler
    print('setuptools._distutils.compiler_source=', inspect.getsourcefile(UnixCCompiler))
    print('--- UnixCCompiler.__init__ ---')
    print(inspect.getsource(UnixCCompiler.__init__))
    print('--- UnixCCompiler._compile ---')
    print(inspect.getsource(UnixCCompiler._compile))
    print('--- customize_compiler ---')
    print(inspect.getsource(sc.customize_compiler))
except Exception as exc:
    print(type(exc).__name__ + ': ' + str(exc))
PY

Repository: NVIDIA/cuda-python

Length of output: 206


Script executed:

set -u
printf '%s\n' '--- declared build backend and setuptools constraints ---'
rg -n -F --glob 'pyproject.toml' --glob '*.txt' --glob '*.cfg' --glob '*.ini' -e 'setuptools' -e 'build-system' cuda_core . wheel-constraints 2>/dev/null || true
printf '%s\n' '--- available distutils implementation ---'
python3 - <<'PY'
import inspect
try:
    import distutils.sysconfig as sc
    from distutils.unixccompiler import UnixCCompiler
    print('distutils.compiler_source=', inspect.getsourcefile(UnixCCompiler))
    print('--- UnixCCompiler.__init__ ---')
    print(inspect.getsource(UnixCCompiler.__init__))
    print('--- UnixCCompiler._compile ---')
    print(inspect.getsource(UnixCCompiler._compile))
    print('--- customize_compiler ---')
    print(inspect.getsource(sc.customize_compiler))
except Exception as exc:
    print(type(exc).__name__ + ': ' + str(exc))
PY

Repository: NVIDIA/cuda-python

Length of output: 8508


important: Preserve the launcher and compiler when querying implicit include directories.

The Linux cuda.core wheel job sets CC to sccache cc. Setuptools therefore passes a command that begins with sccache, but _get_implicit_include_dirs(compile_command[0]) runs sccache -E ... without cc. The probe can return a failure, and the function raises RuntimeError before compilation.

When clang-tidy is available and a handwritten .cpp file is rebuilt, pass the launcher/compiler prefix to the probe and invoke both elements together instead of using only compile_command[0].

Comment thread cuda_core/build_hooks.py Outdated
Comment thread cuda_core/pixi.toml
cuda-nvrtc-dev = "*"
cuda-bindings = "*"
dlpack = "*"
clang-tools = "==22.1.8"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor · Data Integrity & Integration · Quick win

Supported by static analysis

Script executed:

rg -n -i 'lock' ci/README.md CONTRIBUTING.md | head -50
rg -n 'clang-tools|clang-tidy' cuda_core/pixi.lock | head
sed -n '255,285p' cuda_core/pixi.toml

Repository: NVIDIA/cuda-python

Length of output: 4453


Script executed:

set -eu
printf '%s\n' '--- ci/README.md policy ---'
sed -n '176,215p' ci/README.md
printf '%s\n' '--- CONTRIBUTING.md policy ---'
sed -n '286,335p' CONTRIBUTING.md
printf '%s\n' '--- lockfile header and relevant keys ---'
sed -n '1,100p' cuda_core/pixi.lock
rg -n -i 'clang-tools|clang-tidy|^\[environments|^environments|platforms|source-build|lock --check|PIXI_LOCKED' cuda_core/pixi.lock .github ci pixi.toml cuda_core/pixi.toml || test "$?" -eq 1
printf '%s\n' '--- lockfile TOML package/environment inspection ---'
python3 - <<'PY'
from pathlib import Path
import tomllib
p = Path("cuda_core/pixi.lock")
data = tomllib.loads(p.read_text())
print("top-level keys:", sorted(data))
for key in ("environments", "packages", "package"):
    value = data.get(key)
    if value is None:
        continue
    print(f"{key} type={type(value).__name__}")
    if isinstance(value, dict):
        print(f"{key} keys:", list(value)[:20])
    elif isinstance(value, list):
        print(f"{key} length:", len(value))
def walk(obj, path=()):
    if isinstance(obj, dict):
        for k, v in obj.items():
            if "clang" in str(k).lower() or "clang" in str(v).lower():
                print("clang-containing", path + (k,), repr(v)[:500])
            walk(v, path + (k,))
    elif isinstance(obj, list):
        for i, v in enumerate(obj):
            walk(v, path + (i,))
walk(data)
PY
printf '%s\n' '--- lockfile-related CI definitions ---'
rg -n -i 'pixi.*lock|lock.*pixi|PIXI_LOCKED|lockfile freshness' .github ci || test "$?" -eq 1

Repository: NVIDIA/cuda-python

Length of output: 17125


Script executed:

set -eu
printf '%s\n' '--- cuda_core manifest environments ---'
sed -n '210,250p' cuda_core/pixi.toml
printf '%s\n' '--- lockfile environment names and clang references ---'
rg -n '^(environments:|  [A-Za-z0-9_-]+:|    [A-Za-z0-9_-]+:)|clang-tools|clang-tidy' cuda_core/pixi.lock | head -120 || test "$?" -eq 1
printf '%s\n' '--- lockfile package records for clang/toolchain names ---'
rg -n -i 'clang|llvm|gcc|cmake|ninja' cuda_core/pixi.lock | head -100 || test "$?" -eq 1
printf '%s\n' '--- freshness workflow ---'
sed -n '1,180p' .github/workflows/ci-pixi-lockfile-freshness-check.yml
printf '%s\n' '--- source-build lock mode ---'
rg -n -C 5 'PIXI_(FROZEN|LOCKED)|pixi (lock|install|run)' .github/workflows/ci-pixi-source-test.yml ci ci/README.md | head -180 || test "$?" -eq 1
printf '%s\n' '--- PR file diff ---'
git diff --name-status 590a8bfb7bb682526103676d09c14ff1632bd4f7 8ad40301f85e52e155e9afc8083623d9f096b222 -- cuda_core/pixi.toml cuda_core/pixi.lock
git diff --unified=8 590a8bfb7bb682526103676d09c14ff1632bd4f7 8ad40301f85e52e155e9afc8083623d9f096b222 -- cuda_core/pixi.toml cuda_core/pixi.lock

Repository: NVIDIA/cuda-python

Length of output: 32351


important: Regenerate cuda_core/pixi.lock with clang-tools.

The package host dependency applies to the cuda_core environments, but the committed lockfile contains no resolved clang-tools package. Source-build CI uses PIXI_FROZEN=true, so it uses the committed dependency solution instead of refreshing it.

Run pixi lock --manifest-path cuda_core and commit the resulting lockfile update.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔇 Additional comments: 1
cuda_core/build_hooks.py: 1

804-804: Trivial · Stability & Availability · Quick win

⚠️ Unverified finding
Verification ran but could not confirm this finding. It is shown for review, not as a verified issue.

suggestion: Bound both build-time subprocess calls.

If the compiler probe or clang-tidy stalls, subprocess.run waits indefinitely and blocks the build. Set a suitable timeout for each call. Report subprocess.TimeoutExpired with the command and source. (docs.python.org)

Based on learnings: “flag missing timeout arguments” on process-spawning calls.

Also applies to: 856-856

Source: Learnings


Review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between 8ad4030 and 8a90fda.

Files selected for processing: 2
  • cuda_core/build_hooks.py
  • cuda_core/cuda/core/_cpp/rt/memory.cpp
Files skipped from review as they are similar to previous changes: 1
  • cuda_core/cuda/core/_cpp/rt/memory.cpp

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 10 remain after this review.

@mdboom
mdboom marked this pull request as draft October 29, 2026 15:13
@copy-pr-bot

copy-pr-bot Bot commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@mdboom

mdboom commented Oct 29, 2026

Copy link
Copy Markdown
Contributor Author

/ok to test

@mdboom

mdboom commented Oct 29, 2026

Copy link
Copy Markdown
Contributor Author

/ok to test

@mdboom

mdboom commented Oct 29, 2026

Copy link
Copy Markdown
Contributor Author

/ok to test

@mdboom
mdboom marked this pull request as ready for review October 29, 2026 16:39
@mdboom

mdboom commented Oct 29, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review, @rparolin. Since this version of the PR was mostly in reaction to the issues @Andy-Jost found with #3250 (no macOS support, cumbersome to run outside of pre-commit, a whole wild-goose-chase about cleaning up after a failed construction) I'll wait for him to weigh in, too.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


Review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between 8a90fda and 03c6b31.

Files selected for processing: 5
  • cuda_core/MANIFEST.in
  • cuda_core/build_hooks.py
  • cuda_core/cuda/core/_cpp/rt/internal.hpp
  • cuda_core/cuda/core/_cpp/rt/py_driver_fns.cpp
  • cuda_core/setup.py
Files with no reviewable changes: 1
  • cuda_core/MANIFEST.in
Files skipped from review as they are similar to previous changes: 1
  • cuda_core/cuda/core/_cpp/rt/internal.hpp

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 11 remain after this review.

Comment thread cuda_core/setup.py
Comment on lines +112 to +113
except build_hooks.ClangTidyError as e:
failures.append(str(e))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor · Functional Correctness · Quick win

Supported by static analysis

Script executed:

sed -n '80,200p' cuda_core/setup.py
rg -n 'stamp|force|newer|build_temp|clang' cuda_core/setup.py cuda_core/build_hooks.py cuda_core/_build_shared.py

Repository: NVIDIA/cuda-python

Length of output: 11846


Script executed:

set -eu
printf '%s\n' '--- cuda_core/setup.py ---'
nl -ba cuda_core/setup.py | sed -n '35,82p;88,185p'
printf '%s\n' '--- build_hooks stamp/config references ---'
rg -n -C 8 -F -e '_BUILD_CONFIG_STAMP' -e 'check_build_key' -e 'record_build_key' -e 'configuration' cuda_core/build_hooks.py
printf '%s\n' '--- shared stamp implementation ---'
nl -ba cuda_core/_build_shared.py | sed -n '455,525p'
printf '%s\n' '--- build_hooks extension/config lifecycle ---'
nl -ba cuda_core/build_hooks.py | sed -n '320,385p;540,590p;810,875p'
printf '%s\n' '--- installed setuptools build_ext source ---'
python3 - <<'PY'
import pathlib, setuptools
p = pathlib.Path(setuptools.__file__).parent / '_distutils' / 'command' / 'build_ext.py'
print(p)
lines = p.read_text(encoding='utf-8').splitlines()
for lo, hi in [(90,180), (280,390), (410,500)]:
    print(f'--- lines {lo}-{hi} ---')
    for i in range(lo-1, min(hi, len(lines))):
        print(f'{i+1:4} {lines[i]}')
PY

Repository: NVIDIA/cuda-python

Length of output: 31388


Script executed:

set -eu
printf '%s\n' '--- record_build_config callers and backend hooks ---'
rg -n -C 10 -F -e 'record_build_config' -e '_build_cuda_core' -e 'build_wheel' -e 'build_editable' -e 'build_ext' cuda_core --glob '*.py'
printf '%s\n' '--- build backend declarations ---'
rg -n -C 8 -F -e 'build-backend' -e 'backend-path' -e 'setuptools' pyproject.toml cuda_core/pyproject.toml 2>/dev/null || true
printf '%s\n' '--- cleanup/removal operations in build path ---'
rg -n -C 4 -F -e 'unlink(' -e 'rmtree(' -e 'shutil.rmtree' -e 'remove(' -e 'force_build_ext' cuda_core --glob '*.py'

Repository: NVIDIA/cuda-python

Length of output: 42038


Web query:

Setuptools 80.9.0 setuptools/_distutils/command/build_ext.py newer_group up-to-date extension source

Result:

<source_evidence>
<source kind="open_page">
<title>History - setuptools 84.2.1 documentation</title>
<location>https://setuptools.pypa.io/en/latest/history.html</location>
<excerpt>citeturn1view1 [wordlim: 200] Crawled: today; Content type: text/html; Source: open({&quot;ref_id&quot;:&quot;turn0search3&quot;,&quot;lineno&quot;:null}); Total lines: 7609
L92: ## v84.1.0【69†¶】
L93: 
L94: 19 Oct 2026
L95: 
L96: ### Features【70†¶】
L97: 
L98:   * `setuptools.archive_util` now raises the new `UnsafeMember` exception when an archive member would be extracted outside of the extraction directory, where previously such a member was silently skipped. Aborting makes a malicious or malformed archive visible to the caller instead of yielding a quietly incomplete extraction, and matches the behavior of the standard library’s `tarfile` extraction filters.
L99: ### Bugfixes【71†¶】
L100: 
L101:   * `Wheel.install_as_egg` no longer creates namespace package directories outside of the destination egg directory. Entries in a wheel’s `namespace_packages.txt` were split on `.` and passed straight to `os.path.join`, so an entry that was absolute, drive-qualified, or UNC discarded the destination and placed an `__init__.py` at a path chosen by the wheel. Namespace entries are now validated as dotted module names on every platform – see GHSA-xmj3-9gf7-h52w.
L102: This code path is reached only by the deprecated `setup_requires` mechanism when `setup()` is invoked outside a 【72†PEP 517†peps.python.org】 frontend; the setuptools build backend never reaches it.
L103:   * `setuptools.archive_util` no longer extracts archive members outside of the requested extraction directory. Both the tar and zip formats specify `/` as the only path separator, but the guard against `..` components split member names on `/` alone, so a name such as `..\escaped.txt` was treated as a single component and then resolved as a traversal by the filesystem on Windows.
L104: Member names containing a backslash, a drive letter, or a UNC prefix are now rejected on every platform, as are members whose resolved destination falls outside the extraction directory – see GHSA-grgh-hr87-3jpw.
L105: ## v84.0.0【73†¶】
L106: 
L107: 08 Aug 2026
L108: ### Features【74†¶】
L109: 
L110:   * Newline-separated `keywords` and `platforms`, which are invalid and corrupt the generated metadata (【75†pypa/setuptools#4887†github.com】), are now handled forgivingly: each line is treated as a separate item and a deprecation warning is emitted. Newlines were never a valid separator for these fields – the 【76†old specification†peps.python.org】 separated items with spaces and the current one uses commas. (【75†#4887†github.com】)
L111:   * `Extension` is now a dataclass, exposing type annotations for its constructor arguments so subclasses (e.g. in Setuptools) can inherit them without redeclaring each parameter. Passing unknown keyword arguments is now deprecated. (【77†pypa/distutils#373†github.com】) (【78†#5022†github.com】)
L112:   * The C compiler modules now emit log messages through their own `compilers.C.*` loggers instead of the distutils root logger, part of decoupling the compilers package from distutils. The logger names are normalized to a stable `compilers.C.*` prefix so they remain constant as the package migrates toward a standalone `compilers.C` distribution. (【79†#5266†github.com】)
L113:   * The C compilers gained a `Compiler.call` method – a thin wrapper over `subprocess.check_call` (with macOS deployment-target env injection) that is the modern replacement for `Compiler.spawn`.
L114: The compilers no longer depend on `distutils.spawn`, `distutils.dir_util`, `distutils.file_util`, `distutils._modified`, or `distutils.util.execute`/`split_quoted`: the generic `newer`/`newer_group` and `split_quoted` helpers are vendored into the `compilers` package, and `Compiler.mkpath`/`move_file`/`execute` are implemented directly on the standard library (`os.makedirs`/`shutil.move`). The methods are retained for backward compatibility. (【80†#5267†github.com】)
L115:   * The compilers no longer depend on `distutils.util`, `distutils.version`, `distutils.compat`, or `distutils._macos_compat`. The platform-identification helpers (`get_platform`/`get_host_platform`/`is_mingw`) now live in `distutils.compilers.platform.detect` and the macOS deployment-target logic and `compiler_fixup` in `distutils.compilers.platform.macos`; `CygwinCCompiler.gcc_version` returns a `packaging.version.Version`.
L116: `distutils.util` re-exports the platform/macOS helpers from their new homes for backward compatibility rather than keeping duplicate copies. (sysconfig lookups still route through distutils pending its own decoupling.) (【81†#5268†github.com】)
L117:   * The compilers now read their build configuration from the standard library’s `sysconfig` instead of `distutils.sysconfig`. Per-compiler customization – previously `distutils.sysconfig.customize_compiler` – has moved into `Compiler.configure_system()`: a no-op on the base class, with `UnixCCompiler` applying the compiler/flag/archiver settings CPython recorded in `sysconfig` (and the usual `CC`/`CFLAGS`/`LDSHARED`/… environment overrides).
L118: `distutils.sysconfig.customize_compiler` is retained as a thin wrapper that calls `compiler.configure_system()`. (【82†#5269†github.com】)
L119: ### Bugfixes【83†¶】
L120: 
L121:   * The MSVC linker now passes its arguments through a response file when the command line would exceed the Windows maximum length, fixing failures when linking a large number of objects. (【84†#4177†github.com】)
L122: 
L123:   * The Cygwin and MinGW compilers now pass `-O1` instead of a bare `-O`. The two are equivalent to GCC, but `cc1` rejected the bare form when building 32-bit extensions with `-m32`. – by 【85†@dchaudhari7177†github.com】 (【86†#4873†github.com】)
L124:   * `copy_file` now preserves the full precision of the source’s modification time, so a copy is no longer considered older than its source on filesystems with sub-second timestamp resolution. (【87†pypa/distutils#379†github.com】) (【88†#5079†github.com】)
L125: 
L126:   * Setuptools wheels no longer bundled the project’s own test modules. – by 【89†@itscloud0†github.com】 (【90†#5212†github.com】)
L127:   * `build_ext` no longer fails when cross-compiling with a compiler other than MSVC (such as MinGW). `Compiler` now provides a no-op `initialize()` that non-MSVC compilers inherit. (【91†pypa/distutils#399†github.com】)
L128: ### Improved Documentation【92†¶】
L129: 
L130:   * Clarified what “correspond exactly to the directory structure” means in the `packages` section of the Package Discovery user guide. (【93†#4109†github.com】)
L131: 
L132:   * Documented how `bdist_wheel`’s `py_limited_api` option controls `abi3` wheel tagging for extension modules – by 【94†@Himanshuagrawal4†github.com】 (【95†#4741†github.com】)
L133: ### Deprecations and Removals【96†¶】
L134:   * `Compiler.spawn` is deprecated in favor of the new `Compiler.call`. `call` raises native `subprocess` exceptions; `spawn` remains as a shim that emits a `DeprecationWarning` and translates them to `DistutilsExecError`. The MSVC `spawn` compatibility shim for third-party monkeypatches predating the `env` argument (numpy.distutils before 1.19, per 【97†pypa/distutils#15†github.com】) has been removed.
L135: `distutils.spawn.spawn` is likewise reduced to a thin wrapper around `subprocess.check_call`: it no longer resolves `cmd[0]` via `shutil.which` (`subprocess` searches `PATH` itself) nor injects `MACOSX_DEPLOYMENT_TARGET` (that now lives with the compilers, the only callers to which it applied). (【80†#5267†github.com】)
L136:   * Building an extension with a `MACOSX_DEPLOYMENT_TARGET` lower than the interpreter’s configured value now raises `compilers.errors.PlatformError` instead of `distutils.errors.DistutilsPlatformError` (the macOS deployment-target check moved into the compilers package). `CygwinCCompiler.gcc_version` returns a `packaging.version.Version` rather than the removed `distutils.version.LooseVersion`.
L137: Completing the transition begun in 【98†pypa/distutils#246†github.com】, `UnixCCompiler.runtime_library_dir_option` now returns the `[&quot;-Wl,--enable-new-dtags&quot;, &quot;-Wl,-rpath,&lt;dir&gt;&quot;]` list directly for GNU ld rather than collapsing it into a single string, and the temporary `distutils.compat.consolidate_linker_args` shim has been removed. (【81†#5268†github.com】)
L138:   * The compilers now define their own exception vocabulary instead of borrowing distutils’ framework errors. Language-agnostic exceptions (`Error`, `UnknownFileType`, and a new `PlatformError`) live at `distutils.compilers.errors`, leaving room for future `compilers.&lt;language&gt;` siblings; the C/C++-specific `CompileError`/`LinkError`/`LibError`/`PreprocessError` remain in `distutils.compilers.C.errors`.
L139: The compilers now raise `compilers.errors.PlatformError` where they previously raised `distutils.errors.DistutilsPlatformError`/`DistutilsModuleError`, and `compilers._modified.newer` raises the stdlib `FileNotFoundError`.
L140: `distutils.errors` keeps its own framework exceptions and re-exports the compiler ones (`CCompilerError`, `CompileError`, etc.) for backward compatibility; because `CCompilerError` is `compilers.errors.Error`, code catching it (as distutils’ top-level handlers do) still catches the new `PlatformError`. (【99†#5270†github.com】)
L141:   * `customize_compiler` now asserts that the compiler-related config variables (`CC`, `CXX`, `CFLAGS`, etc.) resolve to strings, raising `AssertionError` if any are unexpectedly `None` rather than failing later with a less clear error. (【100†pypa/distutils#363†github.com】)
L142: ## v83.0.0【101†¶】
L143: 
L144: 04 Jul 2026
L145: 
L146: ### Features【102†¶】
L147: 
L148:   * Require Python 3.10 or later.
L149: ### Bugfixes【103†¶】
L150:   * `MANIFEST.in` matching (via `FileList`) is now insensitive to Unicode normalization form. A pattern authored in one form (e.g. NFC, as typically saved by editors) now matches a file whose name is stored on disk in another (e.g. NFD, as produced by macOS APFS/HFS+). Previously an `exclude`, `global-exclude`, `recursive-exclude`, or `prune` rule could silently fail to drop a non-ASCII-named file from the source distribution, publishing it despite the exclusion – see GHSA-h35f-9h28-mq5c.
L151: ### Deprecations and Removals【104†¶】
L152: 
L153:   * Synced with 【105†pypa/distutils@d7633fbed†github.com】 including removal of dry_run support (【106†pypa/distutils#334†github.com】).
L154: 
L155: ## v82.0.1【107†¶】
L156: 
L157: 09 Mar 2026
L158: 
L159: ### Bugfixes【108†¶】
L160: 
L161:   * Fix the loading of `launcher manifest.xml` file. (【109†#5047†github.com】)
L162: 
L163:   * Replaced deprecated `json.__version__` with fixture in tests. (【110†#5186†github.com】)
L164: ### Improved Documentation【111†¶】
L165: 
L166:   * Add advice about how to improve predictability when installing sdists. (【112†#5168†github.com】)
L167: 
L168: ### Misc【113†¶】
L169: 
L170:   * 【114†#4941†github.com】, 【115†#5157†github.com】, 【116†#5169†github.com】, 【117†#5175†github.com】
L171: 
L172: ## v82.0.0【118†¶】
L173: 
L174: 08 Feb 2026
L175: ### Deprecations and Removals【119†¶】
L176: 
L177:   * `pkg_resources` has been removed from Setuptools. Most common uses of `pkg_resources` have been superseded by the 【120†importlib.resources†docs.python.org】 and 【121†importlib.metadata†docs.python.org】 projects. Projects and environments relying on `pkg_resources` for namespace packages or other behavior should depend on older versions of `setuptools`. (【122†#3085†github.com】)
L178: 
L179: ## v81.0.0【123†¶】
L180: 
L181: 06 Feb 2026
L182: ### Deprecations and Removals【124†¶】
L183:   * Removed support for the –dry-run parameter to setup.py. This one feature by its nature threads through lots of core and ancillary functionality, adding complexity and friction. Removal of this parameter will help decouple the compiler functionality from distutils and thus the eventual full integration of distutils. These changes do affect some class and function signatures, so any derivative functionality may require some compatibility shims to support their expected interface.
L184: Please report any issues to the Setuptools project for investigation. (【125†#4872†github.com】)
L185: ## v80.10.2【126†¶】
L186: 
L187: 25 Jan 2026
L188: 
L189: ### Bugfixes【127†¶】
L190: 
L191:   * Update vendored dependencies. (【128†#5159†github.com】)
L192: 
L193: ### Misc【129†¶】
L194: 
L195:   * 【130†#5115†github.com】, 【131†#5128†github.com】
L196: 
L197: ## v80.10.1【132†¶】
L198: 
L199: 21 Jan 2026
L200: 
L201: ### Misc【133†¶】
L202: 
L203:   * 【134†#5152†github.com】
L204: 
L205: ## v80.10.0【135†¶】
L206: 
L207: 19 Jan 2026
L208: 
L209: ### Features【136†¶】
L210: 
L211:   * Remove post-release tags on setuptools’ own build. (【137†#4530†github.com】)
L212: 
L213:   * Refreshed vendored dependencies. (【138†#5139†github.com】)
L214: 
L215: ### Misc【139†¶】
L216: 
L217:   * 【140†#5033†github.com】
L218: ## v80.9.0【141†¶】
L219: 
L220: 26 May 2025
L221: 
L222: ### Features【142†¶】
L223: 
L224:   * Set a deadline for the removal of pkg_resources later this year (December). (【122†#3085†github.com】)
L225: 
L226:   * Removed reliance on pkg_resources in test_wheel. (【122†#3085†github.com】)
L227: 
L228: ## v80.8.0【143†¶】
L229: 
L230: 20 May 2025
L231: ### Features【144†¶】
L232: 
L233:   * Replaced more references to pkg_resources with importlib equivalents in wheel odule. (【122†#3085†github.com】)
L234: 
L235:   * Restore explicit LICENSE file. (【145†#5001†github.com】)
L236: 
L237:   * Removed no longer used build dependency on `coherent.licensed`. (【146†#5003†github.com】)
L238: 
L239: ## v80.7.1【147†¶】
L240: 
L241: 14 May 2025
L242: ### Bugfixes【148†¶】
L243: 
L244:   * Only attempt to fetch eggs for unsatisfied requirements. (【149†#4998†github.com】)
L245: 
L246:   * In installer, when discovering egg dists, let metadata discovery search each egg. (【149†#4998†github.com】)
L247: 
L248: ## v80.7.0【150†¶】
L249: 
L250: 14 May 2025
L251: 
L252: ### Features【151†¶】
L253: 
L254:   * Removed usage of pkg_resources from installer. Set an official deadline on the installer deprecation to 2025-10-31. (【152†#4997†github.com】)
L255: 
L256: ### Misc【153†¶】
L257: 
L258:   * 【154†#4996†github.com】
L259: 
L260: ## v80.6.0【155†¶】
L261: 
L262: 14 May 2025
L263: ### Features【156†¶】
L264: 
L265:   * Added a build dependency on coherent.licensed to inject the declared license text at build time. (【157†#4981†github.com】)
L266: 
L267: ### Misc【158†¶】
L268: 
L269:   * 【159†#4995†github.com】
L270: 
L271: ## v80.5.0【160†¶】
L272: 
L273: 11 May 2025
L274: 
L275: ### Features【161†¶】
L276: 
L277:   * Replaced more references to pkg_resources with importlib equivalents. (【122†#3085†github.com】)
L278: 
L279: ### Misc【162†¶】
L280: 
L281:   * 【163†#4982†github.com】
L282: 
L283: ## v80.4.0【164†¶】
L284: 
L285: 09 May 2025
L286: ### Features【165†¶】
L287: 
L288:   * Simplified the error reporting in editable installs. (【166†#4984†github.com】)
L289: 
L290: ## v80.3.1【167†¶】
L291: 
L292: 04 May 2025
L293: 
L294: ### Bugfixes【168†¶】
L295: 
L296:   * Restored select attributes in easy_install for temporary pbr compatibility. (【169†#4976†github.com】)
L297: 
L298: ## v80.3.0【170†¶】
L299: 
L300: 03 May 2025
L301: 
L302: ### Features【171†¶】
L303: 
L304:   * Removed easy_install and package_index modules. (【172†#917†github.com】)
L305: 
L306:   * Restored license declaration in package metadata. See jaraco/skeleton#171. (【173†#4956†github.com】)
L307: ## v80.2.0【174†¶】
L308: 
L309: 02 May 2025
L310: 
L311: ### Features【175†¶】
L312: 
L313:   * Restored support for install_scripts –executable (and classic behavior for the executable for those invocations). Instead, build_editable provides the portable form of the executables for downstream installers to rewrite. (【176†#4934†github.com】)
L314: 
L315: ## v80.1.0【177†¶】
L316: 
L317: 30 Apr 2025
L318: 
L319: ### Features【178†¶】
L320: 
L321:   * Added a deadline of Oct 31 to the setup.py install deprecation.
L344:   * Develop command no longer uses easy_install, but instead defers execution to pip (which then will re-invoke Setuptools via 【72†PEP 517†peps.python.org】 to build the editable wheel). Most of the options to develop are dropped. This is the final warning before the command is dropped completely in a few months. Use-cases relying on ‘setup.py develop’ should pin to older Setuptools version or migrate to modern build tooling. (【189†#4955†github.com】)
L1055:   * The parsing of the deprecated `metadata.license_file` and `metadata.requires` fields in `setup.cfg` is no longer supported. Users are expected to move to `metadata.license_files` and `options.install_requires` (respectively). (【591†#4066†github.com】)
L1056: 
L1057:   * Passing `config_settings` to `setuptools.build_meta` with deprecated values for `--global-option` is no longer allowed. (【591†#4066†github.com】)
L1577: ### Documentation changes【864†¶】
L1578: 
L1579:   * 【862†#3414†github.com】: Updated 【9†Development Mode】 to reflect on the implementation of 【665†PEP 660†peps.python.org】.
L1580: 
L1581: ## v63.4.3【865†¶】
L1582: 
L1583: 10 Aug 2022
L1584: 
L1585: ### Misc【866†¶】
L1586: 
L1587:   * 【867†#3496†github.com】: Update to 【868†pypa/distutils@b65aa40†github.com】 including more robust support for library/include dir handling in msvccompiler (【869†pypa/distutils#153†github.com】) and test suite improvements.
L1588: 
L1589: ## v63.4.2【870†¶】
L1590: 
L1591: 06 Aug 2022
L1634: ### Changes【894†¶】
L1635: 
L1636:   * 【895†#3395†github.com】: Included a performance optimization: `setuptools.build_meta` no longer tries to 【896†`compile()`†docs.python.org】 the setup script code before 【897†`exec()`†docs.python.org】-ing it.
L1637: 
L1638: ### Misc【898†¶】
L1639: 
L1640:   * 【899†#3435†github.com】: Corrected issue in macOS framework builds on Python 3.9 not installed by homebrew (【900†pypa/distutils#158†github.com】).
L1641: 
L1642: ## v63.1.0【901†¶】
L1643: 
L1644: 03 Jul 2022
L2199: ## v60.2.0【1173†¶】
L2200: 
L2201: 29 Dec 2021
L2202: 
L2203: ### Changes【1174†¶】
L2204: 
L2205:   * 【1175†#2974†github.com】: Setuptools now relies on the Python logging infrastructure to log messages. Instead of using `distutils.log.*`, use `logging.getLogger(name).*`.
L2206: 
L2207:   * 【1176†#2987†github.com】: Sync with 【1177†pypa/distutils@2def21c5d74fdd2fe7996ee4030ac145a9d751bd†github.com】, including fix for missing get_versions attribute (【1178†#2969†github.com】), more reliance on sysconfig from stdlib.
L2208: ### Misc【1179†¶】
L2209: 
L2210:   * 【1180†#2962†github.com】: Avoid attempting to use local distutils when the presiding version of Setuptools on the path doesn’t have one.
L2211: 
L2212:   * 【1181†#2983†github.com】: Restore ‘add_shim’ as the way to invoke the hook. Avoids compatibility issues between different versions of Setuptools with the distutils local implementation.
L2213: 
L2214: ## v60.1.1【1182†¶】
L2215: 
L2216: 28 Dec 2021
L2217: ### Misc【1183†¶】
L2218: 
L2219:   * 【1184†#2980†github.com】: Bypass distutils loader when setuptools module is no longer available on sys.path.
L2220: 
L2221: ## v60.1.0【1185†¶】
L2222: 
L2223: 23 Dec 2021
L2224: ### Changes【1186†¶】
L2225: 
L2226:   * 【1187†#2958†github.com】: In distutils_hack, only add the metadata finder once. In ensure_local_distutils, rely on a context manager for reliable manipulation.
L2227: 
L2228:   * 【1188†#2963†github.com】: Merge with 【1189†pypa/distutils@a5af364910†github.com】. Includes revisited fix for 【97†pypa/distutils#15†github.com】 and improved MinGW/Cygwin support from 【1190†pypa/distutils#77†github.com】.
L2229: 
L2230: ## v60.0.5【1191†¶】
L2231: 
L2232: 23 Dec 2021
L2233: ### Misc【1192†¶】
L2234: 
L2235:   * 【1193†#2960†github.com】: Install schemes fall back to default scheme for headers.
L2236: 
L2237: ## v60.0.4【1194†¶】
L2238: 
L2239: 22 Dec 2021
L2240: 
L2241: ### Misc【1195†¶】
L2242: 
L2243:   * 【1196†#2954†github.com】: Merge with 【1197†pypa/distutils@eba2bcd310†github.com】. Adds platsubdir to config vars available for substitution.
L2244: 
L2245: ## v60.0.3【1198†¶】
L2246: 
L2247: 20 Dec 2021
L2248: 
L2249: ### Misc【1199†¶】
L2250: 
L2251:   * 【1200†#2940†github.com】: Avoid KeyError in distutils hack when pip is imported during ensurepip.
L2252: 
L2253: ## v60.0.2【1201†¶】
L2254: 
L2255: 20 Dec 2021
L2989: ### Changes【1540†¶】
L2990: 
L2991:   * 【1506†#2232†github.com】: In preparation for re-enabling a local copy of distutils, Setuptools now honors an environment variable, SETUPTOOLS_USE_DISTUTILS. If set to ‘stdlib’ (current default), distutils will be used from the standard library. If set to ‘local’ (default in a imminent backward-incompatible release), the local copy of distutils will be used.
L2992: 
L2993: ## v49.1.1【1541†¶】
L2994: 
L2995: 10 Jul 2020
L2996: ### Misc【1542†¶】
L2997: 
L2998:   * 【1543†#2094†github.com】: Removed pkg_resources.py2_warn module, which is no longer reachable.
L2999: 
L3000: ## v49.0.1【1544†¶】
L3001: 
L3002: 05 Jul 2020
L3003: 
L3004: ### Misc【1545†¶】
L3005: 
L3006:   * 【1546†#2228†github.com】: Applied fix for 【1547†pypa/distutils#3†github.com】, restoring expectation that spawn will raise a DistutilsExecError when attempting to execute a missing file.
L3007: 
L3008: ## v49.1.0【1548†¶】
L3009: 
L3010: 03 Jul 2020
L3018: ### Breaking Changes【1551†¶】
L3019: 
L3020:   * 【1552†#2165†github.com】: Setuptools no longer installs a site.py file during easy_install or develop installs. As a result, .eggs on PYTHONPATH will no longer take precedence over other packages on sys.path. If this issue affects your production environment, please reach out to the maintainers at 【1552†#2165†github.com】.
L3021: ### Changes【1553†¶】
L3022: 
L3023:   * 【1554†#2137†github.com】: Removed (private) pkg_resources.RequirementParseError, now replaced by packaging.requirements.InvalidRequirement. Kept the name for compatibility, but users should catch InvalidRequirement instead.
L3024: 
L3025:   * 【1555†#2180†github.com】: Update vendored packaging in pkg_resources to 19.2.
L3026: 
L3027: ### Misc【1556†¶】
L3028: 
L3029:   * 【1557†#2199†github.com】: Fix exception causes all over the codebase by using `raise new_exception from old_exception`
L3030: 
L3031: ## v48.0.0【1558†¶】
L3032: 
L3033: 03 Jul 2020
L3034: ### Breaking Changes【1559†¶】
L3035:   * 【1560†#2143†github.com】: Setuptools adopts distutils from the Python 3.9 standard library and no longer depends on distutils in the standard library. When importing `setuptools` or `setuptools.distutils_patch`, Setuptools will expose its bundled version as a top-level `distutils` package (and unload any previously-imported top-level distutils package), retaining the expectation that `distutils`’ objects are actually Setuptools objects.
L3036: To avoid getting any legacy behavior from the standard library, projects are advised to always “import setuptools” prior to importing anything from distutils. This behavior happens by default when using `pip install` or `pep517.build`. Workflows that rely on `setup.py (anything)` will need to first ensure setuptools is imported. One way to achieve this behavior without modifying code is to invoke Python thus: `python -c &quot;import setuptools; exec(open(&#39;setup.py&#39;).read())&quot; (anything)`.
L3037: ## v47.3.2【1561†¶】
L3038: 
L3039: 03 Jul 2020
L3040: 
L3041: ### Misc【1562†¶】
L3042: 
L3043:   * 【1563†#2071†github.com】: Replaced references to the deprecated imp package with references to importlib
L3044: 
L3045: ## v47.3.1【1564†¶】
L3046: 
L3047: 16 Jun 2020
L3048: 
L3049: ### Misc【1565†¶】
L3050: 
L3051:   * 【1566†#1973†github.com】: Removed `pkg_resources.py31compat.makedirs` in favor of the stdlib. Use `os.makedirs()` instead.
L3052: 
L3053:   * 【1567†#2198†github.com】: Restore `__requires__` directive in easy-install wrapper scripts.
L3054: 
L3055: ## v47.3.0【1568†¶】
L3056: 
L3057: 15 Jun 2020
L3119: ## v46.3.1【1594†¶】
L3120: 
L3121: 15 May 2020
L3122: 
L3123: No significant changes.
L3124: 
L3125: ## v46.3.0【1595†¶】
L3126: 
L3127: 13 May 2020
L3128: 
L3129: ### Changes【1596†¶】
L3130: 
L3131:   * 【1597†#2089†github.com】: Package index functionality no longer attempts to remove an md5 fragment from the index URL. This functionality, added for distribute 【1598†#163†github.com】 is no longer relevant.
L6562: &gt;   * Enhanced `PYTHONPATH` support so that you don’t have to put any eggs on it manually to make it work. `--multi-version` is no longer a silent default; you must explicitly use it if installing to a non-PYTHONPATH, non-“site” directory.
L6563: &gt;
L6564: &gt;   * Expand `$variables` used in the `--site-dirs`, `--build-directory`, `--install-dir`, and `--script-dir` options, whether on the command line or in configuration files.
L6565: &gt;
L6566: &gt;   * Improved SourceForge mirror processing to work faster and be less affected by transient HTML changes made by SourceForge.
L6567: &gt;
L6568: &gt;   * PyPI searches now use the exact spelling of requirements specified on the command line or in a project’s `install_requires`. Previously, a normalized form of the name was used, which could lead to unnecessary full-index searches when a project’s name had an underscore (`_`) in it.
L6569: &gt;
L6766: &gt;   * Added `develop` command to `setuptools`-based packages. This command installs an `.egg-link` pointing to the package’s source directory, and script wrappers that `execfile()` the source versions of the package’s scripts. This lets you put your development checkout(s) on sys.path without having to actually install them. (To uninstall the link, use use `setup.py develop --uninstall`.)
L6767: &gt;
L6770: &gt;   * Enhanced the `test` command so that it doesn’t install the package, but instead builds any C extensions in-place, updates the `.egg-info` metadata, adds the source directory to `sys.path`, and runs the tests directly on the source. This avoids an “unmanaged” installation of the package to `site-packages` or elsewhere.
L6771: &gt;
</excerpt>
</source>
<source kind="search">
<title>Folder: setuptools | Debian Sources</title>
<location>https://sources.debian.org/src/setuptools/80.9.0-2/setuptools</location>
<excerpt>citeturn0search7 [wordlim: 200] Crawled: last week; sources / setuptools / 80.9.0-2 / setuptools ... Image: d   | d  | rwxr-xr-x  | 4,096  | _distutils ... Image: d   | d  | rwxr-xr-x  | 4,096  | command ... Image: -   | -  | rw-r--r--  | 19,968  | build_meta.py
</excerpt>
</source>
<source kind="search">
<title>setuptools/setuptools/command/build_ext.py at main · pypa/setuptools · GitHub</title>
<location>https://github.com/pypa/setuptools/blob/main/setuptools/command/build_ext.py</location>
<excerpt>citeturn0search0 [wordlim: 200] Crawled: yesterday; from distutils.command.build_ext import build_ext as _build_ext ... Ref #1229. ... from distutils.command.build_ext import build_ext as _build_ext ... # See GitHub pull request 4228 in pypa/setuptools (link omitted to avoid creating a cross-reference)
</excerpt>
</source>
<source kind="search">
<title>setuptools · PyPI</title>
<location>https://pypi.org/project/setuptools/80.9.0/</location>
<excerpt>citeturn0search1 [wordlim: 200] Published: 1.4 years ago; Crawled: 2 days ago; `CPAN` `PyPI` `distutils` `eggs` `package` `management` ... Table of built distributions (wheels) for setuptools 80.9.0 ... setuptools-80.9.0-py3-none-any.whl 1.2 MB May 27, 2025 Without provenance  | Python 3  | none  | any  | Details ... On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details.
</excerpt>
</source>
<source kind="search">
<title>Releases · pypa/setuptools · GitHub</title>
<location>https://github.com/pypa/setuptools/releases</location>
<excerpt>citeturn0search2 [wordlim: 200] Crawled: 4 weeks ago; pypa / setuptools Public ...   * v80.9.0 ... This commit was created on GitHub.com and signed with GitHub’s verified signature.
</excerpt>
</source>
<omitted_sources count="22">Additional source records were omitted from this bounded result.</omitted_sources>
</source_evidence>

Citations:

- 1: https://sources.debian.org/src/setuptools/80.9.0-2/setuptools?utm_source=openai

important: Invalidate outputs after a deferred Clang-Tidy failure.

The failure path is real for reused build directories. _clang_tidy_before_compile records the finding, still compiles, and raises only after super().build_extensions() returns. A retry can then skip all up-to-date compiler work, so no compiler command reaches Clang-Tidy. The previous successful configuration stamp does not force a rebuild, and the failed build does not update that stamp.

Delete the affected outputs after a failed check, or persist failed-check state that forces the next build_ext to recompile. Fresh builds with a new build directory do not reach this path, but a cached build directory can allow the retry to pass without rerunning Clang-Tidy.

@github-actions

Copy link
Copy Markdown
Contributor

This branch has not been deployed

No deployments
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.core Everything related to the cuda.core module

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants