# qiBuild documentation

# Managing pre-compiled binary packages with qitoolchain

## When to use pre-compiled packages

Pre-compiled packages are useful for third-party libraries. For instance, if your code depends on `boost`, you may want to make sure that you are using a specific version of `boost`, regardless of whatever version may be already installed on the user machine.

Also, you may want to provide users of your software with pre-compiled packages, because you do not want to share the source code, or to save some compilation time.

## Creating packages

If the project is using `qibuild`, all you have to do is to run

    qibuild package

If not, you have to create the package by hand. Assuming you want to create a pre-compiled package for the `foo` library which uses `autotools` and depends on the `bar` library:

    tar xvfz foo-src.tar.gz
    # Configure, build and install the library as usual:
    ./configure
    make
    DESTDIR=/tmp/foo make install
    cd /tmp/foo

Now that the project is installed, prepare it so that it follows the correct layout:

    mv usr/local* .
    rmdir -p usr/local

    foo
      lib
        libfoo.so
      include
        foo.h

Then write a CMake module so that the foo library can be found:

    cd /tmp/foo
    qibuild gen-cmake-module --name foo .

This will generate a file named `foo-config.cmake` in `share/cmake/foo/foo-config.cmake`, that you can edit so that it looks like:

    set(_root "${CMAKE_CURRENT_LIST_DIR}/../../..")
    get_filename_component(_root ${_root} ABSOLUTE)

    set(FOO_LIBRARIES
      ${_root}/lib/libfoo.so
      CACHE INTERNAL "" FORCE
    )

    set(FOO_INCLUDE_DIRS
      ${_root}/include
      CACHE INTERNAL "" FORCE
    )

    qi_persistent_set(FOO_DEPENDS "BAR")
    export_lib(FOO)

Then write a `package.xml` file looking like:

    <!--- in /tmp/foo/package.xml -->
    <package name="foo" version="0.1" target="linux64" >
      <license>BSD</license>
      <depends buildtime="true" runtime="true" names="bar" />
    </package>

Note

the `<license>` tag is not mandatory, but recommended

In the end the package tree should look like this:

    foo
      package.xml
      lib
        libfoo.so
      include
        foo.h
      share
        cmake
          foo
            foo-config.cmake

Finally, create the package with `qitoolchain make-package`

    qitoolchain make-package /tmp/foo

## Using cross-toolchains

Let’s say you want to cross-compile for ARM. You should find:

- a cross-compiler
- a `sysroot`
- a `toolchain.cmake` that calls `CMAKE_FORCE_C_COMPILER` and `CMAKE_FORCE_CXX_COMPILER`

You should put all of this into a package, with a few additional metadata:

    <ctc>
       package.xml
       sysroot
          etc
          usr
            include
        bin
          arm-linux-gnu-gcc
          arm-linux-gnu-g++
          arm-linux-gnu-gdb

    <!-- in package.xml -->
    <package name="arm-ctc"
             host="linux64"
             target="arm"
             version="r1"
             sysroot="sysroot"
             gdb="bin/arm-linux-gnu-gdb"
             toolchain_file="toolchain.cmake" />

Then you can use:

    qitoolchain make-package ctc
    qitoolchain add-package arm-ctc-linux64-r1.zip

as you would do for a normal package.

## Specifying custom flags

Sometimes you just want to set some compile flags while building. To do that, you can create a package that will set `CMAKE_CXX_FLAGS` for you.

For instance, to activate `C++11` support, you can create a `c++11` package

    c++11
      package.xml
      config.cmake

    <!-- in package.xml -->
    <package name="c++11" toolchain_file="config.cmake" />

    # in config.cmake

    set(CMAKE_CXX_FLAGS "-std=gnu++11" CACHE INTERNAL "" FORCE)

## Excluding files at installation

Say you are creating a binary package for Qt on Windows:

You do not want to include all the compilation tools (such as `moc`, `rcc` or `uic`) when you install a project that has a runtime dependency on Qt.

