[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: relocatable-prog: Use $ORIGIN trick on more platforms
From: |
Bruno Haible |
Subject: |
Re: relocatable-prog: Use $ORIGIN trick on more platforms |
Date: |
Mon, 04 Mar 2019 17:32:08 +0100 |
User-agent: |
KMail/5.1.3 (Linux/4.4.0-141-generic; KDE/5.18.0; x86_64; ; ) |
> 2019-02-23 Bruno Haible <address@hidden>
>
> relocatable-prog: Use wrapper-free installation also on Mac OS X.
> Reported by Paul Smith <address@hidden>.
> * 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'.
This patch works for executables that reference shared libraries
in the same package. But it does not work for shared libraries that
reference other shared libraries in the same package. I'm therefore
reverting this patch and adding this one instead.
2019-03-04 Bruno Haible <address@hidden>
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.
diff --git a/build-aux/libtool-reloc b/build-aux/libtool-reloc
new file mode 100755
index 0000000..9d899ab
--- /dev/null
+++ b/build-aux/libtool-reloc
@@ -0,0 +1,89 @@
+#!/bin/sh
+# libtool-reloc - libtool wrapper with support for relocatable programs
+# Copyright (C) 2019 Free Software Foundation, Inc.
+# Written by Bruno Haible <address@hidden>, 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
diff --git a/build-aux/reloc-ldflags b/build-aux/reloc-ldflags
index 3aed330..625fef2 100755
--- a/build-aux/reloc-ldflags
+++ b/build-aux/reloc-ldflags
@@ -53,6 +53,7 @@ case "$installdir" in
;;
esac
+origin_token=
case "$host_os" in
linux* | gnu* | kfreebsd* | \
freebsd* | dragonfly* | \
@@ -60,54 +61,59 @@ case "$host_os" in
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
diff --git a/doc/relocatable-maint.texi b/doc/relocatable-maint.texi
index 200fcab..d391598 100644
--- a/doc/relocatable-maint.texi
+++ b/doc/relocatable-maint.texi
@@ -38,13 +38,8 @@ here in a platform-specific way:
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.
-
address@hidden
-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
@@ -63,7 +58,10 @@ You can make your program relocatable by following these
steps:
@enumerate
@item
Import the @code{relocatable-prog} module. For libraries, use the
address@hidden or @code{relocatable-lib-lgpl} module.
address@hidden 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}).
@@ -233,20 +231,29 @@ AM_CONDITIONAL([SHLIBS_IN_BINDIR],
@end smallexample
@item
-You may also need to add a couple of variable assignments to your
address@hidden
+In your @file{Makefile.am}, for every library @command{libfoo} that gets
+installed in, say, @file{$(libdir)}, you add:
+
address@hidden
+if RELOCATABLE_VIA_LD
+libfoo_la_LDFLAGS = `$(RELOCATABLE_LDFLAGS) $(libdir)`
+endif
address@hidden example
+
address@hidden
+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
address@hidden to its directory, e.g.
address@hidden to its directory, e.g.
@example
-RELOCATABLE_CONFIG_H_DIR='$(top_builddir)/src'
+RELOCATABLE_CONFIG_H_DIR = $(top_builddir)/src
@end example
@end enumerate
diff --git a/m4/relocatable.m4 b/m4/relocatable.m4
index faa23f2..bbfb44c 100644
--- a/m4/relocatable.m4
+++ b/m4/relocatable.m4
@@ -1,4 +1,4 @@
-# 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,
@@ -22,18 +22,28 @@ dnl The guts of gl_RELOCATABLE. Needs to be expanded only
once.
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
@@ -74,13 +84,17 @@ changequote(,)dnl
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,address@hidden@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" ;;
@@ -88,6 +102,13 @@ changequote([,])dnl
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
@@ -104,7 +125,7 @@ changequote([,])dnl
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.
diff --git a/modules/relocatable-prog b/modules/relocatable-prog
index d984314..4111665 100644
--- a/modules/relocatable-prog
+++ b/modules/relocatable-prog
@@ -5,6 +5,7 @@ properly when copied to an arbitrary directory.
Files:
build-aux/config.libpath
build-aux/reloc-ldflags
+build-aux/libtool-reloc
doc/relocatable.texi
lib/relocatable.h
lib/relocatable.c
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Re: relocatable-prog: Use $ORIGIN trick on more platforms,
Bruno Haible <=