I’ve recently found a need to create relocatable versions of some of my favorite libraries (produced, not-so-coincidentally by the GNU build system). You might find yourself asking “What is relocatable software, and why should I care?” Maybe I can help.
A piece of software is said to be “relocatable” when it does not rely on an absolute path in a filesystem in order to operate correctly. An example of this type of system is OS X’s .app directory/package framework.
As it currently stands, if I were to install iceweasel (or Firefox™) in /usr/local/mozilla/, but later realize there is more disk space available in /opt, I would be SOL. If mozilla were built as a relocatable package, however, moving /usr/local/mozilla/ to /opt/mozilla/ would not be a problem.
There are a couple of things standing in the way of this shiny new future.
1) In its current state, GNU autoconf accepts multiple absolute paths as argument values. In a relocatable package, all related software must be installed relative to a single point, referred to in autoconf nomenclature as the “prefix”. In a perfect world, all directories relative to the prefix would be further constrained as not to be beneath the prefix root. For example, defining the “bindir” as ${prefix}/../bin/ would be a no-no.
I have proposed a solution to this problem on the bug-autoconf list.
2) After a package is created in a relocatable way, how does one find said package once it has been moved?
The solution to this problem lies in the standardization of the use of pkg-config and subsequent modifications to the $PKG_CONFIG_PATH environment variable.
The first step is to ensure that your GNU build system includes a rule to generate a
Here are some examples from the Mono codebase. Note that configure.am is named configure.in in the mono codebase. Note further that I am scowling.
AC_OUTPUT([ Makefile mint.pc mono.pc mono-cairo.pc dotnet.pc mono-uninstalled.pc scripts/mono-nunit.pc ... ])
Here are a couple of examples of the contents of .pc.in files:
cjac@dom0:/usr/src/svn/mono/mono-1.2.5$ cat mint.pc.in prefix=${pcfiledir}/../.. exec_prefix=${pcfiledir}/../.. libdir=${prefix}/lib includedir=${prefix}/include/mono-@API_VER@ Name: Mono Interpreter Description: Mono Interpreter Runtime Version: @VERSION@ Requires: glib-2.0 gthread-2.0 Libs: -L${libdir} @export_ldflags@ -lmint @libmono_ldflags@ Cflags: -I${includedir} @libmono_cflags@ cjac@dom0:/usr/src/svn/mono/mono-1.2.5$ cat mono.pc.in prefix=${pcfiledir}/../.. exec_prefix=${pcfiledir}/../.. libdir=${prefix}/@reloc_libdir@ includedir=${prefix}/include/mono-@API_VER@ Name: Mono Description: Mono Runtime Version: @VERSION@ Requires: glib-2.0 gthread-2.0 Libs: -L${libdir} @export_ldflags@ -lmono @libmono_ldflags@ Cflags: -I${includedir} @libmono_cflags@
Of particular importance in these files is the definition of ${prefix}, ${exec_prefix}, ${libdir} and ${includedir} relative to ${pcfiledir}. ${pcfiledir} is set at pkg-config run time as it iterates over the contents of the $PKG_CONFIG_PATH environment variable.
For example, if $PKG_CONFIG_PATH evaluates as “/home/cjac/opt/mono/lib/pkgconfig:/usr/lib/pkgconfig”, on the first iteration, ${pcfiledir} will store /home/cjac/opt/mono/lib/pkgconfig, and on the second iteration, ${pcfiledir} will store /usr/lib/pkgconfig.
So! Assuming I installed mono to ~/opt/mono, and I wanted to instead move it to /opt/mono, all I would need to do is the following:
$ sudo mv ~/opt/mono /opt $ export PKG_CONFIG_PATH="/opt/mono/lib/pkgconfig:$PKG_CONFIG_PATH"
And voila. All of my mono-related bits and all references to them have been moved. Independent of the absolute path to the mono package, the prefix can be determined in a consistent way:
$ pkg-config mono --variable=prefix
Comment away… I’ll try to get rid of some of the spam crowding my comment backlog…