Unix layout for installed software

The Unix filesystem organization is simple and helps you to know where you should expect find the files. See the root directory: “/”. Many of the folders there is one standard to follow. Each software that you will install must follow this standard, but someones are undesirable exceptions.

Unix layout

The basic at this point that you must understand:

  • /bin Executable files that you can run from command line.
  • /etc Configuration files that you can change.
  • /lib Shared and static compiled libraries.
  • /share Non architect/processor dependent files: default configuration, documentations, examples, etc.

Paths

Your shell has some environment variables that defines where search desirable files, as binaries and libraries. You must keep attention in, at least, two one:

  • $PATH Where find binaries.
  • $LD_LIBRARY_PATH Where find libraries.

Both of them are lists of full paths separated with :. If you type ls <enter> in your terminal(gnome-terminal, konsole, xterm, tty, etc.) running your shell (bash, ash, zsh, csh, etc.), your shell will search the binary ls in $PATH and after it can search (or not) in default locations.

Typically, you should prepend the new path to this variables:

$ export PATH="/A/B/bin:${PATH}"
$ export LD_LIBRARY_PATH="/A/B/lib:${LD_LIBRARY_PATH}"

PS: Use export to any child process can read this new values.

The first occorrency is used, and this is very usefull. We can add a path (e.g. /A/B/bin) that contains a binary called gcc:

$ echo ${PATH}
/usr/local/bin:/usr/bin:/bin
$ which gcc
/usr/bin/gcc
$ ls /A/B/bin/
c++ cc  g++ gcc
$ export PATH="/A/B/bin/:${PATH}"
$ which gcc
/A/B/bin/gcc

Now, when a child process of this shell search for gcc, it will use the /A/B/gcc. Similar procedure occur when ld will dynamic search the shared libraries (*.so).

Prefix

Not all software are installed in same place. See in the last example that is common have, at least, three default paths in $PATH: /, /usr, and /usr/local. Each distribution can define their rules to where put the installed software using their package managers.

The common is use / to essential software, as /bin/bash. Use the /usr to all official supported softwares. And they leave the /usr/local to software that you want install manually to the system. Unsupported softwares can use the /opt/<software name>, and should be explicitly included in path variables.

The idea of prefix is define a prefix to your software: /, /usr/, /usr/local/, /A/B/, /opt/A/,… Many build systems accept a parameter of prefix, use it!

If you are the only user of the system, you can install your software in /usr/local/ but keep in mind that you can install non-related softwares there and remove only one of them can be painful.

I suggest that you can have one prefix for each project, install all related builds in this prefix. Remember that you must add all used prefix to paths, specially the $PATH and $LD_LIBRARY_PATH, every time when you want use this software.

$ export PATH="/A/B/bin/:${PATH}"
$ export LD_LIBRARY_PATH="/A/B/lib/:${LD_LIBRARY_PATH}"

pkg-config

To use installed libraries, you should link them to your software. The problem is that you must use the correct link flags, with the correct libraries locations, and sometimes, use third libraries that are required by each dependecy.

pkg-config is a helper tool used when compiling applications and libraries. It helps you insert the correct compiler options on the command line so an application can use gcc -o test test.c $(pkg-config --libs --cflags glib-2.0) for instance, rather than hard-coding values on where to find glib (or other libraries). It is language-agnostic, so it can be used for defining the location of documentation tools, for instance.

pkg-config use software defined files (<library name>.pc) with the installation metadata. This files are find using the $PKG_CONFIG_PATH environment variable, that common contains the $LD_LIBRARY_PATH plus the /pkgconfig. The pkg-config automatic search in default places: /lib/pkgconfig and /usr/lib/pkgconfig.

The software that give their pkg-config description file install it in <prefix>/lib/pkgconfig.

Note that if you want the benefits of pkg-config, you must keep your $PKG_CONFIG_PATH updated together with $PATH and $LD_LIBRARY_PATH.

$ export PKG_CONFIG_PATH="/A/B/lib/pkgconfig:${PKG_CONFIG_PATH}"

Automatic setup

You can setup you environment variables when login or when open your shell. But do it only when you actual understand the paths and pkg-config. If you automatic put this values before understand, you forget how put them in a early future. This is not a one time use knowledge, absorb it!

As said, I like to keep each project installation in one prefix. I only add this project software to my runtime paths only want use them.