Skip to content

0compile

Maintainer: Thomas Leonard
License: GNU Lesser General Public License
Source: https://github.com/0install/0compile
Zero Install feed: https://apps.0install.net/0install/0compile.xml

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.

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

0install add 0compile https://apps.0install.net/0install/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 0install GUI. The graphical interface provides similar options, but is slightly more limited.

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. 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:

$ 0install run 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):

$ 0install run 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:

$ 0install run -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'

$ 0install run -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
$ 0install run 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

Use 0compile publish to create the archive and feed:

$ 0compile publish
Generated archive 'gnu-hello-linux-x86_64-1.3.tar.bz2' and feed 'GNU-Hello-1.3.xml'.
Upload it to a repository with:
0repo add GNU-Hello-1.3.xml

You can test it with:

$ 0install run GNU-Hello-1.3.xml

To publish the feed and archive, use 0repo (see that page for configuration details):

$ 0repo add GNU-Hello-1.3.xml

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 the implementation cache search path (using 0install run --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.

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.