Command Lines
Generating a project buildsystem
cmake [<options>] -S <path-to-source> -B <path-to-build>
cmake [<options>] <path-to-source>
cmake [<options>] <path-to-existing-build>
#Build in the ./build directory, and use a source from the current directory:
cmake -B build
#Build in the current directory, but take the source from one directory up (note that -S is optional):
cmake -S ..
choose generator
This can be overridden by the CMAKE_GENERATOR
environment variable or by specifying the generator directly on the command line
cmake -G <generator-name> <path-to-source>
We can provide a path to the CMake script, which (only) contains a list of set()
commands to specify variables that will be used to initialize an empty build tree.
cmake -D <var>[:<type>]=<value> <path-to-source>
cmake -S . -B build -D CMAKE_BUILD_TYPE=Release
to build project
cmake --build <dir>
Options for parallel builds
cmake --build <dir> --parallel [<number-of-jobs>]
cmake --build <dir> -j [<number-of-jobs>]
CMake Language
the execution begins from the root file of the source tree (CMakeLists.txt
) or a .cmake
script file that was passed as an argument to cmake
Comments
# single-line comments start with a hash sign "#"
# they can be placed on an empty line
message("Hi"); # or after a command like here.
#[=[
bracket comment
#[[
nested bracket comment
#]]
#]=]
Command invocations
command(argument1 "argument2" argument3) # comment
#[[ multiline comment ]]
double qouted
message(${OpenCL_LIBRARY})
message("1. escape sequence: \" \n in a quoted argument")
message("2. multi...
line")
message("3. and a variable reference: ${CMAKE_VERSION}")
Working with variables
1- Variable names are case-sensitive and can include almost any character.
2-All variables are stored internally as strings, even if some commands can interpret them as values of other data types (even lists!).
3-The basic variable manipulation commands are set()
and unset()
, but there are other commands that can affect variables, such as string()
and list()
.
set(MyString1 "Text1")
set([[My String2]] "Text2")
set("My String 3" "Text3")
message(${MyString1})
message(${My\ String2})
message(${My\ String\ 3})
- If the following reference is encountered –
${MyOuter${MyInner}}
– CMake will try to evaluateMyInner
first, rather than searching for a variable namedMyOuter${MyInner}
. - If the
MyInner
variable is successfully expanded, CMake will repeat the expansion process until no further expansion is possible.
- The
${}
syntax is used to reference normal or cache variables. - The
$ENV{}
syntax is used to reference environment variables. - The
$CACHE{}
syntax is used to reference cache variables.
set(ENV{CXX} "clang++")
cmake_minimum_required(VERSION 3.20.0)
project(Environment)
message("generated with " $ENV{myenv})
#!/bin/bash
export myenv=first
echo myenv is now $myenv
cmake -B build .
cd build
export myenv=second
echo myenv is now $myenv
cmake --build .
$ ./build.sh | grep -v "\-\-"
myenv is now first
generated with first
myenv is now second
Scanning dependencies of target EchoEnv
myenv in build is first
Built target EchoEnv
scope of variables
function(Inner)
message(" > Inner: ${V}")
set(V 3)
message(" < Inner: ${V}")
endfunction()
function(Outer)
message(" > Outer: ${V}")
set(V 2)
Inner()
message(" < Outer: ${V}")
endfunction()
set(V 1)
message("> Global: ${V}")
Outer()
message("< Global: ${V}")
> Global: 1
> Outer: 1
> Inner: 2
< Inner: 3
< Outer: 2
< Global: 1
set(V 3 PARENT_SCOPE)
> Global: 1
> Outer: 1
> Inner: 2
< Inner: 2
< Outer: 3
< Global: 1
Lists
set(myList 1 2 3 4)
set(myList "a;list;of;five;elements")
set(myList a list "of;five;elements")
message("the list is:" ${myList})
The message()
command will receive here six arguments: “the list is:
“, “a
“, “list
“, “of
“, “five
“, “elements
“.
list(LENGTH <list> <out-var>)
list(GET <list> <element index> [<index> ...] <out-var>)
list(JOIN <list> <glue> <out-var>)
list(SUBLIST <list> <begin> <length> <out-var>)
list(FIND <list> <value> <out-var>)
list(APPEND <list> [<element>...])
list(FILTER <list> {INCLUDE | EXCLUDE} REGEX <regex>)
list(INSERT <list> <index> [<element>...])
list(POP_BACK <list> [<out-var>...])
list(POP_FRONT <list> [<out-var>...])
list(PREPEND <list> [<element>...])
list(REMOVE_ITEM <list> <value>...)
list(REMOVE_AT <list> <index>...)
list(REMOVE_DUPLICATES <list>)
list(TRANSFORM <list> <ACTION> [...])
list(REVERSE <list>)
list(SORT <list> [...])
Understanding control structures in CMake
if(<condition>)
<commands>
elseif(<condition>) # optional block, can be repeated
<commands>
else() # optional block
<commands>
endif()
The provided <condition>
expression is evaluated according to a very simple syntax.
The same syntax is valid for if()
, elseif()
, and while()
commands.
The if()
conditions support the NOT
, AND
, and OR
logical operators:
NOT <condition>
<condition> AND <condition>
<condition> OR <condition>
(<condition>) AND (<condition> OR (<condition>))
EQUAL
,LESS
,LESS_EQUAL
,GREATER
, andGREATER_EQUAL
- “A” STREQUAL “${B}”
<file1> IS_NEWER_THAN <file2>
: Checks which file is newe-
<VARIABLE|STRING> IN_LIST <VARIABLE>
- <VARIABLE|STRING> MATCHES <regex>
set(VAR1 FALSE)
set(VAR2 "VAR1")
if(${VAR2})
ON
,Y
,YES
, orTRUE
- A non-zero number
OFF
,NO
,FALSE
,N
,IGNORE
,NOTFOUND
- A string ending with
-NOTFOUND
- An empty string
- Zero
Loops
while(<condition>)
<commands>
endwhile()
foreach(<loop_variable> IN [LISTS <lists>] [ITEMS <items>])
set(MY_LIST 1 2 3) #set(MY_LIST "1;2;3")
foreach(VAR IN LISTS MY_LIST)
message(${VAR})
endforeach()
Command definitions
- A
macro()
command works more like a find-and-replace instruction than an actual subroutine call such asfunction()
. - The
function()
command creates a separate scope for local variables, unlike themacro()
command, which works in the variable scope of a caller.
macro(<name> [<argument>…])
<commands>
endmacro()
function(<name> [<argument>…])
<commands>
endfunction()
macro(MyMacro myVar)
set(myVar "new value")
message("argument: ${myVar}")
endmacro()
set(myVar "first value")
message("myVar is now: ${myVar}")
MyMacro("called value")
message("myVar is now: ${myVar}")
Useful commands
execute_process to run external command
execute_process(COMMAND echo "hello world")
execute_process(COMMAND <cmd1> [args1...]]
[COMMAND <cmd2> [args2...] [...]]
[WORKING_DIRECTORY <directory>]
[TIMEOUT <seconds>]
[RESULT_VARIABLE <variable>]
[OUTPUT_VARIABLE <variable>]
[ERROR_VARIABLE <variable>]
[INPUT_FILE <file>]
[OUTPUT_FILE <file>]
[ERROR_FILE <file>]
[OUTPUT_QUIET]
[ERROR_QUIET]
[OUTPUT_STRIP_TRAILING_WHITESPACE]
[ERROR_STRIP_TRAILING_WHITESPACE])
file to read or write from or to file
file(READ <filename> <out-var> [...])
file({WRITE | APPEND} <filename> <content>...)
file(DOWNLOAD <url> [<file>] [...])
file(GLOB_RECURSE QMLS "${QML_FOLDER}/*.qml") #get files with format as QMLS list
file(COPY ${QMLS} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/${QML_FOLDER}) #Copy files
include to add and execute other CMake file
include(<file|module> [OPTIONAL] [RESULT_VARIABLE <var>])