Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save sdr01810/047d78c737e792b7702a6fa7e2201765 to your computer and use it in GitHub Desktop.
Save sdr01810/047d78c737e792b7702a6fa7e2201765 to your computer and use it in GitHub Desktop.
#!/bin/bash
## Make all references relocatable in each dynamic shared library listed on stdin.
## By Stephen D. Rogers <inbox.c7r@steve-rogers.com>, 2019.
##
## Arguments:
##
## [--relative-to anchor_directory_pn]
##
## Typical uses:
##
## for d1 in My.app/Contents/Frameworks ; do
##
## find -H "$d1" -maxdepth 1 -type f -name '*.dylib' |
## mac-os.relocate-listed-dynamic-shared-libraries --relative-to "$d1"
## done
##
## If `anchor_directory_pn` is not specified, it defaults to the current directory.
##
set -e
set -o pipefail 2>&- || :
##
## from snippet library:
##
function xx() { # ...
echo 1>&2 "${PS4:-+}" "$@"
"$@"
}
function list_id_and_references_specified_in_dynamic_shared_library() { # dynamic_shared_library_pn
local dynamic_shared_library_pn="${1:?missing argument: dynamic_shared_library_pn}" ; shift 1
objdump -macho -dylib-id "${dynamic_shared_library_pn:?}" | perl -lne '
chomp;
if (0) {}
elsif ($. == 1 && m#^\s*(.*?\S):\s*$#) {
printf STDOUT "%-10s %s$/", "pathname", $1;
}
elsif ($. == 2) {
printf STDOUT "%-10s %s$/", "id", $_;
}
';
objdump -macho -dylibs-used "${dynamic_shared_library_pn:?}" | perl -lne '
chomp;
if (0) {}
elsif ($. == 1 && m#^\s*(.*?\S):\s*$#) {
printf STDOUT "%-10s %s$/", "pathname", $1;
}
elsif ($. >= 2 && m#^\s*(.*?\S)(?:\s+\(compatibility version ([\d.]+), current version ([\d.]+)\))#) {
printf STDOUT "%-10s %s$/", "reference", $1;
}
else {
printf STDERR "Unexpected dylib reference: %s$/", $_;
next;
}
';
}
function relocate_mac_os_dynamic_shared_library() { # [--relative-to anchor_directory_pn] dynamic_shared_library_pn
local anchor_directory_pn
local dynamic_shared_library_pn
while [ $# -gt 0 ] ; do
case "${1}" in
--relative-to)
anchor_directory_pn="${2}"
shift 2
break
;;
--)
shift 1
break
;;
*)
break
;;
esac;done
anchor_directory_pn="${anchor_directory_pn:-.}"
dynamic_shared_library_pn="${1:?missing argument: dynamic_shared_library_pn}" ; shift 1
if [ $# -gt 0 ] ; then
echo 1>&2 "Unexpected argument(s): ${@}"
false
fi
##
list_id_and_references_specified_in_dynamic_shared_library "${dynamic_shared_library_pn:?}" |
(
change_set=()
while read type value ; do
case "${type}" in
id)
corrected_value="$(relocate_mac_os_dynamic_shared_library_pathname_relative_to "${anchor_directory_pn}" "${value}")"
if [ -n "${corrected_value}" -a "${corrected_value}" != "${value}" ] ; then
change_set+=( -id "${corrected_value}" )
fi
;;
pathname)
dynamic_shared_library_pn02="${value}"
;;
reference)
corrected_value="$(relocate_mac_os_dynamic_shared_library_pathname_relative_to "${anchor_directory_pn}" "${value}")"
if [ -n "${corrected_value}" -a "${corrected_value}" != "${value}" ] ; then
change_set+=( -change "${value}" "${corrected_value}" )
fi
;;
esac;done
if [ ${#change_set[@]} -gt 0 ] ; then
xx install_name_tool "${change_set[@]}" "${dynamic_shared_library_pn02}"
xx :
fi
)
}
function relocate_mac_os_dynamic_shared_library_pathname_relative_to() { # anchor_directory_pn dynamic_shared_library_pn
local anchor_directory_pn="${1:?}" ; shift 1
local dynamic_shared_library_pn="${1:?}" ; shift 1
local result_untransformed="${dynamic_shared_library_pn}"
local result="${result_untransformed}"
case "${result}" in
'')
: # no transformation
;;
@executable_file/*)
result="${result#@executable_file/../Frameworks/}"
case "${result}" in
@executable_file/*)
result="${result_untransformed}" # fallback
;;
*)
result="@rpath/${result}"
;;
esac
;;
@loader_path/*)
: # no transformation
;;
@rpath/*)
: # no transformation
;;
*)
result="${result#${anchor_directory_pn%/}/}"
case "${result}" in
/*)
result="${result_untransformed}" # fallback
;;
*)
result="@rpath/${result}"
;;
esac
;;
esac
echo "${result}"
}
##
## core logic:
##
function main() { # ...
local f1
while read -r f1 ; do
[ -f "$f1" ] || continue
relocate_mac_os_dynamic_shared_library "$@" "$f1"
done
}
! [ "$0" = "${BASH_SOURCE}" ] || main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment