+2019-03-04 Bruno Haible <bruno@clisp.org>
+
+ relocatable-prog: Use wrapper-free installation on Mac OS X, take 2.
+ This approach supports relocatable installation of shared libraries
+ which depend on other shared libraries from the same package.
+ * m4/relocatable.m4 (gl_RELOCATABLE_BODY): Determine use_macos_tools.
+ If use_macos_tools is true, use reloc-ldflags and set LIBTOOL to be a
+ wrapper around the original LIBTOOL.
+ * build-aux/reloc-ldflags: Add support for Mac OS X, which uses the
+ token '@loader_path' instead of '$ORIGIN'.
+ * build-aux/libtool-reloc: New file.
+ * modules/relocatable-prog (Files): Add it.
+ * doc/relocatable-maint.texi (Supporting Relocation): Update to match
+ the recent changes. Document the need to set the *_LDFLAGS of libraries.
+ RELOCATABLE_LIBRARY_PATH and RELOCATABLE_CONFIG_H_DIR should be set in
+ Makefile.am, not in configure.ac.
+
2019-03-04 Bruno Haible <bruno@clisp.org>
relocatable-prog: Revert "Use wrapper-free installation on Mac OS X."
--- /dev/null
+#!/bin/sh
+# libtool-reloc - libtool wrapper with support for relocatable programs
+# Copyright (C) 2019 Free Software Foundation, Inc.
+# Written by Bruno Haible <bruno@clisp.org>, 2019.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+# Usage: libtool-reloc libtool LIBTOOL_ARGUMENTS
+
+# Outputs a command and runs it.
+func_verbose ()
+{
+ # Make it easy to copy&paste the printed command into a shell in most cases,
+ # by escaping '\\', '"', and '$'. This is not perfect, just good enough.
+ echo "$@" | sed -e 's/\([\\"$]\)/\\\1/g'
+ "$@"
+}
+
+# Determine the mode from the arguments.
+mode=
+for arg
+do
+ case "$arg" in
+ --mode=link) mode=link ;;
+ esac
+done
+
+if test "$mode" = link; then
+ # Determine the target from the arguments.
+ target=
+ next_is_target=false
+ for arg
+ do
+ if $next_is_target; then
+ target="$arg"
+ next_is_target=false
+ else
+ case "$arg" in
+ -o) next_is_target=true ;;
+ *) next_is_target=false ;;
+ esac
+ fi
+ done
+ case "$target" in
+ *.la)
+ # When creating a library:
+ # 1. Add a '-Wl,-rpath,@loader_path' option.
+ # (A '-R @loader_path' option does not work: libtool produces
+ # an error "error: only absolute run-paths are allowed".)
+ # (Also note that 'install_name_tool -add_rpath @loader_path ...'
+ # does not work on Mac OS X 10.5.)
+ # This is done through the RELOCATABLE_LDFLAGS macro.
+ # 2. After creating the library, run
+ # install_name_tool -id @rpath/$dlname $target_dir/.libs/$dlname
+ # (This is easier than to modify the libtool script to emit a different
+ # install_name. Also, an option '-Wl,-install_name,@rpath/$dlname' does
+ # not work since libtool emits another option '-Wl,-install_name,...'
+ # after it.
+ "$@" && {
+ dlname_assignment=`grep '^dlname=' "$target"`
+ dlname=
+ eval "$dlname_assignment"
+ # Nothing to do when --disable-shared was specified.
+ if test -n "$dlname"; then
+ target_dir=`dirname "$target"`
+ if test -f "$target_dir/.libs/$dlname"; then
+ func_verbose install_name_tool -id "@rpath/$dlname" "$target_dir/.libs/$dlname"
+ fi
+ fi
+ }
+ ;;
+ *)
+ "$@"
+ ;;
+ esac
+else
+ "$@"
+fi
;;
esac
+origin_token=
case "$host_os" in
linux* | gnu* | kfreebsd* | \
freebsd* | dragonfly* | \
openbsd* | \
solaris* | \
haiku*)
- rpath=
- save_IFS="$IFS"; IFS=":"
- for dir in $library_path_value; do
- IFS="$save_IFS"
- case "$dir" in
- /*)
- # Make dir relative to installdir. (Works only if dir is absolute.)
- idir="$installdir"
- while true; do
- dfirst=`echo "$dir" | sed -n -e 's,^//*\([^/]*\).*$,/\1,p'`
- ifirst=`echo "$idir" | sed -n -e 's,^//*\([^/]*\).*$,/\1,p'`
- if test -z "$dfirst" || test -z "$ifirst"; then
- break
- fi
- if test "$dfirst" != "$ifirst"; then
- break
- fi
- dir=`echo "$dir" | sed -e 's,^//*[^/]*,,'`
- idir=`echo "$idir" | sed -e 's,^//*[^/]*,,'`
- done
- dir="\$ORIGIN"`echo "$idir" | sed -e 's,//*[^/]*,/..,g'`"$dir"
- # Add dir to rpath.
- rpath="${rpath}${rpath:+ }$dir"
- ;;
- *)
- if test -n "$dir"; then
- echo "libdir is not absolute: $dir" 1>&2
- fi
- ;;
- esac
- done
- IFS="$save_IFS"
- # Output it.
- if test -n "$rpath"; then
- case "$host_os" in
- # At least some versions of FreeBSD, DragonFly, and OpenBSD need the
- # linker option "-z origin". See <https://lekensteyn.nl/rpath.html>.
- freebsd* | dragonfly* | openbsd*)
- echo "-Wl,-z,origin -Wl,-rpath,$rpath" ;;
- *)
- echo "-Wl,-rpath,$rpath" ;;
- esac
- fi
+ origin_token='$ORIGIN'
;;
- *)
- echo "relocation via rpath not supported on this system: $host" 1>&2
- exit 1
+ darwin*)
+ origin_token='@loader_path'
;;
esac
+if test -n "$origin_token"; then
+ rpath=
+ save_IFS="$IFS"; IFS=":"
+ for dir in $library_path_value; do
+ IFS="$save_IFS"
+ case "$dir" in
+ /*)
+ # Make dir relative to installdir. (Works only if dir is absolute.)
+ idir="$installdir"
+ while true; do
+ dfirst=`echo "$dir" | sed -n -e 's,^//*\([^/]*\).*$,/\1,p'`
+ ifirst=`echo "$idir" | sed -n -e 's,^//*\([^/]*\).*$,/\1,p'`
+ if test -z "$dfirst" || test -z "$ifirst"; then
+ break
+ fi
+ if test "$dfirst" != "$ifirst"; then
+ break
+ fi
+ dir=`echo "$dir" | sed -e 's,^//*[^/]*,,'`
+ idir=`echo "$idir" | sed -e 's,^//*[^/]*,,'`
+ done
+ dir="$origin_token"`echo "$idir" | sed -e 's,//*[^/]*,/..,g'`"$dir"
+ # Add dir to rpath.
+ rpath="${rpath}${rpath:+ }$dir"
+ ;;
+ *)
+ if test -n "$dir"; then
+ echo "libdir is not absolute: $dir" 1>&2
+ fi
+ ;;
+ esac
+ done
+ IFS="$save_IFS"
+ # Output it.
+ if test -n "$rpath"; then
+ case "$host_os" in
+ # At least some versions of FreeBSD, DragonFly, and OpenBSD need the
+ # linker option "-z origin". See <https://lekensteyn.nl/rpath.html>.
+ freebsd* | dragonfly* | openbsd*)
+ echo "-Wl,-z,origin -Wl,-rpath,$rpath" ;;
+ *)
+ echo "-Wl,-rpath,$rpath" ;;
+ esac
+ fi
+else
+ echo "relocation via rpath not supported on this system: $host" 1>&2
+ exit 1
+fi
exit 0
On most operating systems, it adds a linker option (@option{-rpath}) that
causes the dynamic linker to search for libraries in a directory relative
to the location of the invoked executable. This works on GNU/Linux and
-modern versions of GNU/Hurd, GNU/kFreeBSD, FreeBSD, NetBSD, OpenBSD, Solaris,
-Haiku.
-
-@item
-On macOS, it modifies the installed executables after installation in a way
-that causes the dynamic linker to search for libraries in a directory relative
-to the location of the invoked executable.
+modern versions of GNU/Hurd, GNU/kFreeBSD, macOS, FreeBSD, NetBSD, OpenBSD,
+Solaris, Haiku.
@item
On other Unix systems, it installs a trampoline executable. The trampoline
@enumerate
@item
Import the @code{relocatable-prog} module. For libraries, use the
-@code{relocatable-lib} or @code{relocatable-lib-lgpl} module.
+@code{relocatable-lib} or @code{relocatable-lib-lgpl} module, if
+the libraries are independent. For installing multiple libraries,
+at least one of which depends on another one, use the @code{relocatable-prog}
+module.
If you need more than one module, or you need to use them with different
settings, you will need multiple copies of gnulib (@pxref{Multiple instances}).
@end smallexample
@item
-You may also need to add a couple of variable assignments to your
-@file{configure.ac}.
+In your @file{Makefile.am}, for every library @command{libfoo} that gets
+installed in, say, @file{$(libdir)}, you add:
+
+@example
+if RELOCATABLE_VIA_LD
+libfoo_la_LDFLAGS = `$(RELOCATABLE_LDFLAGS) $(libdir)`
+endif
+@end example
+
+@item
+Add a couple of variable assignments to your @file{Makefile.am}.
If your package (or any package you rely on, e.g.@: gettext-runtime)
will be relocated together with a set of installed shared libraries,
-then set @var{RELOCATABLE_LIBRARY_PATH} to a colon-separated list
+then set @code{RELOCATABLE_LIBRARY_PATH} to a colon-separated list
of those libraries' directories, e.g.
@example
-RELOCATABLE_LIBRARY_PATH='$(libdir)'
+RELOCATABLE_LIBRARY_PATH = $(libdir)
@end example
If your @file{config.h} is not in @file{$(top_builddir)}, then set
-@var{RELOCATABLE_CONFIG_H_DIR} to its directory, e.g.
+@code{RELOCATABLE_CONFIG_H_DIR} to its directory, e.g.
@example
-RELOCATABLE_CONFIG_H_DIR='$(top_builddir)/src'
+RELOCATABLE_CONFIG_H_DIR = $(top_builddir)/src
@end example
@end enumerate
-# relocatable.m4 serial 21
+# relocatable.m4 serial 23
dnl Copyright (C) 2003, 2005-2007, 2009-2019 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
AC_DEFUN([gl_RELOCATABLE_BODY],
[
AC_REQUIRE([AC_PROG_INSTALL])
+
dnl This AC_BEFORE invocation leads to unjustified autoconf warnings
dnl when gl_RELOCATABLE_BODY is invoked more than once.
+ dnl
dnl We need this AC_BEFORE because AC_PROG_INSTALL is documented to
dnl overwrite earlier settings of INSTALL and INSTALL_PROGRAM (even
dnl though in autoconf-2.52..2.60 it doesn't do so), but we want this
dnl macro's setting of INSTALL_PROGRAM to persist.
- AC_BEFORE([AC_PROG_INSTALL],[gl_RELOCATABLE_BODY])
+ dnl Arghh: AC_BEFORE does not work in this setting :-(
+ dnl AC_BEFORE([AC_PROG_INSTALL],[gl_RELOCATABLE_BODY])
+ dnl
+ dnl LT_INIT sets LIBTOOL, but we want this macro's setting of LIBTOOL to
+ dnl persist.
+ dnl Arghh: AC_BEFORE does not work in this setting :-(
+ dnl AC_BEFORE([LT_INIT],[gl_RELOCATABLE_BODY])
+
AC_REQUIRE([AC_LIB_LIBPATH])
AC_REQUIRE([gl_RELOCATABLE_LIBRARY_BODY])
AC_REQUIRE([AC_CANONICAL_HOST])
is_noop=no
use_elf_origin_trick=no
+ use_macos_tools=no
use_wrapper=no
if test $RELOCATABLE = yes; then
# --enable-relocatable implies --disable-rpath
solaris*) use_elf_origin_trick=yes ;;
# Haiku: yes.
haiku*) use_elf_origin_trick=yes ;;
+ # On Mac OS X 10.4 or newer, use Mac OS X tools. See
+ # <https://wincent.com/wiki/@executable_path,_@load_path_and_@rpath>.
+ darwin | darwin[1-7].*) ;;
+ darwin*) use_macos_tools=yes ;;
changequote([,])dnl
esac
if test $is_noop = yes; then
RELOCATABLE_LDFLAGS=:
AC_SUBST([RELOCATABLE_LDFLAGS])
else
- if test $use_elf_origin_trick = yes; then
+ if test $use_elf_origin_trick = yes || test $use_macos_tools = yes; then
dnl Use the dynamic linker's support for relocatable programs.
case "$ac_aux_dir" in
/*) reloc_ldflags="$ac_aux_dir/reloc-ldflags" ;;
esac
RELOCATABLE_LDFLAGS="\"$reloc_ldflags\" \"\$(host)\" \"\$(RELOCATABLE_LIBRARY_PATH)\""
AC_SUBST([RELOCATABLE_LDFLAGS])
+ if test $use_macos_tools = yes; then
+ dnl Use a libtool wrapper that uses Mac OS X tools.
+ case "$ac_aux_dir" in
+ /*) LIBTOOL="${CONFIG_SHELL-$SHELL} $ac_aux_dir/libtool-reloc $LIBTOOL" ;;
+ *) LIBTOOL="${CONFIG_SHELL-$SHELL} \$(top_builddir)/$ac_aux_dir/libtool-reloc $LIBTOOL" ;;
+ esac
+ fi
else
use_wrapper=yes
dnl Unfortunately we cannot define INSTALL_PROGRAM to a command
fi
fi
AM_CONDITIONAL([RELOCATABLE_VIA_LD],
- [test $is_noop = yes || test $use_elf_origin_trick = yes])
+ [test $is_noop = yes || test $use_elf_origin_trick = yes || test $use_macos_tools = yes])
AM_CONDITIONAL([RELOCATABLE_VIA_WRAPPER], [test $use_wrapper = yes])
dnl RELOCATABLE_LIBRARY_PATH can be set in configure.ac. Default is empty.
Files:
build-aux/config.libpath
build-aux/reloc-ldflags
+build-aux/libtool-reloc
doc/relocatable.texi
lib/relocatable.h
lib/relocatable.c