0compile
| Name | 0compile |
|---|---|
| Maintainer | Thomas Leonard |
| License | GNU Lesser General Public License |
| Run it | Zero Install feed |
| SCM | GIT repository |
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 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.
- Creating the build environment
- Building
- Modifying the source
- Publishing the binary
- Making source available
- Making library headers available (-dev packages)
- Adding run-time dependencies
- Tips
- Further reading
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
0compile will run 0launch --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, although the GNU-Hello example feed doesn't list any.
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-env.xml file recording the version of GNU-Hello selected. 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 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-1.3 for the final result (the exact name will depend on your system and on the chosen version), 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-1.3 directory rather than to the usual /usr/local. In fact, if you have plash installed, the command is run in a sandbox with very limited write permissions. [ update: Plash support is temporarily disabled by default while a few issues are worked out; set $USE_PLASH_0COMPILE to turn it on again ]
Assuming the build is successful, gnu-hello-linux-x86_64-1.3 will contain the final result, including a handy gnu-hello-linux-x86_64-1.3/0install/GNU-Hello.xml local feed file, which you can use to run the new binary:
$ 0launch gnu-hello-linux-x86_64-1.3/0install/GNU-Hello.xml Hello, world!
In fact, since GNU-Hello doesn't list any dependencies, we could have just run the gnu-hello-linux-x86_64-1.3/bin/hello binary directly in this case. For more complex programs, the feed file will be useful. You can also pass it to 0launch --feed to register the new binary under the program's normal URI:
$ 0launch -c http://0install.net/tests/GNU-Hello.xml Can't find all required implementations: - <Interface http://0install.net/tests/GNU-Hello.xml> -> None $ 0launch --feed gnu-hello-linux-x86_64-1.3/0install/GNU-Hello.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-1.3/0install/build-environment.xml file. This is a copy of the 0compile-env.xml used for the build, 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. This file is written before the build starts, so the build process may add to it (or move it, or even delete 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 (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-1.3-1/0install/GNU-Hello.xml Goodbye, world!
Note that the version number in the directory name has changed to have a "-1" on the end! This indicates that you have modified it.
If you compare the new gnu-hello-linux-x86_64-1.3-1/0install directory with the old one, you'll discover a couple of differences:
- A new file is present, gnu-hello-linux-x86_64-1.3-1/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 useful 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-1.3 directory and upload it to an FTP or HTTP server somewhere (remember to upload the 1.3-1 directory if you want to publish your modified version instead). Pass the URL of the remote directory to 0compile and upload the resulting binary:
$ 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.
Making source available
If you wish to make source code available for others to use (as described above) then you need to add source implementations to the program's feed file. This is almost exactly the same as adding binaries, except that you give src as the machine type to 0publish:
$ 0publish /var/www/interfaces/MyProg.xml \ --add-version=5 \ --archive-url=http://mysite/downloads/myprog-5-src.tar.bz2 \ --set-released=today \ --set-arch=*-src
There are also some extra attributes you should add to the implementation element:
- compile:command
- This must be present. Its value is a shell command, executed inside the build directory. It must compile the source in $SRCDIR, putting the final result (ready for distribution) in $DISTDIR. If this command starts to get complicated, you should move it to a script (either inside the main source archive or in a separate dependency) and just set this attribute to the command to run the script.
- compile:binary-main
- This optional attribute gives the value of the main attribute on the binary feed that is created. If it is not given, then the binary created cannot be executed (e.g., it is a library).
The compile prefix must be bound to 0compile's namespace somewhere, e.g.:
xmlns:compile="http://zero-install.sourceforge.net/2006/namespaces/0compile"
Note: You can keep the source implementations in a separate file (MyProg-src.xml) and add a feed from the main feed, e.g.:
<feed src='http://mysite/interfaces/MyProg-src.xml' arch='*-src'/>
The arch attribute lets the injector know that it doesn't need to fetch this file unless it's looking for source code.
Making library headers available (-dev packages)
See Make-headers for information about publishing library source and -dev packages.
Adding run-time dependencies
By default, the feed created for the new binary doesn't have any dependencies. There are two ways to add them:
- You can annotate any <requires> element in your source feed with the 'include-binary' attribute. This
causes the dependency to appear in the generated binary's feed, in addition to being made available at
compile-time. e.g.
<requires compile:include-binary='true' interface="http://my/library"> <environment insert="lib" name="MY_LIBRARY_DIR" mode="replace"/> </requires> - You can edit the feed XML file directly during the build (it's in the $DISTDIR/0install directory).
Tips
- Python distutils
You should use the --build-base option to make distutils build to 0compile's build directory, not under the source code (which is read-only). Unfortunately, this option isn't available with the install command, so you have to do the build in two steps. A typical command is:
cd "$SRCDIR" && python setup.py build --build-base="$BUILDDIR/build" && cd "$BUILDDIR" && python "$SRCDIR"/setup.py install --home="$DISTDIR" --skip-build
Further reading
- Example: SCons
- This example shows how to compile a simple "Hello world" program using the SCons build system. Both the source and SCons are fetched using Zero Install.