Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-16 08:16:24

0001 #!/usr/bin/env bash
0002 # Repair wrapper for the macOS PyPI wheels, invoked as
0003 # CIBW_REPAIR_WHEEL_COMMAND_MACOS with: $1 = wheel, $2 = dest_dir, $3 = archs.
0004 #
0005 # Root cause (diagnosed with delocate-listdeps --all --depending, and confirmed
0006 # against spack's thrift package.py and thrift's own build/cmake/
0007 # DefineOptions.cmake):
0008 #   * libActsPluginArrow.dylib (static Arrow) links spack's openssl:
0009 #       .../spack/opt/spack/.../openssl-<hash>/lib/libssl.3.dylib
0010 #   * spack's libthrift (an Arrow dependency) concretizes `~openssl` (its spack
0011 #     "openssl" variant is off, so spack never wires in spack's openssl for
0012 #     it). But thrift builds with build_system=cmake, and unlike thrift's
0013 #     AutotoolsBuilder, its CMakeBuilder.cmake_args() never passes
0014 #     -DWITH_OPENSSL. Thrift's own DefineOptions.cmake then runs a bare
0015 #     find_package(OpenSSL) regardless of the variant and auto-links whatever
0016 #     it finds on the runner's default search path — the python.org
0017 #     framework's copy:
0018 #       /Library/Frameworks/Python.framework/Versions/<X>/lib/libssl.3.dylib
0019 # delocate then sees two different libssl.3.dylib (and libcrypto.3.dylib) with
0020 # the same basename and aborts:
0021 #   DelocationError: Already planning to copy library with same basename as:
0022 #   libssl.3.dylib
0023 #
0024 # Workaround: before delocation, repoint libthrift's framework openssl
0025 # references at spack's openssl, so the graph resolves to a single copy that
0026 # delocate can vendor. Both are openssl 3.x, and ACTS' Parquet usage does not
0027 # touch TLS. Scoped to libthrift specifically — the only known offender —
0028 # rather than scanning/mutating the whole spack store, to keep this local.
0029 #
0030 # How long this is needed: until thrift's spack package (spack/spack-packages,
0031 # repos/spack_repo/builtin/packages/thrift/package.py) wires its "openssl"
0032 # variant into CMakeBuilder.cmake_args() the way it already does for
0033 # AutotoolsBuilder — a one-line upstream fix
0034 # (self.define_from_variant("WITH_OPENSSL", "openssl")). Once that lands and
0035 # ci-dependencies picks up the updated spack-packages, thrift stops linking the
0036 # framework openssl and the rewrite below finds nothing to do on its own; the
0037 # script can then be deleted.
0038 #
0039 # This modifies the spack store on the (ephemeral) CI runner. delocate re-signs
0040 # the copies it vendors into the wheel, so the invalidated store-lib signatures
0041 # do not matter, and the wheel's tests run against the self-contained wheel.
0042 set -euo pipefail
0043 
0044 wheel="$1"
0045 dest_dir="$2"
0046 archs="$3"
0047 
0048 # Any framework-provided openssl, regardless of soversion.
0049 fw_re='/Library/Frameworks/Python\.framework/.*/lib(ssl|crypto)\.[0-9.]*dylib'
0050 
0051 delocate() {
0052     if ! delocate-wheel --require-archs "$archs" -w "$dest_dir" -v "$wheel"; then
0053         echo "::group::delocate failed — dependency tree"
0054         delocate-listdeps --all --depending "$wheel" || true
0055         echo "::endgroup::"
0056         exit 1
0057     fi
0058 }
0059 
0060 inspect_dir="$(mktemp -d)"
0061 trap 'rm -rf "$inspect_dir"' EXIT
0062 unzip -q "$wheel" -d "$inspect_dir"
0063 
0064 # Derive the spack store root from whatever absolute spack path the wheel's own
0065 # binaries link against. If the wheel does not reference spack at all there is
0066 # nothing to normalize.
0067 spack_root=""
0068 while IFS= read -r bin; do
0069     ref="$(otool -L "$bin" 2>/dev/null | awk '/\/opt\/spack\//{print $1; exit}')" || true
0070     if [ -n "${ref:-}" ]; then
0071         spack_root="${ref%/opt/spack/*}"
0072         break
0073     fi
0074 done < <(find "$inspect_dir" \( -name '*.dylib' -o -name '*.so' \) -type f)
0075 
0076 if [ -z "$spack_root" ]; then
0077     echo "wheel does not link the spack store; delocating as-is"
0078     delocate
0079     exit 0
0080 fi
0081 echo "spack root: ${spack_root}"
0082 
0083 # Locate spack's own openssl, which is the copy we consolidate onto.
0084 spack_ssl="$(find "${spack_root}/opt/spack" -path '*/openssl-*/lib/libssl.*.dylib' \
0085     -type f 2>/dev/null | head -1)"
0086 if [ -z "${spack_ssl:-}" ]; then
0087     echo "no spack openssl found; delocating as-is"
0088     delocate
0089     exit 0
0090 fi
0091 spack_ssl_dir="$(dirname "$spack_ssl")"
0092 echo "spack openssl dir: ${spack_ssl_dir}"
0093 
0094 # libthrift is the only known offender (see root cause above); scope the
0095 # rewrite to it instead of scanning/mutating the whole spack store.
0096 libthrift="$(find "${spack_root}/opt/spack" -name 'libthrift*.dylib' \
0097     -type f 2>/dev/null | head -1)"
0098 if [ -z "${libthrift:-}" ]; then
0099     echo "no libthrift in spack store; delocating as-is"
0100     delocate
0101     exit 0
0102 fi
0103 
0104 echo "::group::Repoint libthrift's framework openssl references to spack openssl"
0105 # `|| true`: grep exits 1 when there is no framework reference (the expected
0106 # steady state once the upstream thrift package is fixed), which would
0107 # otherwise trip `set -e` under pipefail.
0108 fw_refs="$(otool -L "$libthrift" 2>/dev/null | awk 'NR>1{print $1}' \
0109     | grep -E "$fw_re" || true)"
0110 rewrote=0
0111 if [ -n "$fw_refs" ]; then
0112     while IFS= read -r fw; do
0113         target="${spack_ssl_dir}/$(basename "$fw")"
0114         if [ ! -f "$target" ]; then
0115             echo "ERROR: ${libthrift} references ${fw}, but ${target} does not exist" >&2
0116             exit 1
0117         fi
0118         echo "  ${libthrift}: ${fw} -> ${target}"
0119         if ! install_name_tool -change "$fw" "$target" "$libthrift"; then
0120             echo "ERROR: install_name_tool failed to rewrite ${libthrift}" >&2
0121             exit 1
0122         fi
0123         rewrote=$((rewrote + 1))
0124     done <<< "$fw_refs"
0125 fi
0126 echo "rewrote ${rewrote} framework openssl reference(s) in libthrift"
0127 echo "::endgroup::"
0128 
0129 delocate