bug-automake
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [un]install-*-local/install-*-hook does not honor DESTDIR


From: Alexandre Duret-Lutz
Subject: Re: [un]install-*-local/install-*-hook does not honor DESTDIR
Date: 26 Jan 2005 20:45:10 +0100
User-agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/21.3.50

>>> "Eugene" == Eugene Crosser <address@hidden> writes:

 Eugene> Allow me to argue some more

Thanks for doing this!  I may not actually agree, but I find
this discussion very helpful to highlight what needs to be
documented and to find examples to illustrate this.

[...]

 >> Actually I'd rather change the documentation and use another,
 >> better illustration for install-*-local.  Using hard-coded
 >> install-paths always seems an error to me.  (The actual example
 >> in the doc would be better written as `sysconf_DATA = afile'.)

 Eugene> I thought that install*local are specially designed to
 Eugene> cover such cases when "proper" directory structure does
 Eugene> not fit.

I surmise that idea came from the example in the documentation
you mentioned in your first post?  The real purpose of *-local
and *-hook is simply to allow you to augment the existing rules.
There are many reasons to do so.  For instance Automake
currently does not allow you to install a directory
(recursively), it won't help either if you need to modify a file
in the install tree (think about install-info that registers and
unregister files in $(infodir)/dir).

 Eugene> I imagine perfectly legal use of absolute paths, e.g.,
 Eugene> when you want to install a startup script into
 Eugene> /etc/init.d/ & /etc/rcX.d/ or, say, a log rotation
 Eugene> script into /etc/logrotate.d directory.  These
 Eugene> locations are system-wide and have no relation to your
 Eugene> package's installation prefix.

Are there real packages that do such things during `make
install'?  (Not meaning to be flip; a serious question.  I'm
unfortunately not installing such system packages by hand so I
lack the experience.)  I'd find this highly inappropriate: the
layout of /etc is so machine-dependent that installing anything
here seems better left to the installer.  For a package that
installs its own config script, using $(sysconfdir) will allow
the installer to set --sysconf=/etc if needed.  For packages
that needs to populate the directory of other tools, or update
configuration of other tools, I believe a note in `INSTALL' is
far safer (for the installer and for the maintainer).

You could also use install-*-local to print a message.  Texinfo
has a similar problem: it comes with a file, `texinfo.tex' that
should be installed in the Tex tree.  Here is how it does:

install-data-local:
        @echo
        @echo "WARNING: If your texmf tree does not already contain"
        @echo "         up-to-date versions, you must install"
        @echo "             texinfo.tex and txi-??.tex manually,"
        @echo "         perhaps in TEXMF/tex/texinfo/,"
        @echo "         where TEXMF is a root of your TeX tree."
        @echo "         See doc/README for some considerations."
        @echo "         You can run make TEXMF=/your/texmf install-tex to do 
this."
        @echo
        @echo "         You may also need to install epsf.tex and (if you"
        @echo "         use pdftex) pdfcolor.tex in TEXMF/tex/generic/dvips"
        @echo "         and TEXMF/pdftex/plain/misc/pdfcolor.tex respectively,"
        @echo "         if your TeX installation did not include them."


 Eugene> Another case when absolute paths may be legitimately introduced is
 Eugene> when your package is a "plugin module" for another package that is
 Eugene> already installed on your system.  For instance, you may be building a
 Eugene> shared object that is going to be installed into location provided by
 Eugene> *other* package (e.g. via <package>-config script or pkgconfig).  This
 Eugene> needs to be independent of locally specified installation prefix; and
 Eugene> currently it breaks "make distcheck".  If "make distcheck" used
 Eugene> DESTDIR it would work fine.

There is a nice way to fix this, so let's take an example.

Assume you want to install shared library that is a Python
extension module.  If you ask Python where to install the
library, it will answer this:

% python -c 'from distutils import sysconfig; print 
sysconfig.get_python_lib(1,0)'
/usr/lib/python2.3/site-packages

If you indeed use this absolute path to install your shared
library, non-root users will not be able to install the package,
hence distcheck fails.

Let's do better.

| `get_python_lib([plat_specific[, standard_lib[, prefix]]])'
|      Return the directory for either the general or platform-dependent
|      library installation.  If PLAT_SPECIFIC is true, the
|      platform-dependent include directory is returned; if false or
|      omitted, the platform-independent directory is returned.  If
|      PREFIX is given, it is used as either the prefix instead of
|      `PREFIX', or as the exec-prefix instead of `EXEC_PREFIX' if
|      PLAT_SPECIFIC is true.  If STANDARD_LIB is true, the directory for
|      the standard library is returned rather than the directory for the
|      installation of third-party extensions.

% python -c 'from distutils import sysconfig; print 
sysconfig.get_python_lib(1,0,"${exec_prefix}")'
${exec_prefix}/lib/python2.3/site-packages

If you use this new path:

  1) root users can install your package with the same --prefix
     as Python (you get the behavior of the previous attempt)

  2) non-root users can install your package too, they will have
     the extension module in a place that is not searched by
     Python but they can work around this using environment
     variables (and if you installed scripts that use this
     shared library, as in a package I maintain, it's easy to
     tell Python were to look in the beginning of your script,
     so the script works in both situations).

The above path computation is what the macro AM_PATH_PYTHON does.

Of course not all tools are as advanced as Python regarding that
substitution of PREFIX.  So another strategy is to figure the
part of the of the installation directory that must be
preserved.  For instance here is how AM_PATH_LISPDIR computes
$(lispdir):

  $EMACS -batch -q -eval '(while load-path
                             (princ (concat (car load-path) "\n"))
                             (setq load-path (cdr load-path)))' >conftest.out
  lispdir=`sed -n \
    -e 's,/$,,' \
    -e 
'/.*\/lib\/x*emacs\/site-lisp$/{s,.*/lib/\(x*emacs/site-lisp\)$,${libdir}/\1,;p;q;}'
 \
    -e 
'/.*\/share\/x*emacs\/site-lisp$/{s,.*/share/\(x*emacs/site-lisp\),${datadir}/\1,;p;q;}'
 \
    conftest.out`

I.e., it just picks the first directory that looks like
*/lib/*emacs/site-lisp or */share/*emacs/site-lisp in the search
path of emacs, and then substitutes ${libdir} or ${datadir}
appropriately.

The emacs case looks complicated because it processes a list and
expect two possible layouts, otherwise it's easy, and the
benefit for users are really worth it.

 >> If a user wants to install a package on his account, he
 >> will use something like `./configure --prefix ~/usr'.  However
 >> if `make install' tries to write to some hard-coded directory
 >> elsewhere the account, it will fail.  So `make distcheck' should
 >> fail too.

 Eugene> Again, I can see a perfectly legal case when system-wide --prefix is
 Eugene> specified and then "make install DESTDIR=..." is run as *non-root*.
 Eugene> It is building of a package for some OS distribution.  A packager may
 Eugene> want to run non-root for safety, and to be sure that nothing has been
 Eugene> installed into a wrong location (outside DESTDIR).

I agree.  However distcheck already tests --prefix+DESTDIR
installations.  It has done so since version 1.7.  Or did I miss
this point entirely? (It's well possible, I've accumulated a
huge sleep debt over the last two weeks.)

I think this also answers Mark's concern.  Unless I
misunderstood him, he simply want DESTDIR to be supported
correctly, and the current distcheck test ensures that.
-- 
Alexandre Duret-Lutz





reply via email to

[Prev in Thread] Current Thread [Next in Thread]