Zero Install

the antidote to app-stores

0compile

Normally, Zero Install will select a pre-built binary for your system. However, it can also be used to compile a new binary from a source package. This is useful if:

  • no binary is available for your platform;
  • you wish to build using different library versions; or
  • you wish to make changes to a program or library.
Name 0compile
Maintainer Thomas Leonard
License GNU Lesser General Public License
Run it Zero Install feed
SCM GIT repository

This tutorial shows how to use 0compile for these purposes. It is assumed that you have already installed the Zero Install injector (0launch) and know how to run programs using it. To get 0compile itself, use:

$ 0alias 0compile http://0install.net/2006/interfaces/0compile.xml

Note: this page describes the command-line interface to 0compile. There is also a graphical interface, which is used when you click on the Compile button in the injector. The graphical interface provides similar options, but is slightly more limited. Here are some screenshots.

Contents

  1. Autocompile
  2. Manual compilation
  3. Legacy helper features
  4. Recreating a build environment
  5. Making source available
  6. Building in a clean chroot

Autocompile

If you just want to compile some existing source code (without changing it), then the autocompile sub-command does the job. Given the URI of a program, it will download and compile the source in a temporary directory, add the resulting binary to the Zero Install cache, and register the new binary with 0launch. If the source depends on other programs, it will also download and compile them in the same way if no binary is currently available for the preferred version.

For example (GNU-Hello is a simple test program which depends only on "make"):

$ 0compile autocompile http://0install.net/tests/GNU-Hello.xml
================= http://0install.net/tests/GNU-Hello.xml ==================

Selecting versions for GNU Hello...
Selection done.

Plan:

- GNU Hello: Compile 1.3 (sha1=2aae32fd27d194167eac7eb611d7ce0983f83dd7)
  - make: Use existing binary 3.81-5 (Linux-x86_64)

No dependencies need compiling... compile GNU Hello itself...
Waiting for selected implementations to be downloaded...

...

Note that GNU-Hello does not get the C-compiler through Zero Install, so you will need that already (hint: apt-get install build-essential). Once compiled, you can run it like this:

  $ 0launch http://0install.net/tests/GNU-Hello.xml
  Hello, world!

You can also use autocompile --gui for a graphical version. This makes it easier to see the overall progress, because the verbose build output is shown separately in the lower pane:

0compile autocompile --gui

Manual compilation

If you want to modify the source before building, keep the object files around for rebuilding, or choose the versions used, you'll want to use the manual commands, described in the following sections.

Creating the build environment

To get started, run 0compile setup with the URL of the program you want to build. In this example, we'll use GNU-Hello, a simple program written by the FSF to demonstrate use of the popular GNU build tools:

$ 0compile setup http://0install.net/tests/GNU-Hello.xml GNU-Hello
Created directory GNU-Hello

0compile will run 0install select --source to select a suitable version of the source code and download it. It will also locate and download any dependencies (e.g. build tools or header files) the source may have. It will download the make utility in this case, or use your distribution's package.

The final argument names a directory for the build environment. If omitted, it defaults to the last component of the URI, without the ".xml" extension (so we could have just left it off in this case). 0compile will create this directory in the current directory.

All further 0compile commands are run from inside this new directory, which is currently empty except for a 0compile.properties file recording the URI of the program. If you want to change the selected version(s) later, do:

$ cd GNU-Hello
$ 0compile setup

Building

To compile the program, use the build command (from inside the GNU-Hello directory):

$ 0compile build
TMPDIR=/tmp/0compile-T5GJBj
BUILDDIR=/home/me/GNU-Hello/build
DISTDIR=/home/me/GNU-Hello/gnu-hello-linux-x86_64-1.3
SRCDIR=/home/me/.cache/0install.net/implementations/...
cd /tmp/GNU-Hello/build
Executing: "$SRCDIR/configure" --prefix="$DISTDIR" && make install
...

Note: GNU-Hello does not use Zero Install to get the C compiler (gcc) or the standard library header files (libc-dev), so you should install these yourself. They come with most distributions.

0compile starts by creating two sub-directories: gnu-hello-linux-x86_64 for the final result (the exact name will depend on your system) and build for any temporary files. It then executes a command specified in the source feed, which actually builds the software (using the standard GNU build system in this case).

Note that the command installs to the gnu-hello-linux-x86_64 directory rather than to the usual /usr/local.

Assuming the build is successful, gnu-hello-linux-x86_64 will contain the final result, including a handy gnu-hello-linux-x86_64/0install/feed.xml local feed file, which you can use to run the new binary (note: this used to be gnu-hello-linux-x86_64/0install/GNU-Hello.xml on older versions of 0compile):

$ 0launch gnu-hello-linux-x86_64/0install/feed.xml
Hello, world!

In fact, since GNU-Hello doesn't list any run-time dependencies, we could have just run the gnu-hello-linux-x86_64/bin/hello binary directly in this case. For more complex programs, the feed file will be useful. You can also pass it to 0install add-feed to register the new binary under the program's normal URI:

$ 0launch -c http://0install.net/tests/GNU-Hello.xml
Interface 'http://0install.net/tests/GNU-Hello.xml' has no usable implementations

$ 0install add-feed gnu-hello-linux-x86_64/0install/feed.xml
1) Add as feed for 'http://0install.net/tests/GNU-Hello.xml'

$ 0launch -c http://0install.net/tests/GNU-Hello.xml
Hello, world!

If everything worked, you can now delete the build directory to save space. However, if you're planning to modify the source and rebuild (described in the next section) then you'll want to leave it there, as it will make rebuilding faster.

