-
Notifications
You must be signed in to change notification settings - Fork 1.5k
[ci] strip pcms from wheels builds #23071
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: test_macos_wheel_v2
Are you sure you want to change the base?
Changes from all commits
3e26fd7
2c1dcf0
4364d55
c2faa8d
7b4fe45
6e40d2f
c728463
24f8622
3e0a986
7eb02b9
b669c3a
6eb512b
735003a
2f85e77
2d0a7cd
2a899af
1851a3d
f1d53a5
4c69dca
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| import argparse | ||
| import pathlib | ||
| import shutil | ||
| import subprocess | ||
| import sys | ||
| import tempfile | ||
|
|
||
| STRIP_PATTERNS = ("*.pcm", "modules.idx") | ||
|
|
||
|
|
||
| def strip_one_wheel(wheel_path: pathlib.Path) -> None: | ||
| with tempfile.TemporaryDirectory(prefix="strip-wheel-pcms-") as tmp: | ||
| tmp = pathlib.Path(tmp) | ||
| unpack_dir = tmp / "unpacked" | ||
| subprocess.run( | ||
| [sys.executable, "-m", "wheel", "unpack", str(wheel_path), "-d", str(unpack_dir)], | ||
| check=True, | ||
| ) | ||
|
|
||
| # `wheel unpack` creates one <name>-<version> subdirectory | ||
| (extracted,) = list(unpack_dir.iterdir()) | ||
|
|
||
| removed = [] | ||
| for pattern in STRIP_PATTERNS: | ||
| for f in extracted.rglob(pattern): | ||
| f.unlink() | ||
| removed.append(str(f.relative_to(extracted))) | ||
|
|
||
| print(f"{wheel_path.name}: removed {len(removed)} file(s)") | ||
|
|
||
| repacked_dir = tmp / "repacked" | ||
| repacked_dir.mkdir() | ||
| subprocess.run( | ||
| [sys.executable, "-m", "wheel", "pack", str(extracted), "-d", str(repacked_dir)], | ||
| check=True, | ||
| ) | ||
|
|
||
| (new_wheel,) = list(repacked_dir.glob("*.whl")) | ||
| wheel_path.unlink() | ||
| shutil.move(str(new_wheel), str(wheel_path)) | ||
|
|
||
|
|
||
| def main(): | ||
| parser = argparse.ArgumentParser(description=__doc__) | ||
| parser.add_argument("directory", type=pathlib.Path, help="directory containing .whl files to strip") | ||
| args = parser.parse_args() | ||
|
|
||
| wheels = sorted(args.directory.glob("*.whl")) | ||
| if not wheels: | ||
| print(f"No .whl files found in {args.directory}", file=sys.stderr) | ||
| return 1 | ||
|
|
||
| for wheel in wheels: | ||
| strip_one_wheel(wheel) | ||
|
|
||
| return 0 | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| sys.exit(main()) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| # Author: Silia Taider, CERN 08/2026 | ||
|
|
||
| ################################################################################ | ||
| # Copyright (C) 1995-2026, Rene Brun and Fons Rademakers. # | ||
| # All rights reserved. # | ||
| # # | ||
| # For the licensing terms see $ROOTSYS/LICENSE. # | ||
| # For the list of contributors see $ROOTSYS/README/CREDITS. # | ||
| ################################################################################ | ||
|
|
||
| """ | ||
| One-time warm-up that builds every ROOT C++ module ahead of use. | ||
| What we do: explicitly import every module declared in ROOT.modulemap, | ||
| once, right after the interpreter is up. | ||
| This only runs once per installation and is a no-op for builds that don't use C++ | ||
| modules at all. | ||
| """ | ||
|
|
||
| import os | ||
| import re | ||
| import sys | ||
|
|
||
| _MODULE_LINE = re.compile(r'^module\s+"?([A-Za-z_][A-Za-z0-9_]*)"?\s*\{') | ||
|
|
||
|
|
||
| def _module_names(modulemap_path): | ||
| """Extract the top-level module names declared in a Clang modulemap file""" | ||
| names = [] | ||
| with open(modulemap_path) as f: | ||
| for line in f: | ||
| m = _MODULE_LINE.match(line) | ||
| if m: | ||
| names.append(m.group(1)) | ||
| return names | ||
|
|
||
|
|
||
| def _sentinel_path(lib_dir): | ||
| """Empty marker file to record that the module build run once""" | ||
| return os.path.join(lib_dir, ".pcm_warmup_complete") | ||
|
|
||
|
|
||
| def _mark_warmup_complete(lib_dir, sentinel): | ||
| try: | ||
| os.makedirs(lib_dir, exist_ok=True) | ||
| with open(sentinel, "w") as f: | ||
| f.write("1") | ||
| except OSError: | ||
| pass | ||
|
|
||
|
|
||
| def _print_progress(done, total, label): | ||
| width = 30 | ||
| filled = width if total == 0 else int(width * done / total) | ||
| bar = "#" * filled + "-" * (width - filled) | ||
| sys.stderr.write(f"\r[{bar}] {done}/{total} building {label:<28}") | ||
| sys.stderr.flush() | ||
|
|
||
|
|
||
| def warmup(root_facade): | ||
| """Build every C++ module once""" | ||
| this_dir = os.path.dirname(os.path.abspath(__file__)) | ||
| modulemap_path = os.path.join(this_dir, "include", "ROOT.modulemap") | ||
| if not os.path.exists(modulemap_path): | ||
| # runtime_cxxmodules is off in this build | ||
| return | ||
|
|
||
| lib_dir = os.path.join(this_dir, "lib") | ||
| sentinel = _sentinel_path(lib_dir) | ||
| if os.path.exists(sentinel): | ||
| return | ||
|
|
||
| names = _module_names(modulemap_path) | ||
| if not names: | ||
| return | ||
|
|
||
| sys.stderr.write(f"ROOT: preparing this installation for your machine, this may take some time: {len(names)} modules...\n") | ||
| declare = root_facade.gInterpreter.Declare | ||
| for i, name in enumerate(names, 1): | ||
| _print_progress(i, len(names), name) | ||
| try: | ||
| declare(f"#pragma clang module import {name}") | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this out the pcms are being rebuild? If so, I am not sure this is the same as the pcms produced by |
||
| except Exception: | ||
| pass | ||
| sys.stderr.write("\n") | ||
|
|
||
| _mark_warmup_complete(lib_dir, sentinel) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2276,6 +2276,11 @@ const char *TSystem::GetLibraries(const char *regexp, const char *options, | |
|
|
||
| static TRegexp separator("[^ \\t\\s]+"); | ||
| static TRegexp dynload("/lib-dynload/"); | ||
| // Skip libffi, it is a private library used by the system. This is visible in the stub .tbd file: | ||
| // allowable-clients: | ||
| // clients: [ '!' ] | ||
| // See https://github.com/Homebrew/homebrew-core/issues/272324#issuecomment-5119880493 for more info | ||
| static TRegexp libffiMatch("/usr/lib/libffi"); | ||
|
|
||
| Ssiz_t start, index, end; | ||
| start = index = end = 0; | ||
|
|
@@ -2284,7 +2289,7 @@ const char *TSystem::GetLibraries(const char *regexp, const char *options, | |
| index = libs2.Index(separator, &end, start); | ||
| if (index >= 0) { | ||
| TString s = libs2(index, end); | ||
| if (s.Index(dynload) == kNPOS) { | ||
| if (s.Index(dynload) == kNPOS && s.Index(libffiMatch) == kNPOS) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems to (also) be introduced in #22963.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indeed this was merged in master but not in the branch root-project:test_macos_wheel_v2 so I just cherry picked it for the tests to work The PRs I have open on this branch (#22886 and #23071) are just experimenting with the macos wheels, not going into production as they are of course |
||
| if (!maclibs.IsNull()) maclibs.Append(" "); | ||
| maclibs.Append(s); | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.