Post

06. CMake Grammer

06. CMake Grammer

CMake Grammer


1. Overview

CMake is a command-based scripting language where everything is treated as strings.

1
command(arg1 arg2 ...)

There are no strong types like C++ — behavior depends on how strings are interpreted.


2. Variables

2-1. set()

1
set(VAR value)

Description:

Creates or updates a variable.

Behavior:

  • Stored in current scope
  • Overwritten if called again

2-2. Access Variable

1
message(${VAR})

Description:

${} expands the variable into its value.


2-3. List Behavior

1
set(LIST a b c)

Description:

CMake treats lists as semicolon-separated strings.

1
a;b;c

2-4. unset()

1
2
unset(VAR)
unset(VAR CACHE)

Description:

  • Removes variable
  • Optional CACHE removes persistent value

3. Variable Expansion

3-1. Basic Expansion

1
${VAR}

Meaning:

Replace with value of VAR.


3-2. Indirect Expansion (Important)

1
2
3
4
set(name FOO)
set(FOO hello)

message(${${name}})

Meaning:

  1. ${name}FOO
  2. ${FOO}hello

✔ Used for dynamic variable access


3-3. Environment Variables

1
$ENV{HOME}

Description:

Access OS environment variables.


4. Condition (if)

1
2
3
4
if(condition)
elseif(condition)
else()
endif()

Description:

Evaluates condition expressions.


4-1. Numeric Comparison

1
if(A GREATER 10)

✔ Integer comparison


4-2. String Comparison

1
if(A STREQUAL "hello")

✔ Exact string match


4-3. Regex Match

1
if(A MATCHES "h.*o")

✔ Regular expression


4-4. Logical Operators

1
2
3
if(A AND B)
if(A OR B)
if(NOT A)

4-5. Existence Check

1
2
if(DEFINED VAR)
if(EXISTS file.txt)

✔ Check if variable or file exists


4-6. Combined Pattern (Advanced)

1
if(DEFINED ${variable} AND "${${variable}}")

Meaning:

  • Check if referenced variable exists
  • Check if value is TRUE

✔ Common in large projects (e.g., OpenCV)


5. Dynamic Expression Execution

1
2
3
set(cond 2 GREATER 1)

if(${cond})

Behavior:

1
if(2 GREATER 1)

✔ CMake executes expanded string as condition


6. Loops

6-1. foreach()

1
2
3
foreach(x a b c)
  message(${x})
endforeach()

Description:

Iterates over values.


6-2. List Iteration

1
foreach(x ${LIST})

✔ Expands list first


6-3. Range Loop

1
foreach(i RANGE 0 10)

✔ Numeric iteration


6-4. while()

1
2
while(condition)
endwhile()

✔ Loop while condition is true


7. Functions and Macros

7-1. function()

1
2
3
function(foo x)
  message(${x})
endfunction()

Behavior:

  • Has its own scope
  • Variables are local

7-2. macro()

1
2
3
macro(foo x)
  message(${x})
endmacro()

Behavior:

  • No scope
  • Acts like text substitution

✔ Used in OpenCV (OCV_OPTION)


7-3. Arguments

1
2
3
${ARGV0}
${ARGV1}
${ARGN}

8. Cache Variables

1
set(VAR value CACHE STRING "description")

Description:

Stores variable in CMakeCache.txt


Why Important

  • Persists between configure runs
  • User can override via CLI or GUI

Types

TypeMeaning
STRINGtext
BOOLON/OFF
PATHdirectory
FILEPATHfile

FORCE

1
set(VAR value CACHE STRING "" FORCE)

✔ Override existing cache value


9. option()

1
option(USE_CUDA "Enable CUDA" ON)

Description:

Creates user-configurable boolean option.


10. include() vs add_subdirectory()

include()

1
include(utils.cmake)

✔ Executes file inline ✔ No target creation


add_subdirectory()

1
add_subdirectory(src)

✔ Executes another CMakeLists.txt ✔ Adds build targets


11. Targets

11-1. Executable

1
add_executable(App main.cpp)

11-2. Library

1
add_library(MyLib STATIC lib.cpp)

11-3. Linking

1
target_link_libraries(App MyLib)

Description:

Defines dependency between targets.


11-4. Include Directories

1
target_include_directories(App PUBLIC include/)

11-5. Compile Options

1
target_compile_options(App PRIVATE -O2)

11-6. Definitions

