# HG changeset patch # User Bruno Haible # Date 1551716709 -3600 # Node ID 770a5696761eed75020766855da3941b38ae7b6d # Parent 9e8fb35d403237695221516d5f53f751e05f441b 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 -r 9e8fb35d4032 -r 770a5696761e ChangeLog --- a/ChangeLog Mon Mar 04 17:25:04 2019 +0100 +++ b/ChangeLog Mon Mar 04 17:25:09 2019 +0100 @@ -1,3 +1,20 @@ +2019-03-04 Bruno Haible + + 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 relocatable-prog: Revert "Use wrapper-free installation on Mac OS X." diff -r 9e8fb35d4032 -r 770a5696761e build-aux/libtool-reloc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/build-aux/libtool-reloc Mon Mar 04 17:25:09 2019 +0100 @@ -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 , 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 . + +# 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 -r 9e8fb35d4032 -r 770a5696761e build-aux/reloc-ldflags --- a/build-aux/reloc-ldflags Mon Mar 04 17:25:04 2019 +0100 +++ b/build-aux/reloc-ldflags Mon Mar 04 17:25:09 2019 +0100 @@ -53,6 +53,7 @@ ;; esac +origin_token= case "$host_os" in linux* | gnu* | kfreebsd* | \ freebsd* | dragonfly* | \ @@ -60,54 +61,59 @@ 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 . - 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 . + 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 -r 9e8fb35d4032 -r 770a5696761e doc/relocatable-maint.texi --- a/doc/relocatable-maint.texi Mon Mar 04 17:25:04 2019 +0100 +++ b/doc/relocatable-maint.texi Mon Mar 04 17:25:09 2019 +0100 @@ -38,13 +38,8 @@ 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 @@ -63,7 +58,10 @@ @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}). @@ -233,20 +231,29 @@ @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 diff -r 9e8fb35d4032 -r 770a5696761e m4/relocatable.m4 --- a/m4/relocatable.m4 Mon Mar 04 17:25:04 2019 +0100 +++ b/m4/relocatable.m4 Mon Mar 04 17:25:09 2019 +0100 @@ -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 @@ 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 @@ 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 + # . + 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 @@ 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 @@ 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 -r 9e8fb35d4032 -r 770a5696761e modules/relocatable-prog --- a/modules/relocatable-prog Mon Mar 04 17:25:04 2019 +0100 +++ b/modules/relocatable-prog Mon Mar 04 17:25:09 2019 +0100 @@ -5,6 +5,7 @@ Files: build-aux/config.libpath build-aux/reloc-ldflags +build-aux/libtool-reloc doc/relocatable.texi lib/relocatable.h lib/relocatable.c