mirror of
1
0
Fork 0

Fixing older links

This commit is contained in:
Henry Fredrick Schreiner 2018-04-05 12:41:47 +02:00
parent 4046b4e31b
commit 5a46dd718b
4 changed files with 17 additions and 17 deletions

View File

@ -9,13 +9,13 @@ 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/v3.9/command/cmake_minimum_required.html), and use the dropdown to switch documentation between CMake versions.
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.
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/v3.9/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 [here](https://cmake.org/cmake/help/latest/manual/cmake-policies.7.html).
{% hint style='info' %}
If you really need to set to a low value here, you can use [`cmake_policy`](https://cmake.org/cmake/help/v3.0/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 [`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!
{% endhint %}
@ -29,7 +29,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/v3.9/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. Docs [here](https://cmake.org/cmake/help/latest/command/project.html).
{% 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.
@ -45,12 +45,12 @@ 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/v3.9/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 [here](https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html).
## Making a library
[Making a library](https://cmake.org/cmake/help/v3.9/command/add_library.html?highlight=add_library) that compiles is just about as simple:
[Making a library](https://cmake.org/cmake/help/latest/command/add_library.html) that compiles is just about as simple:
```cmake
add_LIBRARY(one STATIC two.cpp three.h)
@ -70,7 +70,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/v3.9/command/target_include_directories.html?highlight=include_directories#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).
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).
We can then chain targets:
@ -79,7 +79,7 @@ add_library(another STATIC another.cpp another.h)
target_link_libraries(another PUBLIC one)
```
[This](https://cmake.org/cmake/help/v3.9/command/target_link_libraries.html#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.
[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.
Focus on using targets everywhere, and keywords everywhere, and you'll be fine.
@ -109,5 +109,5 @@ target_link_libraries(calc PUBLIC calclib)
[^2]: You will sometimes see `FATAL_ERROR` here, that was needed to support nice failures when running this in CMake <2.6, which should not be a problem anymore.
[^3]: The `::` syntax was originally intended for `INTERFACE IMPORTED` libraries, which were explicitly supposed to be libraries defined outside the current project. But, because of this, most of the `target_*` commands don't work on `IMPORTED` libraries, making them hard to set up yourself. So don't use the `IMPORTED` keyword for now, and use an `ALIAS` target instead. There's a project in the works to fix this limitation for CMake 3.11.
[^3]: The `::` syntax was originally intended for `INTERFACE IMPORTED` libraries, which were explicitly supposed to be libraries defined outside the current project. But, because of this, most of the `target_*` commands don't work on `IMPORTED` libraries, making them hard to set up yourself. So don't use the `IMPORTED` keyword for now, and use an `ALIAS` target instead; it will be fine until you start exporting targets. This limitation was fixed in CMake 3.11.

View File

@ -20,11 +20,11 @@ If a target further down the dependency chain specifies a higher C++ level, this
## CMake 3.1+: Compiler features
You can ask for specific compiler features to be available. This was more granular than asking for a C++ version, though it's a bit tricky to pick out just the features a package is using unless you wrote the package and have a good memory. Since this ultimately checks against a list of options CMake knows your compiler supports and picks the highest flag indicated in that list, you don't have to specify all the options you need, just the rarest ones. The syntax is identical to the section above, you just have a list of options to pick instead of `cxx_std_*` options. See the [whole list here](https://cmake.org/cmake/help/v3.9/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html).
You can ask for specific compiler features to be available. This was more granular than asking for a C++ version, though it's a bit tricky to pick out just the features a package is using unless you wrote the package and have a good memory. Since this ultimately checks against a list of options CMake knows your compiler supports and picks the highest flag indicated in that list, you don't have to specify all the options you need, just the rarest ones. The syntax is identical to the section above, you just have a list of options to pick instead of `cxx_std_*` options. See the [whole list here](https://cmake.org/cmake/help/latest/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html).
If you have optional features, you can use the list `CMAKE_CXX_COMPILE_FEATURES` and use `if(... IN_LIST ...)` from CMake 3.3+ to see if that feature is supported, and add it conditionally. See [the docs here](https://cmake.org/cmake/help/v3.9/manual/cmake-compile-features.7.html) for other use cases.
If you have optional features, you can use the list `CMAKE_CXX_COMPILE_FEATURES` and use `if(... IN_LIST ...)` from CMake 3.3+ to see if that feature is supported, and add it conditionally. See [the docs here](https://cmake.org/cmake/help/latest/manual/cmake-compile-features.7.html) for other use cases.
A related feature, (`WriteCompilerDetectionHeader`)[https://cmake.org/cmake/help/v3.9/module/WriteCompilerDetectionHeader.html], is worth checking out. It is a module that lets you make a file with macros allowing you to check and support optional features for specific compilers. Like any header generator, this will require that you build with CMake so that your header can be generated as part of the build process (only important if you care about supporting multiple build systems, or if you are making a no-build header-only library).
A related feature, [`WriteCompilerDetectionHeader`](https://cmake.org/cmake/help/latest/module/WriteCompilerDetectionHeader.html), is worth checking out. It is a module that lets you make a file with macros allowing you to check and support optional features for specific compilers. Like any header generator, this will require that you build with CMake so that your header can be generated as part of the build process (only important if you care about supporting multiple build systems, or if you are making a no-build header-only library).
## CMake 3.1+: Global and property settings

View File

@ -6,7 +6,7 @@ The first and most common feature was C++ standards support, which got it's own
## Platform independent code
[This](https://cmake.org/cmake/help/v3.9/variable/CMAKE_POSITION_INDEPENDENT_CODE.html) is best known as the `-fPIC` flag. Much of the time, you don't need to do anything. CMake will include the flag for `SHARED` or `MODULE` libraries. If you do explicitly need it:
[This](https://cmake.org/cmake/help/latest/variable/CMAKE_POSITION_INDEPENDENT_CODE.html) is best known as the `-fPIC` flag. Much of the time, you don't need to do anything. CMake will include the flag for `SHARED` or `MODULE` libraries. If you do explicitly need it:
```cmake
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
@ -22,9 +22,9 @@ to explicitly turn it `ON` (or `OFF`) for a target.
## Little libraries
If you need to link to the `dl` library, with `-ldl` on Linux, just use the built-in CMake variable [`${CMAKE_DL_LIBS}`](https://cmake.org/cmake/help/v3.9/variable/CMAKE_DL_LIBS.html) in a `target_link_libraries` command. No module or `find_package` needed. (This adds whatever is needed to get `dlopen` and `dlclose`)
If you need to link to the `dl` library, with `-ldl` on Linux, just use the built-in CMake variable [`${CMAKE_DL_LIBS}`](https://cmake.org/cmake/help/latest/variable/CMAKE_DL_LIBS.html) in a `target_link_libraries` command. No module or `find_package` needed. (This adds whatever is needed to get `dlopen` and `dlclose`)
Unfortunately, the math library is not so lucky. If you need to explicitly link to it, you can always do `target_link_libraries(MyTarget PUBLIC m)`, but it might be better to use CMake's generic [`find_library`](https://cmake.org/cmake/help/v3.9/command/find_library.html):
Unfortunately, the math library is not so lucky. If you need to explicitly link to it, you can always do `target_link_libraries(MyTarget PUBLIC m)`, but it might be better to use CMake's generic [`find_library`](https://cmake.org/cmake/help/latest/command/find_library.html):
```cmake
find_library(MATH_LIBRARY m)
@ -39,7 +39,7 @@ You can pretty easily find `Find*.cmake`'s for this and other libraries that you
## Interprocedural optimization
[This](https://cmake.org/cmake/help/v3.9/variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION.html) is available on very recent versions of CMake. You can turn this on with `CMAKE_INTERPROCEDURAL_OPTIMIZATION` (CMake 3.9 only) or the `INTERPROCEDURAL_OPTIMIZATION` property on targets. Support for GCC and Clang was added in CMake 3.8. In `cmake_minimum_required(VERSION 3.9)`, setting this to `ON` on a target is an error if the compiler doesn't support it. You can use [`check_ipo_supported()`](https://cmake.org/cmake/help/v3.9/module/CheckIPOSupported.html), from the built-in `CheckIPOSupported` module, to see if support is available before hand. An example of 3.9 style usage:
[This](https://cmake.org/cmake/help/latest/variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION.html) is available on very recent versions of CMake. You can turn this on with `CMAKE_INTERPROCEDURAL_OPTIMIZATION` (CMake 3.9+ only) or the `INTERPROCEDURAL_OPTIMIZATION` property on targets. Support for GCC and Clang was added in CMake 3.8. In `cmake_minimum_required(VERSION 3.9)`, setting this to `ON` on a target is an error if the compiler doesn't support it. You can use [`check_ipo_supported()`](https://cmake.org/cmake/help/latest/module/CheckIPOSupported.html), from the built-in `CheckIPOSupported` module, to see if support is available before hand. An example of 3.9 style usage:
```cmake
include(CheckIPOSupported)

View File

@ -39,5 +39,5 @@ target_link_libraries(MyExeOrLibrary PUBLIC Boost::filesystem)
[FindBoost]: https://cmake.org/cmake/help/v3.11/module/FindBoost.html
[FindBoost]: https://cmake.org/cmake/help/latest/module/FindBoost.html
[MROldBoost]: https://gitlab.kitware.com/cmake/cmake/merge_requests/1172