CMakeLists.txt files and .cmake scripts and modules share one
language, defined in the cmake-language(7) manual. This page follows that
manual (CMake 4.x); the commands themselves are listed on the
commands page.
Sources: cmake-language(7)
(organisation, syntax, variables, control structures, lists), and the manual pages of
if(), foreach(), macro(), block(),
return(), set() and
cmake-generator-expressions(7), as shipped with CMake 4.4.
Files and encoding
| Kind | Name | How it is read |
|---|---|---|
| Directory | CMakeLists.txt | The entry point is the one in the top source folder; each folder added with add_subdirectory() has its own, and gets its own folder in the build tree. |
| Script | <script>.cmake | Run in script mode with cmake -P: no build system is generated and commands that define targets or actions are not allowed. |
| Module | <module>.cmake | Loaded with include() in the scope of the code that includes it; found through CMAKE_MODULE_PATH or among CMake’s own modules. |
Source should be 7-bit ASCII for portability, but the reader is 8-bit clean, so UTF-8
works where the platform allows it (on Windows from CMake 3.2). A leading UTF-8 byte
order mark is accepted from CMake 3.0. Line endings \n and
\r\n are both read as \n.
Grammar
The manual’s grammar, complete. A file is a sequence of command invocations, comments and blank lines; there is nothing else at the top level.
file ::= file_element*
file_element ::= command_invocation line_ending |
(bracket_comment|space)* line_ending
line_ending ::= line_comment? newline
space ::= <match '[ \t]+'>
newline ::= <match '\n'>
command_invocation ::= space* identifier space* '(' arguments ')'
identifier ::= <match '[A-Za-z_][A-Za-z0-9_]*'>
arguments ::= argument? separated_arguments*
separated_arguments ::= separation+ argument? |
separation* '(' arguments ')'
separation ::= space | line_ending
argument ::= bracket_argument | quoted_argument | unquoted_argument
bracket_argument ::= bracket_open bracket_content bracket_close
bracket_open ::= '[' '='* '['
bracket_content ::= <any text not containing a bracket_close with
the same number of '=' as the bracket_open>
bracket_close ::= ']' '='* ']'
quoted_argument ::= '"' quoted_element* '"'
quoted_element ::= <any character except '\' or '"'> |
escape_sequence | quoted_continuation
quoted_continuation ::= '\' newline
unquoted_argument ::= unquoted_element+ | unquoted_legacy
unquoted_element ::= <any character except whitespace or one of '()#"\'> |
escape_sequence
escape_sequence ::= escape_identity | escape_encoded | escape_semicolon
escape_identity ::= '\' <match '[^A-Za-z0-9;]'>
escape_encoded ::= '\t' | '\r' | '\n'
escape_semicolon ::= '\;'
bracket_comment ::= '#' bracket_argument
line_comment ::= '#' <any text not starting in a bracket_open
and not containing a newline>
Command names are not case-sensitive (ADD_EXECUTABLE and
add_executable are the same); variable names are. Parentheses inside
the arguments must balance, and each unquoted one is passed on as a literal
argument, which is how if((A OR B) AND C) works.
Arguments
| Kind | Example | Escapes and variables | Arguments produced |
|---|---|---|---|
| Bracket | [==[text ]] here]==] | Neither: the content is taken literally. A newline straight after the opening bracket is dropped. Brackets do not nest; the close must have the same number of =. | Exactly one (CMake 3.0 and later). |
| Quoted | "a ${X} b" | Both. A \ at the end of a line joins the next line (CMake 3.0 and later). | Exactly one; semicolons stay in the value. |
| Unquoted | a;b${X} | Both; then the value is split as a list. | Zero or more: an empty value gives none. |
| Unquoted legacy | -Da="b c", $(MAKEVAR) | Balanced double quotes and make-style $(…) inside an unquoted argument are kept literally, for compatibility. Discouraged. | One. |
Escape sequences
| Sequence | Kind | Result |
|---|---|---|
\t | encoded | Tab. |
\r | encoded | Carriage return. |
\n | encoded | Newline. |
\; | semicolon | A semicolon that does not split an unquoted argument into list items; inside a variable reference, a plain ;. |
\ + any other character that is not a letter or digit | identity | That character literally, e.g. \$, \", \\, \(, \#, \ . The grammar has no escape for other letters, digits or ; beyond those above. |
Variable references
| Form | Meaning |
|---|---|
${name} | The variable’s value, looked up through the scopes, then the cache; empty if neither has it. References nest and are expanded from the inside out: ${outer_${inner}}. |
$ENV{name} | An environment variable. |
$CACHE{name} | A cache entry, skipping normal variables. |
A literal variable name may hold letters, digits, /_.+- and escape
sequences. Inside if() a bare name is also read as a variable. Names
starting CMAKE_ or _CMAKE_, or _ followed by a
command name, are reserved.
Build-time generator expressions, $<…>, are not part of
the language: they are ordinary text that certain commands and target properties
evaluate later, for each configuration. They are listed in
cmake-generator-expressions(7).
Control structures
| Commands | Purpose |
|---|---|
if() elseif() else() endif() | Conditional blocks; the condition syntax is below. |
foreach() endforeach() | Loop over items, RANGE, IN LISTS, IN ITEMS or IN ZIP_LISTS. |
while() endwhile() | Loop while a condition holds. |
break() continue() | Leave a loop, or go to its next pass. |
macro() endmacro() | Record commands to run later in the caller’s scope, with textual argument replacement (${arg}, ${ARGN}, ${ARGC}, ${ARGV}, ${ARGV0}…). |
function() endfunction() | Like a macro, but run in a new variable scope with real variables for the arguments; return(PROPAGATE …) passes variables back. |
block() endblock() | A new scope for variables, policies and/or diagnostics (SCOPE_FOR), with PROPAGATE to pass variables out (CMake 3.25 and later). |
return() | Leave a function, a file or a directory. |
Conditions
| Group | Operators and constants |
|---|---|
| True constants | 1, ON, YES, TRUE, Y, or a non-zero number, including floating-point numbers. Named constants are not case-sensitive. |
| False constants | 0, OFF, NO, FALSE, N, IGNORE, NOTFOUND, the empty string, or anything ending -NOTFOUND. Another bare word is a variable name, true unless its value is a false constant. |
| Logic (lowest precedence) | NOT, then AND, then OR; parentheses group. |
| Existence | COMMAND, DIAGNOSTIC (a diagnostic category), POLICY, TARGET, TEST, DEFINED (including DEFINED ENV{x} and DEFINED CACHE{x}), IN_LIST. |
| Files | EXISTS, IS_READABLE, IS_WRITABLE, IS_EXECUTABLE, IS_NEWER_THAN, IS_DIRECTORY, IS_SYMLINK, IS_ABSOLUTE. |
| Regular expression | MATCHES (sets CMAKE_MATCH_<n>). |
| Numbers | LESS, GREATER, EQUAL, LESS_EQUAL, GREATER_EQUAL. |
| Strings | STRLESS, STRGREATER, STREQUAL, STRLESS_EQUAL, STRGREATER_EQUAL. |
| Versions | VERSION_LESS, VERSION_GREATER, VERSION_EQUAL, VERSION_LESS_EQUAL, VERSION_GREATER_EQUAL. |
| Paths | PATH_EQUAL (CMake 3.24; compares paths component by component, without touching the file system). |
Operators bind in this order: parentheses; unary tests (EXISTS,
COMMAND, DEFINED and the rest); binary tests
(EQUAL, MATCHES and the rest); NOT;
AND; OR.
Variable scopes
| Scope | Created by | Lifetime |
|---|---|---|
| Function | Each call of a function() | Until the call returns; set(… PARENT_SCOPE) writes to the caller. |
| Block | block() | Until endblock(). |
| Directory | Each CMakeLists.txt, starting as a copy of its parent’s; a cmake -P script has one | For that directory. |
| Cache | set(… CACHE …), option() | Kept between runs in CMakeCache.txt, the file that marks a build tree (cmake(1)). |
A reference looks in the function calls from the innermost out, then the directory scope, then the cache.
Lists
All values are strings. A list is a string with items separated by ;.
When an unquoted argument is expanded it is split at every ; that is not
escaped as \; and not inside unbalanced square brackets, and empty items
are dropped. So set(x a "b;c") sets x to
a;b;c, a three-item list.
Comments
#[[ … ]],#[=[ … ]=]#directly followed by a bracket open, up to the matching close; may span lines and sit between arguments (CMake 3.0 and later).# …#, to the end of the line.