| # CMake Primer |
| |
| :::{warning} |
| Disclaimer: This documentation is written by LLVM project contributors *not* |
| anyone affiliated with the CMake project. This document may contain |
| inaccurate terminology, phrasing, or technical details. It is provided with |
| the best intentions. |
| ::: |
| |
| ## Introduction |
| |
| The LLVM project and many of the core projects built on LLVM build using CMake. |
| This document aims to provide a brief overview of CMake for developers modifying |
| LLVM projects or building their own projects on top of LLVM. |
| |
| The official CMake language reference is available in the cmake-language |
| manpage and [cmake-language online documentation](https://cmake.org/cmake/help/v3.4/manual/cmake-language.7.html). |
| |
| ## 10,000 ft View |
| |
| CMake is a tool that reads script files in its own language that describe how a |
| software project builds. As CMake evaluates the scripts, it constructs an |
| internal representation of the software project. Once the scripts have been |
| fully processed, if there are no errors, CMake will generate build files to |
| actually build the project. CMake supports generating build files for a variety |
| of command line build tools as well as for popular IDEs. |
| |
| When a user runs CMake it performs a variety of checks similar to how autoconf |
| worked historically. During the checks and the evaluation of the build |
| description scripts CMake caches values into the CMakeCache. This is useful |
| because it allows the build system to skip long-running checks during |
| incremental development. CMake caching also has some drawbacks, but that will be |
| discussed later. |
| |
| ## Scripting Overview |
| |
| CMake's scripting language has a very simple grammar. Every language construct |
| is a command that matches the pattern `_name_(_args_)`. Commands come in three |
| primary types: language-defined (commands implemented in C++ in CMake), defined |
| functions, and defined macros. The CMake distribution also contains a suite of |
| CMake modules that contain definitions for useful functionality. |
| |
| The example below is the full CMake build for building a C++ "Hello World" |
| program. The example uses only CMake language-defined functions. |
| |
| ```cmake |
| cmake_minimum_required(VERSION 3.20.0) |
| project(HelloWorld) |
| add_executable(HelloWorld HelloWorld.cpp) |
| ``` |
| |
| The CMake language provides control flow constructs in the form of `foreach` loops |
| and `if` blocks. To make the example above more complicated you could add an if |
| block to define "APPLE" when targeting Apple platforms: |
| |
| ```cmake |
| cmake_minimum_required(VERSION 3.20.0) |
| project(HelloWorld) |
| add_executable(HelloWorld HelloWorld.cpp) |
| if(APPLE) |
| target_compile_definitions(HelloWorld PUBLIC APPLE) |
| endif() |
| ``` |
| |
| ## Variables, Types, and Scope |
| |
| ### Dereferencing |
| |
| In CMake, variables are "stringly" typed. All variables are represented as |
| strings throughout evaluation. Wrapping a variable in `${}` dereferences it |
| and results in a literal substitution of the name for the value. CMake refers to |
| this as "variable evaluation" in their documentation. Dereferences are performed |
| *before* the command being called receives the arguments. This means |
| dereferencing a list results in multiple separate arguments being passed to the |
| command. |
| |
| Variable dereferences can be nested and be used to model complex data. For |
| example: |
| |
| ```cmake |
| set(var_name var1) |
| set(${var_name} foo) # same as "set(var1 foo)" |
| set(${${var_name}}_var bar) # same as "set(foo_var bar)" |
| ``` |
| |
| Dereferencing an unset variable results in an empty expansion. It is a common |
| pattern in CMake to conditionally set variables knowing that it will be used in |
| code paths that the variable isn't set. There are examples of this throughout |
| the LLVM CMake build system. |
| |
| An example of variable empty expansion is: |
| |
| ```cmake |
| if(APPLE) |
| set(extra_sources Apple.cpp) |
| endif() |
| add_executable(HelloWorld HelloWorld.cpp ${extra_sources}) |
| ``` |
| |
| In this example the `extra_sources` variable is only defined if you're |
| targeting an Apple platform. For all other targets the `extra_sources` will be |
| evaluated as empty before add_executable is given its arguments. |
| |
| ### Lists |
| |
| In CMake, lists are semicolon-delimited strings, and it is strongly advised that |
| you avoid using semicolons in lists; it doesn't go smoothly. A few examples of |
| defining lists: |
| |
| ```cmake |
| # Creates a list with members a, b, c, and d |
| set(my_list a b c d) |
| set(my_list "a;b;c;d") |
| |
| # Creates a string "a b c d" |
| set(my_string "a b c d") |
| ``` |
| |
| ### Lists of Lists |
| |
| One of the more complicated patterns in CMake is lists of lists. Because a list |
| cannot contain an element with a semicolon to construct a list of lists you |
| make a list of variable names that refer to other lists. For example: |
| |
| ```cmake |
| set(list_of_lists a b c) |
| set(a 1 2 3) |
| set(b 4 5 6) |
| set(c 7 8 9) |
| ``` |
| |
| With this layout you can iterate through the list of lists printing each value |
| with the following code: |
| |
| ```cmake |
| foreach(list_name IN LISTS list_of_lists) |
| foreach(value IN LISTS ${list_name}) |
| message(${value}) |
| endforeach() |
| endforeach() |
| ``` |
| |
| You'll notice that the inner foreach loop's list is doubly dereferenced. This is |
| because the first dereference turns `list_name` into the name of the sub-list |
| (a, b, or c in the example), then the second dereference is to get the value of |
| the list. |
| |
| This pattern is used throughout CMake, the most common example is the compiler |
| flags options, which CMake refers to using the following variable expansions: |
| `CMAKE_${LANGUAGE}_FLAGS` and `CMAKE_${LANGUAGE}_FLAGS_${CMAKE_BUILD_TYPE}`. |
| |
| ### Other Types |
| |
| Variables that are cached or specified on the command line can have types |
| associated with them. The variable's type is used by CMake's UI tool to display |
| the right input field. A variable's type generally doesn't impact evaluation; |
| however, CMake does have special handling for some variables such as `PATH`. |
| You can read more about the special handling in [CMake's set documentation](https://cmake.org/cmake/help/v3.5/command/set.html#set-cache-entry). |
| |
| ### Scope |
| |
| CMake inherently has a directory-based scoping. Setting a variable in a |
| CMakeLists file, will set the variable for that file, and all subdirectories. |
| Variables set in a CMake module that is included in a CMakeLists file will be |
| set in the scope they are included from, and all subdirectories. |
| |
| When a variable that is already set is set again in a subdirectory it overrides |
| the value in that scope and any deeper subdirectories. |
| |
| The CMake set command provides two scope-related options. `PARENT_SCOPE` sets a |
| variable into the parent scope, and not the current scope. The `CACHE` option sets |
| the variable in the CMakeCache, which results in it being set in all scopes. The |
| `CACHE` option will not set a variable that already exists in the `CACHE` unless the |
| `FORCE` option is specified. |
| |
| In addition to directory-based scope, CMake functions also have their own scope. |
| This means variables set inside functions do not bleed into the parent scope. |
| This is not true of macros, and it is for this reason LLVM prefers functions |
| over macros whenever reasonable. |
| |
| :::{note} |
| Unlike C-based languages, CMake's loop and control flow blocks do not have |
| their own scopes. |
| ::: |
| |
| ## Control Flow |
| |
| CMake features the same basic control flow constructs you would expect in any |
| scripting language, but there are a few quirks because, as with everything in |
| CMake, control flow constructs are commands. |
| |
| ### If, ElseIf, Else |
| |
| :::{note} |
| For the full documentation on the CMake if command go |
| [here](https://cmake.org/cmake/help/v3.4/command/if.html). That resource is |
| far more complete. |
| ::: |
| |
| In general, CMake `if` blocks work the way you'd expect: |
| |
| ```cmake |
| if(<condition>) |
| message("do stuff") |
| elseif(<condition>) |
| message("do other stuff") |
| else() |
| message("do other other stuff") |
| endif() |
| ``` |
| |
| The single most important thing to know about CMake's `if` blocks coming from a C |
| background is that they do not have their own scope. Variables set inside |
| conditional blocks persist after the `endif()`. |
| |
| ### Loops |
| |
| The most common form of the CMake `foreach` block is: |
| |
| ```cmake |
| foreach(var ...) |
| message("do stuff") |
| endforeach() |
| ``` |
| |
| The variable argument portion of the `foreach` block can contain dereferenced |
| lists, values to iterate, or a mix of both: |
| |
| ```cmake |
| foreach(var foo bar baz) |
| message(${var}) |
| endforeach() |
| # prints: |
| # foo |
| # bar |
| # baz |
| |
| set(my_list 1 2 3) |
| foreach(var ${my_list}) |
| message(${var}) |
| endforeach() |
| # prints: |
| # 1 |
| # 2 |
| # 3 |
| |
| foreach(var ${my_list} out_of_bounds) |
| message(${var}) |
| endforeach() |
| # prints: |
| # 1 |
| # 2 |
| # 3 |
| # out_of_bounds |
| ``` |
| |
| There is also a more modern CMake foreach syntax. The code below is equivalent |
| to the code above: |
| |
| ```cmake |
| foreach(var IN ITEMS foo bar baz) |
| message(${var}) |
| endforeach() |
| # prints: |
| # foo |
| # bar |
| # baz |
| |
| set(my_list 1 2 3) |
| foreach(var IN LISTS my_list) |
| message(${var}) |
| endforeach() |
| # prints: |
| # 1 |
| # 2 |
| # 3 |
| |
| foreach(var IN LISTS my_list ITEMS out_of_bounds) |
| message(${var}) |
| endforeach() |
| # prints: |
| # 1 |
| # 2 |
| # 3 |
| # out_of_bounds |
| ``` |
| |
| Similar to the conditional statements, these generally behave how you would |
| expect, and they do not have their own scope. |
| |
| CMake also supports `while` loops, although they are not widely used in LLVM. |
| |
| ## Modules, Functions and Macros |
| |
| ### Modules |
| |
| Modules are CMake's vehicle for enabling code reuse. CMake modules are just |
| CMake script files. They can contain code to execute on include as well as |
| definitions for commands. |
| |
| In CMake, macros and functions are universally referred to as commands, and they |
| are the primary method of defining code that can be called multiple times. |
| |
| In LLVM we have several CMake modules that are included as part of our |
| distribution for developers who don't build our project from source. Those |
| modules are the fundamental pieces needed to build LLVM-based projects with |
| CMake. We also rely on modules as a way of organizing the build system's |
| functionality for maintainability and reuse within LLVM projects. |
| |
| ### Argument Handling |
| |
| When defining a CMake command handling arguments is very useful. The examples |
| in this section will all use the CMake `function` block, but this also applies |
| to the `macro` block as well. |
| |
| CMake commands can have named arguments that are required at every call site. In |
| addition, all commands will implicitly accept a variable number of extra |
| arguments (In C parlance, all commands are varargs functions). When a command is |
| invoked with extra arguments (beyond the named ones) CMake will store the full |
| list of arguments (both named and unnamed) in a list named `ARGV`, and the |
| sublist of unnamed arguments in `ARGN`. Below is a trivial example of |
| providing a wrapper function for CMake's built in function `add_dependencies`. |
| |
| ```cmake |
| function(add_deps target) |
| add_dependencies(${target} ${ARGN}) |
| endfunction() |
| ``` |
| |
| This example defines a new macro named `add_deps` which takes a required first |
| argument, and just calls another function passing through the first argument and |
| all trailing arguments. |
| |
| CMake provides a module `CMakeParseArguments` which provides an implementation |
| of advanced argument parsing. We use this all over LLVM, and it is recommended |
| for any function that has complex argument-based behaviors or optional |
| arguments. CMake's official documentation for the module is in the |
| `cmake-modules` manpage, and is also available at the |
| [cmake-modules online documentation](https://cmake.org/cmake/help/v3.4/module/CMakeParseArguments.html). |
| |
| :::{note} |
| As of CMake 3.5 the cmake_parse_arguments command has become a native command |
| and the CMakeParseArguments module is empty and only left around for |
| compatibility. |
| ::: |
| |
| ### Functions Vs Macros |
| |
| Functions and Macros look very similar in how they are used, but there is one |
| fundamental difference between the two. Functions have their own scope, and |
| macros don't. This means variables set in macros will bleed out into the calling |
| scope. That makes macros suitable for defining very small bits of functionality |
| only. |
| |
| The other difference between CMake functions and macros is how arguments are |
| passed. Arguments to macros are not set as variables, instead dereferences to |
| the parameters are resolved across the macro before executing it. This can |
| result in some unexpected behavior if using unreferenced variables. For example: |
| |
| ```cmake |
| macro(print_list my_list) |
| foreach(var IN LISTS my_list) |
| message("${var}") |
| endforeach() |
| endmacro() |
| |
| set(my_list a b c d) |
| set(my_list_of_numbers 1 2 3 4) |
| print_list(my_list_of_numbers) |
| # prints: |
| # a |
| # b |
| # c |
| # d |
| ``` |
| |
| Generally speaking, this issue is uncommon because it requires using |
| non-dereferenced variables with names that overlap in the parent scope, but it |
| is important to be aware of because it can lead to subtle bugs. |
| |
| ## LLVM Project Wrappers |
| |
| LLVM projects provide lots of wrappers around critical CMake built-in commands. |
| We use these wrappers to provide consistent behaviors across LLVM components |
| and to reduce code duplication. |
| |
| We generally (but not always) follow the convention that commands prefaced with |
| `llvm_` are intended to be used only as building blocks for other commands. |
| Wrapper commands that are intended for direct use are generally named following |
| with the project in the middle of the command name (i.e. `add_llvm_executable` |
| is the wrapper for `add_executable`). The LLVM `add_*` wrapper functions are |
| all defined in `AddLLVM.cmake` which is installed as part of the LLVM |
| distribution. It can be included and used by any LLVM sub-project that requires |
| LLVM. |
| |
| :::{note} |
| Not all LLVM projects require LLVM for all use cases. For example compiler-rt |
| can be built without LLVM, and the compiler-rt sanitizer libraries are used |
| with GCC. |
| ::: |
| |
| ## Useful Built-in Commands |
| |
| CMake has a collection of useful built-in commands. This document isn't going to |
| go into details about them because The CMake project has excellent |
| documentation. To highlight a few useful functions see: |
| |
| - [add_custom_command](https://cmake.org/cmake/help/v3.4/command/add_custom_command.html) |
| - [add_custom_target](https://cmake.org/cmake/help/v3.4/command/add_custom_target.html) |
| - [file](https://cmake.org/cmake/help/v3.4/command/file.html) |
| - [list](https://cmake.org/cmake/help/v3.4/command/list.html) |
| - [math](https://cmake.org/cmake/help/v3.4/command/math.html) |
| - [string](https://cmake.org/cmake/help/v3.4/command/string.html) |
| |
| The full documentation for CMake commands is in the `cmake-commands` manpage |
| and available on [CMake's website](https://cmake.org/cmake/help/v3.4/manual/cmake-commands.7.html) |