CMake Tutorial
CMake Tutorial
CMake Tutorial
●
1 – Introduction to CMake
●
2 – Using CMake for the ILC Software
●
3 – ILCInstall with CMake
Jan Engels
DESY
20th September 2007
What is CMake
●
CMake:
– Generates native build environments
●
UNIX/Linux -> Makefiles
●
Windows -> VS Projects/Workspaces
●
Apple -> Xcode
– Open-Source :)
– Cross-Platform
●
Variables can be changed directly in the build files (CmakeLists.txt) or through
the command line by prefixing a variable's name with '-D':
– cmake -DBUILD_SHARED_LIBS=OFF
●
GUI also available: ccmake
●
Created in the build tree (CMakeCache.txt)
●
Contains Entries VAR:TYPE=VALUE
●
Populated/Updated during configuration phase
●
Speeds up build process
●
Can be initialized with cmake -C <file>
●
GUI can be used to change values
●
There should be no need to edit it manually!!
Dir3/CMakeLists.txt
Dir1/CMakeLists.txt
SUBDIRS(Dir3 Dir4)
Project's Top-Level
CmakeLists.txt Dir4/CMakeLists.txt
SUBDIRS(Dir1 Dir2)
Dir2/CMakeLists.txt
●
Subdirectories added with SUBDIRS/ADD_SUBDIRECTORY
●
Child inherits from parent (feature that is lacking in traditional Makefiles)
●
Order of processing: Dir1;Dir3;Dir4;Dir2 (When CMake finds a SUBDIR command it
stops processing the current file immediately and goes down the tree branch)
●
Create a build directory (“out-of-source-build” concept)
– mkdir build ; cd build
●
Configure the package for your system:
– cmake [options] <source_tree>
●
Build the package:
Similar to Auto Tools
– make
●
Install it:
– make install
●
The last 2 steps can be merged into one (just “make install”)
int main() {
Hello().Print();
return 0;
} Test Binary
PROJECT( HELLO )
ADD_SUBDIRECTORY( Hello )
ADD_SUBDIRECTORY( Test )
# Adds a library called Hello (libHello.a under Linux) from the source file hello.cc
ADD_LIBRARY( Hello hello )
# Make sure the compiler can find include files from our Hello library.
INCLUDE_DIRECTORIES(${HELLO_SOURCE_DIR}/Hello)
# Add binary called "helloWorld" that is built from the source file "test.cc".
# The extension is automatically found.
ADD_EXECUTABLE(helloWorld test)
●
SET( VAR value [CACHE TYPE DOCSTRING [FORCE]])
●
LIST( APPEND|INSERT|LENGTH|GET|REMOVE_ITEM|REMOVE_AT|SORT ...)
●
STRING( TOUPPER|TOLOWER|LENGTH|SUBSTRING|REPLACE|REGEX ...)
●
SEPARATE_ARGUMENTS( VAR ) convert space separated string to list
●
FILE( WRITE|READ|APPEND|GLOB|GLOB_RECURSE|REMOVE|MAKE_DIRECTORY ...)
●
FIND_FILE
●
FIND_LIBRARY
Check www.cmake.org -> Documentation
●
FIND_PROGRAM
●
FIND_PACKAGE
●
EXEC_PROGRAM( bin [work_dir] ARGS <..> [OUTPUT_VARIABLE var] [RETURN_VALUE var] )
●
OPTION( OPTION_VAR “description string” [initial value] )
●
2 – Using CMake for the ILC Software
●
Packages with CMake (build) support:
– Marlin, MarlinUtil, MarlinReco, CEDViewer, CED, LCIO, GEAR, LCCD,
RAIDA, PandoraPFA, LCFIVertex, SiliconDigi, Eutelescope
●
CMake modules written for external packages:
– CLHEP, CERNLIB, CondDBMySQL, GSL, ROOT, JAVA, AIDAJNI
●
Script for pre-caching variables/options
– SET( VAR “value” CACHE TYPE “description” FORCE )
●
Easy way to change build parameters without having to pass
the every time on the cmd line
●
Use simple steps to build a package:
– mkdir build ; cd build
– cmake -C ../BuildSetup.cmake ..
– make install
●
Still possible to override options on the cmd line
●
Can use more than one -C option:
– cmake -C ../BuildSetup.cmake -C ~/ILCSoft.cmake
– Next file overwrites values from previous file
– Useful for overwriting paths defined in a 'more global' file
●
CMake just ignores redundant variables from global file
●
ILCInstall generates a global file called ILCSoft.cmake
●
Check /afs/desy.de/group/it/ilcsoft/v01-01/ILCSoft.cmake as
an example
# User section
PROJECT( mymarlin )
# project version
SET( ${PROJECT_NAME}_MAJOR_VERSION 0 ) You can add here your own options,
SET( ${PROJECT_NAME}_MINOR_VERSION 1 ) but don't forget at the end of the file to
SET( ${PROJECT_NAME}_PATCH_LEVEL 0 ) display them with a MESSAGE( STATUS)
and to also write them properly to cache!
# project options
OPTION( BUILD_SHARED_LIBS "Set to OFF to build static libraries" ON )
OPTION( INSTALL_DOC "Set to OFF to skip build/install Documentation" ON )
# project dependencies e.g. SET( ${PROJECT_NAME}_DEPENDS "Marlin MarlinUtil LCIO GEAR CLHEP GSL" )
SET( ${PROJECT_NAME}_DEPENDS "Marlin LCIO" )
# set default cmake build type to RelWithDebInfo (None Debug Release RelWithDebInfo MinSizeRel)
IF( NOT CMAKE_BUILD_TYPE )
SET( CMAKE_BUILD_TYPE "RelWithDebInfo" )
ENDIF()
# set default install prefix to project root directory
IF( CMAKE_INSTALL_PREFIX STREQUAL "/usr/local" )
SET( CMAKE_INSTALL_PREFIX "${PROJECT_SOURCE_DIR}" )
ENDIF()
# get list of all source files If you have more sources you
AUX_SOURCE_DIRECTORY( src library_sources ) should add them here (see for ex.
( .... ) LCFIVertex CMakeLists.txt)
# DEPENDENCIES: this code has to be placed before adding any library or
# executable so that these are linked properly against the dependencies
IF( DEFINED ${PROJECT_NAME}_DEPENDS OR DEFINED BUILD_WITH OR DEFINED LINK_WITH )
# load macro
IF( NOT EXISTS "${CMAKE_MODULE_PATH}/MacroCheckDeps.cmake" )
MESSAGE( FATAL_ERROR Dependencies are
"\nSorry, could not find MacroCheckDeps.cmake...\n"
"Please set CMAKE_MODULE_PATH correctly with: " checked here!
"cmake -DCMAKE_MODULE_PATH=<path_to_cmake_modules>" )
ENDIF()
INCLUDE( "${CMAKE_MODULE_PATH}/MacroCheckDeps.cmake" )
CHECK_DEPS()
ENDIF()
# install library
INSTALL( TARGETS lib_${PROJECT_NAME} DESTINATION lib PERMISSIONS
OWNER_READ OWNER_WRITE OWNER_EXECUTE
GROUP_READ GROUP_EXECUTE
WORLD_READ WORLD_EXECUTE )
# force some variables that could be defined in the command line to be written to cache And here you should also add
SET( BUILD_SHARED_LIBS "${BUILD_SHARED_LIBS}" CACHE BOOL
"Set to OFF to build static libraries" FORCE ) your own project options to be
SET( CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" CACHE PATH properly written to cache!
"Where to install ${PROJECT_NAME}" FORCE )
SET( CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE )
SET( CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" CACHE PATH
"Path to custom CMake Modules" FORCE )
SET( INSTALL_DOC "${INSTALL_DOC}" CACHE BOOL
"Set to OFF to skip build/install Documentation" FORCE )
●
Linking static libraries (Only works under linux!)
– -DLINK_STATIC_WHOLE_LIBS="path_to_library/libMyprocessor.a"
– Library gets fully included into the Marlin binary
– For more than one library:
●
-DLINK_STATIC_WHOLE_LIBS="/path1/lib1.a;/path2/lib2.a"
●
3 – ILCInstall with cmake
# python variable for referring the ILC Home directory CMake variables to be
ilcPath = "/afs/desy.de/group/it/ilcsoft/" passed on the cmd line
when building RAIDA
# install RAIDA v01-03
ilcsoft.install( RAIDA( "v01-03" ))
# example for setting cmake variables (“ON”/”OFF” is equivalent to 1/0)
ilcsoft.module( “RAIDA” ).envcmake[“BUILD_RAIDA_EXAMPLE”] = “ON”
ilcsoft.module( “RAIDA” ).envcmake[“RAIDA_DEBUG_VERBOSE_FACTORY”] = 1
●
ILCSoft.cmake is generated by installation script
– Placed in the root directory of installation
– Contains paths for all packages defined in cfg file
●
Only the ones that are supported by the cmake modules!
Thank you!