feat(ops): add imgproxy native runtime tooling and record 103 deployment
Memind CI / Test, build, and release guards (pull_request) Failing after 18s
Memind CI / Test, build, and release guards (pull_request) Failing after 18s
Bundle vendored imgproxy with Mach-O dylibs for 103 launchd, fix install to exec the binary directly with launchctl enable, and document the live native release in the runtime topology. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Executable
+223
@@ -0,0 +1,223 @@
|
||||
#!/usr/bin/env bash
|
||||
# Recursively copy non-system dylibs next to a Mach-O binary and rewrite load paths.
|
||||
set -euo pipefail
|
||||
|
||||
find_homebrew_lib() {
|
||||
local base="$1"
|
||||
find "${HOMEBREW_PREFIX:-/opt/homebrew}/Cellar" "${HOMEBREW_PREFIX:-/opt/homebrew}/opt" \
|
||||
-name "${base}" -path '*/lib/*' 2>/dev/null | head -1
|
||||
}
|
||||
|
||||
resolve_dependency_path() {
|
||||
local owner="$1"
|
||||
local dep="$2"
|
||||
local reference="${3:-${owner}}"
|
||||
|
||||
if [[ "${dep}" != @* ]]; then
|
||||
[[ -f "${dep}" ]] || return 1
|
||||
printf '%s\n' "${dep}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local owner_dir reference_dir
|
||||
owner_dir="$(cd "$(dirname "${owner}")" && pwd)"
|
||||
reference_dir="$(cd "$(dirname "${reference}")" && pwd)"
|
||||
|
||||
case "${dep}" in
|
||||
@loader_path/*)
|
||||
local candidate="${owner_dir}/${dep#@loader_path/}"
|
||||
[[ -f "${candidate}" ]] || return 1
|
||||
printf '%s\n' "${candidate}"
|
||||
;;
|
||||
@executable_path/*)
|
||||
local rel="${dep#@executable_path/}"
|
||||
local candidate="${owner_dir}/${rel}"
|
||||
if [[ ! -f "${candidate}" ]]; then
|
||||
candidate="${reference_dir}/${rel}"
|
||||
fi
|
||||
if [[ ! -f "${candidate}" ]]; then
|
||||
candidate="$(find_homebrew_lib "$(basename "${rel}")")"
|
||||
fi
|
||||
[[ -f "${candidate}" ]] || return 1
|
||||
printf '%s\n' "${candidate}"
|
||||
;;
|
||||
@rpath/*)
|
||||
local rel="${dep#@rpath/}"
|
||||
local rpath candidate
|
||||
while IFS= read -r rpath; do
|
||||
case "${rpath}" in
|
||||
@loader_path/*) candidate="${owner_dir}/${rpath#@loader_path/}/${rel}" ;;
|
||||
@executable_path/*) candidate="${owner_dir}/${rpath#@executable_path/}/${rel}" ;;
|
||||
*) candidate="${rpath}/${rel}" ;;
|
||||
esac
|
||||
if [[ -f "${candidate}" ]]; then
|
||||
printf '%s\n' "${candidate}"
|
||||
return 0
|
||||
fi
|
||||
done < <(
|
||||
otool -l "${owner}" | awk '
|
||||
/cmd LC_RPATH/ { want=1; next }
|
||||
want && /path / {
|
||||
sub(/^.*path /, "", $0)
|
||||
sub(/ \(offset.*$/, "", $0)
|
||||
print
|
||||
want=0
|
||||
}
|
||||
'
|
||||
)
|
||||
candidate="${owner_dir}/${rel}"
|
||||
[[ -f "${candidate}" ]] || return 1
|
||||
printf '%s\n' "${candidate}"
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
list_load_dylibs() {
|
||||
local target="$1"
|
||||
otool -l "${target}" | awk '
|
||||
/cmd LC_LOAD_DYLIB/ { want=1; next }
|
||||
want && /name / {
|
||||
sub(/^.*name /, "", $0)
|
||||
sub(/ \(offset.*$/, "", $0)
|
||||
print
|
||||
want=0
|
||||
}
|
||||
'
|
||||
}
|
||||
|
||||
bundle_mach_dylibs() {
|
||||
local binary="${1:?binary path required}"
|
||||
local lib_dir="${2:?lib directory required}"
|
||||
local reference_binary="${3:-${binary}}"
|
||||
|
||||
[[ -f "${binary}" ]] || {
|
||||
echo "bundle_mach_dylibs: missing binary: ${binary}" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
mkdir -p "${lib_dir}"
|
||||
|
||||
local -a queue=("${binary}")
|
||||
local seen_list=" "
|
||||
local -a sources=()
|
||||
|
||||
is_system_lib() {
|
||||
case "$1" in
|
||||
/usr/lib/*|/System/*|/Library/*) return 0 ;;
|
||||
esac
|
||||
return 1
|
||||
}
|
||||
|
||||
already_seen() {
|
||||
[[ "${seen_list}" == *" $1 "* ]]
|
||||
}
|
||||
|
||||
remember() {
|
||||
seen_list+=" $1 "
|
||||
}
|
||||
|
||||
while ((${#queue[@]} > 0)); do
|
||||
local target="${queue[0]}"
|
||||
queue=("${queue[@]:1}")
|
||||
[[ -f "${target}" ]] || continue
|
||||
|
||||
local dep resolved
|
||||
while IFS= read -r dep; do
|
||||
[[ -n "${dep}" ]] || continue
|
||||
is_system_lib "${dep}" && continue
|
||||
already_seen "${dep}" && continue
|
||||
remember "${dep}"
|
||||
|
||||
resolved="$(resolve_dependency_path "${target}" "${dep}" "${reference_binary}")" || {
|
||||
echo "bundle_mach_dylibs: missing dependency ${dep} for ${target}" >&2
|
||||
return 1
|
||||
}
|
||||
already_seen "${resolved}" || remember "${resolved}"
|
||||
|
||||
if [[ "${resolved}" != "${binary}" ]]; then
|
||||
sources+=("${resolved}")
|
||||
queue+=("${resolved}")
|
||||
fi
|
||||
done < <(list_load_dylibs "${target}")
|
||||
done
|
||||
|
||||
local src base
|
||||
for src in "${sources[@]}"; do
|
||||
base="$(basename "${src}")"
|
||||
cp -f "${src}" "${lib_dir}/${base}"
|
||||
chmod 755 "${lib_dir}/${base}"
|
||||
done
|
||||
|
||||
rewrite_dep() {
|
||||
local target="$1"
|
||||
local dep="$2"
|
||||
local new_path="$3"
|
||||
install_name_tool -change "${dep}" "${new_path}" "${target}" 2>/dev/null || true
|
||||
}
|
||||
|
||||
rewrite_targets() {
|
||||
local target="$1"
|
||||
local prefix="$2"
|
||||
local dep base
|
||||
while IFS= read -r dep; do
|
||||
[[ -n "${dep}" ]] || continue
|
||||
is_system_lib "${dep}" && continue
|
||||
[[ "${dep}" == @* ]] && continue
|
||||
base="$(basename "${dep}")"
|
||||
[[ -f "${lib_dir}/${base}" ]] || continue
|
||||
rewrite_dep "${target}" "${dep}" "${prefix}${base}"
|
||||
done < <(list_load_dylibs "${target}")
|
||||
}
|
||||
|
||||
rewrite_rpath_targets() {
|
||||
local target="$1"
|
||||
local prefix="$2"
|
||||
local dep base
|
||||
while IFS= read -r dep; do
|
||||
[[ -n "${dep}" ]] || continue
|
||||
[[ "${dep}" == @rpath/* ]] || continue
|
||||
base="$(basename "${dep}")"
|
||||
[[ -f "${lib_dir}/${base}" ]] || continue
|
||||
rewrite_dep "${target}" "${dep}" "${prefix}${base}"
|
||||
done < <(list_load_dylibs "${target}")
|
||||
}
|
||||
|
||||
local changed=1
|
||||
while ((changed)); do
|
||||
changed=0
|
||||
rewrite_targets "${binary}" "@executable_path/../lib/"
|
||||
rewrite_rpath_targets "${binary}" "@executable_path/../lib/"
|
||||
for staged in "${lib_dir}"/*.dylib; do
|
||||
[[ -f "${staged}" ]] || continue
|
||||
before="$(list_load_dylibs "${staged}" | { grep -E 'homebrew|^@rpath/' || true; } | wc -l | tr -d ' ')"
|
||||
rewrite_targets "${staged}" "@loader_path/"
|
||||
rewrite_rpath_targets "${staged}" "@loader_path/"
|
||||
after="$(list_load_dylibs "${staged}" | { grep -E 'homebrew|^@rpath/' || true; } | wc -l | tr -d ' ')"
|
||||
[[ "${before}" != "${after}" ]] && changed=1
|
||||
done
|
||||
done
|
||||
|
||||
local remaining
|
||||
remaining="$(list_load_dylibs "${binary}" | grep homebrew || true)"
|
||||
if [[ -n "${remaining}" ]]; then
|
||||
echo "bundle_mach_dylibs: unresolved homebrew dependencies remain:" >&2
|
||||
printf '%s\n' "${remaining}" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
install_name_tool -add_rpath "@executable_path/../lib" "${binary}" 2>/dev/null || true
|
||||
|
||||
local staged
|
||||
for staged in "${lib_dir}"/*.dylib; do
|
||||
[[ -f "${staged}" ]] || continue
|
||||
codesign --force --sign - "${staged}" >/dev/null
|
||||
done
|
||||
codesign --force --sign - "${binary}" >/dev/null
|
||||
}
|
||||
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||
bundle_mach_dylibs "$@"
|
||||
fi
|
||||
Reference in New Issue
Block a user