]> Savannah Git Hosting - gnulib.git/commitdiff
relocatable-prog: Use wrapper-free installation on Mac OS X, take 2.
authorBruno Haible <bruno@clisp.org>
Mon, 4 Mar 2019 16:25:09 +0000 (17:25 +0100)
committerBruno Haible <bruno@clisp.org>
Mon, 4 Mar 2019 16:28:15 +0000 (17:28 +0100)
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.

ChangeLog
build-aux/libtool-reloc [new file with mode: 0755]
build-aux/reloc-ldflags
doc/relocatable-maint.texi
m4/relocatable.m4
modules/relocatable-prog

index 580f7e69c79204d6165d0a1976070c54eae7f063..96083f3ea7c99dc98fc8ffba2bbbaf67e425ae42 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+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."
diff --git a/build-aux/libtool-reloc b/build-aux/libtool-reloc
new file mode 100755 (executable)
index 0000000..9d899ab
--- /dev/null
@@ -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 <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
index 3aed3308dcd1ccdb430e3c913399ba23be2cb536..625fef249fd19ffb942e46fd38043c7da8c6d393 100755 (executable)
@@ -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
index 200fcab349563415c5378164cc6f26b9c06be9fc..d39159810899dc3871964f7ebcdd2b169869e4b6 100644 (file)
@@ -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.
-
-@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 @@ You can make your program relocatable by following these steps:
 @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 @@ AM_CONDITIONAL([SHLIBS_IN_BINDIR],
 @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
index faa23f2460868a2d91abfa2d69b48be2b5fe3249..bbfb44ccfe152c47a6cfd3aae1d9cecbf937e2bd 100644 (file)
@@ -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,_@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" ;;
@@ -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.
index d9843142edc566387440d948101069a8a4b4816f..4111665c339f1393dc6d0ca258207ee5a3ffaa7e 100644 (file)
@@ -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