Edit

kc3-lang/gnulib/doc/relocatable-maint.texi

Branch :

  • Show log

    Commit

  • Author : Bruno Haible
    Date : 2024-10-27 17:01:29
    Hash : c36a0f21
    Message : doc: Add a module index. * doc/Makefile (undocumented-modules.texi): New rule. (%.info, %.html, %.dvi, %.pdf): Depend on undocumented-modules.texi. (mostlyclean): Remove also *.m and *.tmp. (force): New rule. * doc/*.texi: Add module index entries. * doc/*/*.texi: Likewise.

  • doc/relocatable-maint.texi
  • @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