mirror of
1
0
Fork 0

Starting nice linking to CMake docs: basics

This commit is contained in:
Henry Fredrick Schreiner 2018-04-06 08:33:21 +02:00
parent 1ddf77ac2f
commit 7e686f8097
2 changed files with 20 additions and 10 deletions

View File

@ -2,10 +2,20 @@
"title": "Modern CMake",
"description": "A guide to writing simple, powerful, and clean CMake 3.1+ builds.",
"author": "Henry Schreiner",
"plugins": ["collapsible-menu", "hints", "term", "include-codeblock"],
"plugins": ["replace", "hints", "term", "include-codeblock"],
"pluginsConfig": {
"include-codeblock": {
"fixlang": true
},
"replace": {
"substitutes": [
{"pattern": "«cmake:([^`^»]+)»", "flags": "g", "substitute": "[$1](https://cmake.org/cmake/help/latest/$1.7.html)"},
{"pattern": "«command:`?([^`^»]+)`?»", "flags": "g", "substitute": "[`$1`](https://cmake.org/cmake/help/latest/command/$1.html)"},
{"pattern": "«module:([^`^»]+)»", "flags": "g", "substitute": "[$1](https://cmake.org/cmake/help/latest/module/$1.html)"},
{"pattern": "«policy:([^`^»]+)»", "flags": "g", "substitute": "[$1](https://cmake.org/cmake/help/latest/policy/$1.html)"},
{"pattern": "«variable:`?([^`^»]+)`?»", "flags": "g", "substitute": "[`$1`](https://cmake.org/cmake/help/latest//$1.html)"},
{"pattern": "«prop:([^:]+):`?([^`^»]+)`?»", "flags": "g", "substitute": "[`$2`](https://cmake.org/cmake/help/latest/prop_$1/$2.html)"}
]
}
}
}

View File

