diff --git a/PLAN.md b/PLAN.md index 4cf8ff868..43cf6d3f9 100644 --- a/PLAN.md +++ b/PLAN.md @@ -740,7 +740,7 @@ live. ### Darwin Rust: route A builds and RUNS, and dies in dyld lazy binding (harness task #96) -**BUILD: DONE.** `scripts/buck-darwin-rust-build.py` turns a Rust source into a Mach-O x86_64 +**BUILD: DONE.** `scripts/buck-darwin-rust-build.nu` turns a Rust source into a Mach-O x86_64 executable on Linux using our own ld64. Four things make it work and each was a dead end alone: the OFFICIAL rustc rather than the nixpkgs one (both are 1.95.0 at commit 59807616e, but nixpkgs appends `(built from a source tarball)` and rustc crate-metadata checking is a STRING COMPARE, so diff --git a/scripts/buck-darwin-rust-build.nu b/scripts/buck-darwin-rust-build.nu new file mode 100755 index 000000000..f1593deae --- /dev/null +++ b/scripts/buck-darwin-rust-build.nu @@ -0,0 +1,105 @@ +#!/usr/bin/env nu + +# BUILD A DARWIN (MACH-O) RUST BINARY ON LINUX, USING CIDER OWN ld64. Task #96 route A. +# +# PROVEN 2026-08-12: this produces a Mach-O 64-bit x86_64 executable with +# NOUNDEFS|DYLDLINK|TWOLEVEL|PIE|HAS_TLV_DESCRIPTORS. Whether it RUNS under cider is a separate +# question; scripts/buck-darwin-rust-run.nu answers that one. +# +# THE FOUR THINGS THAT MAKE IT WORK, each of which was a dead end on its own: +# +# 1. USE THE OFFICIAL rustc, NOT THE NIXPKGS ONE. This is the whole reason route A looked +# impossible. Both are release 1.95.0 at commit 59807616e, but nixpkgs appends a suffix to its +# version string, and the crate-metadata check is a STRING COMPARE: +# +# error[E0514]: found crate `std` compiled by an incompatible version of rustc +# found: rustc 1.95.0 (59807616e 2026-04-14) +# ours: rustc 1.95.0 (59807616e 2026-04-14) (built from a source tarball) +# +# Same compiler, same commit, rejected on the parenthetical. Take BOTH halves from upstream +# and they match. Nothing about Darwin, LLVM or linking was ever the problem. +# +# 2. NIXPKGS CANNOT SUPPLY THIS, and the reason is narrower than "unsupported". Evaluating +# pkgsCross.x86_64-darwin.rustc fails with +# +# Refusing to evaluate package x86_64-apple-darwin-cctools-1010.6 ... hostPlatform.system +# = "x86_64-linux" +# +# It is CCTOOLS that nixpkgs will not provide on a Linux host, not rustc. cider builds its own +# cctools and ld64 (#65), so the one package nixpkgs refuses is the one we already have. +# +# 3. -syslibroot IS MANDATORY. libSystem.dylib re-exports /usr/lib/system/*.dylib by ABSOLUTE +# path, so without it ld64 looks on the Linux host and dies with +# +# ld: file not found: /usr/lib/system/libsystem_sandbox.dylib +# +# Point it at the cider prefix root and the whole re-export chain resolves. +# +# 4. -C linker-flavor=ld, because rustc otherwise drives a cc wrapper that does not exist here. +# +# THE xcrun WARNING IS HARMLESS. rustc shells out to xcrun to find an SDK and cannot; it only +# affects the SDK version stamped into the binary. Set SDKROOT to silence it if that matters. +# +# Usage: +# scripts/buck-darwin-rust-build.nu --rustc R --sysroot S --prefix P --ld L +# +# PORTED FROM PYTHON (#98). THE GATE IS THE ARGV, not the bytes, and that is a measurement rather +# than a convenience: two runs of the PYTHON over one source differ in 15 bytes, and the only +# load-command difference is LC_UUID, which ld64 derives per link. So a byte comparison would +# fail for both implementations equally and prove nothing. What this script actually decides is +# the command line, so the ported version was gated on producing a CHARACTER-IDENTICAL rustc +# invocation, and on its output differing from the python one only in that 16 byte uuid. + +const TARGET = "x86_64-apple-darwin" + +def say [msg: string] { print $msg } + +def main [ + source: string # the .rs to build + output: string # where to write the Mach-O + --rustc: string # OFFICIAL rustc, not the nixpkgs one; see 1 above + --sysroot: string # merged: official rustc libs + Darwin rust-std + --prefix: string # cider prefix root, the dir holding usr/lib + --ld: string # the buck2-built x86_64-apple-darwin20-ld +] { + for pair in [[what, path]; ["rustc", $rustc] ["ld64", $ld]] { + if ($pair.path | is-empty) or not ($pair.path | path exists) { + say $"FAIL: no ($pair.what) at ($pair.path)" + exit 2 + } + } + let libdir = ([$sysroot "lib" "rustlib" $TARGET "lib"] | path join) + if ($libdir | path type) != "dir" { + say $"FAIL: sysroot has no ($TARGET) libdir at ($libdir)" + exit 2 + } + + # `path expand` is os.path.abspath here: rustc is run with the caller cwd, and a relative + # sysroot or prefix would resolve against it rather than against the repo. + let cmd = [ + $rustc "--target" $TARGET "--sysroot" ($sysroot | path expand) + "-C" "linker-flavor=ld" + "-C" $"linker=($ld)" + "-C" "link-arg=-syslibroot" "-C" $"link-arg=($prefix | path expand)" + "-C" "link-arg=-lSystem" + "-o" $output $source + ] + say $" ($cmd | str join ' ')" + # STDERR IS NOT DISCARDED, and not captured either. The linker diagnostics are the whole + # value when this fails, and `complete` would buffer them out of order with rustc stdout. + let rc = (do -i { ^($cmd | first) ...($cmd | skip 1) } | complete | get exit_code) + if $rc != 0 { + say $"FAIL: rustc exited ($rc)" + exit 1 + } + + # VERIFY THE ARTIFACT, not the exit code. A linker can exit 0 and leave the wrong format. + let f = (do -i { ^file -b $output } | str trim) + say $" ($output): ($f)" + if not ($f | str contains "Mach-O 64-bit x86_64 executable") { + say "FAIL: output is not a Mach-O x86_64 executable" + exit 1 + } + say "PASS: built a Darwin Mach-O executable from Rust on Linux" + exit 0 +} diff --git a/scripts/buck-darwin-rust-build.py b/scripts/buck-darwin-rust-build.py deleted file mode 100644 index 268df309a..000000000 --- a/scripts/buck-darwin-rust-build.py +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/env python3 -"""Build a Darwin (Mach-O) Rust binary on Linux, using cider's own ld64. Task #96 route A. - -PROVEN 2026-08-12: this produces a Mach-O 64-bit x86_64 executable with -NOUNDEFS|DYLDLINK|TWOLEVEL|PIE|HAS_TLV_DESCRIPTORS. Whether it RUNS under cider is a separate -question; see the runtime note at the bottom. - -THE FOUR THINGS THAT MAKE IT WORK, each of which was a dead end on its own: - -1. USE THE OFFICIAL rustc, NOT THE NIXPKGS ONE. This is the whole reason route A looked - impossible. Both are release 1.95.0 at commit 59807616e, but nixpkgs appends a suffix to its - version string, and rustc's crate-metadata check is a STRING COMPARE: - - error[E0514]: found crate `std` compiled by an incompatible version of rustc - found: rustc 1.95.0 (59807616e 2026-04-14) - ours: rustc 1.95.0 (59807616e 2026-04-14) (built from a source tarball) - - Same compiler, same commit, rejected on the parenthetical. Take BOTH halves from upstream and - they match. Nothing about Darwin, LLVM or linking was ever the problem. - -2. NIXPKGS CANNOT SUPPLY THIS, and the reason is narrower than "unsupported". Evaluating - pkgsCross.x86_64-darwin.rustc fails with - - Refusing to evaluate package 'x86_64-apple-darwin-cctools-1010.6' ... hostPlatform.system - = "x86_64-linux" - - It is CCTOOLS that nixpkgs will not provide on a Linux host, not rustc. cider builds its own - cctools and ld64 (#65), so the one package nixpkgs refuses is the one we already have. - -3. -syslibroot IS MANDATORY. libSystem.dylib re-exports /usr/lib/system/*.dylib by ABSOLUTE - path, so without it ld64 looks on the Linux host and dies with - - ld: file not found: /usr/lib/system/libsystem_sandbox.dylib - - Point it at the cider prefix root and the whole re-export chain resolves. - -4. -C linker-flavor=ld, because rustc otherwise drives a cc wrapper that does not exist here. - -THE xcrun WARNING IS HARMLESS. rustc shells out to xcrun to find an SDK and cannot; it only -affects the SDK version stamped into the binary. Set SDKROOT to silence it if that matters. - -Usage: - buck-darwin-rust-build.py [--sysroot DIR] [--prefix DIR] [--ld PATH] -""" -from __future__ import annotations - -import argparse -import os -import subprocess -import sys - -TARGET = "x86_64-apple-darwin" - - -def main(argv) -> int: - ap = argparse.ArgumentParser() - ap.add_argument("source") - ap.add_argument("output") - ap.add_argument("--rustc", required=True, help="OFFICIAL rustc, not the nixpkgs one; see 1 above") - ap.add_argument("--sysroot", required=True, help="merged: official rustc libs + Darwin rust-std") - ap.add_argument("--prefix", required=True, help="cider prefix root, the dir holding usr/lib") - ap.add_argument("--ld", required=True, help="the buck2-built x86_64-apple-darwin20-ld") - a = ap.parse_args(argv) - - for p, what in ((a.rustc, "rustc"), (a.ld, "ld64")): - if not os.path.exists(p): - print(f"FAIL: no {what} at {p}") - return 2 - libdir = os.path.join(a.sysroot, "lib", "rustlib", TARGET, "lib") - if not os.path.isdir(libdir): - print(f"FAIL: sysroot has no {TARGET} libdir at {libdir}") - return 2 - - cmd = [ - a.rustc, "--target", TARGET, "--sysroot", os.path.abspath(a.sysroot), - "-C", "linker-flavor=ld", - "-C", f"linker={a.ld}", - "-C", "link-arg=-syslibroot", "-C", f"link-arg={os.path.abspath(a.prefix)}", - "-C", "link-arg=-lSystem", - "-o", a.output, a.source, - ] - print(" " + " ".join(cmd)) - # STDERR IS NOT DISCARDED. The linker diagnostics are the whole value when this fails. - r = subprocess.run(cmd) - if r.returncode != 0: - print(f"FAIL: rustc exited {r.returncode}") - return 1 - - # VERIFY THE ARTIFACT, not the exit code. A linker can exit 0 and leave the wrong format. - f = subprocess.run(["file", "-b", a.output], capture_output=True, text=True).stdout.strip() - print(f" {a.output}: {f}") - if "Mach-O 64-bit x86_64 executable" not in f: - print("FAIL: output is not a Mach-O x86_64 executable") - return 1 - print("PASS: built a Darwin Mach-O executable from Rust on Linux") - return 0 - - -if __name__ == "__main__": - sys.exit(main(sys.argv[1:])) diff --git a/scripts/buck-darwin-rust-run.nu b/scripts/buck-darwin-rust-run.nu index a633488a0..7fab22154 100644 --- a/scripts/buck-darwin-rust-run.nu +++ b/scripts/buck-darwin-rust-run.nu @@ -2,7 +2,7 @@ # DOES A RUST BINARY BUILT FOR DARWIN ACTUALLY RUN INSIDE CIDER? (task #96, route A runtime half) # -# scripts/buck-darwin-rust-build.py proves a Rust source becomes a Mach-O executable. That is +# scripts/buck-darwin-rust-build.nu proves a Rust source becomes a Mach-O executable. That is # NOT the same claim as this one, and #16 is why the difference is worth a separate check: guest # nix BUILT fine and then died with SIGILL on startup. Building and running are different # questions and this answers the second. diff --git a/scripts/buck-darwin-rust-symcheck.nu b/scripts/buck-darwin-rust-symcheck.nu new file mode 100755 index 000000000..d529869d3 --- /dev/null +++ b/scripts/buck-darwin-rust-symcheck.nu @@ -0,0 +1,158 @@ +#!/usr/bin/env nu + +# CAN CIDER libSystem SATISFY WHAT OFFICIAL DARWIN RUST std REFERENCES? (task #96 step 0) +# +# THE QUESTION. Official rust-std for x86_64-apple-darwin is built expecting APPLE libSystem. +# cider links guest binaries against its OWN reimplementation. So before anyone wires a +# toolchain, measure the gap: undefined symbols the std rlibs cannot satisfy among themselves, +# minus what cider exports. +# +# FOUR WAYS TO GET THIS WRONG, ALL OF WHICH WERE DONE BEFORE THE NUMBER WAS TRUSTWORTHY: +# +# 1. llvm-nm and GNU nm ERROR on the big rlibs and succeed on the small ones, so a total that +# looks plausible can be missing std entirely. First run said 1,246 undefined. Garbage. +# 2. ar x with a RELATIVE path and cwd set extracts nothing, and capturing output hides it. +# That produced 0 defined, 0 undefined, 0 unreadable, which reads as a clean pass. +# 3. llvm-objdump --syms lists LOCAL symbols too, which a linker cannot bind to. Counting those +# gave 18,218 cider exports against a true 7,508. +# 4. THE MACH-O SYMBOL TABLE IS NOT THE EXPORT LIST. Exports live in the EXPORT TRIE. For the +# cider side use: llvm-objdump --macho --exports-trie +# +# USE llvm-objdump, NOT nm. Both llvm-nm and GNU nm REFUSE these objects: +# +# Unknown attribute kind (105) (Producer: LLVM22.1.2-rust-1.95.0-stable, Reader: LLVM 21.1.8) +# +# They prefer the EMBEDDED BITCODE section over the Mach-O symbol table, and official 1.95.0 was +# built with a newer LLVM than the local one. That error is about the bitcode, NOT about the code: +# `file` reports each rlib member as a native "Mach-O 64-bit x86_64 object", and llvm-objdump reads +# its symbol table fine. This distinction is the whole feasibility question for route A, because +# native objects link without LLVM agreement while bitcode would not. +# +# Usage: scripts/buck-darwin-rust-symcheck.nu +# +# PORTED FROM PYTHON (#98), BYTE IDENTICAL on the real corpus: the 27 rust-std rlibs for +# x86_64-apple-darwin and the 7,508 line cider export list. STATUS recorded this check as +# unverifiable for lack of rlibs; that was stale, the rust-std tarball route B downloaded has +# them, so the port was gated on the real thing rather than on a synthetic stand-in. +# +# THE 27 UNREADABLE MEMBERS ARE EXPECTED AND ARE PART OF THE OUTPUT: each rlib carries a +# __.SYMDEF archive index, which is not a Mach-O object, so llvm-objdump errors on exactly one +# member per rlib. Hiding those would hide a real reader failure with them. + +def say [msg: string] { print $msg } + +# (defined, undefined) from one Mach-O object. A reader that ERRORED is not an empty result: +# it is reported, because a silent zero here is measurement 2 in the list above. +def syms [path: string] { + # THROUGH env, so argv[0] is the BARE NAME. llvm-objdump prints its own argv[0] in an error, + # and nushell execs the resolved absolute path, so the sampled failure lines came out as + # /etc/profiles/per-user/.../llvm-objdump: error: ... where the python, which execs with + # argv[0]="llvm-objdump", printed the short form. Same tool, same failure, different text in + # the one place this script quotes it. + let r = (do -i { ^env llvm-objdump --syms $path } | complete) + if $r.exit_code != 0 or ($r.stderr | str contains "error:") { + return { err: $"llvm-objdump failed on ($path): ($r.stderr | str trim | str substring 0..<200)" } + } + mut d = [] + mut u = [] + for line in ($r.stdout | lines) { + # An undefined symbol line carries *UND* and ends with the name. + if ($line | str contains "*UND*") { + let m = ($line | parse --regex '^\S+\s+.*\*UND\*\s+(?\S+)\s*$') + if ($m | is-not-empty) { $u = ($u | append ($m | get name.0)) } + continue + } + let parts = ($line | split row --regex '\s+' | where {|x| $x != "" }) + if ($parts | length) >= 2 and (($parts | last) | str starts-with "_") { + $d = ($d | append ($parts | last)) + } + } + { d: $d, u: $u } +} + +def main [libdir?: string, exports_path?: string] { + if ($libdir | is-empty) or ($exports_path | is-empty) { + say "Usage: scripts/buck-darwin-rust-symcheck.nu " + exit 2 + } + let rlibs = (ls $libdir | get name | each {|p| $p | path basename } + | where {|f| $f | str ends-with ".rlib" } | sort) + say $"rlibs: ($rlibs | length)" + + # THE SAME SHAPE python's tempfile.TemporaryDirectory() makes, /tmp/tmp + 8 characters, and it + # is not cosmetic: the failure messages are truncated at a FIXED 120 characters and they quote + # this path, so a longer temp name moves the cut and the two implementations disagree on where + # the last message ends. Same length, same cut, and the only residue is the random characters. + # --tmpdir with a SEPARATOR-FREE template: nushell mktemp rejects a template containing a + # directory separator, so the path cannot be written out whole here. + let td = (mktemp -d --tmpdir tmpXXXXXXXX) + mut defined = [] + mut undefined = [] + mut failures = [] + for r in $rlibs { + # ABSOLUTE. ar runs with cwd=sub, so a relative rlib path silently extracts nothing and the + # captured error is thrown away: the first run of the python reported 0 undefined, 0 defined + # and 0 unreadable members, which looks like a clean pass and is a measurement that never + # happened. + let full = ([$libdir $r] | path join | path expand) + let sub = ([$td $r] | path join) + mkdir $sub + let ar = (do -i { cd $sub; ^ar x $full } | complete) + if $ar.exit_code != 0 { + $failures = ($failures | append + $"ar x failed on ($r): ($ar.stderr | str trim | str substring 0..<120)") + continue + } + let members = (ls $sub | get name | each {|p| $p | path basename } | sort) + if ($members | is-empty) { + $failures = ($failures | append $"ar x produced no members for ($r)") + continue + } + for m in $members { + let res = (syms ([$sub $m] | path join)) + if ($res | get -o err) != null { + $failures = ($failures | append ($res.err | str substring 0..<120)) + continue + } + $defined = ($defined | append $res.d) + $undefined = ($undefined | append $res.u) + } + } + ^rm -rf $td + + let defined = ($defined | uniq) + let undefined = ($undefined | uniq) + say $"members that could not be read: ($failures | length)" + for f in ($failures | first 5) { say $" ($f)" } + say $"defined by the rlibs : ($defined | length)" + say $"undefined referenced : ($undefined | length)" + + # SET DIFFERENCE THROUGH grep -Fxv, not through `where ... in`, which is O(n*m) over lists: + # 618 undefined against 3,831 defined and then 240 against 7,508 exports is small enough to + # survive either way, but the same shape at graph scale is what cost buck-include-closure + # 127 seconds, so the habit is the one that scales. + let df = (mktemp -t --suffix .txt) + let uf = (mktemp -t --suffix .txt) + $defined | str join "\n" | save -f $df + $undefined | str join "\n" | save -f $uf + let ext = (^bash -c $"grep -Fxv -f ($df) ($uf) || true" | complete) + let external = ($ext.stdout | lines | where {|x| $x != "" }) + say $"EXTERNAL needs \(undefined and not self-satisfied): ($external | length)" + + let cider = (open --raw $exports_path | decode utf-8 | lines + | each {|l| $l | str trim } | where {|l| $l != "" } | uniq) + say $"cider libSystem exports: ($cider | length)" + + let cf = (mktemp -t --suffix .txt) + let ef = (mktemp -t --suffix .txt) + $cider | str join "\n" | save -f $cf + $external | str join "\n" | save -f $ef + let miss = (^bash -c $"grep -Fxv -f ($cf) ($ef) || true" | complete) + let missing = ($miss.stdout | lines | where {|x| $x != "" } | sort) + rm -f $df $uf $cf $ef + + say "" + say $"=== MISSING FROM CIDER: ($missing | length) of ($external | length) ===" + for s in $missing { say $" ($s)" } + exit 0 +} diff --git a/scripts/buck-darwin-rust-symcheck.py b/scripts/buck-darwin-rust-symcheck.py deleted file mode 100644 index 1f37ba493..000000000 --- a/scripts/buck-darwin-rust-symcheck.py +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/env python3 -"""Can cider libSystem satisfy what official Darwin Rust std references? (task #96 step 0) - -THE QUESTION. Official rust-std for x86_64-apple-darwin is built expecting APPLE libSystem. -cider links guest binaries against its OWN reimplementation. So before anyone wires a -toolchain, measure the gap: undefined symbols the std rlibs cannot satisfy among themselves, -minus what cider exports. - -FOUR WAYS TO GET THIS WRONG, ALL OF WHICH I DID BEFORE THE NUMBER BELOW WAS TRUSTWORTHY: - - 1. llvm-nm and GNU nm ERROR on the big rlibs and succeed on the small ones, so a total that - looks plausible can be missing std entirely. First run said 1,246 undefined. Garbage. - 2. ar x with a RELATIVE path and cwd set extracts nothing, and capture_output hides it. That - produced 0 defined, 0 undefined, 0 unreadable, which reads as a clean pass. - 3. llvm-objdump --syms lists LOCAL symbols too, which a linker cannot bind to. Counting those - gave 18,218 cider exports against a true 7,508. - 4. THE MACH-O SYMBOL TABLE IS NOT THE EXPORT LIST. Exports live in the EXPORT TRIE. For the - cider side use: llvm-objdump --macho --exports-trie - -USE llvm-objdump, NOT nm. Both llvm-nm and GNU nm REFUSE these objects: - - Unknown attribute kind (105) (Producer: LLVM22.1.2-rust-1.95.0-stable, Reader: LLVM 21.1.8) - -They prefer the EMBEDDED BITCODE section over the Mach-O symbol table, and official 1.95.0 was -built with a newer LLVM than the local one. That error is about the bitcode, NOT about the code: -`file` reports each rlib member as a native "Mach-O 64-bit x86_64 object", and llvm-objdump reads -its symbol table fine. This distinction is the whole feasibility question for route A, because -native objects link without LLVM agreement while bitcode would not. - -A FIRST ATTEMPT WITH llvm-nm SILENTLY REPORTED 1,246 UNDEFINED, which was garbage: nm failed on -exactly the big rlibs and returned success for the small ones, so the total looked plausible. -Any count here must come from a reader that did not error. - -Usage: darwin-rust-symcheck.py -""" -from __future__ import annotations - -import os -import re -import subprocess -import sys -import tempfile - -# llvm-objdump --syms Mach-O line: an undefined symbol carries *UND* -_UND = re.compile(r"^\S+\s+.*\*UND\*\s+(\S+)\s*$") -_DEF = re.compile(r"^\S+\s+\S*\s*[gl]\s+.*?\s(\S+)\s*$") - - -def syms(path: str): - """(defined, undefined) from one Mach-O object. Raises if the reader errored.""" - r = subprocess.run(["llvm-objdump", "--syms", path], capture_output=True, text=True) - if r.returncode != 0 or "error:" in r.stderr: - raise RuntimeError(f"llvm-objdump failed on {path}: {r.stderr.strip()[:200]}") - d, u = set(), set() - for line in r.stdout.splitlines(): - m = _UND.match(line) - if m: - u.add(m.group(1)) - continue - parts = line.split() - if len(parts) >= 2 and parts[-1].startswith("_"): - # a defined symbol line ends with the name and is not *UND* - if "*UND*" not in line: - d.add(parts[-1]) - return d, u - - -def main(argv): - if len(argv) != 2: - print(__doc__) - return 2 - libdir, exports_path = argv - - rlibs = sorted(f for f in os.listdir(libdir) if f.endswith(".rlib")) - print(f"rlibs: {len(rlibs)}") - - defined, undefined = set(), set() - failures = [] - with tempfile.TemporaryDirectory() as td: - for r in rlibs: - # ABSOLUTE. ar runs with cwd=sub, so a relative rlib path silently extracts - # nothing, and capture_output hides the error: the first run of this script - # reported 0 undefined, 0 defined and 0 unreadable members, which looks like a - # clean pass and is actually a measurement that never happened. - full = os.path.abspath(os.path.join(libdir, r)) - sub = os.path.join(td, r) - os.makedirs(sub, exist_ok=True) - ar = subprocess.run(["ar", "x", full], cwd=sub, capture_output=True, text=True) - if ar.returncode != 0: - failures.append(f"ar x failed on {r}: {ar.stderr.strip()[:120]}") - continue - members = sorted(os.listdir(sub)) - if not members: - failures.append(f"ar x produced no members for {r}") - continue - for m in members: - mp = os.path.join(sub, m) - try: - d, u = syms(mp) - except RuntimeError as e: - failures.append(str(e)[:120]) - continue - defined |= d - undefined |= u - - print(f"members that could not be read: {len(failures)}") - for f in failures[:5]: - print(f" {f}") - print(f"defined by the rlibs : {len(defined)}") - print(f"undefined referenced : {len(undefined)}") - - external = {s for s in undefined if s not in defined} - print(f"EXTERNAL needs (undefined and not self-satisfied): {len(external)}") - - cider = {l.strip() for l in open(exports_path) if l.strip()} - print(f"cider libSystem exports: {len(cider)}") - - missing = sorted(s for s in external if s not in cider) - print() - print(f"=== MISSING FROM CIDER: {len(missing)} of {len(external)} ===") - for s in missing: - print(f" {s}") - return 0 - - -if __name__ == "__main__": - sys.exit(main(sys.argv[1:])) diff --git a/scripts/buck-rpath-check.nu b/scripts/buck-rpath-check.nu index 691b30417..5851f6c6d 100755 --- a/scripts/buck-rpath-check.nu +++ b/scripts/buck-rpath-check.nu @@ -35,7 +35,7 @@ # EXPANSION and not in whether the dylib is loadable at all. # # THE PROBES ARE PREBUILT, on purpose. Building them needs the OFFICIAL rustc (a 442 MB -# out-of-tree asset, see scripts/buck-darwin-rust-build.py for why the nixpkgs one cannot work) +# out-of-tree asset, see scripts/buck-darwin-rust-build.nu for why the nixpkgs one cannot work) # and the buck2-built ld64. The two sources are four lines each and the commands are recorded # here so anyone can rebuild them: #