总结CMake
本文参考
- 知乎回答:https://www.zhihu.com/question/58949190/answer/999701073
- 如何写CMakeList.txt
- C++工程的setup
- Learn CMake’s Scripting Language in 15 Minutes
入门 CMake的目的:It’s all about targets
- Define a target: defines targets using the
add_executable
,add_library
oradd_custom_target
commands. - Define the target’s properties:
- Once a target is created, it has properties that you can manipulate using the
get_property
andset_property
commands. - All target properties are strings.
- In CMake, every variable is a string.
- Other target properties include
LINK_LIBRARIES
,INCLUDE_DIRECTORIES
andCOMPILE_DEFINITIONS
. Those properties are modified, indirectly, by thetarget_link_libraries
,target_include_directories
andtarget_compile_definitions
commands. At the end of the script, CMake uses those target properties to generate the build pipeline.
- There are properties for other CMake entities, too.
- There is a set of directory properties at every file scope.
- There is a set of global properties that is accessible from all scripts.
- And there is a set of source file properties for every C/C++ source file.
- Once a target is created, it has properties that you can manipulate using the
cmake语言的语法总结
- In CMake, every variable is a string.
- In CMake, every statement is a command that takes a list of string arguments and has no return value. Arguments are separated by (unquoted) spaces.
- CMake has a special substitution rule for unquoted arguments. 如果某个argument是通过某个variable来表示的,并且该变量的值含有semicolon,cmake会将该值依据semicolon分开成多个argument。
- CMake对于quoted arguments却永远不会依据semicolon而分裂成多个arguments, even after substitution.
set(ARGS "EXPR;T;1 + 1")
math(${ARGS}) # Equivalent to calling math(EXPR T "1 + 1")
message("${ARGS}") # Prints: EXPR;T;1 + 1
1. 简单打印
2. 定义变量
In cmake, CMake variables are defined at file scope. 所有的变量都是string类型。定义一个变量需要使用set函数,the set
command defines a variable at file scope. The first argument is the name of the variable to assign, and the second argument is its value。 我们可以用定义的变量通过“${ }”来substitute某个string(叫做variable reference),具体如下:
set(THING "funk")
message("We want the ${THING}!")
When a variable is undefined, it defaults to an empty string.
我们可以直接用一个变量variable来定义另一个新的变量:
set(PERSON "JOHN")
set(${PERSON}_NAME "John Goodman")
定义一组变量:cmake语言无法定义类,但是可以通过有相同的prefix定义一组变量:
set(JOHN_NAME "John Smith")
set(JOHN_ADDRESS "123 Fake St")
set(PERSON "JOHN")
message("${${PERSON}_NAME} lives at ${${PERSON}_ADDRESS}.")
定义list:
set(MY_LIST These are separate arguments)
message("${MY_LIST}") # Prints: These;are;separate;arguments
list(REMOVE_ITEM MY_LIST "separate") # Removes "separate"
message("${MY_LIST}") # Prints: These;are;argument
3. 定义函数
Functions run in their own scope. None of the variables defined in a function pollute the caller’s scope. 定义函数需要用function/endfunction。
function(doubleIt VARNAME VALUE)
math(EXPR RESULT "${VALUE} * 2")
# Set the named variable in caller's scope
set(${VARNAME} "${RESULT}" PARENT_SCOPE)
endfunction()
doubleIt(RESULT "4") # call the function
message("${RESULT}") # Prints: 8
4. Including Other Scripts
- The
include
command: 运行另一个CMake script(the calling script). 通常用于定义一组函数或者macros. It uses the variableCMAKE_MODULE_PATH
as a search path. - The
find_package
command: looks for scripts of the formFind*.cmake
and also runs them. often used to help find external libraries.find_package(SDL2)
is equivalent toinclude(FindSDL2.cmake)
. - The
add_subdirectory
command: creates a new scope, then executes the script named CMakeLists.txt from the specified directory in that new scope. typically use it to add another CMake-based subproject, such as a library or executable, to the calling project.
cmake命令generate的4个文件
- CMakeCache.txt
- CMakeFiles
- Makefile
- cmake_install.cmake
target的几种类型
- 可执行文件(.exe)。句法:add_executable(exe_ToBeBuilt source.cpp)
- shared library(.so)。句法:add_library(lib_ToBeBuilt SHARED source.cpp)
- static library(.a)。句法: add_library(lib_ToBeBuilt STATIC source.cpp)
- Using a shared lib or static lib(a 3rd-party library)。句法如下:
# shared library
set(PROJECT_LINK_LIBS libtestStudent.so)
link_directories(~/studentlib_shared/build)
include_directories(~/studentlib_shared/include)
add_executable(libtest libtest.cpp)
target_link_libraries(libtest ${PROJECT_LINK_LIBS})
# static library
set (PROJECT_LINK_LIBS libtestStudent.a)
link_directories(~/studentlib_static/build)
add_executable(libtest libtest.cpp)
target_link_libraries(libtest ${PROJECT_LINK_LIBS})