1
0
mirror of synced 2024-12-22 12:40:00 +01:00

update: nicer discussion of min version

This commit is contained in:
Henry Schreiner 2020-08-03 10:28:14 -04:00
parent 00c307eb73
commit b80a42f5ee

View File

@ -3,46 +3,71 @@
## Minimum Version
Here's the first line of every CMakeLists.txt, which is the required name of the file CMake looks for:
Here's the first line of every `CMakeLists.txt`, which is the required name of
the file CMake looks for:
```cmake
cmake_minimum_required(VERSION 3.1)
```
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.
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. If you set it to 3.3 or less, you'll get the wrong hidden symbols behaviour, etc. A list of policies and versions is available at «cmake:policies».
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. If you set it to 3.3 or less, you'll get the wrong
hidden symbols behaviour, etc. A list of policies and versions is available at
«cmake:policies».
In 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 actually running CMake 3.2-3.11 will only set the 3.1 version of the policies in this example). New versions of policies tend to be most important for macOS and Windows users, who also
usually have a very recent version of CMake.
Starting in CMake 3.12, this supports a range, such as `VERSION 3.1...3.15`;
this means you support as low as 3.1 but have also tested it with the new
policy settings up to 3.15. 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 actually running CMake 3.1-3.11 will only set the 3.1
version of the policies in this example, since those versions didn't treat this
specially). New versions of policies tend to be most important for macOS and
Windows users, who also usually have a very recent version of CMake.
This is what new projects should do:
```cmake
cmake_minimum_required(VERSION 3.1...3.15)
cmake_minimum_required(VERSION 3.7...3.18)
if(${CMAKE_VERSION} VERSION_LESS 3.12)
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
endif()
```
If CMake version is less than 3.12, the if block will be true, and the policy will be set to the current CMake version. If CMake is 3.12 or higher, the if block will be false, but the new syntax in `cmake_minimum_required` will be respected and this will continue to work properly!
If CMake version is less than 3.12, the if block will be true, and the policy
will be set to the current CMake version. If CMake is 3.12 or higher, the if
block will be false, but the new syntax in `cmake_minimum_required` will be
respected and this will continue to work properly!
WARNING: MSVC's CMake server mode [originally had a bug](https://github.com/fmtlib/fmt/issues/809) in reading this format, so if you need to support non-command line Windows builds for older MSVC versions, you will want to do this instead:
WARNING: MSVC's CMake server mode [originally had a
bug](https://github.com/fmtlib/fmt/issues/809) in reading this format, so if
you need to support non-command line Windows builds for older MSVC versions,
you will want to do this instead:
```cmake
cmake_minimum_required(VERSION 3.1)
cmake_minimum_required(VERSION 3.7)
if(${CMAKE_VERSION} VERSION_LESS 3.15)
if(${CMAKE_VERSION} VERSION_LESS 3.18)
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
else()
cmake_policy(VERSION 3.15)
cmake_policy(VERSION 3.18)
endif()
```
{% hint style='info' %}
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!
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 %}
@ -56,17 +81,28 @@ project(MyProject VERSION 1.0
LANGUAGES CXX)
```
Now we see even more syntax. Strings are quoted, whitespace doesn't matter, 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`, `ASM`, `CUDA` (CMake 3.8+), `CSharp` (3.8+), and `SWIFT` (CMake 3.15+ experimental). `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.
Now we see even more syntax. Strings are quoted, whitespace doesn't matter, 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`, `ASM`, `CUDA` (CMake 3.8+), `CSharp` (3.8+), and `SWIFT` (CMake
3.15+ experimental). `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='info' %}
You can add [comments](https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#comments) with the `#` character. CMake does have an inline syntax for comments too, but it is rarely needed, as whitespace doesn't matter.
You can add
[comments](https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#comments)
with the `#` character. CMake does have an inline syntax for comments too, but
it's rarely used.
{% endhint %}
There's really nothing special about the project name. No targets are added at this point.
## Making an executable
Although libraries are much more interesting, and we'll spend most of our time with them, let's start with a simple executable.
Although libraries are much more interesting, and we'll spend most of our time
with them, let's start with a simple executable.
```cmake
add_executable(one two.cpp three.h)