For future reference, there is also a gnu-hello-linux-x86_64/0install/build-environment.xml file. This is a selections file, as produced by 0install select --source --xml, but with a few extra details of the build added, including the hostname of the machine used for the build, a timestamp and your username. You can use this to rebuild later with the same environment (e.g. using this exact version of "make"). The file is written before the build starts, so the build process may add to it.

Modifying the source

By default, 0compile keeps the source code in the (read-only) Zero Install cache, so if you want to make changes, the first step is to make a copy of it:

$ 0compile copy-src
Copied as '/home/me/GNU-Hello/src'

Edit the source as needed with the text editor of your choice. For example, we can change the message (here we're using ed, the standard text editor):

$ ed src/hello.c
5207
%s/Hello, world!/Goodbye, world!/
wq
5209

Recompile with 0compile build as before:

$ 0compile build
$ 0launch gnu-hello-linux-x86_64/0install/feed.xml
Goodbye, world!

If you compare the new gnu-hello-linux-x86_64/0install directory with the old one, you'll discover a couple of differences:

  • A new file is present, gnu-hello-linux-x86_64/0install/from-1.3.patch, containing a diff between the original sources and your modified ones (to display this without rebuilding, use 0compile diff).
  • The version number in the local feed has -1 appended, to indicate that this version has been modified.

These two features make it very easy to keep track of what you changed, which may well come in handy later! However, if you are making larger changes to the code then you will want to use a proper version control system (such as Git).

Publishing the binary

To share our new binary with other people, we just need to archive up the gnu-hello-linux-x86_64 directory and upload it to an FTP or HTTP server somewhere. Pass the URL of the remote directory to 0compile and upload the resulting binary (note: the version will be 1.3-1 if you modified the source):

$ 0compile publish http://mysite/downloads
Now upload 'gnu-hello-linux-x86_64-1.3.tar.bz2' as:
http://mysite/downloads/gnu-hello-linux-x86_64-1.3.tar.bz2
$ scp gnu-hello-linux-x86_64-1.3.tar.bz2 mysite:/var/www/downloads/

As well as the .tar.bz2 file, you will also get a GNU-Hello-1.3.xml file in the main GNU-Hello directory. You can use this new XML file to download the archive and run the program:

$ 0launch GNU-Hello-1.3.xml

You can either ask the maintainer of the program to add the implementation in this file to the master feed, or you can create your own feed (and ask them to add that). See the 0publish page for full details, but as a quick summary you can create a new signed feed like this:

$ 0publish .../GNU-Hello.xml \
  --xmlsign \
  --set-interface-uri=http://mysite/interfaces/GNU-Hello.xml \
  --local=GNU-Hello-1.3.xml

Then upload the signed .../GNU-Hello.xml file and the exported GPG key to your webserver.

Bundling dependencies

You might want to build on a machine without network access, or to archive everything needed to build a particular program. To do that, use this command:

$ 0compile include-deps

The source code and all dependencies will be copied into a new dependencies sub-directory. When building, this directory is added to 0launch's implementation cache search path (using 0launch --with-store).

Legacy helper features

0compile has some special code to detect and handle some common cases in legacy code:

Generated pkgconfig files with absolute paths

If $DISTDIR ends up containing a directory called 'pkgconfig', it checks each .pc file inside for an absolute prefix. If found, it is changed to a relative path.

Note: for "pure" Zero Install libraries, just use a relative path (e.g. prefix=${pcfiledir}/..) in the .pc file in the source, and copy it unchanged to $DISTDIR.

Build dependencies containing /usr/lib/lib*.so broken symlinks

RPM unpacks all packages over the root, so one package can have a symlink to a file provided by a different package. This is often used to set the default version of a library in RPM packages. e.g.

  • -devel package: libSDL.so -> libSDL-1.2.so.0.11.2 (broken link)
  • runtime package: provides libSDL-1.2.so.0.11.2

Since Zero Install keeps every package in its own directory, this doesn't work. Therefore, 0compile searches for such broken links, searches for a matching target, and creates a fixed link in a temporary directory, added to LD_LIBRARY_PATH. This makes it easy to depend on unmodified -devel packages which were designed for non-Zero Install systems.

Note: a "pure" Zero Install library wouldn't need to include the version number in the library filename, so no symlink would be needed. If you did want to include the number in the filename, the symlink to it would go in the runtime package, not the -devel package.

Build dependencies with lib64 directories

If the feed tries to add a directory under 'lib' or 'usr/lib' to $PKG_CONFIG_PATH, and the directory doesn't exist, 0compile uses the corresponding 'lib64' directory instead, if present. This is for existing RPMs which use a different directory structure for different architectures.

Libtool archive (.la) files

0compile searches for lib/*.la files in $DISTDIR and automatically deletes them for you (there is a safely check that it really is a libtool file first). These files were only needed on very old systems that don't support dynamic linking. These days they just cause trouble by using absolute paths which were only valid during the build.

Recreating a build environment

If you want to rebuild a binary package, see if it includes the 0install/build-environment.xml file that 0compile generates automatically. If so, you can re-create the build like this:

  $ 0compile setup .../someprog-binary/0install/build-environment.xml some-prog
  $ cd some-prog
  $ 0compile build

For example, in the GNU-Hello case this would allow you to build using the same source code and the exact same version of "make" used in the original compile.

Making source available

If you want to publish source code so that other people can compile it using 0compile, see 0compile: Developers.

Building in a clean chroot

If you want to build the source package in a clean "chroot" sandbox environment, see 0compile: Chroot Build.