{"id":164,"date":"2007-09-29T03:00:53","date_gmt":"2007-09-29T11:00:53","guid":{"rendered":"http:\/\/wp.colliertech.org\/cj\/?p=164"},"modified":"2007-09-29T03:00:53","modified_gmt":"2007-09-29T11:00:53","slug":"producing-relocatable-packages-with-the-gnu-build-system","status":"publish","type":"post","link":"https:\/\/wp.c9h.org\/cj\/?p=164","title":{"rendered":"Producing relocatable packages with the GNU build system"},"content":{"rendered":"<p>I&#8217;ve recently found a need to create relocatable versions of some of my favorite libraries (produced, not-so-coincidentally by the <a href=\"http:\/\/en.wikipedia.org\/wiki\/GNU_build_system\">GNU build system<\/a>).  You might find yourself asking &#8220;What is relocatable software, and why should I care?&#8221;  Maybe I can help.<\/p>\n<p>A piece of software is said to be &#8220;relocatable&#8221; 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&#8217;s .app directory\/package framework.<\/p>\n<p>As it currently stands, if I were to install iceweasel (or Firefox&trade;) 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.<\/p>\n<p>There are a couple of things standing in the way of this shiny new future.<\/p>\n<p>1) In its current state, <a href=\"https:\/\/savannah.gnu.org\/projects\/autoconf\">GNU autoconf<\/a> 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 &#8220;prefix&#8221;.  In a perfect world, all directories relative to the prefix would be further constrained as not to be <i>beneath<\/i> the prefix root.  For example, defining the &#8220;bindir&#8221; as ${prefix}\/..\/bin\/ would be a no-no.<\/p>\n<p>I have <a href=\"http:\/\/lists.gnu.org\/archive\/html\/bug-autoconf\/2007-09\/msg00021.html\">proposed a solution<\/a> to this problem on the bug-autoconf list.<\/p>\n<p>2) After a package is created in a relocatable way, how does one find said package once it has been moved?<\/p>\n<p>The solution to this problem lies in the standardization of the use of <a href=\"http:\/\/en.wikipedia.org\/wiki\/Pkg-config\">pkg-config<\/a> and subsequent modifications to the $PKG_CONFIG_PATH environment variable.<\/p>\n<p>The first step is to ensure that your GNU build system includes a rule to generate a <package-name-here>.pc file.  The standard way to do this is to include a <package-name-here>.pc.in autoconf template in the distribution as well as an entry in the AC_OUTPUT( &#8230; ) macro of the configure.am file (configure.in in legacy codebases).<\/p>\n<p>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.<\/p>\n<pre>\r\nAC_OUTPUT([\r\nMakefile\r\nmint.pc\r\nmono.pc\r\nmono-cairo.pc\r\ndotnet.pc\r\nmono-uninstalled.pc\r\nscripts\/mono-nunit.pc\r\n...\r\n])\r\n<\/pre>\n<p>Here are a couple of examples of the contents of .pc.in files:<\/p>\n<pre>\r\ncjac@dom0:\/usr\/src\/svn\/mono\/mono-1.2.5$ cat mint.pc.in \r\nprefix=${pcfiledir}\/..\/..\r\nexec_prefix=${pcfiledir}\/..\/..\r\nlibdir=${prefix}\/lib\r\nincludedir=${prefix}\/include\/mono-@API_VER@\r\n\r\n\r\nName: Mono Interpreter\r\nDescription: Mono Interpreter Runtime\r\nVersion: @VERSION@\r\nRequires: glib-2.0 gthread-2.0\r\nLibs: -L${libdir} @export_ldflags@ -lmint @libmono_ldflags@\r\nCflags: -I${includedir} @libmono_cflags@\r\n\r\ncjac@dom0:\/usr\/src\/svn\/mono\/mono-1.2.5$ cat mono.pc.in \r\nprefix=${pcfiledir}\/..\/..\r\nexec_prefix=${pcfiledir}\/..\/..\r\nlibdir=${prefix}\/@reloc_libdir@\r\nincludedir=${prefix}\/include\/mono-@API_VER@\r\n\r\nName: Mono\r\nDescription: Mono Runtime\r\nVersion: @VERSION@\r\nRequires: glib-2.0 gthread-2.0\r\nLibs: -L${libdir} @export_ldflags@ -lmono @libmono_ldflags@\r\nCflags: -I${includedir} @libmono_cflags@\r\n<\/pre>\n<p>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.<\/p>\n<p>For example, if $PKG_CONFIG_PATH evaluates as &#8220;\/home\/cjac\/opt\/mono\/lib\/pkgconfig:\/usr\/lib\/pkgconfig&#8221;, on the first iteration, ${pcfiledir} will store \/home\/cjac\/opt\/mono\/lib\/pkgconfig, and on the second iteration, ${pcfiledir} will store \/usr\/lib\/pkgconfig.<\/p>\n<p>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:<\/p>\n<pre>\r\n$ sudo mv ~\/opt\/mono \/opt\r\n$ export PKG_CONFIG_PATH=\"\/opt\/mono\/lib\/pkgconfig:$PKG_CONFIG_PATH\"\r\n<\/pre>\n<p>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:<\/p>\n<pre>\r\n$ pkg-config mono --variable=prefix\r\n<\/pre>\n<p>Comment away&#8230; I&#8217;ll try to get rid of some of the spam crowding my comment backlog&#8230;<\/p>\n\n<div class=\"twitter-share\"><a href=\"https:\/\/twitter.com\/intent\/tweet?via=cjamescollier\" class=\"twitter-share-button\">Tweet<\/a><\/div>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;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 &#8220;What is relocatable software, and why should I care?&#8221; Maybe I can help. A piece of software is said to be &#8220;relocatable&#8221; when it does not rely on [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[180,40,9,79,75,90,62,152,21,7,12,166,133],"tags":[],"class_list":["post-164","post","type-post","status-publish","format-standard","hentry","category-autotools","category-dbmail","category-firefox","category-free-software","category-gnome","category-gpl","category-gtk","category-gtkglarea","category-gtkglarea-sharp","category-mono","category-mysql","category-software","category-xorg"],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1YDIB-2E","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/wp.c9h.org\/cj\/index.php?rest_route=\/wp\/v2\/posts\/164","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wp.c9h.org\/cj\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wp.c9h.org\/cj\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wp.c9h.org\/cj\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/wp.c9h.org\/cj\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=164"}],"version-history":[{"count":0,"href":"https:\/\/wp.c9h.org\/cj\/index.php?rest_route=\/wp\/v2\/posts\/164\/revisions"}],"wp:attachment":[{"href":"https:\/\/wp.c9h.org\/cj\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=164"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wp.c9h.org\/cj\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=164"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wp.c9h.org\/cj\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=164"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}