<< Modern CMake >> translation 2. CMake basis
Minimum version
This is every CMakeLists.txt
first line of the file. CMakeLists.txt
CMake is required to Profile Name:
cmake_minimum_required(VERSION 3.1)
We come to understand that CMake syntax. Command names cmake_minimum_required
are not case sensitive, so it is common practice to use lowercase. 1 where VERSION is required by the special key command. The version number immediately after the VERSION keyword. Like anywhere else in this book, you simply click on the command name to link to the official document, and then use the drop-down list to switch between different versions of CMake documentation.
This line is very special! 2 version also pointed out the changes in behavior of CMake. So, if you set minimum_required
to VERSION 2.8
on macOS you will get the wrong link behavior, for example, in the latest version of CMake is true. If you put the version is set to 3.3 or lower, you will get the wrong symbols hidden behavior, and so on. In policies have a strategy and a version of the list.
In CMake 3.12, you can write to specify a range of versions CMake support, for example VERSION 3.1...3.12
; this means that you support a minimum 3.1, and also tested and support to the new policy 3.12. This is good for users who need a better set of terms, and due to the skills in grammar, it is backwards compatible with older versions of CMake (although the actual run CMake 3.2-3.11 only set the 3.1 version of the policy in this example). The new version of the policy is often the most important for macOS and Windows users, they usually have the latest version of CMake.
The new project should be written:
cmake_minimum_required(VERSION 3.1...3.15)
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 version of CMake. If CMake is 3.12 or higher, if blocks will be false, this time the new syntax cmake_minimum_required
will work, it will be able to work properly!
Warning: MSVC of CMake server model originally had this format when reading a bug , so if you need to support legacy non-MSVC command line version of Windows, you will need to do the following:
cmake_minimum_required(VERSION 3.1)
if(${CMAKE_VERSION} VERSION_LESS 3.15) cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) else() cmake_policy(VERSION 3.15) endif()
If you do need to set a lower version here, you can use cmake_policy
conditional increase policy level or set a specific policy. Do this for at least your macOS user!
Setting project
Now, each top CMake file ( CMakeLists.txt
) has the following line:
project(MyProject VERSION 1.0
DESCRIPTION "非常出色的项目"
LANGUAGES CXX)
Now we see more new syntax. String surrounded by quotation marks, space can be more or less, the project name is the first parameter (position parameter). All keyword arguments here are optional. By VERSION
parameters, which set a bunch of variables, such as MyProject_VERSION
and PROJECT_VERSION
. LANGUAGE
It can be a C, CXX, Fortran and CUDA (CMake 3.7+). C CXX is the default. In the CMake 3.9, DESCRIPTION add in settings description of the project. You can refer to project
this document.
You can use #
to add at the beginning of a comment . CMake also has inline annotation syntax, but is rarely needed, because the space is not important.
Project Name nothing special. At this time, do not add any goal.
Executable file
Although the link library more interesting, we usually generate most of their time in libraries, but here we want a simple executable file to begin.
add_executable(one two.cpp three.h)
Here are a few things to note. one
Is the name of the executable file generated CMake the name of the target is also created (I guarantee that you will soon hear a lot of information about the target). Immediately after the executable file name of the source file list, you can list a list of any number of source files as needed. CMake is very smart, based on the source file name correctly identify the file extension, so the header file in the list will be CMake understood and ignored. Most of the time, the only reason we list the header files in the source file list is to have them appear in the IDE. For more information about common goals and build system, see buildsystem .
Generating link library
Use add_library
generate link library, it is very simple:
add_library(one STATIC two.cpp three.h)
You can select the type of link library: STATIC, SHARED or MODULE. If no, CMake based variable BUILD_SHARED_LIBS
selection between STATIC and SHARED value.
As you will see in the next section that typically you need to create a pseudo-objective, which is a target not need to compile any file, for example, to include only library header files. This can also be referred to as INTERFACE library; the only difference is the interface with the library can not name the file.
You can also use an existing link library to generate a ALIAS
link library, which simply provide the name of the new target for you. One benefit of this is that you can create a name with ::
link library (see later). 3
Configure the build target
Now that we have specified the target, then how do we add to it the relevant information about it? For example, it may take a include
directory:
target_include_directories(one PUBLIC include)
target_include_directories
The include
directory to the target. PUBLIC
Executable files is of little significance; for a link library that lets CMake know of any links to this goal must also contain the target directory. Other options are PRIVATE
(only affect the current target, without affecting the dependencies) and INTERFACE
(dependent on the required item only).
Now, we can target in series:
add_library(another STATIC another.cpp another.h)
target_link_libraries(another PUBLIC one)
target_link_libraries
CMake is probably the most useful and most confusing command. It requires a target (another) and add a dependency target item. If the called one
destination does not exist, it will add a point on the path is called one
link library (ie, the name of the command). Or you can give it a complete link library path. Or linker flags. Finally, there is something a little confusing, and that is the classic CMake allows you to ignore keyword PUBLIC
, and so on. If the target has been completed link, try to mix styles in the chain further, you will receive an error.
Focuses on the use of targets and keywords in any place, that's right.
Target can contain directories, link libraries (or link target) compiler option, the compiler definition, compiler features (see section C 11 ++) and so on. As you will see in the two chapters that include project, you can usually use the target (and always make goals) to represent all libraries you use. Even if that is not the real link library, such as OpenMP, it can also be expressed in the target. This is the modern CMake great reason!
He started working practice
See if you can understand the following file operations. It creates a simple C ++ 11 libraries and a program to use it. No dependencies. I will discuss later use CMake 3.8 system more C ++ standard options.
cmake_minimum_required(VERSION 3.8)
project(Calculator LANGUAGES CXX)
add_library(calclib STATIC src/calclib.cpp include/calc/lib.hpp) target_include_directories(calclib PUBLIC include) target_compile_features(calclib PUBLIC cxx_std_11) add_executable(calc apps/calc.cpp) target_link_libraries(calc PUBLIC calclib)
1. In this book, I will try to avoid showing you the wrong way of doing things; you can find many examples of this on the Internet. I occasionally mention an alternative approach, but unless absolutely necessary, otherwise these are not recommended. Usually they just help you read the older CMake code. ↩
2. You sometimes see
FATAL_ERROR
in CMake <2.6 version, you need to use it to support fail, now no longer needed.
↩
3.::
syntax originally used to generateINTERFACE IMPORTED
libraries, however, because of this, most of thetarget_*
commands are not applicable toIMPORTED
libraries. This makes them difficult to set their own. So now do not useIMPORTED
keywords, use theALIAS
member target; it can work before you export destination. This limit has been fixed in CMake 3.11 in. ↩