@ -9,16 +9,16 @@ Here's the first line of every CMakeLists.txt, which is the required name of the
cmake_minimum_required(VERSION 3.1)
```
Let's mention a bit of CMake syntax. The function name is case insensitive, so the common practice is to use lower case. [^1] The `VERSION` is a special keyword for this function. And the value of the version follows the keyword. See the excellent documentation [here](https://cmake.org/cmake/help/latest/command/cmake_minimum_required.html), and use the dropdown to switch documentation between CMake versions.
Let's mention a bit of CMake syntax. The command name «command:`cmake_minimum_required`» is case insensitive, so the common practice is to use lower case. [^1] The `VERSION` is a special keyword for this function. And the value of the version follows the keyword. Like everywhere in this book, just click on the command name to see the official documentation, and use the dropdown to switch documentation between CMake versions.
This line is special! [^2] The version of CMake will also dictate the policies, which define behavior changes. So, if you set `minimum_required` to `VERSION 2.8`, you'll get the wrong linking behavior on macOS, for example, even in the newest CMake versions. A list of policies and versions is [here](https://cmake.org/cmake/help/latest/manual/cmake-policies.7.html).
This line is special! [^2] The version of CMake will also dictate the policies, which define behavior changes. So, if you set `minimum_required` to `VERSION 2.8`, you'll get the wrong linking behavior on macOS, for example, even in the newest CMake versions. A list of policies and versions is available at «cmake:policies».
In the upcoming CMake 3.12, this will support a range, such as `VERSION 3.1...3.12`; this means you support as low as 3.1 but have also tested it with the new policy settings up to 3.12. This is much nicer on users that need the better settings, and due to a trick in the syntax, it's backward compatible with older versions of CMake (though 3.2-3.11 will still set the 3.1 version of the policies). New versions of policies tend to be most important for macOS and Windows users, who also
usually have a very recent version of CMake.
{% hint style='info' %}
If you really need to set to a low value here, you can use [`cmake_policy`](https://cmake.org/cmake/help/latest/command/cmake_policy.html) to conditionally increase the policy level or set a specific policy. Please at least do this for your macOS users!
If you really need to set to a low value here, you can use «command:`cmake_policy`» to conditionally increase the policy level or set a specific policy. Please at least do this for your macOS users!
{% endhint %}
@ -32,7 +32,7 @@ project(MyProject VERSION 1.0
LANGUAGES CXX)
```
Now we see even more syntax. Strings are quoted, white space doesn't matter [^3], and the name of the project is the first argument (positional). All the keyword arguments here are optional. The version sets a bunch of variables, like `MyProject_VERSION` and `PROJECT_VERSION`. The languages are C, CXX, FORTRAN, and CUDA (CMake 3.7+). `C CXX` is the default. Docs [here](https://cmake.org/cmake/help/latest/command/project.html).
Now we see even more syntax. Strings are quoted, white space doesn't matter [^3], and the name of the project is the first argument (positional). All the keyword arguments here are optional. The version sets a bunch of variables, like `MyProject_VERSION` and `PROJECT_VERSION`. The languages are C, CXX, FORTRAN, and CUDA (CMake 3.7+). `C CXX` is the default. In CMake 3.9, `DESCRIPTION` was added to set a project description, as well. The documentation for «command:`project`» may be helpful.
{% hint style='danger' %}
CMake doesn't care about white space, and you can add comments with the `#` character, but never put a comment inside the function call parenthesis.
@ -48,15 +48,15 @@ Although libraries are much more interesting, and we'll spend most of our time w
add_executable(one two.cpp three.h)
```
There are several things to unpack here. `one` is both the name of the executable file generated, and the name of the CMake target created (you'll hear a lot more about targets soon, I promise). The source file list comes next, and you can list as many as you'd like. CMake is smart, and will only compile source file extensions. The headers will be, for most intents and purposes, ignored; the only reason to list them is to get them to show up in IDEs. Targets show up as folders in many IDEs. More about the general build system and targets is [here](https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html).
There are several things to unpack here. `one` is both the name of the executable file generated, and the name of the CMake target created (you'll hear a lot more about targets soon, I promise). The source file list comes next, and you can list as many as you'd like. CMake is smart, and will only compile source file extensions. The headers will be, for most intents and purposes, ignored; the only reason to list them is to get them to show up in IDEs. Targets show up as folders in many IDEs. More about the general build system and targets is available at «cmake:buildsystem».
## Making a library
[Making a library](https://cmake.org/cmake/help/latest/command/add_library.html) that compiles is just about as simple:
Making a library is done with «command:`add_library`», and is just about as simple:
```cmake
add_LIBRARY(one STATIC two.cpp three.h)
add_library(one STATIC two.cpp three.h)
```
You get to pick a type of library, STATIC, SHARED, or MODULE. If you leave this choice off, the value of `BUILD_SHARED_LIBS` will be used to pick between STATIC and SHARED.
@ -73,7 +73,7 @@ Now we've specified a target, how do we add information about it? For example, m
target_include_directories(one PUBLIC include)
```
This [command](https://cmake.org/cmake/help/latest/command/target_include_directories.html) adds an include directory to a target. `PUBLIC` doesn't mean much for an executable; for a library it lets CMake know that any targets that link to this target must also need that include directory. Other options are `PRIVATE` (only affect the current target, not dependencies), and `INTERFACE` (only needed for dependencies).
«command:`target_include_directories» adds an include directory to a target. `PUBLIC` doesn't mean much for an executable; for a library it lets CMake know that any targets that link to this target must also need that include directory. Other options are `PRIVATE` (only affect the current target, not dependencies), and `INTERFACE` (only needed for dependencies).
We can then chain targets:
@ -82,7 +82,7 @@ add_library(another STATIC another.cpp another.h)
target_link_libraries(another PUBLIC one)
```
[This](https://cmake.org/cmake/help/latest/command/target_link_libraries.html) is probably the most useful and confusing command in CMake. It takes a target (`another`) and adds a dependency if a target is given. If no target of that name (`one`) exists, then it adds a link to a library called `one` on your path (hence the name of the command). Or you can give it a full path to a library. Or a linker flag. Just to add a final bit of confusion, classic CMake allowed you to skip the keyword selection of `PUBLIC`, etc. If this was done on a target, you'll get an error if you try to mix styles further down the chain.
«command:`target_link_libraries`» is probably the most useful and confusing command in CMake. It takes a target (`another`) and adds a dependency if a target is given. If no target of that name (`one`) exists, then it adds a link to a library called `one` on your path (hence the name of the command). Or you can give it a full path to a library. Or a linker flag. Just to add a final bit of confusion, classic CMake allowed you to skip the keyword selection of `PUBLIC`, etc. If this was done on a target, you'll get an error if you try to mix styles further down the chain.
Focus on using targets everywhere, and keywords everywhere, and you'll be fine.