#18 Installation does not honor prefix

v0.7.x
open-fixed
CJP
5
2008-07-07
2007-10-27
Jan Hudec
No

It is often important to install with different prefix than what was specified to configure.

To achieve this, the paths generated by autoconf are expanded at make time, so:

make install prefix=/different/prefix

or

make install DESTDIR=/destdir

(normally prefix is defined by autoconf as ${DESTDIR}/usr/local)
will correctly install under the specified path.

However the definition of usdatadir at configure.ac:243 (as of revision 1.20 of that file) violates this.

The definition is written as:

usdatadir="${prefix}/share/ultimatestunts/"

which gets expanded by shell at configure time. It should be written as:

usdatadir='${prefix}/share/ultimatestunts/'

It should be even better to use:

usdatadir='${datadir}/ultimatestunts/'

because datadir is by default defined to '${prefix}/share' but configurable with option.

Discussion

  • CJP
    CJP
    2007-10-29

    Logged In: YES
    user_id=595430
    Originator: NO

    There is one problem with make-time prefix changes, and this problem is the configuration file ultimatestunts.conf.

    Ultimate Stunts has no "standard" location of its data files. Instead, it finds the location of the data files by reading the ultimatestunts.conf file. The file ultimatestunts.conf itself is found by searching several standard locations. For details about this, see:

    http://www.ultimatestunts.nl/documentation/en/general.htm
    (section "Location of the configuration file")

    In order to make an installation from source work without problems, ultimatestunts.conf needs to be placed in a standard location where Ultimate Stunts can find it, and it needs to contain the directory location where the data files are installed.

    Currently, ultimatestunts.conf is generated at configure-time from ultimatestunts.conf.in. So, at configure-time, the location of the data files is filled in in ultimatestunts.conf. When you change the location of the datafiles later at make-time, the system won't work anymore because ultimatestunts.conf will point to the wrong location.

    I am always open to better alternatives, but I would like to know how you would solve this aspect of the problem.

     
  • CJP
    CJP
    2007-10-29

    • assigned_to: nobody --> cornware-cjp
     
  • CJP
    CJP
    2008-01-30

    • status: open --> open-fixed
     


  • 2008-02-16

    Logged In: YES
    user_id=1449057
    Originator: NO

    In addition to the ${prefix}/share -> ${datadir} change, ${sysconfdir} should be used instead of ${prefix}/etc.

    DESTDIR is used for installing into a temporary directory, it doesn't need to be able to run from that directory.

     
  • Jan Hudec
    Jan Hudec
    2008-02-17

    Logged In: YES
    user_id=977494
    Originator: YES

    Indeed, if I set either $prefix or $DESTDIR at make install time, I /want/ the program to still look for the files in the path specified at configure time. It is used in cases, where I need to install the files into a place that is, for wantever reason, different from what will be seen by the program at runtime. The reason might be:

    - Using GNU stow (http://www.gnu.org/software/stow). I install the program into /usr/local/stow/programname and use stow to create symlinks to /usr/local. So the $prefix must be /usr/local -- that's what the program will see at runtime -- except at install time, when it must be /usr/local/stow/programname

    - Creating packages. The package builder needs to install the data under a temporary directory and packs everything under that directory, but it will be extracted to root when installing the package. DESTDIR is normally used for this.

    - Installing on a server. The root for the client machine is installed in some directory on the server, so if installing on the server (perhaps because the client does not have a compiler installed or does not actually have permission to write the directories), the installation needs to go to a different directory, than the program will see when running on the client.

    All these cases need the $prefix and $DESTDIR be overridable at install time, while the configure (or make; that does not matter) time values be compiled in the program and/or it's main configuration file.

     
  • CJP
    CJP
    2008-02-18

    • status: open-fixed --> open
     
  • CJP
    CJP
    2008-02-18

    Logged In: YES
    user_id=595430
    Originator: NO

    So, if I understand your posts correctly, configure should do the following things:

    (1) the location where data files are stored should be '${datadir}/ultimatestunts/', with ${datadir} un-evaluated, so that it can be changed at make-time

    (2) The datadir location as stored in ultimatestunts.conf should be "${datadir}/ultimatestunts/", with ${datadir} evaluated at configure-time.

    (3) ultimatestunts.conf should be installed in ${sysconfdir}, which should be evaluated at make-time

    (4) One of the locations where Ultimate Stunts searches for ultimatestunts.conf is now ${prefix}/etc, with ${prefix} evaluated at configure-time, but it should be ${sysconfdir}, which should be evaluated at configure-time

    All of this can be done, but there are still some issues to be solved:
    * ${datadir} and ${sysconfdir} are not always present at configure-time, so we need to have reasonable default values if the user doesn't supply them. Preferable WITHOUT a dirty hack like lines 10..13 in the current (version 1.22) configure.ac

    * I need to be sure that ${datadir} and ${sysconfdir} get the configure-time values by default at make-time, so that things work if a user doesn't override them at make-time

     
  • Jan Hudec
    Jan Hudec
    2008-02-19

    Logged In: YES
    user_id=977494
    Originator: YES

    Yes, you do understand correctly.

    As of datadir and sysconfdir, the generated configure script contains the snippet (line 337 in configure in ):

    # Installation directory options.
    # These are left unexpanded so users can "make install exec_prefix=/foo"
    # and all the variables that are supposed to be based on exec_prefix
    # by default will actually change.
    # Use braces instead of parens because sh, perl, etc. also accept them.
    bindir='${exec_prefix}/bin'
    sbindir='${exec_prefix}/sbin'
    libexecdir='${exec_prefix}/libexec'
    datadir='${prefix}/share'
    sysconfdir='${prefix}/etc'
    sharedstatedir='${prefix}/com'
    localstatedir='${prefix}/var'
    libdir='${exec_prefix}/lib'
    includedir='${prefix}/include'
    oldincludedir='/usr/include'
    infodir='${prefix}/info'
    mandir='${prefix}/man'

    therefore: the datadir and sysconfdir are always defined.

    As for the prefix, autoconf substitutes the final value much later in the process. The point being, that you must not attempt to expand $prefix, nor any of the variables depending on it, at configure time, but at make time. There are two reasons for that:
    - You can't actually do it. Make expands variables recursively, but shell does not. And these variables normally form a long dependency chain.
    - Standard way of doing it is in makefile. While I can't think of a case where I'd need to override prefix at build-time, it's traditionally expanded there and users come to expect it.

    Yes, it means expanding the variable to ultimatestunts.conf manually via sed instead of via the handy AC_CONFIG_FILE mechanism (which uses sed anyway), but since you expand just two variables, this should do:

    usdatadir = @usdatadir@

    ultimatestunts.conf: ultimatestunts.conf.in
    sed 's/[@]PACKAGE_VERSION@/$(PACKAGE_VERSION)/;s/[@]usdatadir@/$(usdatadir)/' < $< > $@

    (note: I failed to type in a tab, so you'll need to fix up the spacing. I also didn't test it, so there might be a typo or bug or something)

    Quoting from the Autoconf manual (section Installation Directory Variables):

    This behavior is mandated by the GNU coding standards, so that when the user runs:
    `make'
    she can still specify a different prefix from the one specified to
    `configure', in which case, if needed, the package shall hard code
    dependencies corresponding to the make-specified prefix.

    `make install'
    she can specify a different installation location, in which case
    the package _must_ still depend on the location which was compiled
    in (i.e., never recompile when `make install' is run). This is an
    extremely important feature, as many people may decide to install
    all the files of a package grouped together, and then install
    links from the final locations to there.

    In order to support these features, it is essential that `datadir' remains being defined as `${prefix}/share' to depend upon the current value of `prefix'.
    A corollary is that you should not use these variables except in Makefiles. For instance, instead of trying to evaluate `datadir' in `configure' and hard-coding it in Makefiles using e.g., `AC_DEFINE_UNQUOTED(DATADIR, "$datadir")', you should add `-DDATADIR="$(datadir)"' to your `CPPFLAGS'.

     
  • CJP
    CJP
    2008-06-09

    Logged In: YES
    user_id=595430
    Originator: NO

    It should be fixed now in the CVS tree; please confirm that it works as you want. If it doesn't, I can still fix it before the next release.

    I don't think your commend "Yes, you do understand correctly" was correct. Based on your other comments, I found out that my points (2) and (4) contradict with the GNU coding standards. I think that what I made now is better:

    * You can set anything at configure time; these will be the defaults for make time.
    * You can override anything at make time; the make-time values will be hard-coded in the code and the .conf file. They will also be the defaults for make install time.
    * You can override anything at make install time; the hard-coded values will still be the ones at make time, but the program will be installed at the make install given locations.

    For this to be possible, ultimatestunts.conf is now generated at make time with a sed command (without slashes, as the autoconf manual says). Also, SYSCONFDIR cannot be in config.h, as config.h is generated at configure time. Therefore, SYSCONFDIR is added as a -D flag to the compilation commandline.

     
  • CJP
    CJP
    2008-07-07

    • status: open --> open-fixed
     
  • Jan Hudec
    Jan Hudec
    2009-03-13

    Hello,

    I believe this was already explained, but let me reiterate. There are cases (packages, stow, NFS mounts, etc.), where the files need to be copied into temporary location by make install and will be moved into the final location by some post-install step. Therefore the user running make install needs an option to set that temporary location.

    This is normally assured by autoconf defering the paths expansion to the Makefile and prefixing them with $(DESTDIR), which is normally empty. So the Makefile normally contains settings like:

    DESTDIR=
    prefix=/usr/local
    bindir=${prefix}/bin
    libdir=${prefix}/lib
    datadir=${prefix}/share
    sysconfdir=${prefix}/etc

    and so on. For normal user there's no difference, because he will not override those variables, so they will have the same value as they had at configure time and all is well. But e.g. the Debian package builder needs to run:

    make install DESTDIR=./debian/tmp

    and than tars up the ./debian/tmp directory. Dpkg will later untar it into /, so ultimatestunts will find it's config in the path specified at configure time, but the install command had to put in in different location. The stow case is similar, but since the extra path components are inserted after the original prefix, the command is:

    make install prefix=/usr/local/stow/ultimatestunts

    instead. Note, that this works properly for all the files installed -- except ultimatestunts.conf. Also note, that it will really not affect regular users, who simply run

    make install

    so the prefix will be set to whatever it was at configure time and there will be no change for them at all.

    Thanks,
    Jan