Table Of Contents

Previous topic

CMake: icetray’s build system

Next topic

Organization/Structure of Projects and Metaprojects

This Page

User’s Guide

CMake is a cross-platform build system which generates build files for use by native build systems for different platforms. On UNIX-like systems it generates makefiles. CMake provides easier per-project build configuration, a more standard build environment across different platforms, additional testing infrastructure, and out-of-source compilation.

Out-of-source compilation uses a separate object directory for build results while leaving the original source directory untouched. This makes it possible to perform multiple simultaneous builds for multiple platforms from one single source directory, and to more easily see which files have changed when committing new code.

Building with cmake

To begin building with CMake start with a clean workspace. Set your I3_PORTS and JAVA_HOME environment variables. You’ll also need LD_LIBRARY_PATH set to include the architecture-dependent directory containing libzip.so for anything that will require Java (the following examples use bash as an example):

$ export I3_PORTS=~/IceCube/i3tools
$ export JAVA_HOME=/usr/java/j2sdk1.4.2
$ export LD_LIBRARY_PATH=${JAVA_HOME}/jre/lib/amd64

With cmake one does “out-of-source” builds. This makes it easier to build several configurations against one set of source, and to be sure that the build process does not modify the source itself (e.g. no temporary files end up laying around in your checkout. So create a work directory and check out source to a directory called src:

mkdir -p ~/IceCube/meta-projects/offline-software/trunk
cd ~/IceCube/meta-projects/offline-software/trunk
svn co http://code.icecube.wisc.edu/svn/meta-projects/offline-software/trunk src

Note the “src” on the end of the svn co command

Create the object directory parallel to the source directory and execute cmake in the object directory to create the build environment:

$ pwd
~/IceCube/meta-projects/offline-software/trunk
$ mkdir build
$ ls
build src
$ cd build
$ $I3_PORTS/bin/cmake ../src
<lots of cmake output omitted>
-- Configuring done
-- Generating done
-- Build files have been written to: ~/IceCube/meta-projects/offline-software/build

At this point the contents of the object directory should look somewhat like that of the source directory. Main differences:

  • there are no sourcefiles in the subdirectories of build/
  • build contains directories CMakeFiles/, bin/, and lib/
  • build contains files CMakeCache.txt, env-shell.sh, and tarball_hook.sh.
$ ls
CMakeCache.txt  cmake_install.cmake  glshovel/         pfclasses/
CMakeFiles/     coordinate-service/  icepick/          pfreader/
DOMcalibrator/  daq-decode/          icetray/          phys-services/
I3Db/           dataclasses/         interfaces/       tarball_hook.sh*
Makefile        dataio/              jebclasses/       twr-decode/
Testing/        docs/                lib/              twrclasses/
amanda-core/    env-shell.sh*        log4cplus.conf    util/
bin/            examples/            mutineer/
cmake/          filter-tools/        payload-parsing/

And the source directory will have been untouched:

$ ls ../src
CMakeLists.txt@      dataclasses/   icepick/          pfclasses/
DOMcalibrator/       dataio/        icetray/          pfreader/
I3Db/                docs/          interfaces/       phys-services/
amanda-core/         examples/      jebclasses/       tarball_hook.sh.in
cmake/               filter-tools/  twr-decode/       util/
coordinate-service/  mutineer/      twrclasses/
daq-decode/          glshovel/      payload-parsing/

While still in the build directory execute make:

$ pwd
~/IceCube/meta-projects/offline-software/build
$ make

After make returns your build results will be in the object directory. Assuming no builds are made inside of the original source directory that directory can be reused for other builds, even if the platforms or build configurations differ.

The make target help will provide a list of valid targets in the CMake-generated Makefile:

$ pwd
~/IceCube/meta-projects/offline-software/build
$ make help
The following are some of the valid targets for this Makefile:
... all (the default if no target is provided)
... clean
... depend
<more targets omitted>

Configuring your build

Editing the CMake cache

Having run cmake and generated a ‘’build’’ directory full of makefiles, one sets build options by editing the cmake cache. You can start the editor with “make edit_cache”, or by invoking the cache editor, ccmake, directly:

cd ~/Icecube/meta-projects/offline-software/trunk/build
make edit_cache

A handy curses app will pop up allowing you to change the values of various configuration variables. As you move the cursor over them a description is shown at the bottom of the window:

BDB_FOUND                        OFF
BDB_INCLUDE_DIR                  BDB_INCLUDE_DIR-NOTFOUND
BDB_LIBRARIES
BOOST_FOUND                      ON
BOOST_INCLUDE_DIR                /Users/troy/ports/include/boos
BOOST_LIBRARIES                  /Users/troy/ports/lib/boost-1.
BUILD_AMANDA-CORE                ON
BUILD_ANALYSIS-TREE              ON
BUILD_COORDINATE-SERVICE         ON
BUILD_DAQ-DECODE                 ON
BUILD_DATACLASSES                ON
BUILD_DATAIO                     ON
BUILD_DOMCALIBRATOR              ON
BUILD_EXAMPLES                   ON
BUILD_I3DB                       ON

BDB_FOUND: BDB found successfully
Press [enter] to edit option          CMake Version 2.4 - patch 6
Press [c] to configure
Press [h] for help         Press [q] to quit without generating
Press [t] to toggle advanced mode (Currently Off)

After you have set things as you like them press c to run the configuration. You may have to do this twice. When cmake feels ready to generate makefiles, an option g will appear in the menu. Press g to generate the new makefiles and exit.

Command line configuration

If you know what you want to set, you can also just do so from the command line. For instance, I have checked out source to directory src/ and am in a parallel directory build/. I want to build the “release” variant, the one with optimizations on, i issue:

cmake -DCMAKE_BUILD_TYPE:STRING=Release ../src

You will notice that the type of the variable is represented after the colon. Almost everything can be handled with STRING and BOOL. For BOOL, use the values ON and OFF.

Not all of the variables are useful. Here are some that are:

Useful configuration variables
Option Description Default
BUILD_PROJECT Toggles the build of project PROJECT. e.g. BUILD_ICETRAY, BUILD_DATAIO. One should appear per project in the current workspace. ON
USE_CCACHE
Use ccache (if detected) OFF
USE_DISTCC
Use distcc (if detected) OFF
USE_GFILT
Use the gfilt stl error message decryptor ON
USE_GOLD
Use the new gold linker from GNU binutils. EXPERIMENTAL OFF
CMAKE_BUILD_TYPE
What kind of build you want. The choices are Release, Debug, RelWithDebInfo, MinSizeRel, RelWithAssert, Coverage, or empty for none of the above. Release

Verbose build

If you issue the ccmake command t the advanced variables will be shown. The most useful of these are:

Option Description
CMAKE_VERBOSE_MAKEFILE
Shows commands used while building. Useful for debugging cmake.

Though you can also make the build verbose at any time by adding VERBOSE=1 to the command line:

make dataio-pybindings VERBOSE=1

The cmake cache CMakeCache.txt

These cache variables are stored in a file CMakeCache.txt in the build directory. You may modify this file directly instead of using make edit_cache or the ccmake utility as above.

If you do so, cmake will detect that this file has been modified and automatically regenerate your makefiles. However if you add or remove files that a glob should match, e.g.:

i3_add_library(mylib private/mylib/*.cxx)

there is no way for cmake to know that a new file (e.g. private/mylib/newfile.cxx exists that should match private/mylib/*.cxx, as this regular expression no longer exists. It has been expanded into e.g. ‘’private/mylib/file1.cxx private/mylib/file2.cxx’‘. There are two ways to handle this:

  1. Don’t use globs: list the files explicitly, e.g.:

    i3_add_library(mylib private/mylib/file1.cxx private/mylib/file2.cxx).
    

    This way to add/remove files one edits a CMakeLists.txt and cmake will detect that the file has been modified, and regenerate the makefiles.

  2. make rebuild_cache: The make target rebuild_cache will cause the makefiles to be regenerated. During this process the globs from each CMakeLists.txt will again be expanded and things will work.

Note

If you add or remove projects you must run make rebuild_cache. This is because the list of projects in the workspace is, as with the lists of files above, collected with a glob.

Testing

Projects that have test executables or scripts will have their tests run when make test is issued. Test binaries are found in $I3_BUILD/bin, the workspace target test-bins will build these test binaries.

There is also a generated file runtests.py in $I3_BUILD/bin. This is a test driver script that you can use to run individual tests or groups of tests.:

% ./bin/runtests.py --help
Usage: runtests.py [options]

Options:
  -h, --help            show this help message and exit
  -p PROJECTS, --project=PROJECTS
                        List of projects to run tests on
  -s, --scripts-only    Run only test scripts
  -u, --units-only      Run only compiled unit tests
  -v, --verbose         Show verbose output

For example, to run the test scripts for project dataio, issue:

% ./bin/runtests.py -p dataio -s
27 projects loaded.
0:0  ...  dataio/scripts/a_nocompression.py
1:0  ...  dataio/scripts/b_default.py