有关cmake和CMakeLists.txt

2023-12-21 21:09:50

安装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

find_package()的Config模式

// 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}"
)
  • 开发者调用时直接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_COMPILERC 编译器的名称。
CMAKE_CXX_COMPILERC++ 编译器的名称。
CMAKE_BUILD_TYPE构建的类型,例如 Debug、Release 等。
CMAKE_C_FLAGSC 编译器的额外编译选项。
CMAKE_CXX_FLAGSC++ 编译器的额外编译选项。
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)

相关

文章来源:https://blog.csdn.net/ResumeProject/article/details/130367221
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。