有关cmake和CMakeLists.txt

安装cmake

  • 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”

cmake的简单模板

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 生成可执行文件

        add_executable 命令用于生成一个可执行文件目标。该命令将源代码文件添加到项目中,并为其生成一个可执行文件目标。可执行文件目标可以被编译和链接,以生成可执行文件。例如,以下 CMakeLists.txt 文件使用 add_executable 命令生成一个名为 myapp 的可执行文件目标:

cmake_minimum_required(VERSION 3.13)

project(myapp)

add_executable(myapp main.cpp)

add_library 生成库文件

  • cmake add_library 默认生成静态库。
add_library(common STATIC util.cpp) # 生成静态库
add_library(common SHARED util.cpp) # 生成动态库或共享库

set 设置变量

// 更多可见 https://cmake.org/cmake/help/latest/command/set.html
set(my_variable "Hello, World!")
message (">>> value = ${my_variable }")

set_property

  • 在开发过程碰到需要在上级目录中构建,而源代码又分别写在下级目录的情况,同时又要根据不同的情况选择性地添加不同的源代码进行编译,所以考虑将需要编译的源代码放到一个 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”编译成一个可以作为动态链接库或共享对象使用的目标文件。

  • cmakelist的set_property作用? cmake(14):利用set_property命令设置全局属性

include_directories 设置头文件查找路径

        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"

link_directories 设置库文件查找路径

        当我们在CMake中使用link_directories命令时,我们可以指定一个或多个目录,这些目录中的库文件将被链接到我们的项目中。下面是一个示例:

        假设我们有一个名为my_project的项目,其中包含两个源文件main.cppfoo.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与target_include_directories区别

  • include_directories 作用于整个 CMakeLists.txt 文件及其子目录。会为当前CMakeLists.txt的所有目标,以及之后添加的所有子目录的目标添加头文件搜索路径。

  • target_include_directories 只会为指定目标包含头文件搜索路径。

link_libraries 为目标指定链接库

        当使用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

        target_link_libraries用在add_executable之后使用, target_link_libraries 命令是将库链接到指定的目标中,因此应该在创建目标之后使用

include 引入.cmake配置文件

        假设有一个名为 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()

find

find_package:自动查找库的头文件和库文件

  • 在CMake中,find_package()的作用是在系统中寻找对应的软件包,并将其引入到项目中,以便在构建和安装过程中使用。find_package()通常需要与相关的软件包模块(如FindXXX.cmake或XXXConfig.cmake文件)一起使用,以告知CMake在哪里寻找软件包,并提供所需的编译和链接参数。通常,find_package()用于找到安装在系统中的第三方库或工具,它们可能是其他项目的依赖项。使用find_package()函数可以简化项目构建和依赖项管理的过程。常见的第三方库如Boost、OpenCV、Eigen等都可以使用find_package()来引入到CMake项目中。
  • 为了方便我们在项目中引入外部依赖包,cmake官方为我们预定义了许多寻找依赖包的Module,他们存储在path_to_your_cmake/share/cmake-/Modules目录下。每个以Find.cmake命名的文件都可以帮我们找到一个包。我们也可以在官方文档中查看到哪些库官方已经为我们定义好了,我们可以直接使用find_package函数进行引用
  • find_package不是必须的,比如这个例子:https://github.com/wang-xinyu/tensorrtx/blob/master/alexnet/CMakeLists.txt

find_path :查找头文件目录

        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: 查找库文件路径

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 中。然后,通过条件判断,我们输出消息表示是否找到了库文件。

find可以有多个 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内置的变量

CMAKE_MODULE_PATH

  • CMAKE_MODULE_PATH 变量: 是一个CMake内置的变量,用于指定CMake在查找模块文件时要搜索的路径。CMAKE_MODULE_PATH是供find_package搜索第三方库用的。cmake的默认Modules目录在安装目录中:cmake-3.11.3-win64-x64\share\cmake-3.11\Modules。

CMAKE_MODULE_PATH的Module模式

// 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 的模块路径中。
    有关cmake和CMakeLists.txt_第1张图片

find_package()的Config模式

  • 完整例子:https://github.com/forexample/package-example
  • 需要引入的库在安装时进行了配置,比如opencv
// https://github1s.com/forexample/package-example/blob/master/Foo/CMakeLists.txt#L206-L222
# Config
#   * /lib/cmake/Foo/FooConfig.cmake
#   * /lib/cmake/Foo/FooConfigVersion.cmake
install(
    FILES "${project_config}" "${version_config}"
    DESTINATION "${config_install_dir}"
)
  • 开发者调用时直接find_package即可
> 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。

install

        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)

相关

  • CPP项目中使用CUDA(opencv+cuda or pybind+cuda)
  • linux pybind11 python c++ 混合编程 opencv(暂记)
  • c++库文件头文件链接原理(全)
  • 库文件通过头文件向外导出接口,用户通过头文件找到库文件中需要的函数实现代码进行链接至程序当中。 添加链接描述
  • VSCode:使用CMakeLists.txt构建C++项目https://blog.csdn.net/zhizhengguan/article/details/128056009

你可能感兴趣的:(语言学习笔记,c++)