Difference between revisions of "CMake"

Line 9: Line 9:
   $ git clone git://gitorious.org/samba-wip/samba-wip.git
   $ git clone git://gitorious.org/samba-wip/samba-wip.git
   $ cd samba-wip
   $ cd samba-wip
  $ git checkout -b cmake origin/cmake
   $ cd lib/talloc
   $ cd lib/talloc

Revision as of 14:48, 12 January 2010

CMake is a cross-platform, open-source meta build system to build, test and package software. It creates Makefile or other build files (KDevelop, Eclipse). The intention is to test it if people like it and if we could replace the current build system with CMake.

Hands on


Lets start to do a checkout and compile something. Run some commands and then come back and talk about the features.

 $ git clone git://gitorious.org/samba-wip/samba-wip.git
 $ cd samba-wip
 $ cd lib/talloc

CMake is designed to build out of the source. This has several advantages. You don't have to create thousand of entries in .gitignore. You can create a build directory for *every local git branch* you create. CMake can be invoked by differnet executables:

  • cmake: the commandline tool
  • ccmake: a ncurses based gui
  • cmake-gui: a Qt gui.
 $ mkdir build
 $ cd build
 $ cmake ..

This is a talloc stand alone build. Normally you have to copy libreplace in the talloc dir but there is a check to look for ../replace, if you're in the Samba tree. It does all the required configure checks here to build on Linux as this is just a test.

 $ make

I think you know what it does. What's nice it shows only what it's building and the warnings and errors. If you want to see how make/cmake invokes the compiler, try the following:

 $ make clean
 $ make VERBOSE=1

To see what targets are availalbe, you can use

 $ make help

If you go to a source directory you have a target for each .c file.

 $ cd replace
 $ make help
 $ cd ..

You can execute every binary in the build directory and it will work. CMake uses rpath to build executables so that test scripts are able to find the right libraries, and things like make test can be run from the build directory without requiring you to install or build everything static. Executables are re-linked at install time to remove the rpath restriction. http://www.cmake.org/Wiki/CMake_RPATH_handling See:

 $ ldd talloc_testsuite

Building with RPATH can be disabled with 'cmake -DSKIP_BUILD_RPATH=OFF ..'. You have to set environment variables in this case to get executables working.


Lets look at tevent. I've created a way to let tevent use talloc from the system or compile it in source if you're in the samba tree.

 $ cd lib/tevent
 $ mkdir build
 $ cd build
 $ cmake ..
 $ make

This will build against the talloc system library. CMake uses so called "Find Packages" to find a library. There is no standard way to search for libraries and header files so CMake created a way to to it. You write a module and all you have to do is call 'find_package(Talloc REQUIRED)'. You can take a look at 'cmake/Modules/FindTalloc.cmake' in the tevent source directory if you want. Here is the way to build it in the Samba source tree.

 $ cd lib/tevent/build
 $ rm CMakeCache.txt
 $ make


CMake is pretty simple to learn. The way to tell CMake what to do, is to create a CMakeLists.txt file in each source directory. If you want to get started I suggest to look at http://www.cmake.org/cmake/help/examples.html.

I've tried to document the CMakeLists.txt a bit to make it easier to start. Everything else is documented in 'man cmake'.

A short example:

Assume we have created a Find Module for finding talloc (see lib/tevent/cmake/Modules/FindTalloc.cmake; this was created using a script I've written).

gladiac@magrathea:~/workspace/projects/csync/cmake/Scripts> ruby generate_findpackage_file
Name of package: Talloc
Your Name (for copyright): Andreas Schneider
Your mail (for copyright): asn@redhat.com
pkgconfig package name (e.g. "libxml-2.0", leave empty to skip pkgconfig): talloc
Look for header (e.g. "jpeglib.h" or "libxml/xpath.h"): talloc.h
Look for header subdir (e.g. "libxml2", empty to skip ):
Look for library (e.g. "xml2" or "avcodec avutil"): talloc
Done, generated FindTalloc.cmake

The way to compile a library if you have such a Find Module, cmake has more than 100 shipped by default, is fairly easy.

  # find the talloc package and require it!
  find_package(Talloc REQUIRED)


  # set the source files

  # create a library target
  add_library(tevent SHARED ${tevent_SRCS})
  target_link_libraries(tevent ${TALLOC_LIBRARIES})

  # install it

Isn't this easy to write and understand?

If you want to use functions or macros which are not covered by the cmake documentation then you find it at the top of each file. They are in '/usr/share/cmake/Modules' or in cmake/Modules if you look at replace/talloc/tevent here.


If you need help with cmake there are different sources:

Advantages of CMake

  • Out of source build
  • Automatic dependency generation (parallel builds)
  • Build system in *one* language
  • Good documentation (man cmake)
  • Works on a lot of different machines and operating systems -> http://www.cdash.org/CDash/index.php?project=CMake
  • Support for complex custom commands like qt moc, yacc, pidl! This means compile a source generator, then use the source generator to generate source code from special input files (compile pidl then: foo.idl -> pidl -> foo.c)
  • Reruns itself if one of the input files has changed
  • Compiler independent



The migration to CMake can be done in parallel to the current build system. As you write CMakeLists.txt file and do out of source build you don't have to touch the current build system. You can work on CMake and still have a working build using the old system. As soon as CMake is fully working you can remove the old build system.

CTest and CDash

CMake would allow us to easily use CTest and CDash for automatic testing. It has some nice features like running tests and check how long they run. Then create a graph out of it. Do code coverage and run automatically valgrind on each test. Everything is reported to CDash.