http://www.cmake.org DRAFT compiled on October 4, 2012
This presentation is licensed
http://creativecommons.org/licenses/by-sa/3.0/us/ https://github.com/TheErk/CMake-tutorial Initially given by Eric Noulard for Toulibre on February, 8th 2012.
CMake tutorial N
1 / 119
Thanks to. . . Kitware for making a really nice set of tools and making them open-source the CMake mailing list for its friendliness and its more than valuable source of information CMake developers for their tolerance when I break the dashboard or mess-up with the Git workflow, CPack users for their patience when things don’t work as they should expect Alan, Alex, Bill, Brad, Clint, David, Eike, Julien, Mathieu, Michael & Michael, and many more. . . My son Louis for the nice CPack 3D logo done with Blender. and...Toulibre for hosting this presention in Toulouse, France. CMake tutorial N
2 / 119
And thanks to contributors as well. . . History
This presentation was initially made by Eric Noulard for a Toulibre (http://www.toulibre.fr) given in Toulouse (France) on February, 8th 2012. After that, the source of the presentation has been release under CC-BY-SA, http://creativecommons.org/licenses/by-sa/3.0/us/ and put on https://github.com/TheErk/CMake-tutorial then contributors stepped-in.
Many thanks to all contributors (alphabetical order): Contributors
S´ebastien Dinot, Andreas Mohr.
CMake tutorial N
3 / 119
Outlines
CMake tool sets CMake CMake is a cross-platform build systems generator which makes it easier to build software in a unified manner on a broad set of platforms: , Windows, Mac OS, AIX, IRIX,
, iOS · · ·
CMake has friends softwares that may be used on their own or together: CMake: build system generator CPack: package generator CTest: systematic test driver CDash: a dashboard collector CMake tutorial N
4 / 119
Outlines
Outline of Part I: CMake 1
Basic CMake usage
2
Discovering environment specificities Handling platform specificities Working with external packages
3
More CMake scripting Custom commands Generated files
4
Advanced CMake usage Cross-compiling with CMake Export your project
CMake tutorial N
5 / 119
Outlines
Outline of Part II: CPack
5
CPack: Packaging made easy
6
CPack with CMake
7
Various package generators
CMake tutorial N
6 / 119
Outlines
Outline of Part III: CTest and CDash
8
Systematic Testing
9
CTest submission to CDash
10
References
CMake tutorial N
7 / 119
Outlines
Build what? Software build system A software build system is the usage of a [set of] tool[s] for building software applications. Why do we need that?
Outlines
Build what? Software build system A software build system is the usage of a [set of] tool[s] for building software applications. Why do we need that? because most softwares consist of several parts that need some building to put them together,
Outlines
Build what? Software build system A software build system is the usage of a [set of] tool[s] for building software applications. Why do we need that? because most softwares consist of several parts that need some building to put them together, because softwares are written in various languages that may share the same building process,
Outlines
Build what? Software build system A software build system is the usage of a [set of] tool[s] for building software applications. Why do we need that? because most softwares consist of several parts that need some building to put them together, because softwares are written in various languages that may share the same building process, because we want to build the same software for various computers (PC, Macintosh, Workstation, mobile phones and other PDA, embedded computers) and systems (Windows, Linux, *BSD, other Unices (many), Android, etc. . . ) CMake tutorial N
8 / 119
Outlines
Programming languages Compiled vs interpreted or what? Building an application requires the use of some programming language: Python, Java, C++, Fortran, C, Go, Tcl/Tk, Ruby, Perl, OCaml,. . . ?byte-compile?
interpreter
Perl
interprets
C++ Fortran C
compiles
links
executable
OCaml
object code
Programming languages
Python
executes
Running program
CMake tutorial N
9 / 119
Outlines
Programming languages Compiled vs interpreted or what? Building an application requires the use of some programming language: Python, Java, C++, Fortran, C, Go, Tcl/Tk, Ruby, Perl, OCaml,. . . ?byte-compile?
interpreter
Perl
interprets
C++ Fortran C
compiles
links
executable
OCaml
object code
Programming languages
Python
executes
Running program
CMake tutorial N
9 / 119
Outlines
Build systems: several choices Alternatives CMake is not the only build system [generator]: (portable) hand-written Makefiles, depends on make tool. Apache ant http://ant.apache.org/, dedicated to Java (almost). Portable IDE: Eclipse, Code::Blocks, Geany, NetBeans, . . . GNU Autotools: Autoconf, Automake, Libtool. Produce makefiles. Bourne shell needed (and M4 macro processor). see e.g. http://www.gnu.org/software/autoconf/ SCons: http://www.scons.org only depends on Python. Extensible with Python. ... CMake tutorial N
10 / 119
Outlines
Comparisons and [success] stories Disclaimer This presentation is biased. I mean totally. I am a big CMake fan, I’m contributing to CMake, thus I’m not impartial at all. But I will be ready to discuss why CMake is the greatest build system out there :-) Go and forge your own opinion: Bare list: http://en.wikipedia.org/wiki/List_of_build_ automation_software A comparison: http://www.scons.org/wiki/SconsVsOtherBuildTools KDE success story (2006): “Why the KDE project switched to CMake – and how” http://lwn.net/Articles/188693/ CMake tutorial N
11 / 119
Outlines
CMake/Auto[conf|make] on Ohloh
https://www.ohloh.net/languages/compare Language comparison of CMake to automake and autoconf showing the percentage of developers commits that modify a source file of the respective language. CMake tutorial N
12 / 119
Outlines
CMake/Auto[conf|make] on Google Trend
http://www.google.com/trends Scale is based on the average worldwide traffic of CMake in all years. CMake tutorial N
13 / 119
Basic CMake usage
Outline 1
Basic CMake usage
2
Discovering environment specificities Handling platform specificities Working with external packages
3
More CMake scripting Custom commands Generated files
4
Advanced CMake usage Cross-compiling with CMake Export your project
CMake tutorial N
14 / 119
Basic CMake usage
A build system generator CMake is a generator: it generates native build systems files (Makefile, Ninja, IDE project files, . . . ), CMake scripting language (declarative) is used to describe the build, The developer edits CMakeLists.txt, invokes CMake but should never edit the generated files, CMake may be (automatically) re-invoked by the build system,
CMake tutorial N
15 / 119
Basic CMake usage
The CMake workflow
When do things take place? CMake is a generator which means it does not compile (i.e. build) the sources, the underlying build tool (make, XCode, Code::Blocks. . . ) does. CMake tutorial N
16 / 119
Basic CMake usage
The CMake workflow CMake time: CMake is running & processing CMakeLists.txt
1
When do things take place? CMake is a generator which means it does not compile (i.e. build) the sources, the underlying build tool (make, XCode, Code::Blocks. . . ) does. CMake tutorial N
16 / 119
Basic CMake usage
The CMake workflow 1
CMake time: CMake is running & processing CMakeLists.txt
2
Build time: the build tool runs and invokes (at least) the compiler
When do things take place? CMake is a generator which means it does not compile (i.e. build) the sources, the underlying build tool (make, XCode, Code::Blocks. . . ) does. CMake tutorial N
16 / 119
Basic CMake usage
The CMake workflow 1
CMake time: CMake is running & processing CMakeLists.txt
2
Build time: the build tool runs and invokes (at least) the compiler
3
Install time: the compiled binaries are installed i.e. from build area to an install location.
When do things take place? CMake is a generator which means it does not compile (i.e. build) the sources, the underlying build tool (make, XCode, Code::Blocks. . . ) does. CMake tutorial N
16 / 119
Basic CMake usage
The CMake workflow 1
CMake time: CMake is running & processing CMakeLists.txt
2
Build time: the build tool runs and invokes (at least) the compiler
3
Install time: the compiled binaries are installed i.e. from build area to an install location. CPack time: CPack is running for building package
4
When do things take place? CMake is a generator which means it does not compile (i.e. build) the sources, the underlying build tool (make, XCode, Code::Blocks. . . ) does. CMake tutorial N
16 / 119
Basic CMake usage
The CMake workflow 1
CMake time: CMake is running & processing CMakeLists.txt
2
Build time: the build tool runs and invokes (at least) the compiler
3
Install time: the compiled binaries are installed i.e. from build area to an install location.
4
CPack time: CPack is running for building package
5
Package Install time: the package (from previous step) is installed
When do things take place? CMake is a generator which means it does not compile (i.e. build) the sources, the underlying build tool (make, XCode, Code::Blocks. . . ) does. CMake tutorial N
16 / 119
Basic CMake usage
The CMake workflow (pictured) CMakeLists.txt
Source files
CMake tutorial N
17 / 119
Basic CMake usage
The CMake workflow (pictured) CMakeLists.txt
Project file(s), Makefiles, . . .
Source files Generated Sources files CMake time
CMake tutorial N
17 / 119
Basic CMake usage
The CMake workflow (pictured) CMakeLists.txt
Project file(s), Makefiles, . . .
Object files
Source files Generated Sources files CMake time Build time
CMake tutorial N
17 / 119
Basic CMake usage
The CMake workflow (pictured) CMakeLists.txt
Project file(s), Makefiles, . . .
Object files
Installed files
Source files Generated Sources files CMake time Build time Install time
CMake tutorial N
17 / 119
Basic CMake usage
The CMake workflow (pictured) CMakeLists.txt
Project file(s), Makefiles, . . .
Object files
Installed files
Source files Generated Sources files
Binary package
CMake time
Source package
Build time Install time CPack time
CMake tutorial N
17 / 119
Basic CMake usage
The CMake workflow (pictured) CMakeLists.txt
Project file(s), Makefiles, . . .
Object files
Installed files
Source files Generated Sources files
Binary package
CMake time
Source package
Build time Install time CPack time
Installed package
Package Install time
CMake tutorial N
17 / 119
Basic CMake usage
Building an executable
1 2 3 4 5 6
Listing 1: Building a simple program cmake minimum required (VERSION 2 . 8 ) # T h i s p r o j e c t use C s o u r c e code project ( TotallyFree C) # build executable using s p e c i f i e d # l i s t of source f i l e s add executable ( A c r o l i b r e a c r o l i b r e . c ) CMake scripting language is [mostly] declarative. It has commands which are documented from within CMake: $ cmake --help-command-list | wc -l 96 $ cmake --help-command add_executable ... add_executable Add an executable to the project using the specified source files. CMake tutorial N
18 / 119
Basic CMake usage
Builtin documentation 1 2 3 4
CMake builtin doc for ’project’ command $ cmake --help-command project cmake version 2.8.7.20120121-g751713-dirty project Set a name for the entire project.
5
project( [languageName1 languageName2 ... ] )
6 7
Sets the name of the project. Additionally this sets the variables _BINARY_DIR and _SOURCE_DIR to the respective values.
8 9 10 11
Optionally you can specify which languages your project supports. Example languages are CXX (i.e. C++), C, Fortran, etc. By default C and CXX are enabled. E.g. if you do not have a C++ compiler, you can disable the check for it by explicitly listing the languages you want to support, e.g. C. By using the special language "NONE" all checks for any language can be disabled.
12 13 14 15 16 17
CMake tutorial N
19 / 119
Basic CMake usage
Generating & building Building with CMake is easy: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
CMake + Unix Makefile $ ls totally-free acrolibre.c CMakeLists.txt $ mkdir build $ cd build $ cmake ../totally-free -- The C compiler identification is GNU 4.6.2 -- Check for working C compiler: /usr/bin/gcc -- Check for working C compiler: /usr/bin/gcc -- works ... $ make Scanning dependencies of target Acrolibre [100%] Building C object CMakeFiles/Acrolibre.dir/acrolibre.c.o Linking C executable Acrolibre [100%] Built target Acrolibre $ ./Acrolibre toulibre
Source tree vs Build tree Even the most simple project should never mix-up sources with generated files. CMake supports out-of-source build. CMake tutorial N
20 / 119
Basic CMake usage
Always build out-of-source Out-of-source is better People are lazy (me too) and they think that because building in source is possible and authorizes less typing they can get away with it. In-source build is a BAD choice. Out-of-source build is always better because:
CMake tutorial N
21 / 119
Basic CMake usage
Always build out-of-source Out-of-source is better People are lazy (me too) and they think that because building in source is possible and authorizes less typing they can get away with it. In-source build is a BAD choice. Out-of-source build is always better because: 1
Generated files are separate from manually edited ones (thus you don’t have to clutter your favorite VCS ignore files).
CMake tutorial N
21 / 119
Basic CMake usage
Always build out-of-source Out-of-source is better People are lazy (me too) and they think that because building in source is possible and authorizes less typing they can get away with it. In-source build is a BAD choice. Out-of-source build is always better because: 1
Generated files are separate from manually edited ones (thus you don’t have to clutter your favorite VCS ignore files).
2
You can have several build trees for the same source tree
CMake tutorial N
21 / 119
Basic CMake usage
Always build out-of-source Out-of-source is better People are lazy (me too) and they think that because building in source is possible and authorizes less typing they can get away with it. In-source build is a BAD choice. Out-of-source build is always better because: 1
Generated files are separate from manually edited ones (thus you don’t have to clutter your favorite VCS ignore files).
2
You can have several build trees for the same source tree
3
This way it’s always safe to completely delete the build tree in order to do a clean build CMake tutorial N
21 / 119
Basic CMake usage
Building program + autonomous library
We now have the following set of files in our source tree: acrolibre.c, the main C program acrodict.h, the Acrodict library header acrodict.c, the Acrodict library source CMakeLists.txt, the soon to be updated CMake entry file
CMake tutorial N
22 / 119
Basic CMake usage
Building program + autonomous library Conditional build We want to keep a version of our program that can be compiled and run without the new Acrodict library and the new version which uses the library. We now have the following set of files in our source tree: acrolibre.c, the main C program acrodict.h, the Acrodict library header acrodict.c, the Acrodict library source CMakeLists.txt, the soon to be updated CMake entry file
CMake tutorial N
22 / 119
The main program source 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
#i n c l u d e < s t d l i b . h> #i n c l u d e #i n c l u d e < s t r i n g s . h> #i f d e f USE ACRODICT #i n c l u d e "acrodict.h" #e n d i f i n t main ( i n t argc , c h a r ∗ a r g v [ ] ) { c o n s t c h a r ∗ name ; #i f d e f USE ACRODICT c o n s t a c r o I t e m t ∗ item ; #e n d i f i f ( argc < 2) { f p r i n t f ( s t d e r r , "%s: you need one argument\n" , a r g v [ 0 ] ) ; f p r i n t f ( s t d e r r , "%s \n" , a r g v [0]) ; e x i t ( EXIT FAILURE ) ; } name = a r g v [ 1 ] ; #i f n d e f USE ACRODICT i f ( s t r c a s e c m p ( name , "toulibre" ) ==0) { p r i n t f ( "Toulibre is a french
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
organization promoting FLOSS .\n" ) ; } #e l s e item = a c r o d i c t g e t ( name ) ; i f (NULL!= item ) { p r i n t f ( "%s: %s\n" , item−>name , item−> description ) ; } e l s e i f ( item=a c r o d i c t g e t a p p r o x ( name ) ) { p r i n t f ( " <%s> is unknown may be you mean :\n" , name ) ; p r i n t f ( "%s: %s\n" , item−>name , item−> description ) ; } #e n d i f else { p r i n t f ( "Sorry , I don’t know: <%s>\n " , name ) ; r e t u r n EXIT FAILURE ; } r e t u r n EXIT SUCCESS ; }
CMake tutorial N
23 / 119
The library source 1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9
#i f n d e f ACRODICT H #d e f i n e ACRODICT H typedef s t r u c t acroItem { c h a r ∗ name ; char ∗ d e s c r i p t i o n ; } acroItem t ; const acroItem t ∗ a c r o d i c t g e t ( c o n s t c h a r ∗ name ) ; #e n d i f
#i n c l u d e < s t d l i b . h> #i n c l u d e < s t r i n g . h> #i n c l u d e "acrodict.h" s t a t i c const acroItem t acrodict [ ] = { {"Toulibre" , "Toulibre is a french organization promoting FLOSS" } , {"GNU" , "GNU is Not Unix" } , {"GPL" , "GNU general Public License" }, {"BSD" , "Berkeley Software Distribution" } , {"CULTe" , "Club des Utilisateurs de Logiciels libres et de gnu/ linux de Toulouse et des environs" } ,
{"Lea" , "Lea -Linux: Linux entre ami(e )s" } , {"RMLL" , "Rencontres Mondiales du Logiciel Libre" } , {"FLOSS" , "Free Libre Open Source Software" } , {"" , "" } } ; const acroItem t ∗ a c r o d i c t g e t ( c o n s t c h a r ∗ name ) { i n t c u r r e n t =0; i n t found =0; w h i l e ( ( s t r l e n ( a c r o d i c t [ c u r r e n t ] . name ) >0) && ! found ) { i f ( s t r c a s e c m p ( name , a c r o d i c t [ c u r r e n t ] . name ) ==0) { found =1; } else { c u r r e n t ++; } } i f ( found ) { r e t u r n &( a c r o d i c t [ c u r r e n t ] ) ; } else { r e t u r n NULL ; } }
CMake tutorial N
24 / 119
Basic CMake usage
Building a library I Listing 2: Building a simple program + shared library 1 2 3 4 5 6 7 8 9
cmake minimum required (VERSION 2 . 8 ) p r o j e c t ( TotallyFree C) add executable ( Acrolibre a c r o l i b r e . c ) s e t ( LIBSRC a c r o d i c t . c a c r o d i c t . h ) a d d l i b r a r y ( a c r o d i c t ${LIBSRC } ) add executable ( A c r o d i c t l i b r e a c r o l i b r e . c ) t a r g e t l i n k l i b r a r i e s ( Acrodictlibre acrodict ) set target properties ( Acrodictlibre PROPERTIES COMPILE FLAGS "-DUSE_ACRODICT" )
Basic CMake usage
Building a library II And it builds... All in all CMake generates appropriate Unix makefiles which build all this smoothly. 1 2 3 4 5 6 7 8 9 10 11 12 13
CMake + Unix Makefile $ make [ 33%] Building C object CMakeFiles/acrodict.dir/acrodict.c.o Linking C shared library libacrodict.so [ 33%] Built target acrodict [ 66%] Building C object CMakeFiles/Acrodictlibre.dir/acrolibre.c.o Linking C executable Acrodictlibre [ 66%] Built target Acrodictlibre [100%] Building C object CMakeFiles/Acrolibre.dir/acrolibre.c.o Linking C executable Acrolibre [100%] Built target Acrolibre $ ls -F Acrodictlibre* CMakeCache.txt cmake_install.cmake Makefile Acrolibre* CMakeFiles/ libacrodict.so*
CMake tutorial N
26 / 119
Basic CMake usage
Building a library III And it works... We get the two different variants of our program, with varying capabilities. 1 2 3 4 5 6
Generated Makefiles has several builtin targets besides the expected ones:
$ ./Acrolibre toulibre Toulibre is a french organization promoting FLOSS. $ ./Acrolibre FLOSS Sorry, I don’t know: $ ./Acrodictlibre FLOSS FLOSS: Free Libre Open Source Software $ make help The following are some of the valid targets for this Makefile: ... all (the default if no target is provided) ... clean ... depend ... Acrodictlibre ... Acrolibre ... acrodict ...
one per target (library or executable) clean, all more to come . . .
Basic CMake usage
User controlled build option User controlled option Maybe our users don’t want the acronym dictionary support. We can use CMake OPTION command. Listing 3: User controlled build option 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
cmake minimum required (VERSION 2 . 8 ) # T h i s p r o j e c t use C s o u r c e code p r o j e c t ( TotallyFree C) # B u i l d o p t i o n w i t h d e f a u l t v a l u e t o ON o p t i o n (WITH ACRODICT "Include acronym dictionary support" ON) s e t ( BUILD SHARED LIBS t r u e ) # build executable using s p e c i f i e d l i s t of source f i l e s add executable ( Acrolibre a c r o l i b r e . c ) i f (WITH ACRODICT) s e t ( LIBSRC a c r o d i c t . h a c r o d i c t . c ) a d d l i b r a r y ( a c r o d i c t ${LIBSRC } ) add executable ( A c r o d i c t l i b r e a c r o l i b r e . c ) t a r g e t l i n k l i b r a r i e s ( Acrodictlibre acrodict ) s e t t a r g e t p r o p e r t i e s ( A c r o d i c t l i b r e PROPERTIES COMPILE FLAGS "-DUSE_ACRODICT" ) e n d i f (WITH ACRODICT) CMake tutorial N
28 / 119
Basic CMake usage
Too much keyboard, time to click? I CMake comes with severals tools A matter of choice / taste: a command line: cmake a curses-based TUI: ccmake a Qt-based GUI: cmake-gui
Calling convention All tools expect to be called with a single argument which may be interpreted in 2 different ways. path to the source tree, e.g.: cmake /path/to/source path to an existing build tree, e.g.: cmake-gui .
CMake tutorial N
29 / 119
Basic CMake usage
Too much keyboard, time to click? II ccmake : the curses-based TUI (demo)
Here we can choose to toggle the WITH ACRODICT OPTION.
CMake tutorial N
30 / 119
Basic CMake usage
Too much keyboard, time to click? III cmake-gui : the Qt-based GUI (demo)
Again, we can choose to toggle the WITH ACRODICT OPTION. CMake tutorial N
31 / 119
Basic CMake usage
Remember CMake is a build generator? The number of active generators depends on the platform we are running on Unix, Apple, Windows: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Borland Makefiles MSYS Makefiles MinGW Makefiles NMake Makefiles NMake Makefiles JOM Unix Makefiles Visual Studio 10 Visual Studio 10 IA64 Visual Studio 10 Win64 Visual Studio 11 Visual Studio 11 Win64 Visual Studio 6 Visual Studio 7 Visual Studio 7 .NET 2003 Visual Studio 8 2005 Visual Studio 8 2005 Win64
Equally simple on other platforms It is as easy for a Windows build, however names for executables and libraries are computed in a platform specific way. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
CMake + MinGW Makefile $ ls totally-free acrodict.h acrodict.c acrolibre.c CMakeLists.txt $ mkdir build-win32 $ cd build-win32 ... $ make Scanning dependencies of target acrodict [ 33%] Building C object CMakeFiles/acrodict.dir/acrodict.c.obj Linking C shared library libacrodict.dll Creating library file: libacrodict.dll.a [ 33%] Built target acrodict Scanning dependencies of target Acrodictlibre [ 66%] Building C object CMakeFiles/Acrodictlibre.dir/acrolibre.c.obj Linking C executable Acrodictlibre.exe [ 66%] Built target Acrodictlibre Scanning dependencies of target Acrolibre [100%] Building C object CMakeFiles/Acrolibre.dir/acrolibre.c.obj Linking C executable Acrolibre.exe [100%] Built target Acrolibre
CMake tutorial N
33 / 119
Basic CMake usage
Installing things Install Several parts or the software may need to be installed: this is controlled by the CMake install command. Remember cmake --help-command install!! Listing 4: install command examples 1 2 3 4 5 6 7 8 9 10 11
... add executable ( Acrolibre a c r o l i b r e . c ) i n s t a l l (TARGETS A c r o l i b r e DESTINATION b i n ) i f (WITH ACRODICT) ... i n s t a l l (TARGETS A c r o d i c t l i b r e a c r o d i c t RUNTIME DESTINATION b i n LIBRARY DESTINATION l i b ARCHIVE DESTINATION l i b / s t a t i c ) i n s t a l l ( FILES a c r o d i c t . h DESTINATION i n c l u d e ) e n d i f (WITH ACRODICT)
CMake tutorial N
34 / 119
Basic CMake usage
Controlling installation destination Use relative DESTINATION One should always use relative installation DESTINATION unless you really want to use absolute path like /etc. Then depending on when you install:
CMake tutorial N
35 / 119
Basic CMake usage
Controlling installation destination Use relative DESTINATION One should always use relative installation DESTINATION unless you really want to use absolute path like /etc. Then depending on when you install: At CMake-time set CMAKE INSTALL PREFIX value $ cmake --help-variable CMAKE_INSTALL_PREFIX
CMake tutorial N
35 / 119
Basic CMake usage
Controlling installation destination Use relative DESTINATION One should always use relative installation DESTINATION unless you really want to use absolute path like /etc. Then depending on when you install: At CMake-time set CMAKE INSTALL PREFIX value $ cmake --help-variable CMAKE_INSTALL_PREFIX At Install-time use DESTDIR mechanism (Unix Makefiles) $ make DESTDIR=/tmp/testinstall install
CMake tutorial N
35 / 119
Basic CMake usage
Controlling installation destination Use relative DESTINATION One should always use relative installation DESTINATION unless you really want to use absolute path like /etc. Then depending on when you install: At CMake-time set CMAKE INSTALL PREFIX value $ cmake --help-variable CMAKE_INSTALL_PREFIX At Install-time use DESTDIR mechanism (Unix Makefiles) $ make DESTDIR=/tmp/testinstall install At CPack-time, CPack what? . . . be patient. At Package-install-time, we will see that later CMake tutorial N
35 / 119
Basic CMake usage
The CMake workflow (pictured) CMakeLists.txt
Project file(s), Makefiles, . . .
Object files
Installed files
Source files Generated Sources files
Binary package
CMake time
Source package
Build time Install time CPack time
Installed package
Package Install time
CMake tutorial N
36 / 119
Basic CMake usage
Using CMake variables CMake variables They are used by the user to simplify its CMakeLists.txt, but CMake uses many (˜170+) of them to control/change its [default] behavior. Try: cmake --help-variables-list. Inside a CMake script set (CMAKE INSTALL PREFIX /home/eric/testinstall) $ cmake --help-command set On the command line/TUI/GUI Remember that (besides options) each CMake tool takes a single argument (source tree or existing build tree) $ cmake -DCMAKE_INSTALL_PREFIX=/home/eric/testinstall . CMake tutorial N
37 / 119
Basic CMake usage
The install target Install target The install target of the underlying build tool (in our case make) appears in the generated build system as soon as some install commands are used in the CMakeLists.txt. 1 2 3 4 5 6 7 8 9 10 11 12
$ make DESTDIR=/tmp/testinstall install [ 33%] Built target acrodict [ 66%] Built target Acrodictlibre [100%] Built target Acrolibre Install the project... -- Install configuration: "" -- Installing: /tmp/testinstall/bin/Acrolibre -- Installing: /tmp/testinstall/bin/Acrodictlibre -- Removed runtime path from "/tmp/testinstall/bin/Acrodictlibre" -- Installing: /tmp/testinstall/lib/libacrodict.so -- Installing: /tmp/testinstall/include/acrodict.h $ CMake tutorial N
38 / 119
Basic CMake usage
Package the whole thing CPack CPack is a CMake friend application (detailed later) which may be used to easily package your software. Listing 5: add CPack support 1 2 3 4 5 6 7 8 9 10 11 12
... e n d i f (WITH ACRODICT) ... # Near t h e end o f t h e CMakeLists . t x t # Chose y o u r CPack g e n e r a t o r s e t (CPACK GENERATOR "TGZ" ) # Setup package v e r s i o n s e t (CPACK PACKAGE VERSION MAJOR 0 ) s e t ( CPACK PACKAGE VERSION MINOR 1 ) s e t ( CPACK PACKAGE VERSION PATCH 0 ) # ’ c a l l ’ CPack i n c l u d e ( CPack )
$ make package [ 33%] Built target acrodict [ 66%] Built target Acrodictlibre [100%] Built target Acrolibre Run CPack packaging tool... CPack: Create package using TGZ CPack: Install projects CPack: - Run preinstall target for: TotallyFree CPack: - Install project: TotallyFree CPack: Create package CPack: - package: /... TotallyFree-0.1.0-Linux.tar.gz generated. $ tar ztvf TotallyFree-0.1.0-Linux.tar.gz ... TotallyFree-0.1.0-Linux/include/acrodict.h ... TotallyFree-0.1.0-Linux/bin/Acrolibre ... TotallyFree-0.1.0-Linux/bin/Acrodictlibre ... TotallyFree-0.1.0-Linux/lib/libacrodict.so
CMake tutorial N
39 / 119
Basic CMake usage
CPack the packaging friend CPack is a standalone generator As we will see later on, CPack is standalone application, which like CMake is a generator. $ cpack -G ZIP CPack: Create package using ZIP CPack: Install projects CPack: - Run preinstall target for: TotallyFree CPack: - Install project: TotallyFree CPack: Create package CPack: - package: /... TotallyFree-0.1.0-Linux.zip generated. $ unzip -t TotallyFree-0.1.0-Linux.zip Archive: TotallyFree-0.1.0-Linux.zip testing: To.../include/acrodict.h OK testing: To.../bin/Acrolibre OK testing: To.../bin/Acrodictlibre OK testing: To.../lib/libacrodict.so OK No errors detected in compressed data of TotallyFree-0.1.0-Linux.zip.
Didn’t you mentioned testing? I CTest CTest is a CMake friend application (detailed later) which may be used to easily test your software. Listing 6: add CTest support 1 2 3 4 5 6 7 8 9 10 11 12
... e n d i f (WITH ACRODICT) ... enable testing ( ) a d d t e s t ( t o u l i b r e −b u i l t i n A c r o l i b r e "toulibre" ) a d d t e s t ( t o u l i b r e −d i c t A c r o d i c t l i b r e "toulibre" ) a d d t e s t ( FLOSS−d i c t A c r o d i c t l i b r e "FLOSS" ) a d d t e s t ( FLOSS−f a i l A c r o l i b r e "FLOSS" )
$ make test Running tests... Test project /build Start 1: toulibre-builtin 1/4 Test #1: toulibre-builtin .... Passed Start 2: toulibre-dict 2/4 Test #2: toulibre-dict........ Passed Start 3: FLOSS-dict 3/4 Test #3: FLOSS-dict .......... Passed Start 4: FLOSS-fail 4/4 Test #4: FLOSS-fail ..........***Failed
0.00 sec 0.00 sec 0.00 sec 0.00 sec
75% tests passed, 1 tests failed out of 4 Total Test time (real) =
0.01 sec
The following tests FAILED: 4 - FLOSS-fail (Failed) CMake tutorial N
41 / 119
Basic CMake usage
Didn’t you mentioned testing? II Tailor success rule CTest uses the return code in order to get success/failure status, but one can tailor the success/fail rule. Listing 7: add CTest support 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
... e n d i f (WITH ACRODICT) ... enable testing ( ) a d d t e s t ( t o u l i b r e −b u i l t i n A c r o l i b r e "toulibre" ) a d d t e s t ( t o u l i b r e −d i c t A c r o d i c t l i b r e "toulibre" ) a d d t e s t ( FLOSS−d i c t A c r o d i c t l i b r e "FLOSS" ) a d d t e s t ( FLOSS−f a i l A c r o l i b r e "FLOSS" ) s e t t e s t s p r o p e r t i e s ( FLOSS−f a i l PROPERTIES PASS REGULAR EXPRESSION "Sorry , I don ’t know :.* FLOSS" )
$ make test Running tests... Test project /build Start 1: toulibre-builtin 1/4 Test #1: toulibre-builtin .... Passed Start 2: toulibre-dict 2/4 Test #2: toulibre-dict........ Passed Start 3: FLOSS-dict 3/4 Test #3: FLOSS-dict .......... Passed Start 4: FLOSS-fail 4/4 Test #4: FLOSS-fail .......... Passed
0.00 sec 0.00 sec 0.00 sec 0.00 sec
100% tests passed, 0 tests failed out of 4 Total Test time (real) =
0.01 sec
CMake tutorial N
42 / 119
Basic CMake usage
CTest the testing friend CTest is a standalone generic test driver As we will see later on, CTest is standalone application, which can run a set of test programs. $ ctest -R toulibre$ ctest -R FLOSS-fail -V Test project /build Test project Start 1: toulibre-builtin Constructing a list of tests 1/2 Test #1: toulibre-builtin .. Passed 0.00 sec Done constructing a list of tests Start 2: toulibre-dict Checking test dependency graph... 2/2 Test #2: toulibre-dict ..... Passed 0.00 sec Checking test dependency graph end test 4 100% tests passed, 0 tests failed out of 2 Start 4: FLOSS-fail 4: Test command: /Acrolibre "FLOSS" Total Test time (real) = 0.01 sec 4: Test timeout computed to be: 9.99988e+06 4: Sorry, I don’t know: 1/1 Test #4: FLOSS-fail ...........***Failed 0.00 sec 0% tests passed, 1 tests failed out of 1 Total Test time (real) = 0.00 sec The following tests FAILED: 4 - FLOSS-fail (Failed) Errors while running CTest CMake tutorial N
43 / 119
Basic CMake usage
CDash the test results publishing Dashboard CTest may help publishing the results of the tests on a CDash dashboard (http://www.cdash.org/) for easing collective regression testing. More on this later. . . http://www.orfeo-toolbox.org/–http://dash.orfeo-toolbox.org/
CMake tutorial N
44 / 119
Basic CMake usage
Summary CMake basics Using CMake basics we can already do a lot of things with minimal writing.
Write simple build specification file: CMakeLists.txt Discover compilers (C, C++, Fortran) Build executable and library (shared or static) in a cross-platform manner Package the resulting binaries with CPack Run systematic tests with CTest and publish them with CDash CMake tutorial N
45 / 119
Basic CMake usage
Seeking more information or help There are several places you can go by yourself: 1
Read the FAQ: http://www.cmake.org/Wiki/CMake_FAQ
2
Read the Wiki: http://www.cmake.org/Wiki/CMake
3
Ask on the Mailing List: http://www.cmake.org/cmake/help/mailing.html
4
Browse the built-in help: cmake --help-xxxxx
CMake tutorial N
46 / 119
Discovering environment specificities
Outline 1
Basic CMake usage
2
Discovering environment specificities Handling platform specificities Working with external packages
3
More CMake scripting Custom commands Generated files
4
Advanced CMake usage Cross-compiling with CMake Export your project
CMake tutorial N
47 / 119
Discovering environment specificities
Outline 1
Basic CMake usage
2
Discovering environment specificities Handling platform specificities Working with external packages
3
More CMake scripting Custom commands Generated files
4
Advanced CMake usage Cross-compiling with CMake Export your project
CMake tutorial N
48 / 119
Discovering environment specificities
How to discover system System/compiler specific variables Right after the project command CMake has set up a bunch of variables which can be used to tailor the build in a platform specific way. system specific WIN32 True on Windows systems, including Win64. UNIX True for UNIX and UNIX like operating systems. APPLE True if running on Mac OS X. CYGWIN True for Cygwin. compiler specific MSVC True when using Microsoft Visual C CMAKE COMPILER IS GNU True if the compiler is GNU.
MINGW true if the compiler is MinGW. N
CMake tutorial
49 / 119
Discovering environment specificities
Handle system specific code Some functions like strcasestr (lines 6 and 7) may not be available on all platforms. Listing 8: excerpt from acrodict.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
c o n s t a c r o I t e m t ∗ a c r o d i c t g e t a p p r o x ( c o n s t c h a r ∗ name ) { i n t c u r r e n t =0; i n t found =0; #i f d e f GUESS NAME w h i l e ( ( s t r l e n ( a c r o d i c t [ c u r r e n t ] . name) >0) && ! found ) { i f ( ( s t r c a s e s t r ( name , a c r o d i c t [ c u r r e n t ] . name ) ! = 0 ) | | ( s t r c a s e s t r ( a c r o d i c t [ c u r r e n t ] . name , name ) ! = 0 ) ) { found =1; } else { c u r r e n t ++; } } i f ( found ) { r e t u r n &( a c r o d i c t [ c u r r e n t ] ) ; } else #e n d i f { r e t u r n NULL ; } } CMake tutorial N
50 / 119
Discovering environment specificities
Use system specific 1 2 3 4 5 6 7 8 9 10 11 12 13 14
option
# B u i l d o p t i o n w i t h d e f a u l t v a l u e t o ON o p t i o n (WITH ACRODICT "Include acronym dictionary support" ON) i f (NOT WIN32 ) o p t i o n (WITH GUESS NAME "Guess acronym name" ON) e n d i f (NOT WIN32 ) ... i f (WITH ACRODICT) # l i s t o f sources in our l i b r a r y s e t ( LIBSRC a c r o d i c t . h a c r o d i c t . c ) i f (WITH GUESS NAME) s e t s o u r c e f i l e s p r o p e r t i e s ( a c r o d i c t . c PROPERTIES COMPILE FLAGS "-DGUESS_NAME" ) e n d i f (WITH GUESS NAME) a d d l i b r a r y ( a c r o d i c t ${LIBSRC } ) ...
Line 4 defines a CMake option, but not on WIN32 system. Then on line 11, if the option is set then we pass a source specific compile flags. cmake --help-command set source files properties
CMake tutorial N
51 / 119
Discovering environment specificities
System specific in real life Real [numeric] life project Real projects (i.e. not the toy of this tutorial) have many parts of their CMakeLists.txt which deal with system/compiler specific option/feature. MuseScore : http://musescore.org http://mscore.svn.sourceforge.net/viewvc/mscore/trunk/mscore/mscore/
Display CMakeLists.txt from MuseScore CERTI : https://savannah.nongnu.org/projects/certi/ http://cvs.savannah.gnu.org/viewvc/certi/?root=certi
CMake (of course): http://www.cmake.org LLVM: http://llvm.org/docs/CMake.html many more . . .
CMake tutorial N
52 / 119
Discovering environment specificities
What about projectConfig.h file? I Project config files Sometimes it’s easier to test for features and then write a configuration file (config.h, project config.h, . . . ). The CMake way to do that is to: 1
lookup system information using CMake variable, functions, macros (built-in or imported) then set various variables,
2
use the defined variable in order to write a template configuration header file
3
then use configure file in order to produce the actual config file from the template.
CMake tutorial N
53 / 119
Discovering environment specificities
What about projectConfig.h file? II Listing 9: Excerpt from CERTI project’s main CMakeLists.txt 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
# Load C h ec ke r macros INCLUDE ( C h e c k F u n c t i o n E x i s t s ) FIND FILE ( HAVE STDINT H NAMES s t d i n t . h ) FIND FILE ( HAVE SYS SELECT H NAMES s e l e c t . h PATH SUFFIXES s y s ) INCLUDE ( C h e c k I n c l u d e F i l e ) CHECK INCLUDE FILE ( time . h HAVE TIME H ) FIND LIBRARY ( RT LIBRARY r t ) i f ( RT LIBRARY ) SET( CMAKE REQUIRED LIBRARIES ${CMAKE REQUIRED LIBRARIES} ${RT LIBRARY } ) e n d i f ( RT LIBRARY ) CHECK FUNCTION EXISTS ( c l o c k g e t t i m e HAVE CLOCK GETTIME) CHECK FUNCTION EXISTS ( c l o c k s e t t i m e HAVE CLOCK SETTIME ) CHECK FUNCTION EXISTS ( c l o c k g e t r e s HAVE CLOCK GETRES ) CHECK FUNCTION EXISTS ( c l o c k n a n o s l e e p HAVE CLOCK NANOSLEEP) IF (HAVE CLOCK GETTIME AND HAVE CLOCK SETTIME AND HAVE CLOCK GETRES ) SET( HAVE POSIX CLOCK 1 ) ENDIF (HAVE CLOCK GETTIME AND HAVE CLOCK SETTIME AND HAVE CLOCK GETRES ) ... CONFIGURE FILE ( ${CMAKE CURRENT SOURCE DIR} / c o n f i g . h . cmake ${CMAKE CURRENT BINARY DIR} / c o n f i g . h )
CMake tutorial N
54 / 119
Discovering environment specificities
What about projectConfig.h file? III 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
Excerpt from CERTI config.h.cmake /* define if the compiler has numeric_limits */ #cmakedefine HAVE_NUMERIC_LIMITS /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STDLIB_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STRINGS_H 1 ... /* Name of package */ #cmakedefine PACKAGE "@PACKAGE_NAME@" /* Define to the address where bug reports for this package should be sent. */ #cmakedefine PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@" /* Define to the full name of this package. */ #cmakedefine PACKAGE_NAME "@PACKAGE_NAME@" /* Define to the full name and version of this package. */ #cmakedefine PACKAGE_STRING "@PACKAGE_NAME@-@PACKAGE_VERSION@"
CMake tutorial N
55 / 119
Discovering environment specificities
What about projectConfig.h file? IV And you get something like: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
Excerpt from generated CERTI config.h /* define if the compiler has numeric_limits */ #define HAVE_NUMERIC_LIMITS /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 ... /* Name of package */ /* #undef PACKAGE */ /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "[email protected]" /* Define to the full name of this package. */ #define PACKAGE_NAME "CERTI" /* Define to the full name and version of this package. */ /* #undef PACKAGE_STRING */
CMake tutorial N
56 / 119
Discovering environment specificities
Outline 1
Basic CMake usage
2
Discovering environment specificities Handling platform specificities Working with external packages
3
More CMake scripting Custom commands Generated files
4
Advanced CMake usage Cross-compiling with CMake Export your project
CMake tutorial N
57 / 119
Discovering environment specificities
The
find package
command I
Finding external package Project may be using external libraries, programs, files etc. . . Those can be found using the find package command.
Listing 10: using libxml2 1 2 3 4 5 6 7 8 9
f i n d p a c k a g e ( LibXml2 ) i f ( LIBXML2 FOUND ) a d d d e f i n i t i o n s (−DHAVE XML ${LIBXML2 DEFINITIONS } ) i n c l u d e d i r e c t o r i e s ( ${LIBXML2 INCLUDE DIR } ) e l s e ( LIBXML2 FOUND ) s e t ( LIBXML2 LIBRARIES "" ) e n d i f ( LIBXML2 FOUND ) ... t a r g e t l i n k l i b r a r i e s ( MyTarget ${LIBXML2 LIBRARIES } ) CMake tutorial N
58 / 119
Discovering environment specificities
The
find package
command II
Find modules usually define standard variables (for module XXX) 1
2
3
4
5 6
XXX FOUND: Set to false, or undefined, if we haven’t found, or don’t want to use XXX. XXX INCLUDE DIRS: The final set of include directories listed in one variable for use by client code. XXX LIBRARIES: The libraries to link against to use XXX. These should include full paths. XXX DEFINITIONS: Definitions to use when compiling code that uses XXX. XXX EXECUTABLE: File location of the XXX tool’s binary. XXX LIBRARY DIRS: Optionally, the final set of library directories listed in one variable for use by client code.
See doc cmake --help-module FindLibXml2 Many modules are provided by CMake (130 as of CMake 2.8.7)
CMake tutorial N
59 / 119
Discovering environment specificities
The
find package
command III
You may write your own: http://www.cmake.org/Wiki/CMake:Module_Maintainers You may find/borrow modules from other projects which use CMake KDE4: http://websvn.kde.org/trunk/KDE/kdelibs/cmake/modules/ PlPlot: http://plplot.svn.sourceforge.net/viewvc/plplot/ trunk/cmake/modules/ http://cmake-modules.googlecode.com/svn/trunk/Modules/ probably many more. . .
A module may provide not only CMake variables but new CMake macros (we will see that later with the MACRO, FUNCTION CMake language commands)
CMake tutorial N
60 / 119
Discovering environment specificities
The other
find xxxx
commands I
The find xxx command family find package is a high level module finding mechanism but there are lower-level CMake commands which may be used to write find modules or anything else inside CMakeLists.txt
to find an executable program: find program to find a library: find library to find any kind of file: find file to find a path where a file resides: find path
# − Find P r e l u d e c o m p i l e r # Find t h e P r e l u d e s y n c h r o n o u s language c o m p i l e r w i t h a s s o c i a t e d i n c l u d e s p a t h . # See h t t p : / / www . l i f l . f r / ˜ f o r g e t / p r e l u d e . h t m l # T h i s module d e f i n e s # PRELUDE COMPILER , t h e p r e l u d e c o m p i l e r # PRELUDE COMPILER VERSION , t h e v e r s i o n o f t h e p r e l u d e c o m p i l e r # PRELUDE INCLUDE DIR , where t o f i n d dword . h , e t c . # PRELUDE FOUND, I f f a l s e , P r e l u d e was n o t f o u n d . # On can s e t PRELUDE PATH HINT b e f o r e u s i n g f i n d p a c k a g e ( P r e l u d e ) and t h e # module w i t h use t h e PATH as a h i n t t o f i n d p r e l u d e c . ... i f ( PRELUDE PATH HINT ) message (STATUS "FindPrelude: using PATH HINT: ${PRELUDE_PATH_HINT}" ) else ( ) s e t ( PRELUDE PATH HINT ) endif ( ) # FIND PROGRAM t w i c e u s i n g NO DEFAULT PATH on f i r s t s h o t f i n d p r o g r a m ( PRELUDE COMPILER NAMES p r e l u d e c PATHS ${PRELUDE PATH HINT} PATH SUFFIXES b i n NO DEFAULT PATH DOC "Path to the Prelude compiler command ’preludec ’" ) f i n d p r o g r a m ( PRELUDE COMPILER NAMES p r e l u d e c PATHS ${PRELUDE PATH HINT} PATH SUFFIXES b i n DOC "Path to the Prelude compiler command ’preludec ’" )
i f ( PRELUDE COMPILER ) # g e t t h e p a t h where t h e p r e l u d e c o m p i l e r was f o u n d g e t f i l e n a m e c o m p o n e n t (PRELUDE PATH ${PRELUDE COMPILER} PATH) # remove b i n g e t f i l e n a m e c o m p o n e n t (PRELUDE PATH ${PRELUDE PATH} PATH) # add p a t h t o PRELUDE PATH HINT l i s t (APPEND PRELUDE PATH HINT ${PRELUDE PATH} ) e x e c u t e p r o c e s s (COMMAND ${PRELUDE COMPILER} −v e r s i o n OUTPUT VARIABLE PRELUDE COMPILER VERSION OUTPUT STRIP TRAILING WHITESPACE ) e n d i f ( PRELUDE COMPILER ) f i n d p a t h ( PRELUDE INCLUDE DIR NAMES dword . h PATHS ${PRELUDE PATH HINT} PATH SUFFIXES l i b / p r e l u d e DOC "The Prelude include headers" ) ... # h a n d l e t h e QUIETLY and REQUIRED a r g u m e n t s and s e t PRELUDE FOUND t o TRUE i f # a l l l i s t e d v a r i a b l e s a r e TRUE i n c l u d e ( FindPackageHandleStandardArgs ) FIND PACKAGE HANDLE STANDARD ARGS(PRELUDE REQUIRED VARS PRELUDE COMPILER PRELUDE INCLUDE DIR )
CMake tutorial N
63 / 119
Discovering environment specificities
Advanced use of external package I Installed External package The previous examples suppose that you have the package you are looking for on your host. you did install the runtime libraries you did install eventual developer libraries, headers and tools
What if the external packages: are only available as source (tarball, VCS repositories, . . . ) use a build system (autotools or CMake or . . . )
CMake tutorial N
64 / 119
Discovering environment specificities
Advanced use of external package II ExternalProject Add The ExternalProject.cmake CMake module defines a highlevel macro which does just that: 1
download/checkout source
2
update/patch
3
configure
4
build
5
install (and test)
. . . an external project $ cmake --help-module ExternalProject
CMake tutorial N
65 / 119
More CMake scripting
Outline 1
Basic CMake usage
2
Discovering environment specificities Handling platform specificities Working with external packages
3
More CMake scripting Custom commands Generated files
4
Advanced CMake usage Cross-compiling with CMake Export your project
CMake tutorial N
66 / 119
More CMake scripting
The different CMake “modes” Normal mode: the mode used when processing CMakeLists.txt Command mode: cmake -E , command line mode which offers basic commands in a portable way: