cmake --version
去https://github.com/Kitware/CMake/releases/下载需要版本的命令文件,比如wget https://github.com/Kitware/CMake/releases/download/v3.26.3/cmake-3.26.3-linux-x86_64.sh
bash ./cmake-3.26.4-linux-x86_64.sh --skip-licence --prefix=/usr
export PATH=“/usr/cmake-3.26.4-linux-x86_64/bin:$PATH”
message("simple template") # 输出一个在CMake配置过程中显示的消息。
include_directories("${project_root_path}/include/") # 包含头文件的目录
link_directories(./lib) # 链接库文件的目录,指定了查找库文件的目录
add_executable(myapp myapp.cpp) # 从源文件 "myapp.cpp" 创建可执行文件
target_link_libraries(myapp mylib) # 将可执行文件 "myapp" 与库文件 "mylib" 进行链接
????????add_executable 命令用于生成一个可执行文件目标。该命令将源代码文件添加到项目中,并为其生成一个可执行文件目标。可执行文件目标可以被编译和链接,以生成可执行文件。例如,以下 CMakeLists.txt 文件使用 add_executable 命令生成一个名为 myapp 的可执行文件目标:
cmake_minimum_required(VERSION 3.13)
project(myapp)
add_executable(myapp main.cpp)
add_library(common STATIC util.cpp) # 生成静态库
add_library(common SHARED util.cpp) # 生成动态库或共享库
// 更多可见 https://cmake.org/cmake/help/latest/command/set.html
set(my_variable "Hello, World!")
message (">>> value = ${my_variable }")
在开发过程碰到需要在上级目录中构建,而源代码又分别写在下级目录的情况,同时又要根据不同的情况选择性地添加不同的源代码进行编译,所以考虑将需要编译的源代码放到一个 cmake 列表中。但是 set() 对应生成的变量都是局部变量(即不同的目录下不共用),于是使用 set_property() 命令。
set_property(TARGET softmax_int8_kernels PROPERTY POSITION_INDEPENDENT_CODE ON)的含义
这个命令是用于设置目标文件(TARGET)的属性(PROPERTY)。具体来说,它将名为“softmax_int8_kernels”的目标文件设置为具有位置独立代码(Position Independent Code,PIC)的属性。位置独立代码是一种编译选项,它使得代码中的地址不依赖于加载时的位置,从而使得代码可以在不同的地址空间中运行,这对于动态链接库(Dynamic Linking Library,DLL)和共享对象(Shared Object,SO)非常有用。因此,这个命令的含义是将“softmax_int8_kernels”编译成一个可以作为动态链接库或共享对象使用的目标文件。
????????include_directories用来提供找头文件路径的,在main.cpp中有#include"cv.h"
,但是这个cv.h的路径是/usr/local/include/opencv,我们可在maincpp文件中写#include “/usr/local/include/opencv/cv.h”
,或者在CmakeLists.txt中使用include_directories,include_directories(/usr/local/include)
后直接#include"cv.h"
????????当我们在CMake中使用link_directories
命令时,我们可以指定一个或多个目录,这些目录中的库文件将被链接到我们的项目中。下面是一个示例:
????????假设我们有一个名为my_project
的项目,其中包含两个源文件main.cpp
和foo.cpp
。我们希望链接一个名为my_library
的库文件,该库文件位于/path/to/my_library
目录中。CMakeLists.txt文件内容如下:
cmake_minimum_required(VERSION 3.0)
project(my_project)
# 添加可执行文件
add_executable(my_project main.cpp foo.cpp)
# 添加链接库的目录
link_directories(/path/to/my_library)
# 链接库文件
target_link_libraries(my_project my_library)
在这个例子中,我们使用link_directories
命令指定了/path/to/my_library
目录,该目录中的库文件将被链接到我们的项目中。然后,我们使用target_link_libraries
命令将my_library
库文件链接到my_project
可执行文件中。
include_directories 作用于整个 CMakeLists.txt 文件及其子目录。会为当前CMakeLists.txt的所有目标,以及之后添加的所有子目录的目标添加头文件搜索路径。
target_include_directories 只会为指定目标包含头文件搜索路径。
????????当使用CMake构建一个项目时,可以使用link_libraries
命令来指定需要链接的库。下面是一个使用link_libraries
的简单示例:
cmake_minimum_required(VERSION 3.0)
project(MyProject)
# 添加可执行文件
add_executable(MyExecutable main.cpp)
# 添加库的源文件
add_library(MyLibrary source1.cpp source2.cpp)
# 指定可执行文件与库的链接关系
target_link_libraries(MyExecutable MyLibrary)
cmake_minimum_required(VERSION 3.0)
project(MyProject)
# 添加可执行文件
add_executable(MyExecutable main.cpp)
# 指定需要链接的库
link_libraries(MyExecutable MyLibrary)
# 添加子目录
add_subdirectory(library)
在上面的示例中,我们首先定义了一个名为MyExecutable
的可执行文件。然后使用link_libraries
命令指定了需要链接的库,其中MyLibrary
是一个自定义的库名。最后,我们通过add_subdirectory
命令添加了一个名为library
的子目录,该目录中包含了MyLibrary
库的源代码。
请注意,link_libraries
命令会将指定的库链接到所有的目标中,包括可执行文件和库。如果只想将库链接到特定的目标中,可以使用target_link_libraries
命令来替代。
????????target_link_libraries用在add_executable之后使用, target_link_libraries 命令是将库链接到指定的目标中
,因此应该在创建目标之后使用
????????假设有一个名为 my_config.cmake
的配置文件,内容如下:
# my_config.cmake
# 设置一个变量
set(MY_CONFIG_VARIABLE "Hello from my_config.cmake")
# 定义一个函数
function(my_function)
message("Executing my_function from my_config.cmake")
endfunction()
????????然后,可以在CMakeLists.txt 文件中使用 include
来引入这个配置文件:
# CMakeLists.txt
# 引入配置文件
include(my_config.cmake)
# 输出配置文件中的变量
message("Value of MY_CONFIG_VARIABLE: ${MY_CONFIG_VARIABLE}")
# 调用配置文件中的函数
my_function()
cmake官方为我们预定义了许多寻找依赖包的Module
,他们存储在path_to_your_cmake/share/cmake-/Modules目录下。每个以Find.cmake命名的文件都可以帮我们找到一个包。我们也可以在官方文档中查看到哪些库官方已经为我们定义好了,我们可以直接使用find_package函数进行引用????????find_path
命令是 CMake 中用于在系统中查找文件或目录路径的命令。它可以用于定位头文件、库文件或其他项目依赖项的路径。以下是其基本语法:
find_path(VARIABLE_NAME
NAMES [name1 [path1 path2 ...]]
[HINTS [path1 path2 ...]]
[PATH_SUFFIXES [suffix1 suffix2 ...]]
[PATHS [path1 path2 ...]]
[DOC "Documentation string"]
[NO_DEFAULT_PATH]
)
具体的参数解释如下:
VARIABLE_NAME
: 用于存储找到的路径的变量的名称。
NAMES
: 要查找的文件或目录的名称。可以指定多个名称。
HINTS
: 提供一组路径,CMake 将在这些路径下查找文件或目录。这是一个可选的参数。
PATH_SUFFIXES
: 提供文件或目录的可选子目录,用于缩小查找范围。
PATHS
: 指定额外的路径,CMake 将在这些路径下查找文件或目录。
DOC
: 用于提供关于此查找操作的文档字符串。
NO_DEFAULT_PATH
: 如果设置了这个标志,CMake 将不会在默认路径中查找。
下面是一个示例,假设我们要查找头文件 “myheader.h” 的路径:
find_path(MY_HEADER_PATH
NAMES myheader.h
HINTS /path/to/search/directory
PATH_SUFFIXES include
)
if (MY_HEADER_PATH)
message(STATUS "Found myheader.h at: ${MY_HEADER_PATH}")
else ()
message(FATAL_ERROR "Could not find myheader.h")
endif ()
????????在这个例子中,find_path
将在指定的路径 /path/to/search/directory
下的 include
子目录中查找名为 myheader.h
的文件。如果找到,将路径存储在变量 MY_HEADER_PATH
中。然后,通过条件判断,我们输出消息表示是否找到了文件。
find_library
命令是 CMake 中用于在系统中查找库文件路径的命令。它通常用于查找外部依赖项的库文件,以便在 CMake 构建过程中链接这些库。以下是其基本语法:
find_library(VARIABLE_NAME
NAMES [name1 [path1 path2 ...]]
[HINTS [path1 path2 ...]]
[PATH_SUFFIXES [suffix1 suffix2 ...]]
[PATHS [path1 path2 ...]]
[DOC "Documentation string"]
[NO_DEFAULT_PATH]
)
具体的参数解释如下:
VARIABLE_NAME
: 用于存储找到的库文件路径的变量的名称。
NAMES
: 要查找的库文件的名称。可以指定多个名称。
HINTS
: 提供一组路径,CMake 将在这些路径下查找库文件。这是一个可选的参数。
PATH_SUFFIXES
: 提供库文件的可选子目录,用于缩小查找范围。
PATHS
: 指定额外的路径,CMake 将在这些路径下查找库文件。
DOC
: 用于提供关于此查找操作的文档字符串。
NO_DEFAULT_PATH
: 如果设置了这个标志,CMake 将不会在默认路径中查找。
下面是一个示例,假设我们要查找名为 “mylibrary” 的库文件:
find_library(MY_LIBRARY_PATH
NAMES mylibrary
HINTS /path/to/search/directory
PATH_SUFFIXES lib
)
if (MY_LIBRARY_PATH)
message(STATUS "Found mylibrary at: ${MY_LIBRARY_PATH}")
else ()
message(FATAL_ERROR "Could not find mylibrary")
endif ()
????????在这个例子中,find_library
将在指定的路径 /path/to/search/directory
下的 lib
子目录中查找名为 mylibrary
的库文件。如果找到,将路径存储在变量 MY_LIBRARY_PATH
中。然后,通过条件判断,我们输出消息表示是否找到了库文件。
NAMES
参数的原因????????find_library
等命令可以有多个 NAMES
参数是为了考虑到不同平台或系统可能对同一个库的命名有所不同。不同的操作系统、编译器或库提供者可能会为同一个库文件取不同的名称,因此提供多个备选名称可以增加查找成功的概率,提高跨平台的兼容性。当列出多个 NAMES
参数时,CMake 将按顺序依次尝试每个名称,一旦找到一个存在的库文件,就会立即停止查找,将路径存储在指定的变量中。例如,考虑以下情况,我们想要查找一个名为 “mylibrary” 或 “mylib” 的库文件:
find_library(MY_LIBRARY_PATH
NAMES mylibrary mylib
HINTS /path/to/search/directory
PATH_SUFFIXES lib
)
CMAKE_MODULE_PATH
变量: 是一个CMake内置的变量,用于指定CMake在查找模块文件时要搜索的路径。CMAKE_MODULE_PATH是供find_package搜索第三方库用的。cmake的默认Modules目录在安装目录中:cmake-3.11.3-win64-x64\share\cmake-3.11\Modules。// https://dawnarc.com/2018/04/buildcmake%E5%B8%B8%E7%94%A8%E9%85%8D%E7%BD%AE%E9%A1%B9/
// https://stackoverflow.com/questions/52730397/how-can-i-set-cmake-module-path-for-doing-regular-and-out-of-source-builds-in-cm
CMakeLists.txt
cmake/
|-- FindSomeLibrary.cmake
|-- FindAnotherLibrary.cmake
完整例子
: set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} “${CMAKE_SOURCE_DIR}/cmake/Modules”) 代码的作用是将项目的 “/cmake/Modules” 目录添加到 CMake 的模块路径中。完整例子
:https://github.com/forexample/package-example// https://github1s.com/forexample/package-example/blob/master/Foo/CMakeLists.txt#L206-L222
# Config
# * <prefix>/lib/cmake/Foo/FooConfig.cmake
# * <prefix>/lib/cmake/Foo/FooConfigVersion.cmake
install(
FILES "${project_config}" "${version_config}"
DESTINATION "${config_install_dir}"
)
> cat CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(Boo)
# import library target `foo`
find_package(Foo CONFIG REQUIRED)
add_executable(boo Boo.cpp Boo.hpp)
target_link_libraries(boo foo)
> cmake -H. -B_builds -DCMAKE_VERBOSE_MAKEFILE=ON
> cmake --build _builds
Linking CXX executable Boo
/usr/bin/c++ ... -o Boo /usr/local/lib/libfoo.a
????????注:Cmake对于新版本提供了FetchContent redirection模式,类似于Config模式,详见官方文档
变量名 | 含义 |
---|---|
CMAKE_SOURCE_DIR | 项目的顶层源代码目录的路径,最外层CMakeLists.txt所在目录。 |
CMAKE_BINARY_DIR | 生成的二进制文件目录的路径。 |
CMAKE_CURRENT_SOURCE_DIR | 当前处理的 CMakeLists.txt 文件所在的目录。 |
CMAKE_CURRENT_BINARY_DIR | 当前处理的 CMakeLists.txt 文件的输出目录。 |
CMAKE_INSTALL_PREFIX | 安装(install)目标的根目录。 |
CMAKE_MODULE_PATH | 指定额外的模块文件搜索路径,用于查找 Find.cmake 模块。 |
CMAKE_C_COMPILER | C 编译器的名称。 |
CMAKE_CXX_COMPILER | C++ 编译器的名称。 |
CMAKE_BUILD_TYPE | 构建的类型,例如 Debug、Release 等。 |
CMAKE_C_FLAGS | C 编译器的额外编译选项。 |
CMAKE_CXX_FLAGS | C++ 编译器的额外编译选项。 |
CMAKE_EXE_LINKER_FLAGS | 可执行文件链接器的额外选项。 |
CMAKE_SHARED_LINKER_FLAGS | 共享库链接器的额外选项。 |
CMAKE_SYSTEM | 当前操作系统的名称。 |
CMAKE_SYSTEM_NAME | 当前系统的名称,与 CMAKE_SYSTEM 不同,这里不包含版本信息。 |
CMAKE_SYSTEM_VERSION | 当前系统的版本信息。 |
CMAKE_SYSTEM_PROCESSOR | 当前系统的处理器架构。 |
CMAKE_PREFIX_PATH | 查找依赖包时的额外路径。 |
CMAKE_FIND_ROOT_PATH | 在交叉编译时指定额外的根路径。 |
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) | 开启生成compile_commands.json,包含所有编译单元所执行的指令 |
????????更多的变量参见:CMake - Variables。
????????cmake install
命令用于配置和安装构建后的文件到指定目录,包括可执行文件、库文件、头文件等。通过这个命令,你可以将项目构建出来的文件复制到指定的安装路径,以便在系统上使用或与其他项目共享。以下是一个简单的示例:
# CMakeLists.txt
# 定义一个可执行文件
add_executable(my_executable main.cpp)
# 安装可执行文件到 /usr/local/bin 目录
install(TARGETS my_executable DESTINATION /usr/local/bin)
# 安装 README.md 文件到 /usr/local/share/my_project 目录
install(FILES README.md DESTINATION /usr/local/share/my_project)