Cmake cheatsheet

#Cmake cheat sheet in markdown

#Cmake cheat sheet

## quick start
1. first example, see more details at <>

cmake_minimum_required (VERSION 2.8.0)#cmake grammar evolves, 
project (testcpp) # define the output executive name

add_executable (testcpp testcpp.cpp) #define source to object relation

2. in source build cmdline:  
`cmake <path to toplevel cmakelists.txt> -G <generator> && make` 

out of source build is recommended to keep source tree clean:  
cd dir_of_source_with_toplevel_cmakelists.txt && mkdir build 
cd build && camke .. &&make
make install

using `nmake` on windows visual studio build tool, as cmake generate platform specific makefile

3. GUI tool `cmake-gui <path to toplevel cmakelists.txt>`
build option can be turn on and off in GUI  
option(<option_variable> "help string describing option"
       [initial value])
4. FindGTK module, work like `pkg-config` to get include and lib path

GTK_INCLUDE_DIR   - Directories to include to use GTK
GTK_LIBRARIES     - Files to link against to use GTK
GTK_FOUND         - GTK was found
GTK_GL_FOUND      - GTK's GL features were found
for more details see <>

## cmake language syntax

cmake is a script language, similar with shell to some extent.
see [cmake wiki](

+ only one kind of variable, i.e. string,   
> but it will be interpreted as bool in `IF (var)`  
or integer `IF (var GREATER 10) ... ENDIF`

+ variable substitution `${VAR}`, SET and UNSET, `IF(DEFINED x)`

+ only one kind of data structure: LIST, string sperated by semicolon  
`SET(var a b c)` is equal to `SET(var "a;b;c")`

+ quotation mark to reserve sapce "hello world"
SET( x a b c   ) # stores a list "a;b;c" in x      (without quotes)
SET( y "a b c" ) # stores a string "a b c" in y      (without quotes)
MESSAGE( a b c ) # prints "abc"   to stdout, automatically concat (without quotes)
MESSAGE( ${x} )  # prints "abc"   to stdout (without quotes)
MESSAGE("${x}")  # prints "a;b;c" to stdout (without quotes)
MESSAGE( ${y} )  # prints "a b c" to stdout (without quotes)
MESSAGE("${y}")  # prints "a b c" to stdout (without quotes)
+ comment by #, escape by \, line continuation by /
> but in path string: "http://////"

> but it is different from bash shell

> newline to split list element

- cmake variable and command is case insensitive  
> but UPPER case for command is recommended   
and varible content like filename is case sensitive

- ""(empty string), "NO; N; FALSE; <var>-NOTFOUND; OFF;0;" or lower case is regarded false in IF()

- only integer algorithm `MATH(EXPR outputvar expr)`  
SET( expression 4 LESS 10 ) # ${expression} is now "4;LESS;10"
IF( ${expression} )         # expands to IF( 4;LESS;10 )
  MESSAGE( "CMake believes that 4 is less than 10." )
ENDIF( ${expression} )
bash shell math: `$((math_expr))` 

- generate `config.h` from `config.h.cmake` template   
> by replacing "@var" with var defined in camkelists.txt
`MESSAGE( ${x}${y} ) # displays "31"`

- function is different from macro whose variables have global scope

## important command and variable
### 1.commands

+ $ENV{HOME} #access to environment variable
+ EXECUTE_PROCESS(cmd var_to_hold_result)
+ INSTALL(TARGETS|FILES list_of_f dest)
+ CONFIGURE_FILE() #generate config.h from config template input file
+ INCLUDE_DIRECTORY() #subdir with cmakelists.txt
+ ADD_LIBRARY(), ADD_EXECUTABLE(), add_definitions, add_dependencies
+ INCLUDE(extra_cmake_file) #as include in c++ for extra functions

### 2. location variables

> where FIND_PACKAGE(FooBar) can find `findFooBar.cmake`

+ CMAKE_SOURCE_DIR # top source dir containing the top-level CMakeLists.txt,
+ CMAKE_BINARY_DIR # top folder to build binary object
+ CMAKE_CURRENT_LIST_FILE # full path of the current processed cmakelists.txt
+ CMAKE_INCLUDE_PATH  # path to search for header file e.g. `/usr/include`
+ CMAKE_INSTALL_PREFIX #just as DESTDIR in `make DESTDIR=/home/john install`

### 3. compiler control variables
+ CMAKE_<Lang>_FLAGS # for build_type NONE
+ enable C++ standard support in a portable way
set(CMAKE_CXX_STANDARD 11) #98, 14, 17

### 4. predefined platform and compiler detection varibles   
platform like: WIN32, APPLE, UNIX (linux is UNIX but not APPLE), MYSYS, CYGWIN

### 5. command line help
cmake --variable-list
cmake --command-list
cmake --module-list
cmake -h #show all generator


## Why cmake?

cmake is a new language, why should we learn a new language instead of json or python (as in scons)?

1. cmake inherits some conception of traditional unix makefile

2. multiple programming lang support and cross-platform with generators for majourity of IDE tools

3. plenty of official modules like "FindXXX.cmake"

4. speedup by var cache `SET(var value CACHE)`

5. CPACK for binary package and windows NSIS installer generation

6. Generating Dependency Graphs with CMake, `cmake .`

7. tool to generate cmakelists.txt from scratch or convert from existent build system

## what I do not like

- cmake is not a precise or clear script lang
- confusing string quotation and substitution
- un-intuitive function style programming to c/python programmers
- messed up of variable_content and variable
- mixed up argument list and keyword in function call, not sep by comma
> relies heavily on this fuction to parse function/command input arg
`CMAKE_PARSE_ARGUMENTS(<prefix> <options> <one_value_keywords> <multi_value_keywords> args...)` 


This entry was posted in Uncategorized. Bookmark the permalink.