CMake Tools supports a variety of settings that can be set at the user orworkspace level via VSCode’s settings.json
file. This page talks aboutthe available options and how they are used.
Options marked with Supports substitution allow variable references to appearin their strings. See the Variable Substitution section
Available Settings¶
CMake Tools’ Quick Start¶ CMake Tools provides a CMake: Quick Start command to quickly generate a very bare-bones CMake project that can be configured and built with minimal friction. Start by selecting CMake: Quick Start from the command palette: CMake Tools will then prompt you for the following information. CMake is a tool to simplify the build process for development projects across different platforms. CMake automatically generates build systems, such as Makefiles and Visual Studio project files. CMake is a 3rd party tool with its own documentation. This topic describes how to use CMake 3.1.0 with Qt 5. Table of Contents. Get started with CMake.
cmake.buildArgs
¶
CMake has a special substitution rule for unquoted arguments. If the entire argument is a variable reference without quotes, and the variable’s value contains semicolons, CMake will split the value at the semicolons and pass multiple arguments to the enclosing command.
An array of additional arguments to pass to cmake--build
.
Default:
[]
(Empty array, no additional arguments)Supports substitution
cmake.buildBeforeRun
¶
If true
, build the launch/debug target before letting it execute.
Default:
true
cmake.buildDirectory
¶
Specify the build directory (The root directory where CMakeCache.txt
willbe generated).
Default:
${workspaceFolder}/build
.Supports substitution
cmake.buildEnvironment
¶
An object containing key:value
pairs of environment variables,which will be passed ONLY onto the compiler.
Default:
null
(Unspecified)Supports substitution
cmake.buildToolArgs
¶
An array of additional arguments to pass to the underlying build tool.
Default:
[]
(Empty array, no additional arguments)Supports substitution
cmake.cacheInit
¶
Path or list of paths to cache-initialization files. Passed to CMake via the-C
command-line argument.
Default:
[]
(Empty array, no cache initializer files)
cmake.cmakePath
¶
Specify location of the cmake executable.
Default:
cmake
, which causes CMake Tools to search thePATH
environmentvariable, as well as some hard-coded guesses.Supports substitution of
workspaceRoot
,workspaceFolder
,workspaceRootFolderName
,userHome
,${command:..}
and${env:..}
. Other substitutions willresult in empty string.
cmake.configureArgs
¶
Arguments to CMake that will be passed during the configure process.
Default:
[]
(Empty array, no arguments)Supports substitution
Warning
Always prefer to use cmake.configureSettings
or CMake Variants.Never pass -D
arguments using this setting.
cmake.configureEnvironment
¶
An object containing key:value
pairs of environment variables,which will be passed onto CMake ONLY when configuring.
Default:
null
(Unspecified)Supports substitution
cmake.configureSettings
¶
An object containing key:value
pairs, which will bepassed onto CMake when configuring.It does the same thing as passing -DVAR_NAME=ON
viacmake.configureArgs
.
Default:
null
(Unspecified)Supports substitution
cmake.copyCompileCommands
¶
If not null
, copies the compile_commands.json
file generated by CMaketo the path specified by this setting every time CMake successfully configures.
Default:
null
(Do not copy the file)Supports substitution
cmake.defaultVariants
¶
Override the default set of variants that will be supplied when no variants fileis present. Best imac. See CMake Variants.
cmake.environment
¶
An object containing key:value
pairs of environment variables,which will be passed onto CMake when configuring and to the compiler.
Default:
null
(Unspecified)Supports substitution
cmake.generator
¶
Set to a string to override CMake Tools’ preferred generator logic. If this isset, CMake will unconditionally use it as the -G
CMake generator commandline argument.
cmake.installPrefix
¶
If specified, sets a value for CMAKE_INSTALL_PREFIX
when running CMakeconfigure. If not, no value will be passed.
Default:
null
(Unspecified)Supports substitution
Note
If CMAKE_INSTALL_PREFIX
is set via cmake.configureArgs
orcmake.configureSettings
, cmake.installPrefix
will be ignored.
cmake.loggingLevel
¶
An enumerated string setting to change the amount of output CMake Toolsproduces in its output channel. Set to one of “trace”, “debug”, “info”, “note”,“warning”, “error”, or “fatal”, with “trace” being the most verbose.
Default:
info
Note
Regardless of the logging level, CMake Tools writes all levels of loggingto the CMake Tools log file. This file is useful fortroubleshooting.
cmake.mingwSearchDirs
¶
List of paths to search for a MinGW installation. This means that GCC does notneed to be on your $PATH
for it to be found via Kit scanning.
Default:
['C:MinGW']
(Search in C:MinGW for a MinGW installation)
cmake.parallelJobs
¶
By specifying a number, you can define how many jobs are run in parallel during the build.
cmake.preferredGenerators
¶
A list of strings of generator names to try in order when configuring a CMakeproject for the first time.
cmake.saveBeforeBuild
¶
If true
(the default), saves open text documents when build or configure isinvoked before running CMake.
Default:
true
cmake.sourceDirectory
¶
Directory where the root CMakeLists.txt
will be found.
Default:
${workspaceFolder}
Supports substitution
Variable Substitution¶
Some options support the replacement of special values in their string valueusing ${variable}
syntax. The following built-in variables are expanded:
${workspaceRoot}
DEPRECATED. The full path to the workspace root directory
${workspaceFolder}
The full path to the workspace root directory
Cmake Windows
${workspaceRootFolderName}
The name of the leaf directory in the workspace directory path
${buildType}
The current CMake build type, eg. Debug
, Release
, MinSizeRel
${buildKit}
The current CMake kit name, eg. GCC7.3.0
${generator}
The name of the CMake generator, eg. Torrent program pc. Ninja
${projectName}
DEPRECATED. Expands to the constant string “ProjectName
”
Note
This was deprecated as CMake does not consider there to be oneproject name to use. The concept of a single project does not work inCMake, and this made this feature problematic and buggy. Alternativesinclude ${workspaceRootFolderName}
.
${userHome}
The full path to the current user’s home directory
Environment Variables¶
Additionally, environment variables may be substituted with ${env:VARNAME}
and ${env.VARNAME}
syntax, where the string for the VARNAME
environmentvariable will be replaced. If the named environment variable is undefined, an emptystring will be expanded instead.
Variant Substitution¶
Variant options may also be substituted with the ${variant:VARIANTNAME}
syntax,where the name of the currently active choice of the provided VARIANTNAME
variantoption will be replaced. If the variant option is undefined, an empty string will beexpanded instead.
Command Substitution¶
CMake Tools also supports expanding of VSCode commands, similar tolaunch.json
. Running a command ${command:foo.bar}
will execute thefoo.bar
VSCode command and replace the string value. Beware of long-runningcommands! It is unspecified when and how many times CMake Tools will execute acommand for a given expansion.
As explained in my previous post, every CMake-based project must contain a script named CMakeLists.txt
. This script defines targets, but it can also do a lot of other things, such as finding third-party libraries or generating C++ header files. CMake scripts have a lot of flexibility.
Every time you integrate an external library, and often when adding support for another platform, you’ll need to edit the script. I spent a long time editing CMake scripts without really understanding the language, as the documentation is quite scattered, but eventually, things clicked. The goal of this post is to get you to the same point as quickly as possible.
This post won’t cover all of CMake’s built-in commands, as there are hundreds, but it is a fairly complete guide to the syntax and programming model of the language.
Hello World
If you create a file named hello.txt
with the following contents:
…you can run it from the command line using cmake -P hello.txt
. (The -P
option runs the given script, but doesn’t generate a build pipeline.) As expected, it prints “Hello world!”.
All Variables Are Strings
In CMake, every variable is a string. You can substitute a variable inside a string literal by surrounding it with ${}
. This is called a variable reference. Modify hello.txt
as follows:
Now, if we define NAME
on the cmake
command line using the -D
option, the script will use it:
When a variable is undefined, it defaults to an empty string:
To define a variable inside a script, use the set
command. The first argument is the name of the variable to assign, and the second argument is its value:
Quotes around arguments are optional, as long as there are no spaces or variable references in the argument. For example, I could have written set('THING' funk)
in the first line above – it would have been equivalent. For most CMake commands (except if
and while
, described below), the choice of whether to quote such arguments is simply a matter of style. When the argument is the name of a variable, I tend not to use quotes.
You Can Simulate a Data Structure using Prefixes
CMake does not have classes, but you can simulate a data structure by defining a group of variables with names that begin with the same prefix. You can then look up variables in that group using nested ${}
variable references. For example, the following script will print “John Smith lives at 123 Fake St.”:
You can even use variable references in the name of the variable to set. For example, if the value of PERSON
is still “JOHN”, the following will set the variable JOHN_NAME
to “John Goodman”:
Every Statement is a Command
In CMake, every statement is a command that takes a list of string arguments and has no return value. Arguments are separated by (unquoted) spaces. As we’ve already seen, the set
command defines a variable at file scope.
As another example, CMake has a math
command that performs arithmetic. The first argument must be EXPR
, the second argument is the name of the variable to assign, and the third argument is the expression to evaluate – all strings. Note that on the third line below, CMake substitutes the string value of MY_SUM
into the enclosing argument before passing the argument to math
.
There’s a CMake command for just about anything you’ll need to do. The string
command lets you perform advanced string manipulation, including regular expression replacement. The file
command can read or write files, or manipulate filesystem paths.
Flow Control Commands
Even flow control statements are commands. The if
/endif
commands execute the enclosed commands conditionally. Whitespace doesn’t matter, but it’s common to indent the enclosed commands for readablity. The following checks whether CMake’s built-in variable WIN32
is set:
CMake also has while
/endwhile
commands which, as you might expect, repeat the enclosed commands as long as the condition is true. Here’s a loop that prints all the Fibonacci numbers up to one million:
CMake’s if
and while
conditions aren’t written the same way as in other languages. For example, to perform a numeric comparison, you must specify LESS
as a string argument, as shown above. The documentation explains how to write a valid condition.
if
and while
are different from other CMake commands in that if the name of a variable is specified without quotes, the command will use the variable’s value. In the above code, I took advantage of that behavior by writing while(A LESS '1000000')
instead of while('${A}' LESS '1000000')
– both forms are equivalent. Other CMake commands don’t do that.
Cmake Example
Lists are Just Semicolon-Delimited Strings
CMake has a special substitution rule for unquoted arguments. If the entire argument is a variable reference without quotes, and the variable’s value contains semicolons, CMake will split the value at the semicolons and pass multiple arguments to the enclosing command. For example, the following passes three arguments to math
:
On the other hand, quoted arguments are never split into multiple arguments, even after substitution. CMake always passes a quoted string as a single argument, leaving semicolons intact:
If more than two arguments are passed to the set
command, they are joined by semicolons, then assigned to the specified variable. This effectively creates a list from the arguments:
Cmake Windows
You can manipulate such lists using the list
command:
The foreach
/endforeach
command accepts multiple arguments. It iterates over all arguments except the first, assigning each one to the named variable:
You can iterate over a list by passing an unquoted variable reference to foreach
. As with any other command, CMake will split the variable’s value and pass multiple arguments to the command:
Functions Run In Their Own Scope; Macros Don’t
In CMake, you can use a pair of function
/endfunction
commands to define a function. Here’s one that doubles the numeric value of its argument, then prints the result:
Cmake.org
Functions run in their own scope. None of the variables defined in a function pollute the caller’s scope. If you want to return a value, you can pass the name of a variable to your function, then call the set
command with the special argument PARENT_SCOPE
:
Similarly, a pair of macro
/endmacro
commands defines a macro. Unlike functions, macros run in the same scope as their caller. Therefore, all variables defined inside a macro are set in the caller’s scope. We can replace the previous function with the following:
Both functions and macros accept an arbitrary number of arguments. Unnamed arguments are exposed to the function as a list, through a special variable named ARGN
. Here’s a function that doubles every argument it receives, printing each one on a separate line:
Including Other Scripts
CMake variables are defined at file scope. The include
command executes another CMake script in the same scope as the calling script. It’s a lot like the #include
directive in C/C++. It’s typically used to define a common set of functions or macros in the calling script. It uses the variable CMAKE_MODULE_PATH
as a search path.
The find_package
command looks for scripts of the form Find*.cmake
and also runs them in the same scope. Such scripts are often used to help find external libraries. For example, if there is a file named FindSDL2.cmake
in the search path, find_package(SDL2)
is equivalent to include(FindSDL2.cmake)
. (Note that there are several ways to use the find_package
command – this is just one of them.)
Visual Studio Cmake
CMake’s add_subdirectory
command, on the other hand, creates a new scope, then executes the script named CMakeLists.txt
from the specified directory in that new scope. You typically use it to add another CMake-based subproject, such as a library or executable, to the calling project. The targets defined by the subproject are added to the build pipeline unless otherwise specified. None of the variables defined in the subproject’s script will pollute the parent’s scope unless the set
command’s PARENT_SCOPE
option is used.
As an example, here are some of the scripts involved when you run CMake on the Turf project:
Cmake Download
Getting and Setting Properties
A CMake script defines targets using the add_executable
, add_library
or add_custom_target
commands. Once a target is created, it has properties that you can manipulate using the get_property
and set_property
commands. Unlike variables, targets are visible in every scope, even if they were defined in a subdirectory. All target properties are strings.
Decent paint brushes. Other target properties include LINK_LIBRARIES
, INCLUDE_DIRECTORIES
and COMPILE_DEFINITIONS
. Those properties are modified, indirectly, by the target_link_libraries
, target_include_directories
and target_compile_definitions
commands. At the end of the script, CMake uses those target properties to generate the build pipeline.
There are properties for other CMake entities, too. There is a set of directory properties at every file scope. There is a set of global properties that is accessible from all scripts. And there is a set of source file properties for every C/C++ source file.
Congratulations! You now know the CMake scripting language – or at least, it should be easier to understand large scripts using CMake’s command reference. Otherwise, the only thing missing from this guide, that I can think of, is generator expressions. Let me know if I forgot anything else!