But you still want to include `lrelease`, `lupdate` because your application uses these tools at runtime.

You also want to remove all the debug `.dll` when you install your application in release mode.

The solution is to create masks in the package looking like this:

    # in /path/to/Qt/runtime.mask

    # Remove all tools
    exclude bin/.*\.exe

    # But keep lrelease, lupdate:
    include bin/lrelease\.exe
    include bin/lupdate\.exe

    # in /path/to/Qt/release.mask

    exclude lib/.*d\.dll

Blank lines and comments starting with `#` are ignored. Other lines should contain the word `include` or `exclude`, followed by a regular expression.

## Creating a toolchain feed

You will need a place to host the packages and the feeds. It can be a simple HTTP or FTP web server.

Let’s assume you have `foo` and `bar` packages. Write a feed looking like

    <toolchain>
      <package name="foo" version="0.1" url="http://example.com/foo-0.1.zip" />
      <package name="bar" version="0.2" url="http://example.com/bar-0.2.zip" />
    </toolchain>

Alternatively, you can create a git repository to store your feed. Just make sure it is in a ‘feeds’ subdirectory, like this:

    <toolchains.git>
      feeds
        foo.xml

## Using a toolchain

Once the feed has been created, run:

    qitoolchain create my-toolchain http://example.com/feed.xml

Or:

    qitoolchain create --feed-name foo my-toolchain git@example.com:toolchains.git

Here `--feed-name` is the name of the feed in the `feeds` directory on the git repository, without the `.xml` extension.

Then use:

    qibuild add-config my-toolchain --toolchain my-toolchain
    qibuild configure -c my-toolchain

## Importing binary packages

`qitoolchain` also has support for importing binary packages coming from the `gentoo` distribution.

    qitoolchain import-package -t my-toolchain --name foo /path/to/foo.tbz2

## Putting binary packages in a subversion repository

Instead of hosting zips on a HTTP server, you may want to host the pre-compiled packages in a subversion server. Why subversion ? Because it allows partial checkouts, and it is not that bad at managing binary blobs.

You may have a layout like this on the server:

    <svn root>
     master
         win32-vs2010
           boost
           qt
         linux64
           boost
           qt

Then you can specify packages in the XML feed using a `svn_package` element:

    <!-- in feeds/linux64.xml -->
    <feed>
      <svn_package name="boost" url="svn://example.org/toolchains/master/linux64/boost" />
      <svn_package name="qt" url="svn://example.org/toolchains/master/linux64/qt" />
    </feed>

When using `qitoolchain create`, the packages will be created using `svn checkout`, and then `svn update` will be called when using `qitoolchain update`.

You can also specify a revision inside the feed:

    <!-- in feeds/linux64.xml -->
    <feed>
      <svn_package name="boost" url="svn://example.org/toolchains/master/linux64/boost" revision="42" />
    </feed>

## Using sub feeds

Let’s assume you want to create several feeds for cross-compiling on several operating systems. Each feed will contain a specific package for the cross-compiler, which is host dependent, and a list of common packages for the third-party libraries, which are host independent.

To solve this problem, you can include some feeds into an other one, like this:

    arm.xml
    linux64-arm.xml
    mac64-arm.xml

    <!-- in arm.xml -->
    <feed>
      <package name="boost" url="..." />
    </feed>

    <!-- in linux64-arm.xml -->
    <feed>
      <feed url="http://example.com/feeds/arm.xml" />
      <package name="ctc-linux64-arm" url="..." />
    </feed>

    <!-- in mac64-arm.xml -->
    <feed>
      <feed url="http://example.com/feeds/arm.xml" />
      <package name="ctc-mac64-arm" url="..." />
    </feed>

If you chose to put the feeds in a git repository, you can specify sub feeds by name, like this

    <!-- in feeds/linux64-arm.xml -->
    <feed>
      <feed name="arm" />
      ...
    </feed>

Changelog CMake index Python index Index