tags:

views:

107

answers:

4

Programs on Linux install data for programs into $PREFIX/share/programname, how does the program know where that is, does it need to be compiled in?

Would it be suitable to assume that the binary is in $PREFIX/bin, and use that to determine $PREFIX?

This only needs to work on Linux, and specifically, I am using C.

+2  A: 

It depends entirely on the program. A common pattern is to define PREFIX as a preprocessor directive. GNU autoconf has standard names and allows them to be overridden at configure time.

p00ya
How many programs obey -DPREFIX at all, without a build configuration? How many autoconf configured projects ever pass -DPREFIX? Sorry, -1.
Tim Post
@tpost: If you're using autoconf, use the more specific `datadir` rather than PREFIX. Using preprocessor symbols is a suggested behavior, see info "(autoconf) Installation Directory Variables". perl-ish things use -Dprefix, and I never made any claims about packages "without a build configuration".
p00ya
A: 

One of the files that autotools creates is config.h, and it's in here that the various paths are stored. You can customize config.h.in to add additional paths for your application's use.

Ignacio Vazquez-Abrams
+1  A: 

As p00ya has pointed out, it depends on the program. I'd say most programs have a compile-time default, and some also use an environment variable to locate their data files; the environment variable technique can be handy if you're not distributing the sources of your software and you don't expect administrators or package maintainers to recompile it for their system. If you're planning on using an environment variable, you should probably generate wrapper scripts with the proper paths at install-time, or provide your users with appropriate instructions (i.e. what to add to their shell init script).

rz0
+1  A: 

Lets take a hypothetical:

You are compiling the program foo that needs a version of libfoo that is newer than the one provided by the system. You lack adequate privileges to upgrade the system libfoo, additionally the program wants to deposit files into /etc, where you don't have permission to write. How could you compile and install the program?

Most build configuration software offers a lot more than just --prefix, many give you the ability to specify the system configuration location (--sysconfdir), the location to look for shared libraries by default (--libdir), the location to deposit compiled executables (--bindir) and other 'all in one' shortcuts like --datarootdir.

In fact:

tpost@tpost-desktop:~/Desktop/oss-projects/srce/srce.hg$ ./configure --help                                                                                                                                                       
`configure' configures SRCE 1.0.9 to adapt to many kinds of systems.                                                                                                                                                              

Usage: ./configure [OPTION]... [VAR=VALUE]...

To assign environment variables (e.g., CC, CFLAGS...), specify them as
VAR=VALUE.  See below for descriptions of some of the useful variables.

Defaults for the options are specified in brackets.

Configuration:
  -h, --help              display this help and exit
      --help=short        display options specific to this package
      --help=recursive    display the short help of all the included packages
  -V, --version           display version information and exit               
  -q, --quiet, --silent   do not print `checking...' messages                
      --cache-file=FILE   cache test results in FILE [disabled]              
  -C, --config-cache      alias for `--cache-file=config.cache'              
  -n, --no-create         do not create output files                         
      --srcdir=DIR        find the sources in DIR [configure dir or `..']    

Installation directories:
  --prefix=PREFIX         install architecture-independent files in PREFIX
                          [/usr/local]                                    
  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX 
                          [PREFIX]                                        

By default, `make install' will install all the files in
`/usr/local/bin', `/usr/local/lib' etc.  You can specify
an installation prefix other than `/usr/local' using `--prefix',
for instance `--prefix=$HOME'.

For better control, use the options below.

Fine tuning of the installation directories:
  --bindir=DIR           user executables [EPREFIX/bin]
  --sbindir=DIR          system admin executables [EPREFIX/sbin]
  --libexecdir=DIR       program executables [EPREFIX/libexec]
  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
  --libdir=DIR           object code libraries [EPREFIX/lib]
  --includedir=DIR       C header files [PREFIX/include]
  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
  --datarootdir=DIR      read-only arch.-independent data root [PREFIX/share]
  --datadir=DIR          read-only architecture-independent data [DATAROOTDIR]
  --infodir=DIR          info documentation [DATAROOTDIR/info]
  --localedir=DIR        locale-dependent data [DATAROOTDIR/locale]
  --mandir=DIR           man documentation [DATAROOTDIR/man]
  --docdir=DIR           documentation root [DATAROOTDIR/doc/srce]
  --htmldir=DIR          html documentation [DOCDIR]
  --dvidir=DIR           dvi documentation [DOCDIR]
  --pdfdir=DIR           pdf documentation [DOCDIR]
  --psdir=DIR            ps documentation [DOCDIR]

Optional Features and Packages:
  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
  --enable-unsafe         enable unsafe operation [default=no]
  --with-user             specify the system user [default=root]

Some influential environment variables:
  CC          C compiler command
  CFLAGS      C compiler flags
  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
              nonstandard directory <lib dir>
  CPPFLAGS    C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
              you have headers in a nonstandard directory <include dir>
  CPP         C preprocessor

Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.

Report bugs to <[email protected]>.

If a program is actually utilizing the build system configuration tool correctly, it allows you to fine tune each knob that dictates the build process. For instance, you might want --prefix to be /home, but use a location somewhere in /usr/share for a custom version of libfoo that root has deposited for people who can't use the system version for whatever reason.

Some of these paths are set when a program is linked , not merely compiled, but yes they are a part of the resulting ELF object. Other files that are installed as plain text (i.e. config files, interpreted languages, etc) are either:

  • Modified or generated en situ so that they contain the paths you specified
  • Smart enough to search for the files that they need, given your PATH setting
  • Smart enough to search for the files that they need, even outside of PATH (env variables usually come into play here)

Its usually a combination of the three.

Lets look at a dummy foo.ini.in file that would be used to generate the real foo.ini:

[global]
output_path=@prefix@/var/spool

Which, if configured with --prefix=/home/sam would produce a foo.ini that looks like this:

[global]
output_path=/home/sam/var/spool

Note, the above is autoconf centric, but does illustrate the concept.

The other important thing to realize is that not all programs that use a build configuration tool actually use the preferences it allows you to set. I've seen a lot of programs that just obey the --prefix and --with-somelib / --without-somelib options that they add.

In short, not one behavior fits all, but that's a brief overview of how it usually works.

Tim Post