Skip to content

NumPy wheels bundle LGPL-2.1+ libquadmath and GCC-exception runtime: owner decision and Fortran-free replacement path #2136

Open

Description

@seonghobae

Summary

For numpy 2.5.3, the official wheels that fast-mlsirm users receive through Requires-Dist: numpy>=1.24 bundle GCC runtime components:

  • Linux x86_64 and macOS < 14: the wheels bundle and dynamically load libquadmath, which is LGPL-2.1-or-later with no runtime exception. It loads at import numpy through this DT_NEEDED chain: _multiarray_umath → libscipy_openblas64_ → libgfortran → libquadmath.
  • Every supported platform except macOS ≥ 14 (Accelerate): the wheels carry libgfortran, and on some platforms libgcc_s/libstdc++. These are GPL-3.0-or-later WITH GCC-exception-3.1.

fast-mlsirm does not redistribute any of these libraries, but they are part of its runtime dependency closure. Under the release license policy, GPL/LGPL/AGPL dependencies are replaced, never auto-approved, and dropping NumPy is not an option.

The evidence is in docs/security/license-evidence-0.11.5.md, section 6. It gives per-platform wheel contents, readelf/otool output, and the GCC libquadmath/COPYING.LIB and source headers.

User license boundary, 2026-09-26

Standard glibc CPython/manylinux Linux support stays. The user excluded operating-system-provided basic components such as glibc from this license-policy test. This does not exempt GPL/LGPL/AGPL code bundled or vendored in wheel/sdist/Rust artifacts or obtained as build, development, or optional dependencies. libgcc_s, libstdc++, libgfortran, and libquadmath each require evidence of actual provider, bundle status, source license and any exception; no automatic system-library or GCC-runtime-exception approval. The earlier all-runtime glibc conflict and musl migration requirement are withdrawn.

The Fortran-free NumPy 2.5.2 cp312 Linux candidate c6fbea22… removes gfortran/quadmath links but still has external libgcc_s/libstdc++; its OpenBLAS/LAPACK NOTICE is staged, not embedded. s1 supplies libgcc_s through Ubuntu libgcc-s1 and libstdc++ through libstdc++6, but release builders and consumers are not yet classified. A read-only clang++ -### using libc++/compiler-rt/libunwind selects LLVM runtime inputs while retaining GCC search paths; actual artifacts must prove the closure. The coordinator clarified that OS-supplied, unbundled libgcc_s/libstdc++ links of Ubuntu clang/cargo do not alone bar a local build. Prior local parity is not release proof.

Next: use the verified NumPy/OpenBLAS/#2157 source bytes and isolated targets for one s1 cp312 pair with pinned build dependencies. Inspect actual wheel/ELF/NOTICE, consumer library provider, ABI and numeric results; keep full LLVM exploration paused unless this candidate needs it. If it qualifies, verify the 12-wheel matrix (Linux x86_64/aarch64, macOS universal2, Windows x86_64; each cp312/313/314), sdist and both Rust crates. Windows #2155, exact-head required hosted checks, eligible independent approval and downstream immutable-artifact consumption remain HOLD. Plan/evidence: /Users/seonghobae/.local/orca-watchdog/reports/fmls-a3-glibc-boundary-release-plan-20260926.md, SHA-256 064aea83…. A single isolated s1 cp312 candidate-pair build is now authorized for validation; 12-wheel expansion, merge and release are not.

Replacement path (keeps NumPy and all functionality)

  • (a) Upstream request (cheap, starts now): ask NumPy / scipy-openblas to ship Fortran-free x86_64 OpenBLAS.

  • (b) Fortran-free OpenBLAS in NumPy wheels built for our four platforms (manylinux x86_64/aarch64, win_amd64; macOS stays on Accelerate for ≥ 14). Two build options:

    • C_LAPACK=1, which uses the BSD C-translated LAPACK and needs no gfortran, so there is no libgfortran or libquadmath;
    • the LLVM flang runtime (Apache-2.0 WITH LLVM-exception). The official numpy 2.5.3 win_arm64 wheel already uses the flang 20.1.8 runtime, which shows the toolchain supports it.

    This needs a wheel build and hosting pipeline, provenance, and NumPy test-suite parity. It is a separate project, and the owner needs to approve it before it starts.

  • Not acceptable: removing NumPy, or relying on a numpy version pin (no Linux x86_64 wheel without libquadmath is known).

Found while auditing the 0.11.5 release license evidence.

