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" >
<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



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:



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

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

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>