xref: /trunk/main/solenv/bin/macosx-check-load-commands.sh (revision c42fc0a9ce106621d53d9635e05c6ca7fd6a53e1)
1#!/bin/bash
2#**************************************************************
3#
4#  Licensed to the Apache Software Foundation (ASF) under one
5#  or more contributor license agreements.  See the NOTICE file
6#  distributed with this work for additional information
7#  regarding copyright ownership.  The ASF licenses this file
8#  to you under the Apache License, Version 2.0 (the
9#  "License"); you may not use this file except in compliance
10#  with the License.  You may obtain a copy of the License at
11#
12#    http://www.apache.org/licenses/LICENSE-2.0
13#
14#  Unless required by applicable law or agreed to in writing,
15#  software distributed under the License is distributed on an
16#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17#  KIND, either express or implied.  See the License for the
18#  specific language governing permissions and limitations
19#  under the License.
20#
21#**************************************************************
22#
23# Fail when a Mach-O under the given paths still loads from or searches a
24# build-time location: the CPython staging prefix or an unresolved @_______
25# placeholder that macosx-change-install-names.pl should have rewritten.
26#
27#   ./solenv/bin/macosx-check-load-commands.sh <bundle-or-file> ...
28
29set -euo pipefail
30
31[ $# -gt 0 ] || { echo "usage: $(basename "$0") <bundle-or-file> ..." >&2; exit 2; }
32
33machos=()
34while IFS= read -r -d '' f && IFS= read -r type; do
35    case "$type" in ": Mach-O"*) machos+=("$f") ;; esac
36done < <(find "$@" -type f -print0 | xargs -0 file --no-pad --print0 -- 2>/dev/null)
37# Every caller passes a real app bundle or binary that is expected to contain
38# Mach-O content; zero matches means a wrong path or missing build output, not
39# "nothing to check" - fail loudly instead of silently passing.
40if [ ${#machos[@]} -eq 0 ]; then
41    echo "no Mach-O files found under: $*" >&2
42    exit 1
43fi
44
45# A dylib's own ID (LC_ID_DYLIB) is never used to locate it at runtime.
46bad=$(printf '%s\0' "${machos[@]}" | xargs -0 otool -l | awk '
47    /^[^[:space:]].*:$/ { file = $0; next }
48    $1 == "cmd" { cmd = $2; next }
49    cmd != "LC_ID_DYLIB" && ($1 == "name" || $1 == "path") && /python-inst|@_______/ {
50        print file " " cmd " " $2
51    }')
52if [ -n "$bad" ]; then
53    echo "unrelocated Mach-O load commands:" >&2
54    echo "$bad" >&2
55    exit 1
56fi
57