Activity

  1. seonghobae commented on Sep 23, 2026

    @seonghobae
    ContributorAuthor

    Feasibility report: Fortran-free OpenBLAS (C_LAPACK) NumPy for Linux x86_64

    I verified one candidate: numpy 2.5.3 built from the PyPI sdist against OpenBLAS 0.3.34 with NOFORTRAN=1, which forces C_LAPACK=1 (the BSD C-translated LAPACK). The build otherwise mirrors the official scipy-openblas64 x86_64 configuration.

    I chose it over the flang-runtime path for three reasons:

    • It needs no Fortran compiler or Fortran runtime at all.
    • It keeps the same OpenBLAS kernels, so performance should match.
    • The manylinux_2_28 image used for official numpy wheels can build it with no extra toolchain.

    The flang path and a no-BLAS (lapack_lite) path remain candidates, not verified.

    Scope of this report: Linux x86_64, CPython 3.12 only, on host s1. No dependency swap or PR has been made.

    Verdict

    Feasible for the LGPL problem. It does not by itself clear the GCC-runtime-exception question.

    • Removed: libquadmath (LGPL-2.1+, no exception) and libgfortran are gone from both the wheel and the import-time link chain.
    • Unchanged from stock: NumPy's own C++ extensions still NEED the OS-provided libstdc++.so.6 and libgcc_s.so.1 (GPL-3.0+ WITH GCC-exception-3.1). These are not bundled in either wheel. Removing them would take a clang/libc++ (compiler-rt, libunwind) build of NumPy itself, which is unverified. This is still owner decision 1 above.

    Evidence (host s1.cluster.seonghobae.me, dir /data/orca/workspaces/fmls-2136-numpy-s1)

    Inputs

    input sha256
    numpy-2.5.3.tar.gz (PyPI sdist) df2d5874ff183595a4ba404edd04f6bd9b5505c1d7708573f6a6c17489a67563
    OpenBLAS-0.3.34.tar.gz (GitHub release) cd7e129868320cc2d033afa920e31202dfe0b8066a5b66661900ccc0f197dfed
    stock numpy-2.5.3-cp312-…manylinux_2_28_x86_64.whl (PyPI) b7e18c623bb5c95acb3b3328861272816ba199fb531921c5d6d0b675f1fde9e3
    stock scipy_openblas64-0.3.34.106.0 wheel e3d0667352f91ad851141a99eb326a6bbb4142db898e4f68bff8665247f0e951
    MacPython/openblas-libs tools/build_steps.sh (flags mirrored) ec73326c6aaa33dc4a15224d78453ae0561ff010124a7608a44c1ed24343c795

    Build environment

    • Container: quay.io/pypa/manylinux_2_28_x86_64@sha256:ae21cd1c8220f773f9b5934f3b845d677494d4cd4b8981c1e416f654e8afa74e (image sha256:705368385f1b…).
    • gcc-toolset-14 14.2.1, auditwheel 6.8.2, patchelf 0.19.1, pkgconf 1.4.2.
    • Build isolation resolved Cython 3.3.0, meson 1.12.1, meson-python 0.21.1 and ninja 1.13.2. These versions were logged for builds A and B; builds A3 and A4 ran the same day with unlogged versions.
    • SOURCE_DATE_EPOCH=1790068752.

    OpenBLAS flags: BUFFERSIZE=20 DYNAMIC_ARCH=1 DYNAMIC_LIST="PRESCOTT NEHALEM SANDYBRIDGE HASWELL SKYLAKEX" TARGET=PRESCOTT USE_OPENMP=0 NUM_THREADS=64 BINARY=64 INTERFACE64=1 SYMBOLSUFFIX=64_ LIBNAMESUFFIX=64_ SYMBOLPREFIX=scipy_ LIBNAMEPREFIX=scipy_ FIXED_LIBNAME=1 NOFORTRAN=1 FC=/nonexistent-fortran-compiler

    numpy options: -Duse-ilp64=true -Dallow-noblas=false, the same as the official cibuildwheel config.

    Proof the path is Fortran-free

    • The build points FC at a path that does not exist, so any Fortran invocation would fail the build. The build succeeded, and the make log has 0 occurrences of gfortran or the fake FC.
    • OpenBLAS 0.3.34 Makefile.system L396-399 has ifeq ($(NOFORTRAN), 1) then C_LAPACK = 1 and override FEXTRALIB =.
    • C translations exist for the routines numpy uses (e.g. lapack-netlib/SRC/{dgesdd,dsyevd,dgesv}.c), and those C sources have 0 references to quadmath or __float128.
    • The generated pkg-config has extralib=-lm -lpthread. The official scipy-openblas64 .pc has extralib=-lm -lpthread -lgfortran -lquadmath.

    Link chain

    Stock wheel:

    • _multiarray_umath → libscipy_openblas64_-f48b354e.so (432e1c17…) → libgfortran-83c28eba…so.5.0.0 (a6a36832…) → libquadmath-2284e583…so.0.0.0 (6bc30690…).

    Candidate wheel:

    • numpy.libs/ contains only libscipy_openblas64_-940c6557.so (2f8c8605…46a0), which NEEDs only libm libpthread libc ld-linux.
    • _multiarray_umath NEEDs that library plus libstdc++.so.6 libm libgcc_s.so.1 libc ld-linux. The system libstdc++ and libgcc_s dependency is the same as stock.
    • _umath_linalg NEEDs the OpenBLAS library plus libm libc.
    • Across all .so files in the wheel there are 0 NEEDED entries for gfortran, quadmath, gomp or flang.
    • At runtime, LD_DEBUG=libs python -c 'import numpy' loads bundled OpenBLAS, glibc libs, libgcc_s and libstdc++. It loads no libquadmath and no libgfortran.

    Licenses

    • OpenBLAS: OpenBLAS-0.3.34/LICENSE (BSD-3-Clause, 190b5a9c…).
    • LAPACK: lapack-netlib/LICENSE (modified BSD, 97853924…).
    • numpy: LICENSE.txt (BSD-3, 1be1df33…).
    • Gap: the candidate wheel's numpy-2.5.3.dist-info/licenses/LICENSE.txt has only numpy's own 25 lines. The stock wheel's copy (756 lines) appends the OpenBLAS (L40), LAPACK (L76) and GCC runtime (L131+) notices from numpy CI's tools/wheels/LICENSE_linux.txt, which is not in the sdist. A distributable candidate must add the OpenBLAS and LAPACK notices (without the GCC section).

    Build-time GPL tools (not shipped): GCC 14 and patchelf 0.19.1, which auditwheel uses to set the grafted library's soname/RUNPATH. Neither is in the runtime closure. Avoiding patchelf would mean hand-setting $ORIGIN RUNPATH and retagging (unverified).

    Build determinism

    OpenBLAS: two independent builds at different paths gave an identical libscipy_openblas64_.so (940c6557fc88fb9f30124e3b37d79f8c1abec07c1b8b93ead0407f336ba8f476).

    numpy, built through pip wheel numpy-2.5.3.tar.gz: not reproducible.

    • pip unpacks the sdist to a random /tmp/pip-req-build-* directory, and Cython embeds that path (…/numpy/__init__.cython-30.pxd).
    • This changed _multiarray_umath, random/* and RECORD by 27–37 bytes per file.
    • A differing OpenBLAS prefix also changed the RUNPATH and __config__.py.

    numpy, built from a fixed extracted source path and fixed build dir: reproducible.

    • Two clean builds gave identical raw wheels (6bc8b84585bb7be9bea8c0f20849706a33356d08d35f3fed764d526a589475e3).
    • They also gave identical repaired wheels: numpy-2.5.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl = e8e0a0c6f175571a439eb8a7c7801b4e52c264f6750bead7885243257405528b. This is the tested candidate artifact.

    Two caveats:

    • These are same-container repeat builds, not independent-environment provenance.
    • The numpy build dependencies were resolved from PyPI without hash pins; a pipeline must hash-pin them.

    Install control (verified on s1)

    A plain numpy>=1.24 cannot control this; the default install path still delivers libquadmath. The verified mechanism is a hash-locked requirements file used with --no-index and a controlled wheelhouse:

    # requirements-fortran-free-linux-x86_64-cp312.txt  (sha256 ccbaa9ca5a272f58c4189d6dc30a59ec8a5eca534d9eb466c125f1bf429b1f99)
    fast-mlsirm==0.11.4 --hash=sha256:1e65070ffab835a8af7e3eef3f67740b5146e9325d1a52b84b72f30e8b23998e
    numpy==2.5.3 --hash=sha256:e8e0a0c6f175571a439eb8a7c7801b4e52c264f6750bead7885243257405528b
    
    pip install --only-binary :all: --no-index --find-links <wheelhouse> --require-hashes -r requirements-fortran-free-linux-x86_64-cp312.txt
    
    install path result
    (1) controlled path above, fresh venv rc=0; numpy.libs = ['libscipy_openblas64_-940c6557.so']
    (2) same hash file, resolving from PyPI rc=1, hash mismatch (Expected e8e0a0c6…, Got b7e18c62…); nothing installed (fail-closed)
    (3) default pip install fast-mlsirm==0.11.4 from PyPI rc=0; numpy.libs = libgfortran, libquadmath, libscipy_openblas64 (forbidden wheel)

    So the candidate only protects users and CI that install through the controlled path: the hashes in requirements/ci.txt plus a hosted wheelhouse, and a documented product install. PyPI users running pip install fast-mlsirm are not protected, and no package metadata can change that.

    The candidate wheel also has the same filename as the PyPI wheel. A local version label (e.g. 2.5.3+fortranfree) is worth considering to avoid cache and filename confusion (not tested).

    Regression (s1, CPython 3.12, fast-mlsirm 0.11.4 PyPI wheel 1e65070f…, OPENBLAS_NUM_THREADS=4 for timings)

    Numerical agreement with stock (regress.py):

    check result
    simulate output (Y, theta; uses multivariate_normal) bit-identical
    numpy-backend fit_reference (theta/alpha/b/xi/zeta/objective) bit-identical
    rust-backend fit (theta/alpha/b/xi/zeta/objective) bit-identical
    matmul, solve bit-identical
    svd (singular values), eigh (eigenvalues) differ at rounding level: max abs 9.2e-14 / 5.7e-14 (rel ≤ 2.7e-15)
    multivariate_normal draws max abs 1.8e-15

    Performance (best of N, seconds, stock → candidate):

    operation stock candidate
    matmul 1500 0.156 0.157
    solve 1500 0.269 0.275
    svd 600 0.260 0.261
    eigh 1500 0.869 0.876
    fit_reference 1.27 1.26
    rust fit 4.99 4.01

    The two rust-fit timings are within noise on a shared host. Both builds select the same runtime OpenBLAS kernel on s1 (openblas_get_corename = Nehalem).

    NumPy's own test suite (pytest --pyargs numpy -m "not slow" -n 4):

    • Candidate and stock both gave 3 failed / 46441 passed / 1827 skipped / 132 errors.
    • The 135 failure and error ids are identical in both environments. All are environmental: meson is not installed for the f2py, configtool and mem_policy tests. All linalg tests pass in both.

    fast-mlsirm v0.11.4 test suite against the installed wheel (-o pythonpath=., -n 4, --timeout=600 --timeout-method=thread; run 4 below):

    env result rc output sha256
    candidate 2 failed, 6979 passed, 6 skipped, 0 timeouts (18:40) 1 128b819ad14fbde8c75efd36d8b0fffcacbd2cbda95056aa6f5859e1c4aa61ef
    stock 2 failed, 6979 passed, 6 skipped, 0 timeouts (18:41) 1 f0e8e109c7a58198304bf01c94199d723e52f1579cdaef6b21fc5b7960dc1375

    The failing tests are identical in both environments:

    • tests/test_bifactor_grm.py::test_issue_1976_dense_q_never_tolerance_met_at_start_slopes
    • tests/test_cov_c_fitstats.py::test_dif_analysis_accepts_boolean_mask (RuntimeError: dif_analysis requires converged parameters ... status=max_iter_reached)

    This is parity of failure, not a PASS: the candidate is not worse than stock on this suite, and it must not be read as "the candidate works". The two failures are pre-existing in the 0.11.4 test suite run against the installed wheel and are not caused by the candidate.

    NumPy's own suite, its 132 errors and 3 failures explained (identical in both environments):

    • 124 errors are f2py/tests and 8 are _core/tests/test_mem_policy setup. All of them are FileNotFoundError: 'meson': these tests compile extension modules at setup, and meson is not installed in the test venv.
    • The 3 failures are test_configtool: numpy-config is not on PATH because the venv python was invoked without activating the venv.

    Those 135 tests were not exercised in either environment, so this also establishes parity of failure over the tests that did run (46441 passed). It is not a PASS.

    Run log (all on s1, /data/orca/workspaces/fmls-2136-numpy-s1/results/):

    1. tests.sh, sequential cand → stock, no per-test timeout.
      • The numpy suites for cand and stock both completed.
      • The fmls cand run sat at 92% for ~55 min. I stopped it (along with tests.sh) by explicit PID. Output: fmls-suite-cand.txt (no summary line).
    2. fmls-suite-stock-par.txt: stock run started in parallel to check for a shared tail. It reached the same 92% position, and I stopped it by explicit PID.
    3. fmls-suite-{cand,stock}-t-signal-aborted.txt: rerun with pytest-timeout 2.x, --timeout=600, signal method.
      • No timeout fired in ~30 min at 92%. The long work runs in native code that does not return to the Python signal handler.
      • I stopped these by explicit PID.
    4. fmls-suite-{cand,stock}-t.txt: --timeout=600 --timeout-method=thread, started 02:25:02 KST. Completed.
      • Parent PIDs: 1460611 (cand) and 1460612 (stock). Each has 4 xdist workers at nice 10 with OPENBLAS_NUM_THREADS=1 RAYON_NUM_THREADS=2.
      • Both completed at ~02:44 with rc=1 (the 2 identical failures above) and 0 timeouts.

    Environment changes made for these runs (in my own venvs only):

    • Installed pytest-xdist and pytest-timeout into venv-cand and venv-stock.
    • Installed py-spy into a separate tools venv. It was not usable (ptrace is denied).

    Resource note: the cand and stock runs in parallel used about 10.4 of s1's 12 CPUs (nice 10), and s1 load reached ~35–40. The worker CPU is in the Rust threads, not llvmpipe: the llvmpipe threads were idle at 0%. RAYON_NUM_THREADS=2 did not cap all thread pools; there were up to 106 threads per worker.

    Still unverified

    • Platforms and Python versions: only x86_64 Linux cp312 was checked. aarch64 Linux, win_amd64 and cp313/cp314 were not; macOS ≥ 14 uses Accelerate.
    • OpenBLAS source revision: the official wheel reports 0.3.34.106.0, a post-0.3.34 openblas-libs commit, while the candidate used the v0.3.34 release tarball. I could not resolve the exact upstream commit because of a GitHub API rate limit. A production build should pin the same commit.
    • Other CPUs: only one CPU (Nehalem kernel path) was tested. AVX2/AVX-512 kernels were not benchmarked.
    • Not done yet: hosting, provenance and signing for the wheelhouse; hash-pinned numpy build dependencies; adding the OpenBLAS/LAPACK license notices to the wheel; a CI job that builds and verifies this.
    • Owner decision: whether the system libstdc++/libgcc_s (GCC-exception) dependency of NumPy's own C++ code is acceptable. This candidate does not remove it.
    • Scope: the build-toolchain license policy (GCC 14.2.1, patchelf 0.19.1, auditwheel 6.8.2, meson/Cython/ninja) is a separate item and is not covered by these runs.
    • Environment consistency: pytest-timeout was installed into both venvs after runs 1–2, so runs 3–4 are not the same environment as runs 1–2. The NumPy-suite results come from runs 1–2 and the fast-mlsirm-suite result comes from run 4.

    🤖 Generated with Claude Code

  2. seonghobae commented on Sep 24, 2026

    @seonghobae
    ContributorAuthor

    Independent verification update (read-only), status: HOLD

    Scope: this checks the existing s1 Linux x86_64 cp312 candidate from #issuecomment-5801609907 against its preserved bytes and logs. Nothing was rebuilt and no suite was rerun. The findings below are independently verified; claims taken from the earlier comment are not re-asserted here unless they were re-checked.

    Newly verified

    1. Official OpenBLAS source revision (was "unresolved").
      • scipy-openblas64 0.3.34.106.0, which the official numpy 2.5.3 wheels vendor, is MacPython/openblas-libs tag v0.3.34.106.0 = 78fc0eaf6de71d92fd98f74f7e5bfa356a2f83e3.
      • Its OpenBLAS submodule is 446c436e10450c348169808f1a6b3fae0925c9f7. That is v0.3.34 (e0166008be8e466242aa76b2ff75ce3f0fbf574a) plus 106 commits: 262 files, +37,998/−3,249.
      • The candidate was built from the v0.3.34 release tarball (cd7e1298…), so its source is not the official wheel's source. A replacement build must pin 446c436e, or justify the delta.
    2. Candidate wheel native closure, from bytes.
      • Wheel e8e0a0c6f175571a439eb8a7c7801b4e52c264f6750bead7885243257405528b: 20 .so files, 0 NEEDED entries matching gfortran/quadmath/gomp/flang.
      • Stock b7e18c62… has 2: libgfortran and libquadmath.
      • The candidate still NEEDs system libstdc++.so.6 and libgcc_s.so.1 (2 each), which are GPL-3.0-or-later WITH GCC-exception-3.1. Under the project policy the GCC runtime exception is not acceptable, so the candidate is still HOLD. It removes LGPL libquadmath and libgfortran, but not this dependency.
    3. License/SBOM, from bytes.
      • Candidate dist-info/licenses/LICENSE.txt is 30 lines (sha 1be1df33…), with no OpenBLAS or LAPACK notice.
      • Stock is 935 lines (sha 4860083c…). The earlier comment said 25/756; the wc -l counts here are authoritative.
      • Neither wheel has an SBOM (dist-info/sboms/ is absent).
      • The candidate OpenBLAS pkg-config has extralib=-lm -lpthread.
    4. Rust↔NumPy shared-point parity, itemised (fast-mlsirm 0.11.4, _core f05458cb… in both envs, PYTHONHASHSEED=0, OPENBLAS_NUM_THREADS=1):
      • tests/test_rust_parity.py -vv: candidate 64 passed / 0 failed / 0 skipped and stock the same, with identical case IDs.
      • A direct measurement over 40 logged-seed cases gives worst |rust−numpy| 3.08e-11 in both, and candidate-vs-stock objective/loglik are bit-identical.
      • Caveat: the test's fixture seeds use hash(), so they vary per process unless PYTHONHASHSEED is fixed.
    5. regress.py producer re-run (bounded, logged, originals untouched, both exit 0):
      • Each rerun reproduces its own original npz on 16/19 arrays, and the discriminating mvn array matches its own environment exactly. So attribution of cand.npz and stock.npz to their environments is supported, though not byte-proven.
      • Fresh candidate vs fresh stock: 17/19 identical, max abs 3.9e-14.
    6. Official win_amd64 OpenBLAS DLL (ed4f167a…, the one vendored by numpy win_amd64):
      • The DLL is byte-identical to the wheel in CI artifact wheels-x64-1 (id 9039665676) from run 31317225529, job 93254323637, at 78fc0eaf. The PyPI attestation was verified with gh attestation verify (exit 0).
      • Its link invocation used -static -static-libgcc -lgfortran … --defsym quadmath_snprintf=snprintf.
      • The fail-closed gate on that build's own output.map printed "no 'libquadmath' used". So libquadmath is absent per the CI link-map gate, and libgfortran and libgcc are statically linked per the actual link command.
      • The member-level map was not retained. Windows stays HOLD.

    Still missing before any replacement of official NumPy wheels

    • Platforms / Python: cp313 and cp314 (CI tests CPython 3.12 and 3.14; pyproject.toml declares requires-python = ">=3.12"); manylinux aarch64; macOS < 14 x86_64/arm64 (≥ 14 uses Accelerate); win_amd64. Windows currently has static libgfortran, so it needs a NOFORTRAN or flang-runtime build. No musllinux candidate exists either.
    • Policy blocker: the system libstdc++/libgcc_s GCC-exception dependency of numpy's own C++ code. Removing it would need a libc++/compiler-rt/libunwind toolchain, which is unverified.
    • Numerical:
      • LAPACK drivers beyond solve/svd/eigh (lstsq, qr, cholesky, det, complex, float32) and ill-conditioned inputs;
      • multi-threaded runs; AVX2 and AVX-512 kernels (only the Nehalem path ran);
      • numpy's full suite with meson installed (135 tests were never exercised);
      • the fast-mlsirm suite on every target.
    • Security / provenance:
      • hash-pinned numpy build dependencies;
      • OpenBLAS pinned to 446c436e;
      • an independent-environment reproducible build;
      • build provenance attestation and an SBOM for the rebuilt wheels;
      • osv/trivy scans of the build environment.
    • Packaging:
      • OpenBLAS and LAPACK notices in LICENSE.txt;
      • a local version label (e.g. +fortranfree);
      • a hosted wheelhouse or index, and hash-locked install enforcement in requirements/ci.txt.
      • PyPI pip install fast-mlsirm users stay unprotected.

    Smallest next hosted lane (proposal, nothing created)

    A single workflow_dispatch-only workflow in this repo that:

    • builds the NOFORTRAN numpy wheel in the pinned manylinux_2_28 image, with OpenBLAS at 446c436e and hash-pinned build dependencies, for linux x86_64 cp312 only;
    • gates on readelf NEEDED;
    • runs numpy.linalg tests and fast-mlsirm test_rust_parity.py, plus regress.py against stock;
    • uploads the wheel, SBOM and actions/attest-build-provenance;
    • publishes nothing.

    The issue has no assignee. The repository's only collaborator is its admin (the issue author), so an owner decision is still needed.

    Evidence reports (worker-local): fmls-2136-fortran-free-numpy-verification.md, fmls-2136-rust-parity-itemised.md, fmls-2153-windows-openblas-ci-evidence.md. No merge, release, exception acceptance or deployment.

  3. seonghobae commented on Sep 25, 2026

    @seonghobae
    ContributorAuthor

    A3 NumPy 2.5.2 Linux x86_64 cp312 single-wheel feasibility update (2026-09-25 16:03Z). Release and research adoption remain HOLD. This is not a 12-wheel matrix result.

    • Isolated s1 build: NumPy 2.5.2 source SHA-256 d482d171c406ae88c5b19cad3b6a1c4c5209f886ab74bc44c2c865c23f52d860, OpenBLAS 0.3.34 source cd7e129868320cc2d033afa920e31202dfe0b8066a5b66661900ccc0f197dfed, recipe 3cd142a5233321286540a09e974dbb9b2d8b8d9965a28fe166100f547187957d. Exit 0; repaired candidate wheel SHA-256 c6fbea224227ebfcb80d694be15f74c72a06c901833f3f073df3405ade4e07a9, bundled OpenBLAS .so 940c6557fc88fb9f30124e3b37d79f8c1abec07c1b8b93ead0407f336ba8f476. Outer/OpenBLAS/NumPy build logs: 63fa69ac..., 1e324075..., 5925c0ff... respectively. auditwheel show reports minimum manylinux_2_27. No libgfortran/libquadmath file, DT_NEEDED, or undefined symbol in the 20 wheel ELF shared objects.
    • The repaired wheel omits the bundled OpenBLAS/GotoBLAS/LAPACK/LAPACKE notices. Exact source notices are staged, SHA-256 9f21f7061f26cdc6f173c29a5a2754c68326d7b397c6bc75bfb4f7543ed21ba4; they are not yet inside the wheel. The six observed PEP 517 backend packages are version and wheel-hash pinned in a cp312 Linux build requirements file SHA-256 2ae4e6719087e7d79efd01e3604ee15352f626b20c7b383040e0cc3a36b6cddc; offline pip download --require-hashes with dependency resolution passed (log f8b34c6c...). The completed build fetched these dynamically, so reproducibility has not been demonstrated.
    • Runtime closure still fails the project's strict no-GPL policy: NumPy's _multiarray_umath and _pocketfft_umath require external libgcc_s.so.1 and libstdc++.so.6; the exact Expose adjusted R squared and verify HC3 normal Wald contrasts #2157 _core also directly needs libgcc_s.so.1 and GCC _Unwind symbols. GCC describes libstdc++ and libgcc source as GPLv3 with the GCC Runtime Library Exception. That exception does not turn them into a non-GPL license under this project's exclusion rule. A pinned Clang/LLVM plus libc++/compiler-rt/libunwind route is a proposal only; the current builder image lacks the toolchain, and no replacement binary or parity evidence exists.
    • PR #2157 head rechecked as e1fa5189d21a6321b60e6b2ce3b9eb73d1a1625f, OPEN/REVIEW_REQUIRED. Its tracked archive SHA-256 4665f02a9d1164352316a4980ff3da81f6c6032a69eef91ef4405be229f3f049 was built in isolated s1 with this NumPy candidate (editable build exit 0, log 49c8a3c4..., native _core SHA-256 217133f5f3891923844c38fb8ab5091e33ba6dd91a4f2ddf88addbfa1ee28f26). Focused tests/test_rust_regression_ols_hc_parity.py exit 0, 10/10 passed; log SHA-256 47795c308cde97f832311e2fd466ec7fa6ed739823a055040d620b739b4ca291. This is local representative HC3/contrast/adjusted-R² evidence, not hosted CI or a qualifying non-author approval.

    All local artifacts and complete hashes are retained on s1 under /data/orca/workspaces/fmls-numpy252-linux-x86_64-candidate-20260925/audit_A/ (followup-20260925.md SHA-256 bf1ecab441e01a6eb49ea634ae0053352093e955e0f2960ea84e155d13b79b2a). Next gate: one permitted-runtime Linux pair with embedded notices, locked builder, ELF/SBOM closure and exact-head numerical acceptance, then decide whether to expand the matrix. Windows remains with #2155 owner. No merge, rerun of required checks, or release occurred.

  4. seonghobae commented on Sep 25, 2026

    @seonghobae
    ContributorAuthor

    2026-09-26 A3 read-only toolchain preflight under the clarified user boundary:

    • s1 Ubuntu's /usr/lib/llvm-14/bin/clang (SHA-256 31925065…) directly requires libstdc++.so.6 and libgcc_s.so.1; its libc++abi.so.1 (SHA-256 0539aa51…) also requires libgcc_s.so.1. /usr/bin/cargo directly requires libgcc_s.so.1. The complete dpkg -S, sha256sum, and readelf -d transcript is /Users/seonghobae/.local/orca-watchdog/reports/fmls-a3-s1-toolchain-preflight-20260926.log, SHA-256 003d4a5547a482f409a5f74d23acb3b0f967ec36adcb59409558c857e22f782d.
    • libgcc_s.so.1 is supplied here by Ubuntu libgcc-s1; libstdc++.so.6 resolves to Ubuntu libstdc++6. This host observation is not an automatic policy exception and does not prove the 12 release builders' or consumers' providers. GNU libstdc++ is GPLv3 plus the GCC Runtime Library Exception (upstream terms); the user explicitly requires individual provider/bundle/license/exception classification.
    • clang++ -### with -stdlib=libc++ --rtlib=compiler-rt --unwindlib=libunwind -fuse-ld=lld selects the intended LLVM libraries for a hypothetical output, but the command still includes GCC search directories. It produced no artifact. The installed s1 Clang/Cargo stack cannot be treated as a qualified GPL-free build/development closure. The next bounded gate is a pinned toolchain and build-dependency inventory before any second candidate build; then inspect actual NumPy and _core ELF/ABI/NOTICE closure.

    Standard glibc CPython/manylinux remains supported; only OS-provided basic components such as glibc are outside the license-policy test. A3 HOLD, no build or release from this preflight.

  5. seonghobae commented on Sep 25, 2026

    @seonghobae
    ContributorAuthor

    Correction to my preceding toolchain preflight: the coordinator clarified the user policy boundary. Ubuntu-provided clang/cargo executable links to OS-supplied, unbundled libgcc_s/libstdc++ do not by themselves disqualify an isolated local build. Their observed ELF links remain evidence for classifying actual release artifacts and consumer providers; no automatic exception for bundled/vendor, project-acquired build/dev/optional dependencies, or non-OS external runtime libraries follows. I am proceeding with one isolated s1 cp312 NumPy 2.5.2 + #2157 e1fa518 candidate pair from verified source bytes. Full LLVM exploration is paused. NOTICE, artifact ELF/ABI/license and numeric results can fail; 12-wheel expansion, merge, release and research adoption remain HOLD.

  6. seonghobae commented on Sep 25, 2026

    @seonghobae
    ContributorAuthor

    A3 single cp312 pair evidence at #2157 exact e1fa5189d21a6321b60e6b2ce3b9eb73d1a1625f (s1, pinned manylinux_2_28 image, network disabled):

    • NumPy 2.5.2 + OpenBLAS NOFORTRAN=1 C_LAPACK=1 noticed wheel SHA256 e3edaf4608013413d6aabe0f5bdbe3d3f15bb697b77de683d87bdd8b03a3c4d9; _core wheel SHA256 46198f7ed6b3cbea30271e54f5eec294bb9609de534eb8d0084eb344fedb3ccc.
    • Installed-wheel synthetic HC3/contrast/distribution-tail/adjusted-R² regressions: 10/10 PASS, log SHA256 7fffc74d02fca1300c73238193c58d09d9ae2e3a2e5d478c389f958aed80c991. Core build exit 0; auditwheel log SHA256 0966c41987c0de9eff72abd6d9f42c8547333076f29a6f0651595ee83ad93918 reports manylinux_2_28 floor.
    • Actual ZIP inventory: 1,043 NumPy and 266 core members; NumPy includes OpenBLAS notice, core includes MIT LICENSE; neither bundles files named libgfortran/libquadmath/libgcc_s/libstdc++. Core DT_NEEDED still includes libgcc_s.so.1; in the pinned image it resolves to OS /lib64/libgcc_s.so.1 (RPM libgcc-8.5.0-28.el8_10.alma.1), not a bundled wheel file. Per the clarified OS boundary, that system link alone did not bar the local build.
    • The prior Ubuntu-host core wheel had a glibc 2.35 floor and is not the 2.28 candidate. This new pair still does not prove the current Linux release matrix's manylinux2014/glibc 2.17 support.

    HOLD: full project-acquired build/dev/optional/Rust/sdist license closure, remaining 11 wheel legs, 2.17 compatibility decision, hosted required checks, valid non-author approval, Windows runtime evidence, merge, release, and research adoption. No policy exception or platform reduction is inferred.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions