| @node Supporting Relocation | |
| @section Supporting Relocation | |
| It has been a pain for many users of GNU packages for a long time that | |
| packages are not relocatable. It means a user cannot copy a program, | |
| installed by another user on the same machine, to his home directory, | |
| and have it work correctly (including i18n). So many users need to go | |
| through @code{configure; make; make install} with all its | |
| dependencies, options, and hurdles. | |
| Red Hat, Debian, and other binary distributions solve the ``ease of | |
| installation'' problem, but they hardwire path names, usually to | |
| @file{/usr} or @file{/usr/local}. This means that users need root | |
| privileges to install a binary package, and prevents installing two | |
| different versions of the same binary package. | |
| A relocatable program can be moved or copied to a different location | |
| on the file system. It is possible to make symlinks to the installed | |
| and moved programs, and invoke them through the symlink. It is | |
| possible to do the same thing with a hard link @emph{only} if the hard | |
| link file is in the same directory as the real program. | |
| @mindex relocatable-prog | |
| The @code{relocatable-prog} module aims to ease the process of making a | |
| GNU program relocatable. It helps overcome two obstacles. First, it aids | |
| with relocating the hard-coded references to absolute file names that | |
| GNU programs often contain. These references must be fixed up at | |
| runtime if a program is to be successfully relocated. The | |
| @code{relocatable-prog} module provides a function @code{relocate} that | |
| does this job. | |
| Second, the loader must be able to find shared libraries linked to | |
| relocatable executables or referenced by other shared libraries linked | |
| to relocatable executables. The @code{relocatable-prog} module helps out | |
| here in a platform-specific way: | |
| @itemize | |
| @item | |
| 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, macOS, FreeBSD, NetBSD, OpenBSD, | |
| Solaris, Haiku. | |
| @item | |
| On other Unix systems, it installs a trampoline executable. The trampoline | |
| sets the environment variable that controls shared library searching | |
| (usually @env{LD_LIBRARY_PATH}) and then invokes the real executable. | |
| This applies to operating systems such as AIX, HP-UX, or Minix. | |
| @item | |
| On Windows, the executable's own directory is searched for libraries, | |
| so installing shared libraries into the executable's directory is | |
| sufficient. | |
| @end itemize | |
| You can make your program relocatable by following these steps: | |
| @enumerate | |
| @item | |
| @mindex relocatable-lib | |
| @mindex relocatable-lib-lgpl | |
| Import the @code{relocatable-prog} module. For libraries, use the | |
| @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}). | |
| @item | |
| In every program, add to @code{main} as the first statement (even | |
| before setting the locale or doing anything related to libintl): | |
| @example | |
| set_program_name (argv[0]); | |
| @end example | |
| The prototype for this function is in @file{progname.h}. | |
| @item | |
| If you want your code to be portable to platforms that do not support | |
| automatic initialization, call @code{set_relocation_prefix}. | |
| @item | |
| Everywhere where you use a constant pathname from installation-time, | |
| wrap it in @code{relocate} so it gets translated to the run-time situation. | |
| Example: | |
| @example | |
| bindtextdomain (PACKAGE, LOCALEDIR); | |
| @end example | |
| @noindent | |
| becomes: | |
| @example | |
| bindtextdomain (PACKAGE, relocate (LOCALEDIR)); | |
| @end example | |
| The prototype for this function is in @file{relocatable.h}. | |
| There is also a variant of this function, named @code{relocate2}, that | |
| makes it easy to reclaim the memory allocated by the call. | |
| @item | |
| The @code{set_program_name} function can also configure some | |
| additional libraries to relocate files that they access, by defining | |
| corresponding C preprocessor symbols to 1. The libraries for which | |
| this is supported and the corresponding preprocessor symbols are: | |
| @table @asis | |
| @item libcharset | |
| @code{DEPENDS_ON_LIBCHARSET} | |
| @item libiconv | |
| @code{DEPENDS_ON_LIBICONV} | |
| @item libintl | |
| @code{DEPENDS_ON_LIBINTL} | |
| @end table | |
| Defining the symbol for a library makes every program in the package | |
| depend on that library, whether the program really uses the library or | |
| not, so this feature should be used with some caution. | |
| @item | |
| @mindex relocatable-script | |
| If your package installs shell scripts, also import the | |
| @code{relocatable-script} module. Then, near the beginning of each | |
| shell script that your package installs, add the following: | |
| @smallexample | |
| @@relocatable_sh@@ | |
| prefix="@@prefix@@" | |
| exec_prefix="@@exec_prefix@@" # usually needs $prefix. | |
| datarootdir="@@datarootdir@@" # usually needs $prefix. | |
| if test "@@RELOCATABLE@@" = yes; then | |
| bindir="@@bindir@@" | |
| orig_installdir="$bindir" # see Makefile.am's *_SCRIPTS variables | |
| func_find_curr_installdir # determine curr_installdir | |
| func_find_prefixes | |
| relocate () @{ | |
| echo "$1/" \ | |
| | sed -e "s%^$@{orig_installprefix@}/%$@{curr_installprefix@}/%" \ | |
| | sed -e 's,/$,,' | |
| @} | |
| else | |
| relocate () @{ | |
| echo "$1" | |
| @} | |
| fi | |
| # Get some relocated directory names. | |
| sysconfdir=`relocate "@@sysconfdir@@"` # usually needs $prefix. | |
| some_datadir=`relocate "@@datadir@@/something"` # usually needs $datarootdir. | |
| bindir=`relocate "@@bindir@@"` # usually needs $exec_prefix, hence $prefix. | |
| @end smallexample | |
| You must adapt the definition of @code{orig_installdir}, depending on | |
| where the script gets installed. Also, at the end, instead of | |
| @code{sysconfdir} and @code{some_datadir}, transform those variables | |
| that you need. | |
| @item | |
| @mindex relocatable-perl | |
| If your package installs Perl scripts, also import the | |
| @code{relocatable-perl} module. Then, near the beginning of each | |
| Perl script that your package installs, add the following: | |
| @smallexample | |
| @@relocatable_pl@@ | |
| if ("@@RELOCATABLE@@" eq "yes") @{ | |
| my $exec_prefix = "@@exec_prefix@@"; | |
| my $orig_installdir = "@@bindir@@"; # see Makefile.am's *_SCRIPTS variables | |
| my ($orig_installprefix, $curr_installprefix) = | |
| find_prefixes($orig_installdir, find_curr_installdir()); | |
| # the subroutine is defined whether or not the enclosing block is executed | |
| sub relocate @{ | |
| my ($dir) = @@_; | |
| if ("@@RELOCATABLE@@" eq "yes") @{ | |
| $dir =~ s%^$orig_installprefix/%$curr_installprefix/%; | |
| $dir =~ s,/$,,; | |
| @} | |
| return $dir; | |
| @} | |
| @} | |
| # Get some relocated directory names. | |
| # (The gnulib module 'configmake' can help with this.) | |
| $sysconfdir = relocate("@@sysconfdir@@"); | |
| $some_datadir = relocate(@@datadir@@/something"); | |
| @end smallexample | |
| You must adapt the definition of @code{$orig_installdir}, depending on | |
| where the script gets installed. Also, at the end, instead of | |
| @code{sysconfdir} and @code{some_datadir}, transform those variables | |
| that you need. | |
| @item | |
| In your @file{Makefile.am}, for every program @command{foo} that gets | |
| installed in, say, @file{$(bindir)}, you add: | |
| @example | |
| foo_CPPFLAGS = -DINSTALLDIR=$(bindir_c_make) | |
| if RELOCATABLE_VIA_LD | |
| foo_LDFLAGS = `$(RELOCATABLE_LDFLAGS) $(bindir)` | |
| endif | |
| @end example | |
| Similarly, if a program @command{foo} gets installed in @file{$(pkglibdir)}, | |
| you add: | |
| @example | |
| foo_CPPFLAGS = -DINSTALLDIR=$(pkglibdir_c_make) | |
| if RELOCATABLE_VIA_LD | |
| foo_LDFLAGS = `$(RELOCATABLE_LDFLAGS) $(pkglibdir)` | |
| endif | |
| @end example | |
| The Makefile variables @code{bindir_c_make} or @code{pkglibdir_c_make} | |
| get defined by the Autoconf macros | |
| @code{gl_BUILD_TO_HOST_BINDIR} or @code{gl_BUILD_TO_HOST_PKGLIBDIR}, | |
| respectively. | |
| These Autoconf macros are defined in the file @code{m4/build-to-host.m4}. | |
| You need to | |
| @itemize @bullet | |
| @item | |
| Import this file @code{m4/build-to-host.m4} into your package, for example | |
| by using of a command like @samp{gnulib-tool --copy m4/build-to-host.m4}. | |
| @item | |
| Invoke the corresponding macro(s) from your package's @file{configure.ac}. | |
| @end itemize | |
| @item | |
| When building gnulib to use with a relocatable library, you need to | |
| define the preprocessor symbol @code{IN_LIBRARY}. | |
| You may also want to build with @code{ENABLE_COSTLY_RELOCATABLE}, in which case | |
| you will also need to define @code{INSTALLDIR}. | |
| The following fragment can be added to an override @code{Makefile.am} used | |
| to build gnulib (@pxref{Modified build rules}). | |
| @example | |
| AM_CPPFLAGS += -DIN_LIBRARY -DENABLE_COSTLY_RELOCATABLE | |
| if SHLIBS_IN_BINDIR | |
| AM_CPPFLAGS += -DINSTALLDIR=$(bindir_c_make) | |
| else | |
| AM_CPPFLAGS += -DINSTALLDIR=$(libdir_c_make) | |
| endif | |
| @end example | |
| @code{SHLIBS_IN_BINDIR} is defined in @file{configure.ac} as follows: | |
| @smallexample | |
| AM_CONDITIONAL([SHLIBS_IN_BINDIR], | |
| [case "$host_os" in mingw* | cygwin*) true;; *) false;; esac]) | |
| @end smallexample | |
| @item | |
| 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 @code{RELOCATABLE_LIBRARY_PATH} to a colon-separated list | |
| of those libraries' directories, e.g. | |
| @example | |
| RELOCATABLE_LIBRARY_PATH = $(libdir) | |
| @end example | |
| If your @file{config.h} is not in @file{$(top_builddir)}, then set | |
| @code{RELOCATABLE_CONFIG_H_DIR} to its directory, e.g. | |
| @example | |
| RELOCATABLE_CONFIG_H_DIR = $(top_builddir)/src | |
| @end example | |
| @end enumerate |