'''Index''' [[TableOfContents]] Perform the following steps to get the [http://www.cmake.org CMake Make System] working for you. The example shows how to set things up such that the binary {{{startCompletionServer}}} is built by a call to ''make'' and that the distribution {{{autocompletion-0.1.1-Source.tar.gz}}} is built by a call to {{{make package_source}}}. It further demonstrates the basic work cycle and some advanced features of CMake. = Basic workcycle = Let us assume that all your source files (.h and .cpp files) are located in one top level directory called {{{autocompletion}}}. In this directory, create a file called {{{CMakeLists.txt}}} with the following content: {{{ PROJECT(autocompletion) SET(BASEFILES Globals.cpp Globals.h HYBCompleter.cpp HYBCompleter.h IndexBase.cpp IndexBase.h History.cpp History.h codes.cpp codes.h nrutil.c nrutil.h QueryParameters.cpp QueryParameters.h HYBIndex.cpp HYBIndex.h WordsFile.cpp WordsFile.h ConcurrentLog.cpp ConcurrentLog.h DocsDB.cpp DocsDB.h Document.cpp Document.h ExcerptsGenerator.cpp ExcerptsGenerator.h CompletionServer.cpp CompletionServer.h CompleterBase.cpp CompleterBase.h ) ADD_EXECUTABLE(startCompletionServer StartCompletionServer.cpp ${BASEFILES}) # TODO: the following ist not portable! # we could use IF(UNIX) or IF($ENV{OSTYPE} EQUAL linux-gnu) ADD_DEFINITIONS(-fexceptions -static -O6 -Wall -DVERSION=\"'`date +\"Version %d%b%y %H:%M\"`'\" -DNDEBUG -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_REENTRANT ) TARGET_LINK_LIBRARIES(startCompletionServer pthread z) }}} This tells CMake the name of the project, the basic .h and .cpp files that every executable is made from, the name and the dependencies of the executable {{{startCompletionServer}}} that you want to build, some compiler and linker options to be applied in every compiler and linker run, and the libraries against which {{{startCompletionServer}}} has to be linked. Now create a sibling directory (or a directory anywhere out of the subtree rooted at {{{autocompletion}}}), change into this directory and make an "out-of-source" build: {{{ $ cd .. $ mkdir build $ cd build $ cmake ../autocompletion # out-of-source: build in a completely different tree $ make $ ./startCompletionServer }}} == Some terminology == Before we go any further, let us clarify some important CMake terminology: The '''source tree''' is where source files (*.c, etc.) and configuration files (C``MakeList.txt, etc.) live. The '''build tree''' is where you build the software. It contains everything that is configured or built. It has got a lot of files in it (e.g., *.o) that are essential to the build of executables or libraries, but which are not of interest to pure users of the software. It is possible to do an '''in-source build''' where the build tree is superimposed on the source tree, but it is just easier to keep the two separate since it allows you to entirely remove your build tree and start over without molesting your source tree. The latter is called an '''out-of-source build'''. The '''install tree''' is where you install the subset of the build tree that is used by pure users. So it consists normally of just executables, libraries, and documentation. The various {{{CMakeLists.txt}}} files that are in the source tree specify exactly what is to be put in the install tree. The install tree should be kept entirely separate from the source tree and from the build tree. A '''source package''' normally just contains a packager-specified subset of the source tree (e.g., the packager would want to skip .svn or CVS directories) in some packager-specified format (e.g., compressed tarball). A software packager can generate source packages of its software using CMake (via the CPack utility). Users of source packages obviously have to build the packaged software for themselves using CMake, but that gives them a lot of freedom since CMake configures the build for the special circumstances of their particular system. For example, it is very good at finding 3rd-party libraries required for the build that happen to be in non-standard locations or modifying the build (e.g., dropping parts of it) if certain 3rd-party components are not found. A '''binary package''' contains everything that is in the install tree in some packager-specified format (e.g., compressed tarball). A software packager can generate binary packages of its software using CMake (via CPack). Users of binary packages do not have to build anything (they just use the executables and libraries that are supplied), but such binary packages demand a lot in terms of standardization. For example, they normally expect 3rd-party libraries to be of the same version and in the same location for the user as they were for the packager. So binary packages are great if built for a standard environment, such as a particular Linux distribution, but if there is any variation in the standard (e.g., Debian versus RedHat), the departure from the expected standards leads to trouble, and the user is better off building the software from a source package. == Installing == To specify that the executable {{{startCompletionServer}}} shall be installed into the {{{bin}}} subdirectory relative to the {{{CMAKE_INSTALL_PREFIX}}}, add the following line to {{{CMakeLists.txt}}}: {{{ INSTALL(TARGETS startCompletionServer RUNTIME DESTINATION bin) }}} Now rerun CMake in the build tree, selecting the build tree top-level directory as the value for {{{CMAKE_INSTALL_PREFIX}}}: {{{ $ cmake ../autocompletion -DCMAKE_INSTALL_PREFIX=. $ make help }}} The last command shows you that you now have an {{{install}}} target that you can make: {{{ $ make install $ bin/startCompletionServer }}} As you can see, the executable has been installed into the {{{bin}}} subdirectory of your current (build tree) directory. Of course, at your customer's site the executable would not be installed into the build tree, but rather into the install tree located somewhere below {{{/usr/local}}}. == Packaging == To create a binary and a source package, add the following lines to {{{CMakeLists.txt}}}: {{{ SET(CPACK_GENERATOR TGZ) SET(CPACK_SOURCE_GENERATOR TGZ) INCLUDE(CPack) }}} Now make the following targets: {{{ $ make rebuild_cache $ make help $ make package $ make package_source }}} {{{make help}}} shows you that you now have the additional targets {{{package}}} and {{{package_source}}}. As you can see, your directory now contains the files {{{autocompletion-0.1.1-Linux.tar.gz}}} and {{{autocompletion-0.1.1-Source.tar.gz}}} == The CMake cache == You may wonder what the above target ''rebuild_cache'' is about. When running CMake for the first time, you notice that it creates a file {{{CMakeCache.txt}}}. The cache is best thought of as a configuration file. Indeed Unix users could consider the cache as equivalent to the set of flags passed to the ''./configure'' command. The first time CMake is run, it produces a {{{CMakeCache.txt}}} file. This file contains things such as the existence and location of a native JPEG library. The entries are added in response to certain CMake commands (e.g. FIND_LIBRARY) as they are processed anywhere in {{{CMakeLists.txt}}} files anywhere in the source tree. After CMake has been run and created a {{{CMakeCache.txt file}}} - you may edit it. The CMake GUI ({{{ccmake .}}}) will allow you to edit the options easily, or you can edit the file directly. The main reason for editing the cache would be to give CMake the location of a native library such as JPEG, or to stop it from using a native library and use a version of the library in your source tree. CMake will not alter an existing entry in the cache file itself. If your {{{CMakeLists.txt}}} files change significantly, you will need to remove the relevant entries from the cache file. If you have not already hand-edited the cache file, you could just delete it before re-running CMake. When running CMake from the command line, it is possible to specify command line options to CMake that will set values in the cache. This is done with a {{{-DVARIABLE:TYPE=VALUE}}} syntax on the command line. Here is an example: Say that in your source code, a preprocessor macro {{{ #if defined(USE_MEMSET) ... #elif defined(USE_BZERO) ... #endif }}} decides on whether you want to use the function {{{memset()}}} or {{{bzero()}}} to set the first n bytes of a byte area to zero. When you invoke CMake for the first time, you do it like this in your build tree; {{{ $ cmake -DMEMSET:string=USE_MEMSET /path/to/source/tree }}} This defines a variable {{{MEMSET}}} in the CMake cache, with a default value of {{{USE_MEMSET}}}. You can alter the value of this variable in the cache by calling {{{ccmake .}}} or {{{make edit_cache}}}. In your {{{CMakeLists.txt}}}, you have a section {{{ IF(MEMSET STREQUAL USE_MEMSET) ADD_DEFINITIONS(-DUSE_MEMSET) ELSE(MEMSET STREQUAL USE_BZERO) ADD_DEFINITIONS(-DUSE_BZERO) ENDIF(MEMSET STREQUAL USE_MEMSET) }}} that passes on the correct macro value to the preprocessor. Some projects are very complex and setting one value in the cache may cause new options to appear the next time the cache is built. The rule is to keep building the cache until it doesn't change. For most projects this will be just once. For some complicated ones it will be twice. The ''rebuild_cache'' target runs CMake on the source tree and picks up additional cache entries if they exist. == Running CMake from the command line == From the command line, CMake can be run as an interactive question and answer session or as a non-interactive program. To run in interactive mode, just pass the option '-i' to {{{cmake}}}. This will cause CMake to ask you to enter a value for each value in the cache file for the project. The process stops when there are no longer any more questions to ask. Using CMake to build a project in non-interactive mode is a simple process if the project does not have many options. For larger projects, using {{{ccmake}}} or {{{cmake -i}}} is recommended. This is because as you change options in the {{{CMakeCache.txt}}} file, CMake may add new entries to that file. It can be difficult to know when to stop the "run CMake and edit the cache file" cycle without the aid of an interface. To build with just {{{cmake}}}, change directory into where you want the binaries to be placed. Run {{{cmake}}} and provide the path to the source code as its argument. Once you have edited the {{{CMakeCache.txt}}} file, rerun {{{cmake}}}, and repeat this process until you are happy with the cache settings. Then type {{{make}}} and your project should compile. Some projects will have install targets as well, so you can type {{{make install}}} to install them. = Testing = CMake comes with a testing framework, [http://www.cmake.org/Wiki/CMake#CTest CTest]. To use it, add the following lines to {{{CMakeLists.txt}}}: {{{ ENABLE_TESTING() ADD_EXECUTABLE(test-adler32 test-adler32.cpp ${BASEFILES}) TARGET_LINK_LIBRARIES(test-adler32 pthread z) ADD_TEST(adler32 test-adler32 4711) # 4711 is an arbitrary input to test-adler32 }}} Then type the following commands: {{{ $ make rebuild_cache $ make $ make test }}} = Creating libraries = You may have noticed that most of the object files for {{{test-adler32}}} are built again, even though they already have been built for {{{startCompletionServer}}}. You may also have noticed that cmake is building files inside a build directory different for each target. It is really meant to be that way! (Normally you may have different compile flags for different targets so you want that.) If you do not want that then just put your BASEFILES in a "convenience library" and reuse it from both targets such as: {{{ ADD_LIBRARY(base ${BASEFILES}) ADD_EXECUTABLE(target1 target1.cpp) TARGET_LINK_LIBRARIES(target1 base) ADD_EXECUTABLE(target2 target2.cpp) TARGET_LINK_LIBRARIES(target2 base) }}} = Using subdirectories = When your project becomes larger, you may want to divide it into several subdirectories, such as {{{src}}}, {{{include}}}, {{{lib}}}, {{{doc}}}, etc. For example, create a {{{src}}} subdirectory, move all your .h and .cpp files along with the current {{{CMakeLists.txt}}} into it, and create a new {{{CMakeLists.txt}}} in the top-level directory: {{{ # top-level CMakeLists.txt PROJECT(autocompletion) # Recurse into subdirs ADD_SUBDIRECTORY(src) }}} CMake works recursively, descending from the current diretory into any directory listed in the {{{ADD_SUBDIRECTORY}}} command. Values of variables are inherited. = Generating and using config.h = If you want to write software that compiles and runs on different operating systems, you have to take care for the special properties of the different platforms. On different operating systems there are subtle differences, e.g. on FreeBSD you should not use {{{malloc.h}}}, while it is perfectly ok to use it on Linux. These differences are typically handled by providing a header file that contains a bunch of define-statements according to the platform properties. This file is usually named {{{config.h}}} and is listed as the first {{{#include}}} in every header file. To create {{{config.h}}}, first create a template file {{{config.h.cmake}}} with, for example, the following content: {{{ #cmakedefine HAVE_MALLOC_H 1 #cmakedefine HAVE_SYS_MOUNT_H 1 #cmakedefine HAVE_MEMCPY 1 #cmakedefine HAVE_FLOEDELDOE 1 #ifdef HAVE_MEMCPY #define bla foo #else #define bla baz #endif }}} Now add the following lines to your {{{CMakeLists.txt}}}: {{{ INCLUDE (CheckIncludeFiles) # usage: CHECK_INCLUDE_FILES (
) CHECK_INCLUDE_FILES (malloc.h HAVE_MALLOC_H) # If another header is required to use the header you are looking for, # you have to list the header files separated by semicolons CHECK_INCLUDE_FILES ("sys/param.h;sys/mount.h" HAVE_SYS_MOUNT_H) INCLUDE (CheckFunctionExists) CHECK_FUNCTION_EXISTS(memcpy HAVE_MEMCPY) CHECK_FUNCTION_EXISTS(floedeldoe HAVE_FLODELDOE) CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h) }}} Now CMake will use the template file and the results of the various {{{CHECK_}}} commands to create your {{{config.h}}}. For example, the following file could be created: {{{ #define HAVE_MALLOC_H 1 #define HAVE_SYS_MOUNT_H 1 #define HAVE_MEMCPY 1 /* #undef HAVE_FLOEDELDOE 1 */ #ifdef HAVE_MEMCPY #define bla foo #else #define bla baz #endif }}} = Useful commands = {{{ # Add include directories to the build. INCLUDE_DIRECTORIES(/usr/include/nspr) # Set the minimum required version of cmake for a project. CMAKE_MINIMUM_REQUIRED(VERSION 2.4) # the following line works in 2.4, but not in 2.0 :-) # CMAKE_MINIMUM_REQUIRED(VERSION 2.4 FATAL_ERROR) # workaround for stopping cmake IF(CMAKE_SYSTEM_VERSION LESS 2.4) MESSAGE(FATAL_ERROR "STOPPED! You need at least CMake version 2.4 for this.") ENDIF(CMAKE_SYSTEM_VERSION LESS 2.4) # option to produce more 'verbose' compiling SET(CMAKE_VERBOSE_MAKEFILE ON) # set a variable to a value and test against this value SET(BASERT USE_NSPR) IF(BASERT STREQUAL USE_NSPR) ADD_DEFINITIONS(-DUSE_NSPR) ELSE(BASERT STREQUAL USE_NSPR) ADD_DEFINITIONS(-DUSE_LINUX) ENDIF(BASERT STREQUAL USE_NSPR) }}} You can finde more useful CMake variables on http://www.cmake.org/Wiki/CMake_Useful_Variables = Getting help and further reading = == On your command line == {{{ $ man cmake $ cmake --help $ cmake --help-command CMAKE_MINIMUM_REQUIRED }}} == On the web == [http://www.cmake.org/HTML/Documentation.html CMake Original Documentation] [http://www.cmake.org/Wiki/CMake CMake Wiki] [http://www.cmake.org/mailman/listinfo/cmake CMake Mailing List] [http://www.cmake.org/Wiki/CMake_FAQ The CMake FAQ] [http://www.cmake.org/cmake/help/syntax.html Quick syntax introduction] = CMake troubleshooting = '''Problem''': You want to put all your object files into a static convenience library `libconv.a`. You want to link statically against this library and against all other (system) libraries, that is, you want to create a completely static executable, for example `startCompletionServer`, that you can send around to other people. But when you start the binary, you get {{{ $ ./startCompletionServer -bash: ./startCompletionServer: No such file or directory }}} '''Solution''': Make sure that you use CMake 2.6. The above is a linker error produced by earlier versions of CMake, which mixes static with dynamic linking instructions.