summaryrefslogtreecommitdiff
path: root/build-aux/install-reloc
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2019-02-23 22:42:54 +0100
committerBruno Haible <bruno@clisp.org>2019-02-23 22:42:54 +0100
commit4fe3afa8f45e1461eb864abd468078997c4cc4ce (patch)
treee58c36603f307d9ee790a0acc7a32c80fb712238 /build-aux/install-reloc
parent015c30cac9dffe6e53a7f3bedc22e462c54150ed (diff)
downloadgnulib-4fe3afa8f45e1461eb864abd468078997c4cc4ce.tar.gz
relocatable-prog: Use wrapper-free installation also on Mac OS X.
Reported by Paul Smith <psmith@gnu.org>. * build-aux/install-reloc: Accept a 'mode' argument as first argument. (func_relativize): New function, from gnulib-tool. Handle mode 'macosx' through invocations of 'otool' and 'install_name_tool'. * m4/relocatable.m4 (gl_RELOCATABLE_BODY): Determine use_macos_tools. If use_macos_tools is true, set INSTALL_PROGRAM_ENV to an 'install-reloc' invocation with mode 'macosx'.
Diffstat (limited to 'build-aux/install-reloc')
-rwxr-xr-xbuild-aux/install-reloc395
1 files changed, 270 insertions, 125 deletions
diff --git a/build-aux/install-reloc b/build-aux/install-reloc
index 980303c10d..e68386e7f2 100755
--- a/build-aux/install-reloc
+++ b/build-aux/install-reloc
@@ -1,5 +1,8 @@
#!/bin/sh
-# install-reloc - install a program including a relocating wrapper
+# install-reloc - install a program in a way that it will find its shared
+# libraries even when relocated,
+# - either including a relocating wrapper,
+# - or using Mac OS X specific tools.
# Copyright (C) 2003-2019 Free Software Foundation, Inc.
# Written by Bruno Haible <bruno@clisp.org>, 2003.
#
@@ -17,10 +20,15 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# Usage 1:
-# install-reloc -- library_path_var library_path_value prefix destdir \
+# install-reloc -- 'wrapper' \
+# library_path_var library_path_value prefix destdir \
# compile_command srcdir builddir config_h_dir exeext \
# strip_command \
# install_command... destprog
+# install-reloc -- 'macosx' \
+# prefix destdir \
+# strip_command \
+# install_command... destprog
# where
# - library_path_var is the platform dependent runtime library path variable
# - library_path_value is a colon separated list of directories that contain
@@ -40,7 +48,8 @@
# - install_command is the install command line, excluding the final destprog
# - destprog is the destination program name
# Usage 2:
-# env RELOC_LIBRARY_PATH_VAR=library_path_var \
+# env RELOC_MODE='wrapper' \
+# RELOC_LIBRARY_PATH_VAR=library_path_var \
# RELOC_LIBRARY_PATH_VALUE=library_path_value \
# RELOC_PREFIX=prefix \
# RELOC_DESTDIR=destdir \
@@ -51,59 +60,120 @@
# RELOC_EXEEXT=exeext \
# RELOC_STRIP_PROG=strip_command \
# RELOC_INSTALL_PROG=install_command... \
-# install-reloc prog1 ... destprog
+# install-reloc prog1 ... destprog
+# env RELOC_MODE='macosx' \
+# RELOC_PREFIX=prefix \
+# RELOC_DESTDIR=destdir \
+# RELOC_STRIP_PROG=strip_command \
+# RELOC_INSTALL_PROG=install_command... \
+# install-reloc prog1 ... destprog
# where destprog is either the destination program name (when only one program
# is specified) or the destination directory for all programs.
-# install-reloc renames destprog to destprog.bin and installs a relocating
-# wrapper in the place of destprog.
+# In the 'wrapper' mode, install-reloc renames destprog to destprog.bin and
+# installs a relocating wrapper in the place of destprog.
progname=$0
-if test $# -ge 12 && test "x$1" = "x--"; then
+func_usage ()
+{
+ echo "Usage: $0 -- 'wrapper'" \
+ "library_path_var library_path_value prefix destdir" \
+ "compile_command srcdir builddir config_h_dir exeext" \
+ "strip_command" \
+ "install_command... destprog"
+ echo "Usage: $0 -- 'macosx'" \
+ "prefix destdir" \
+ "strip_command" \
+ "install_command... destprog"
+}
+
+if test "x$1" = "x--"; then
# Get fixed position arguments.
- shift
- library_path_var=$1
- library_path_value=$2
- prefix=$3
- destdir=$4
- shift
- shift
- shift
- shift
- compile_command=$1
- srcdir=$2
- builddir=$3
- config_h_dir=$4
- exeext=$5
- shift
- shift
- shift
- shift
- shift
- strip_prog=$1
- shift
- install_prog=$1 # maybe not including the "-c" option
- shift
+ case "$2" in
+ wrapper)
+ if test $# -ge 13; then
+ mode=$2
+ shift
+ shift
+ library_path_var=$1
+ library_path_value=$2
+ prefix=$3
+ destdir=$4
+ shift
+ shift
+ shift
+ shift
+ compile_command=$1
+ srcdir=$2
+ builddir=$3
+ config_h_dir=$4
+ exeext=$5
+ shift
+ shift
+ shift
+ shift
+ shift
+ strip_prog=$1
+ shift
+ install_prog=$1 # maybe not including the "-c" option
+ shift
+ else
+ func_usage 1>&2; exit 1
+ fi
+ ;;
+ macosx)
+ if test $# -ge 6; then
+ mode=$2
+ shift
+ shift
+ prefix=$1
+ destdir=$2
+ shift
+ shift
+ exeext=
+ strip_prog=$1
+ shift
+ install_prog=$1 # maybe not including the "-c" option
+ shift
+ else
+ func_usage 1>&2; exit 1
+ fi
+ ;;
+ *)
+ func_usage 1>&2; exit 1
+ ;;
+ esac
else
if test $# -ge 2; then
# Get arguments from environment variables.
- library_path_var=$RELOC_LIBRARY_PATH_VAR
- library_path_value=$RELOC_LIBRARY_PATH_VALUE
- prefix=$RELOC_PREFIX
- destdir=$RELOC_DESTDIR
- compile_command=$RELOC_COMPILE_COMMAND
- srcdir=$RELOC_SRCDIR
- builddir=$RELOC_BUILDDIR
- config_h_dir=$RELOC_CONFIG_H_DIR
- exeext=$RELOC_EXEEXT
- strip_prog=$RELOC_STRIP_PROG
- install_prog=$RELOC_INSTALL_PROG # including the "-c" option
+ mode=$RELOC_MODE
+ case "$mode" in
+ wrapper)
+ library_path_var=$RELOC_LIBRARY_PATH_VAR
+ library_path_value=$RELOC_LIBRARY_PATH_VALUE
+ prefix=$RELOC_PREFIX
+ destdir=$RELOC_DESTDIR
+ compile_command=$RELOC_COMPILE_COMMAND
+ srcdir=$RELOC_SRCDIR
+ builddir=$RELOC_BUILDDIR
+ config_h_dir=$RELOC_CONFIG_H_DIR
+ exeext=$RELOC_EXEEXT
+ strip_prog=$RELOC_STRIP_PROG
+ install_prog=$RELOC_INSTALL_PROG # including the "-c" option
+ ;;
+ macosx)
+ prefix=$RELOC_PREFIX
+ destdir=$RELOC_DESTDIR
+ exeext=
+ strip_prog=$RELOC_STRIP_PROG
+ install_prog=$RELOC_INSTALL_PROG # including the "-c" option
+ ;;
+ *)
+ func_usage 1>&2; exit 1
+ ;;
+ esac
else
- echo "Usage: $0 -- library_path_var library_path_value prefix destdir" \
- "compile_command srcdir builddir config_h_dir exeext" \
- "strip_command" \
- "install_command... destprog" 1>&2
- exit 1
+ func_usage 1>&2; exit 1
fi
fi
@@ -179,30 +249,13 @@ if test "$strip_prog" != ':'; then
func_iterate func_strip
fi
-# If the platform doesn't support LD_LIBRARY_PATH or similar, we cannot build
-# a wrapper.
-test -n "$library_path_var" || exit 0
-
-libdirs=
-save_IFS="$IFS"; IFS=":"
-for dir in $library_path_value; do
- IFS="$save_IFS"
- if test -n "$dir"; then
- case "$libdirs" in
- *"\"$dir\""*) ;; # remove duplicate
- *) libdirs="$libdirs\"$dir\"," ;;
- esac
- fi
-done
-IFS="$save_IFS"
-# If there are no library directories to add at runtime, we don't need a
-# wrapper.
-test -n "$libdirs" || exit 0
-
# Determine installdir from destprog, removing a leading destdir if present.
if test -n "$destprog_directory"; then
+ # There's possibly multiple programs to install, but all go into the same
+ # directory.
installdir="$destprog_directory"
else
+ # There's only one program to install.
installdir=`echo "$destprog" | sed -e 's,/[^/]*$,,'`
fi
if test -n "$destdir"; then
@@ -211,68 +264,160 @@ if test -n "$destdir"; then
installdir=`echo "$installdir" | sed -e "$sed_remove_destdir"`
fi
-# Compile and install wrapper.
-func_create_wrapper ()
+# func_relativize DIR1 DIR2
+# computes a relative pathname RELDIR such that DIR1/RELDIR = DIR2.
+# Input:
+# - DIR1 relative pathname, relative to the current directory
+# - DIR2 relative pathname, relative to the current directory
+# Output:
+# - reldir relative pathname of DIR2, relative to DIR1
+func_relativize ()
{
- # Remove trailing $exeext, if present.
- if test -n "$exeext"; then
- destprog=`echo "$destprog" | sed -e "$sed_remove_exeext"`
- fi
+ dir0=`pwd`
+ dir1="$1"
+ dir2="$2"
+ sed_first='s,^\([^/]*\)/.*$,\1,'
+ sed_rest='s,^[^/]*/*,,'
+ sed_last='s,^.*/\([^/]*\)$,\1,'
+ sed_butlast='s,/*[^/]*$,,'
+ while test -n "$dir1"; do
+ first=`echo "$dir1" | sed -e "$sed_first"`
+ if test "$first" != "."; then
+ if test "$first" = ".."; then
+ dir2=`echo "$dir0" | sed -e "$sed_last"`/"$dir2"
+ dir0=`echo "$dir0" | sed -e "$sed_butlast"`
+ else
+ first2=`echo "$dir2" | sed -e "$sed_first"`
+ if test "$first2" = "$first"; then
+ dir2=`echo "$dir2" | sed -e "$sed_rest"`
+ else
+ dir2="../$dir2"
+ fi
+ dir0="$dir0"/"$first"
+ fi
+ fi
+ dir1=`echo "$dir1" | sed -e "$sed_rest"`
+ done
+ reldir="$dir2"
+}
- # Compile wrapper.
- func_verbose $compile_command \
- -I"$builddir" -I"$srcdir" -I"$config_h_dir" \
- -DHAVE_CONFIG_H -DIN_RELOCWRAPPER -DNO_XMALLOC \
- -D"INSTALLPREFIX=\"$prefix\"" -D"INSTALLDIR=\"$installdir\"" \
- -D"LIBPATHVAR=\"$library_path_var\"" -D"LIBDIRS=$libdirs" \
- -D"EXEEXT=\"$exeext\"" \
- "$srcdir"/relocwrapper.c \
- "$srcdir"/progname.c \
- "$srcdir"/progreloc.c \
- "$srcdir"/areadlink.c \
- "$srcdir"/careadlinkat.c \
- "$srcdir"/allocator.c \
- "$srcdir"/readlink.c \
- "$srcdir"/stat.c \
- "$srcdir"/canonicalize-lgpl.c \
- "$srcdir"/malloca.c \
- "$srcdir"/lstat.c \
- "$srcdir"/relocatable.c \
- "$srcdir"/setenv.c \
- "$srcdir"/c-ctype.c \
- -o "$destprog.wrapper$exeext"
- rc=$?
- # Clean up object files left over in the current directory by the native C
- # compilers on Solaris, HP-UX, OSF/1, IRIX.
- rm -f relocwrapper.o \
- progname.o \
- progreloc.o \
- areadlink.o \
- careadlinkat.o \
- allocator.o \
- readlink.o \
- stat.o \
- canonicalize-lgpl.o \
- malloca.o \
- lstat.o \
- relocatable.o \
- setenv.o \
- c-ctype.o
- test $rc = 0 || exit $?
- # Clean up debugging information left over by the native C compiler on MacOS X.
- rm -rf "$destprog.wrapper$exeext.dSYM"
- test $rc = 0 || exit $?
+case "$mode" in
- # Strip wrapper.
- test "$strip_prog" = ':' || func_verbose "$strip_prog" "$destprog.wrapper$exeext" || exit $?
+ wrapper)
+ # If the platform doesn't support LD_LIBRARY_PATH or similar, we cannot
+ # build a wrapper.
+ test -n "$library_path_var" || exit 0
- # Rename $destprog.wrapper -> $destprog -> $destprog.bin.
- ln -f "$destprog$exeext" "$destprog.bin$exeext" \
- || { rm -f "$destprog.bin$exeext" \
- && cp -p "$destprog$exeext" "$destprog.bin$exeext"; } \
- || exit 1
- mv "$destprog.wrapper$exeext" "$destprog$exeext" || exit 1
-}
-func_iterate func_create_wrapper
+ libdirs=
+ save_IFS="$IFS"; IFS=":"
+ for dir in $library_path_value; do
+ IFS="$save_IFS"
+ if test -n "$dir"; then
+ case "$libdirs" in
+ *"\"$dir\""*) ;; # remove duplicate
+ *) libdirs="$libdirs\"$dir\"," ;;
+ esac
+ fi
+ done
+ IFS="$save_IFS"
+ # If there are no library directories to add at runtime, we don't need a
+ # wrapper.
+ test -n "$libdirs" || exit 0
+
+ # Compile and install wrapper.
+ func_create_wrapper ()
+ {
+ # Remove trailing $exeext, if present.
+ if test -n "$exeext"; then
+ destprog=`echo "$destprog" | sed -e "$sed_remove_exeext"`
+ fi
+
+ # Compile wrapper.
+ func_verbose $compile_command \
+ -I"$builddir" -I"$srcdir" -I"$config_h_dir" \
+ -DHAVE_CONFIG_H -DIN_RELOCWRAPPER -DNO_XMALLOC \
+ -D"INSTALLPREFIX=\"$prefix\"" -D"INSTALLDIR=\"$installdir\"" \
+ -D"LIBPATHVAR=\"$library_path_var\"" -D"LIBDIRS=$libdirs" \
+ -D"EXEEXT=\"$exeext\"" \
+ "$srcdir"/relocwrapper.c \
+ "$srcdir"/progname.c \
+ "$srcdir"/progreloc.c \
+ "$srcdir"/areadlink.c \
+ "$srcdir"/careadlinkat.c \
+ "$srcdir"/allocator.c \
+ "$srcdir"/readlink.c \
+ "$srcdir"/stat.c \
+ "$srcdir"/canonicalize-lgpl.c \
+ "$srcdir"/malloca.c \
+ "$srcdir"/lstat.c \
+ "$srcdir"/relocatable.c \
+ "$srcdir"/setenv.c \
+ "$srcdir"/c-ctype.c \
+ -o "$destprog.wrapper$exeext"
+ rc=$?
+ # Clean up object files left over in the current directory by the native C
+ # compilers on Solaris, HP-UX, OSF/1, IRIX.
+ rm -f relocwrapper.o \
+ progname.o \
+ progreloc.o \
+ areadlink.o \
+ careadlinkat.o \
+ allocator.o \
+ readlink.o \
+ stat.o \
+ canonicalize-lgpl.o \
+ malloca.o \
+ lstat.o \
+ relocatable.o \
+ setenv.o \
+ c-ctype.o
+ test $rc = 0 || exit $?
+ # Clean up debugging information left over by the native C compiler on
+ # Mac OS X.
+ rm -rf "$destprog.wrapper$exeext.dSYM"
+ test $rc = 0 || exit $?
+
+ # Strip wrapper.
+ test "$strip_prog" = ':' || func_verbose "$strip_prog" "$destprog.wrapper$exeext" || exit $?
+
+ # Rename $destprog.wrapper -> $destprog -> $destprog.bin.
+ ln -f "$destprog$exeext" "$destprog.bin$exeext" \
+ || { rm -f "$destprog.bin$exeext" \
+ && cp -p "$destprog$exeext" "$destprog.bin$exeext"; } \
+ || exit 1
+ mv "$destprog.wrapper$exeext" "$destprog$exeext" || exit 1
+ }
+ func_iterate func_create_wrapper
+ ;;
+
+ macosx)
+ # Insert a reference to @loader_path in selected shared library references.
+ # For executables, @executable_path is equivalent to @loader_path.
+ func_reference_loader_path ()
+ {
+ # For using 'install_name_tool -change ...' we need to know the precise
+ # library version of each reference. The linker command line does not give
+ # us the information; only 'otool' provides it.
+ # Documentation:
+ # <https://www.manpagez.com/man/1/otool/>
+ # <https://www.unix.com/man-page/osx/1/otool/>
+ # The install_name_tool exists in versions without and with rpath support:
+ # <https://www.manpagez.com/man/1/install_name_tool/>
+ # <https://www.unix.com/man-page/osx/1/install_name_tool/>
+ otool -L "$destprog" | sed -e '/:$/d' -e 's/^[ ]*//' -e 's/ (.*$//' | \
+ while read libfilename; do
+ case "$libfilename" in
+ "$prefix"/* )
+ func_relativize "$installdir" "$libfilename"
+ new_libfilename="@loader_path/$reldir"
+ func_verbose install_name_tool -change "$libfilename" "$new_libfilename" "$destprog"
+ ;;
+ esac
+ done
+ }
+ func_iterate func_reference_loader_path
+ ;;
+
+esac
exit 0