
What is CMake?
Authors: Claus Klein Date: 05.02.2010 Revision: 0.3 Description: Quick overview how to use CMake [10] to build projects in a portable way Contents
CMake basic concepts Source-tree Binary-tree Out-of-source build In-source build CMakeLists.txt CMake (Find) Module Usage Example Generators CMake Variables CMAKE_MODULE_PATH CMAKE_INSTALL_PREFIX CMAKE_BUILD_TYPE MAKE_CONFIGURATION_TYPES EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH BUILD_SHARED_LIBS CMAKE_VERBOSE_MAKEFILE CMAKE_USE_RELATIVE_PATHS Notes to authors of FindXXX.cmake files CMake Cross Compiling Setting up the system and toolchain CMAKE_SYSTEM_NAME CMAKE_SYSTEM_VERSION CMAKE_SYSTEM_PROCESSOR CMAKE_C_COMPILER CMAKE_CXX_COMPILER Resources Footnotes CMake [1] is an open-source, cross-platform build manager that can generate native build environments for your projects. It takes as input common text files (named CMakeLists.txt) which define your project build parameters. These text files are written in a very simple syntax [2] and are system independent, meaning that you can port your projects to different platforms with almost no effort at all.
This schema shows how the CMake [10] build-system generator works:
If you are interested in learning more about cmake read the book "Mastering CMake" [3] or check the CMake Wiki [11].
Warning
The cmake files for the software should be designed, written and tested exclusively for Out-of-source build, therefore we strongly disencourage In-source build!! It is also in our concept that a package should be installed first (with make install) before it can be used by other packages, therefore we also strongly disencourage trying to use the Binary-tree from one package as the "installation directory" to other packages. CMake basic concepts
Source-tree
Top level directory where the sources of the project are located. This directory is usually the root directory of a package (i.e. where the top CMakeLists.txt file is located). This directory can be referenced incmake with the variable PROJECT_SOURCE_DIR.
Binary-tree
Top level directory where cmake puts the objects, libraries, executables and other files resulting from the build process. (see: Out-of-source build) This directory can be referenced in cmake with the variablePROJECT_BINARY_DIR.
Out-of-source build
CMake [10] offers the possibility to build a software project in a directory tree completely separate from the source-tree directory. This way your source-tree directory is kept clean, i.e. you don't mix your source code with objects and other files generated from the build process. To do an out-of-source build you just need to call cmake in a separate directory and pass the project's source-tree as the last argument:
$ cd /var/tmp $ cmake /data/myproject In-source build
Hint
CMake developers strongly disencourage the use of in-source builds! CMakeLists.txt
Text files written in simple cmake language [2] for defining the project parameters and it's build components.
A very simple example is the following file:
cmake_minimum_required(VERSION 2.6) # # Name the project PROJECT(Simple)
# setup the build configuration option(BUILD_SHARED_LIBS "Build shared libraries" ON) option(CMAKE_USE_RELATIVE_PATHS "Use relative paths in makefiles" ON) if (MSVC) set(CMAKE_INSTALL_PREFIX "C:/usr" CACHE STRING "Install path prefix" FORCE) endif (MSVC) set(CMAKE_VERBOSE_MAKEFILE ON CACHE INTERNAL "Setup makefile to verbose" FORCE) if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE) endif(NOT CMAKE_BUILD_TYPE)
# Tell CMake to define some CPP vars and include pathes add_definitions(-DUSE_MOCK_DB ...) remove_definitions(-DFOO -DBAR ...) include_directories(include) # add generic include path to search
# Tell CMake to build a shared library from some source files add_library(mylib SHARED lib/foo.c lib/bar.c)
# make sure the library gets installed install(TARGETS mylib DESTINATION lib)
# Tell CMake to build an executable add_executable(exampleProgram main.c utils.c) target_link_libraries(exampleProgram mylib) # add generic lib name to link
# install it too install(TARGETS exampleProgram DESTINATION bin)
# and install all header files to a subdir of ${CMAKE_INSTALL_PREFIX} install(DIRECTORY include DESTINATION include/${PROJECT_NAME} FILES_MATCHING PATTERN "*.h")
CMake (Find) Module
CMake [10] script for finding software packages and set it's libraries and header files into appropriate variables so that they can be used in the build process of another project. (e.g. FindACE.cmake, FindZLIB.cmake, FindQt4.cmake) See [4] for more information on "How to find libraries".
In CMakeLists.txt, write:
find_package(LibSMI REQUIRED) include_directories(${LibSMI_INCLUDE_DIRS}) set(LIBS ${LIBS} ${LibSMI_LIBRARIES}) Then, after detecting all the libraries, for your target:
target_link_libraries(exampleProgram ${LIBS}) For this to work, you'll need a file called FindLibSMI.cmake in your CMAKE_MODULE_PATH. The CMake Documentation [12] list all available commands and modules deliverd with CMake [10].
Usage Example
After doing cd build; cmake -G 'Visual Studio 8 2005' .. on a dos cmd window:
Generators
The following generators are available on windows platform:
Borland Makefiles Generates Borland makefiles. MSYS Makefiles Generates MSYS makefiles. MinGW Makefiles Generates a make file for use with mingw32-make. NMake Makefiles Generates NMake makefiles. Unix Makefiles Generates standard UNIX makefiles. Visual Studio 10 Generates Visual Studio 10 project files. Visual Studio 10 Win64 Generates Visual Studio 10 Win64 project files. Visual Studio 6 Generates Visual Studio 6 project files. Visual Studio 7 Generates Visual Studio .NET 2002 project files. Visual Studio 7 .NET 2003 Generates Visual Studio .NET 2003 project files. Visual Studio 8 2005 Generates Visual Studio .NET 2005 project files. Visual Studio 8 2005 Win64 Generates Visual Studio .NET 2005 Win64 project files. Visual Studio 9 2008 Generates Visual Studio 9 2008 project files. Visual Studio 9 2008 Win64 Generates Visual Studio 9 2008 Win64 project files. Watcom WMake Generates Watcom WMake makefiles. CodeBlocks - MinGW Makefiles Generates CodeBlocks project files. CodeBlocks - NMake Makefiles Generates CodeBlocks project files. CodeBlocks - Unix Makefiles Generates CodeBlocks project files. Eclipse CDT4 - MinGW Makefiles Generates Eclipse CDT 4.0 project files. Eclipse CDT4 - NMake Makefiles Generates Eclipse CDT 4.0 project files. Eclipse CDT4 - Unix Makefiles Generates Eclipse CDT 4.0 project files. Hint
The Generator and the Compilers used can't be changed after generate! You need to edit or delete the CMakeCache.txt file to change this. CMake Variables
CMake [10] has already a bunch of predefined variables for the most common options that should exist within a project. Of course you are also free to define your own variables and to change the default values of these variables.
The variable's value can be changed directly on the command line by prefixing a variable's name with '-D' (e.g. cmake - DCMAKE_BUILD_TYPE=Release) or by setting this variables in the fileCMakeLists.txt. You can also use cmake's GUI: ccmake. For more information about cmake variables check the link "Useful CMake Variables" in the CmakeWiki [5].
Some of the most important variables are listed below:
CMAKE_MODULE_PATH
Path to where CMake [10] modules are searched first when you use find_package() or include().
CMAKE_INSTALL_PREFIX
Path to where libraries/binaries/headers are installed when calling make install.
CMAKE_BUILD_TYPE
A variable which controls the type of build when using a single- configuration generator like the Makefile generator. Valid options are:
None Debug Release RelWithDebInfo MinSizeRel CMake [10] automatically sets the appropriate compiler flags for the different kinds of builds. This flags can be checked or modified by using ccmake.
MAKE_CONFIGURATION_TYPES
When using a multi-configuration generator, such as the one for Visual Studio, this variable contains a list of the available configurations.
Note
MSVC appends "${CMAKE_BUILD_TYP}" to the EXECUTABLE_OUTPUT_PATH and LIBRARY_OUTPUT_PATH, NMake does not! EXECUTABLE_OUTPUT_PATH
Set this variable to specify a common place where CMake [10] should put all executable files (instead of CMAKE_CURRENT_BINARY_DIR):
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) LIBRARY_OUTPUT_PATH
Set this variable to specify a common place where CMake [10] should put all libraries (instead of CMAKE_CURRENT_BINARY_DIR):
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) BUILD_SHARED_LIBS
Switch to build shared instead of static libraries.
CMAKE_VERBOSE_MAKEFILE
If set to 1 cmake displays the full compile and link commands during the build. Alternatively you can call make like follows:
make VERBOSE=1 make install VERBOSE=1 DESTDIR=/tmp/buildroot CMAKE_USE_RELATIVE_PATHS
If set to 1, the generated makefiles use relative pathes.
Hint
Although not strictly supported to move the build and source tree. If you set CMAKE_SUPPRESS_REGENERATION to true, and CMAKE_USE_RELATIVE_PATHS to true, you might get things to work. Notes to authors of FindXXX.cmake files
We would like all FindXXX.cmake files to produce consistent variable names.
Please use the following consistent variable names for general use.
XXX_FOUND : Set to false, or undefined, if we haven't found, or don't want to use XXX. XXX_YYY_FOUND : If False, optional YYY part of XXX sytem is not available. XXX_INCLUDE_DIRS : The final set of include directories listed in one variable for use by client code. This should not be a cache entry! XXX_LIBRARIES : The libraries to link against to use XXX. These should include full paths. This should not be a cache entry! XXX_LIBRARY_DIRS : Optionally The final set of library directories listed in one variable for use by client code. This should not be a cache entry! XXX_DEFINITIONS : Definitions to use when compiling code that uses XXX. Note
This really shouldn't include options such as (-DHAS_JPEG) that a client source-code file uses to decide whether to #include <jpeg.h>. Too, it must not include any compiler flags like -O3 -Wall to be tool independent! XXX_EXECUTABLE : Where to find the XXX tool. XXX_YYY_EXECUTABLE : Where to find the YYY tool that comes with XXX. XXX_ROOT_DIR : Where to find the base directory of XXX. XXX_RUNTIME_LIBRARY_DIRS : Optionally The runtime library search path for use when running an executable linked to shared libraries. The list should be used by user code to create the PATH on windows or LD_LIBRARY_PATH on unix. This should not be a cache entry! XXX_VERSION_STRING : A human-readable string containing the version of the package found, if any. XXX_VERSION_MAJOR : The major version of the package found, if any. XXX_VERSION_MINOR : The minor version of the package found, if any. XXX_VERSION_PATCH : The patch version of the package found, if any. XXX_VERSION_YY : Expect Version YY if true. Make sure at most one of these is ever true. XXX_WRAP_YY : If False, do not try to use the relevent CMake wrapping command. Tip
You do not have to provide all of the above variables. You should provide XXX_FOUND under most circumstances. If XXX is a library, then XXX_LIBRARIES, should also be defined, and XXX_INCLUDE_DIRS should usually be defined. The following names should not usually be used in CMakeLists.txt files, but they may be usefully modified in users' CMake Caches to control stuff.
XXX_LIBRARY : Name of XXX Library. A User may set [9] this and XXX_INCLUDE_DIR to ignore to force non-use of XXX. XXX_YY_LIBRARY : Name of YY library that is part of the XXX system. It may or may not be required to use XXX. XXX_INCLUDE_DIR : Where to find xxx.h, etc. XXX_YY_INCLUDE_DIR : Where to find xxx_yy.h, etc. Tip
For tidiness's sake, try to keep as many options as possible out of the cache, leaving at least one option which can be used to disable use of the module, or locate a not-found library (e.g.XXX_ROOT_DIR). For the same reason, mark most cache options as advanced. MARK_AS_ADVANCED(XXX_LIBRARY XXX_INCLUDE_DIR) If you need other commands to do special things then it should still begin with XXX_. This gives a sort of namespace effect and keeps things tidy for the user. You should put comments describing all the exported settings, plus descriptions of any the users can use to control stuff.
You really should also provide backwards compatibility any old settings that were actually in use. Make sure you comment them as deprecated, so that no-one starts using them.
To correctly document a module, create a comment block at the top with # comments. There are three types of comments that can be in the block:
The brief description of the module, this is done by:
# - a small description A paragraph of text. This is done with all text that has a single space between the # and the text. To create a new paragraph, just put a # with no text on the line.
A verbatim line. This is done with two spaces between the # and the text. For example:
# - This is a cool module # This module does really cool stuff. # It can do even more than you think. # # It even needs to paragraphs to tell you about it. # And it defines the following variables: # VAR_COOL - this is great isn't it? # VAR_REALLY_COOL - cool right? # To have a FindXXX.cmake file in this directory NOT show up in the modules documentation [8], you should start the file with a blank line.
A FindXXX.cmake module will typically be loaded by the command:
FIND_PACKAGE(XXX [major[.minor[.patch[.tweak]]]] [EXACT] [QUIET] [[REQUIRED|COMPONENTS] [components...]]) If any version numbers are given to the command it will set the following variables before loading the module:
XXX_FIND_VERSION full requested version string XXX_FIND_VERSION_MAJOR major version if requested, else 0 XXX_FIND_VERSION_MINOR minor version if requested, else 0 XXX_FIND_VERSION_PATCH patch version if requested, else 0 XXX_FIND_VERSION_TWEAK tweak version if requested, else 0 XXX_FIND_VERSION_COUNT number of version components, 0 to 4 XXX_FIND_VERSION_EXACT true if EXACT option was given If the find module supports versioning it should locate a version of the package that is compatible with the version requested. If a compatible version of the package cannot be found the module should not report success. The version of the package found should be stored in "XXX_VERSION..." version variables documented by the module.
If the QUIET option is given to the command it will set the variable XXX_FIND_QUIETLY to true before loading the FindXXX.cmake module. If this variable is set the module should not complain about not being able to find the package.
If the REQUIRED option is given to the command it will set the variable XXX_FIND_REQUIRED to true before loading the FindXXX.cmake module. If this variable is set the module should issue aFATAL_ERROR if the package cannot be found. For each package-specific component, say YYY, listed after the REQUIRED option a variable XXX_FIND_REQUIRED_YYY to true.
The set of components listed after either the REQUIRED option or the COMPONENTS option will be specified in a XXX_FIND_COMPONENTS variable. This can be used by the FindXXX.cmakemodule to determine which sub- components of the package must be found.
If neither the QUIET nor REQUIRED options are given then the FindXXX.cmake module should look for the package and complain without error if the module is not found.
Tip
To get this behaviour you can use the FIND_PACKAGE_HANDLE_STANDARD_ARGS() macro, as an example see FindLibSmi.cmake [7]. # - Find LIBSMI # Find the native LIBSMI includes and library # This module defines # LIBSMI_INCLUDE_DIR, where to find smi.h, etc. # LIBSMI_LIBRARY, the LIBSMI library with full path. # LIBSMI_FOUND, If false, do not try to use LIBSMI. # also defined, but not for general use are # LIBSMI_LIBRARIES, The libraries needed to use LIBSMI. # LIBSMI_LIBRARY_DIRS, where to find the LIBSMI library. # LIBSMI_DEFINITIONS - You should add_definitons($ {LIBSMI_DEFINITIONS}) before # compiling code that includes netsnmp library files.
INCLUDE(FindPkgConfig) IF (PKG_CONFIG_FOUND) IF (LIBSMI_FIND_REQUIRED AND LIBSMI_FIND_VERSION) SET(_PACKAGE_ARGS libsmi>=${LIBSMI_FIND_VERSION} REQUIRED) ELSE () SET(_PACKAGE_ARGS libsmi) ENDIF () PKG_CHECK_MODULES(LIBSMI ${_PACKAGE_ARGS}) ENDIF (PKG_CONFIG_FOUND) SET(LIBSMI_DEFINITIONS ${LIBSMI_CFLAGS_OTHER})
FIND_PATH(LIBSMI_INCLUDE_DIR smi.h HINTS ${LIBSMI_INCLUDE_DIRS})
FIND_LIBRARY(LIBSMI_LIBRARY NAMES smi HINTS ${LIBSMI_LIBRARY_DIRS}) IF (NOT PKG_CONFIG_FOUND) SET(LIBSMI_LIBRARIES smi) GET_FILENAME_COMPONENT(LIBSMI_LIBRARY_DIRS ${LIBSMI_LIBRARY} PATH) ENDIF (NOT PKG_CONFIG_FOUND)
# handle the QUIETLY and REQUIRED arguments and set LIBSMI_FOUND to TRUE if all # listed variables are TRUE INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBSMI DEFAULT_MSG LIBSMI_LIBRARY LIBSMI_INCLUDE_DIR LIBSMI_LIBRARIES LIBSMI_LIBRARY_DIRS ) MARK_AS_ADVANCED(LIBSMI_LIBRARY LIBSMI_INCLUDE_DIR LIBSMI_LIBRARIES LIBSMI_LIBRARY_DIRS LIBSMI_DEFINITIONS)
For internal implementation, it's a generally accepted convention that variables starting with underscore (_XXX) are for temporary use only. (variable starting with an underscore are not intended as a reserved prefix).
For more information about how to contribute modules to CMake, see this page: http://www.itk.org/Wiki/CMake:Module_Maintainers
CMake Cross Compiling
Cross compiling is supported by CMake [10] starting with version 2.6.0.
Cross compiling means that the software is built for a different system than the one which does the build. This means
CMake cannot autodetect the target system usually the executables don't run on the build host the build process has to use a different set of include files and libraries for building, i.e. not the native ones Setting up the system and toolchain
When cross compiling [6], CMake [10] cannot guess the target system, so you have to preset some CMake variables, e.g. using a toolchain file. The following variables have to be preset:
CMAKE_SYSTEM_NAME
This one is mandatory, it is the name of the target system, i.e. the same as CMAKE_SYSTEM_NAME would have if CMake [10] would run on the target system. Typical examples are "Linux" and "Windows". This variable is used for constructing the file names of the platform files like Linux.cmake or Windows-gcc.cmake. If your target is an embedded system without OS setCMAKE_SYSTEM_NAME to "Generic". If CMAKE_SYSTEM_NAME is preset, the CMake variable CMAKE_CROSSCOMPILING is automatically set to TRUE, so this can be used for testing in the CMake files.
CMAKE_SYSTEM_VERSION
optional, version of your target system, not used very much.
CMAKE_SYSTEM_PROCESSOR
optional, processor (or hardware) of the target system. This variable is not used very much except for one purpose, it is used to load a CMAKE_SYSTEM_NAME-compiler-CMAKE_SYSTEM_PROCESSOR.cmake file, which can be used to modify settings like compiler flags etc. for the target. You probably only have to set this one if you are using a cross compiler where every target hardware needs special build settings.
Since CMake cannot guess the target system, it also cannot guess which compiler it should use, so you have to preset this too:
CMAKE_C_COMPILER
the C compiler executable, may be the full path or just the filename. If it is specified with full path, then this path will be prefered when searching the C++ compiler and the other tools (binutils, linker, etc.). If this compiler is a gcc-cross compiler with a prefixed name (e.g. "arm-elf-gcc") CMake [10] will detect this and automatically find the corresponding C++ compiler (i.e. "arm-elf-c++"). The compiler can also be preset using cmake -D:
mkdir crossbuild && cd crossbuild cmake -DCMAKE_C_COMPILER=arm-elf-gcc -DCMAKE_CXX_COMPILER=arm-elf-c++ .. CMAKE_CXX_COMPILER
the C++ compiler executable, may be the full path or just the filename. It is handled the same way as CMAKE_C_COMPILER. If the toolchain is a GNU toolchain, you only need to set one of both.
Once the system and the compiler are determined by CMake [10], it loads the corresponding files in the following order:
Platform/${CMAKE_SYSTEM_NAME}.cmake (mandatory) Platform/${CMAKE_SYSTEM_NAME}-<compiler>.cmake (optional) Platform/${CMAKE_SYSTEM_NAME}-<compiler>-$ {CMAKE_SYSTEM_PROCESSOR}.cmake (optional) <compiler> is either the basename of the compiler executable, e.g. "gcc" (this is also used if gcc has a different name) or "cl", or by a compiler id, which is detected by compiling a test source file.
For testing the host system, there is a corresponding set of variables, which is set automatically by CMake [10]:
CMAKE_HOST_SYSTEM_NAME CMAKE_HOST_SYSTEM_VERSION CMAKE_HOST_SYSTEM_PROCESSOR CMAKE_HOST_SYSTEM Without cross compiling the variables for the host system and the target system are identical. In most cases you will want to test for the target system, then the same way as without cross compiling use theCMAKE_SYSTEM_XXX variables, this will work both for cross compiling and for native building.
With these variables correctly set, CMake [10] will now use the cross compiling toolchain for building and in the CMakeLists.txt you can still use the CMAKE_SYSTEM_XXX variables for testing for which system you are building. This is already enough to use CMake [10] for cross compiling simple (buildsystem-wise) projects.
Warning
Once you Setting up the system and toolchain with cmake, you can't change this for a single build! You have to change it with cmake. Do not try to use:
make CC=arm-elf-gcc CXX=arm-elf-c++ ... all Resources
[7] file:../Tutorials/cmake/FindLibSmi.cmake [8] http://www.cmake.org/cmake/help/cmake-2-8-docs.html#section_Standard%20CMake... [9] http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:set [10] (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18) http://www.cmake.org [11] http://www.cmake.org/Wiki [12] http://www.cmake.org/cmake/help/cmake-2-8-docs.html Footnotes
[1] : http://www.cmake.org [2] (1, 2) : http://www.cmake.org/cmake/help/syntax.html [3] : K. Martin, B. Hoffman, Mastering CMake, 2006, Kitware Inc., 1-930934-16-5 [4] : http://www.cmake.org/Wiki/CMake:How_To_Find_Libraries [5] : http://www.cmake.org/Wiki/CMake_Useful_Variables [6] : http://www.cmake.org/Wiki/CMake_Cross_Compiling