1
target_compile_definitions(App PRIVATE USE_FEATURE)

12. install()

1
2
install(TARGETS App DESTINATION bin)
install(FILES a.h DESTINATION include)

Description:

Defines how build outputs are copied into a structured install directory.


12-1. Basic Concept

install() does not build anything.

It copies and organizes artifacts produced during build.

Example result:

1
2
3
4
install/
 ├── bin/
 ├── lib/
 ├── include/

12-2. Common Signatures

Install targets

1
install(TARGETS App DESTINATION bin)

✔ Executables / libraries


Install files

1
install(FILES a.h DESTINATION include)

✔ Headers or config files


Install directories

1
install(DIRECTORY include/ DESTINATION include)

✔ Entire folder copy


12-3. COMPONENT (Important)

1
2
install(TARGETS App DESTINATION bin COMPONENT runtime)
install(FILES a.h DESTINATION include COMPONENT dev)

Description:

COMPONENT groups install rules into logical parts.


Why it exists

Allows partial installation.

1
cmake --install build --component dev

✔ installs only development files (headers)


Typical Convention

ComponentMeaning
runtimeexecutables
devheaders, cmake configs
libraryshared/static libs

Important Insight

1
2
COMPONENT is NOT a variable and NOT a folder name.
It is a label used by CMake to group install rules.

13. File Operations

1
2
file(GLOB SRC "*.cpp")
file(COPY src DESTINATION build)

14. string()

1
2
string(REPLACE "a" "b" OUT ${VAR})
string(TOUPPER ${VAR} OUT)

Description:

Performs string manipulation.


14-1. REPLACE

1
2
set(VAR "apple")
string(REPLACE "a" "b" OUT ${VAR})

Result:

1
OUT = bpple

14-2. TOUPPER / TOLOWER

1
string(TOUPPER "hello" OUT)

Result:

1
OUT = HELLO

14-3. CONCAT

1
string(CONCAT OUT "Hello " "World")

Result:

1
OUT = Hello World

14-4. REGEX

1
string(REGEX MATCH "h.*o" OUT "hello")

✔ Pattern matching


Important Insight

1
2
string() does NOT modify variables directly.
It always writes to an output variable.

15. list()

1
2
3
list(APPEND MYLIST item)
list(REMOVE_ITEM MYLIST item)
list(LENGTH MYLIST len)

Description:

Manipulates list variables.


15-1. Append

1
2
set(MYLIST a b)
list(APPEND MYLIST c)

Result:

1
a;b;c

15-2. Remove

1
list(REMOVE_ITEM MYLIST b)

Result:

1
a;c

15-3. Length

1
list(LENGTH MYLIST len)

Result:

1
len = 2

15-4. Get Element

1
list(GET MYLIST 0 first)

✔ Index-based access


Important Insight

1
CMake lists are just strings separated by ';'

16. message()

1
2
3
4
message("Hello")
message(STATUS "Info")
message(WARNING "Warning")
message(FATAL_ERROR "Stop")

Description:

Outputs messages during configure/build.


16-1. Levels

LevelMeaning
STATUSnormal info
WARNINGwarning message
AUTHOR_WARNINGdev warning
FATAL_ERRORstop execution

Example

1
message(STATUS "Building project...")

Behavior

1
message(FATAL_ERROR "Something failed")

✔ Immediately stops CMake


Important Insight

1
2
message() is mainly used during configure phase
for debugging and logging

17. Built-in Variables

1
2
3
4
5
CMAKE_SYSTEM_NAME
CMAKE_SOURCE_DIR
CMAKE_BINARY_DIR
CMAKE_CURRENT_SOURCE_DIR
CMAKE_CURRENT_BINARY_DIR

18. Comments

18-1. Single-line

1
# This is a comment

18-2. Multi-line

1
2
3
#[[
This is a multi-line comment
]]

Important Behavior

1
Comments are ignored during parsing

Common Usage

1
2
# Enable CUDA if available
option(USE_CUDA "Enable CUDA" ON)

Important Insight

1
2
CMake has no inline comment syntax (like // or /* */)
Only # and #[[ ]] are valid

19. Key Concepts

1
2
3
4
5
6
7
✔ Everything is string-based
✔ ${} controls execution
✔ if() evaluates expressions, not just values
✔ CACHE variables persist
✔ include executes code
✔ add_subdirectory builds structure
✔ target is the core abstraction
This post is licensed under CC BY 4.0 by the author.