Next: func, Previous: Visual Studio Compatibility, Up: Particular Modules [Contents][Index]
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 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 /usr or /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 only if the hard link file is in the same directory as the real program.
The 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
relocatable-prog
module provides a function 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 relocatable-prog
module helps out
here in a platform-specific way:
LD_LIBRARY_PATH
) and then invokes the real executable.
This approach does not always work. On OpenBSD and OpenServer, prereleases of Libtool 1.5 put absolute file names of libraries in executables, which prevents searching any other locations.
You can make your program relocatable by following these steps:
relocatable-prog
module.
main
as the first statement (even
before setting the locale or doing anything related to libintl):
set_program_name (argv[0]);
The prototype for this function is in progname.h.
relocate
so it gets translated to the run-time situation.
Example:
bindtextdomain (PACKAGE, LOCALEDIR);
becomes:
bindtextdomain (PACKAGE, relocate (LOCALEDIR));
The prototype for this function is in relocatable.h.
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:
DEPENDS_ON_LIBCHARSET
DEPENDS_ON_LIBICONV
DEPENDS_ON_LIBINTL
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.
relocatable-script
module. Then, near the beginning of each
shell script that your package installs, add the following:
@relocatable_sh@ if test "@RELOCATABLE@" = yes; then exec_prefix="@exec_prefix@" 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@"` some_datadir=`relocate "@datadir@/something"`
You must adapt the definition of orig_installdir
, depending on
where the script gets installed. Also, at the end, instead of
sysconfdir
and some_datadir
, transform those variables
that you need.
relocatable-perl
module. Then, near the beginning of each
Perl script that your package installs, add the following:
@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()); sub relocate { # the subroutine is defined whether or not the enclosing block is executed my ($dir) = @_; if ("@RELOCATABLE@" eq "yes") { $dir =~ s%^$orig_installprefix/%$curr_installprefix/%; $dir =~ s,/$,,; } return $dir; } } # Get some relocated directory names. $sysconfdir = relocate("@sysconfdir@"); $some_datadir = relocate(@datadir@/something");
You must adapt the definition of $orig_installdir
, depending on
where the script gets installed. Also, at the end, instead of
sysconfdir
and some_datadir
, transform those variables
that you need.
foo
that gets
installed in, say, $(bindir), you add:
foo_CPPFLAGS = -DINSTALLDIR=\"$(bindir)\" if RELOCATABLE_VIA_LD foo_LDFLAGS = `$(RELOCATABLE_LDFLAGS) $(bindir)` endif
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 RELOCATABLE_LIBRARY_PATH to a colon-separated list of those libraries’ directories, e.g.
RELOCATABLE_LIBRARY_PATH='$(libdir)'
If your config.h is not in $(top_builddir), then set RELOCATABLE_CONFIG_H_DIR to its directory, e.g.
RELOCATABLE_CONFIG_H_DIR='$(top_builddir)/src'
Next: func, Previous: Visual Studio Compatibility, Up: Particular Modules [Contents][Index]