makefile常用规则

1 add_subdirectory

  • 原理

add_subdirectory 是 CMake 中的一个命令,用于将一个子目录添加到当前项目的构建过程中。这个子目录通常包含一个独立的项目或模块,其内部有自己的 CMakeLists.txt 文件。

  • 基本用法
    在主项目的 CMakeLists.txt 文件中,使用 add_subdirectory 命令来添加子目录:

  • cmake
    add_subdirectory(path_to_subdirectory)
    这里的 path_to_subdirectory 是子目录的路径,可以是相对路径或绝对路径。当 CMake 处理主项目时,它会去找这个子目录下的 CMakeLists.txt 文件,并按照子目录中的构建指令来处理。

  • 使用示例
    假设你有一个主项目,结构如下:

project/
├── CMakeLists.txt
└── subproject/
├── CMakeLists.txt
└── source.cpp
其中,project/CMakeLists.txt 可以包含类似以下内容:

cmake
cmake_minimum_required(VERSION 3.0)
project(MyProject)

  • 添加子目录
    add_subdirectory(subproject)

  • 主项目的其他设置
    而 project/subproject/CMakeLists.txt 可能是这样的:

  • cmake
    子项目的 CMakeLists.txt

  • 构建一个库或可执行文件
    add_library(MyLibrary STATIC source.cpp)

  • 或者是一个可执行文件
    . add_executable(MyExecutable source.cpp)

  • 子项目的其他设置
    这样,当在 project 目录下运行 CMake 时,它会同时处理主项目和子项目,生成对应的构建系统文件(如 Makefile 或 Visual Studio 项目文件)。

注意事项
子目录中的 CMakeLists.txt 可以定义和配置任意类型的项目,如库、可执行文件等。
add_subdirectory 可以嵌套使用,即在子目录的 CMakeLists.txt 文件中也可以使用 add_subdirectory 来添加更深层次的子目录。
使用 add_subdirectory 可以帮助组织大型项目,使得每个子模块可以独立配置和构建,同时可以共享变量和设置。
通过这种方式,CMake 提供了一种灵活而强大的机制来管理复杂项目的构建过程。

set使用方法

在 CMake 中,set() 函数主要用于设置变量。它的基本语法是:

  • cmake
    set( … [CACHE [FORCE]])
    其中:

    variable是要设置的变量名。
    value … 是要赋给变量的值。可以是一个或多个值,用空格分隔。
    [CACHE [FORCE]] 是可选参数,用于将变量缓存,允许用户在命令行或 CMake GUI 中修改。
    基本用法示例
    设置一个普通变量:

  • cmake
    set(my_var “Hello, CMake!”)
    这会将 “Hello, CMake!” 赋给 my_var 变量。

  • 设置一个列表:

cmake
set(my_list_var 1 2 3 4 5)
这将创建一个包含数字 1 到 5 的列表,并将其存储在 my_list_var 变量中。

  • 设置一个缓存变量:

cmake
set(my_cached_var “Default Value” CACHE STRING “Description of my_cached_var”)
这会创建一个名为 my_cached_var 的缓存变量,其默认值为 “Default Value”,并在 CMake GUI 或命令行中显示描述 “Description of my_cached_var”。

用法注意事项

  • 多行字符串: 可以使用多个参数将多行文本分配给变量。例如:

cmake
set(multi_line_var
“This is line 1”
“This is line 2”
“And this is line 3”
)

  • 变量修改: 如果变量已经存在,set() 将覆盖其现有值。如果要在不覆盖现有值的情况下添加内容,可以使用 ${} 语法或 list(APPEND …) 等 CMake 命令。

  • 缓存变量: 缓存变量允许用户通过 CMake GUI 或命令行修改变量的值,适用于需要灵活配置的情况。

示例
在项目中,set() 函数通常用于设置项目名称、版本号、路径等常见的配置变量。例如:

cmake
cmake_minimum_required(VERSION 3.0)
project(MyProject)

set(MY_PROJECT_VERSION_MAJOR 1)
set(MY_PROJECT_VERSION_MINOR 0)
set(MY_PROJECT_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)

configure_file(config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/include/config.h)
这个示例中,set() 函数用于设置项目的主要版本号、次要版本号和包含目录路径。configure_file() 则用于生成配置文件 config.h,在生成期间将变量替换为相应的值。

总之,set() 是 CMake 中基本而重要的命令,用于管理变量和配置项目。

include_directories

在 CMake 中,include_directories 函数用于添加头文件目录到 CMake 构建系统中。它的主要作用是告诉编译器在哪里可以找到特定的头文件,以便在编译时正确地包含这些头文件。

基本语法

  • cmake
    include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 …])
    AFTER 或 BEFORE:可选参数,指定添加的目录相对于其他已存在的目录的位置,通常用于控制搜索路径的优先级。
    SYSTEM:可选参数,将目录添加到系统头文件目录列表,编译器在处理这些目录中的头文件时,不会生成警告信息。
    示例用法
    添加单个目录:

  • cmake
    include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
    这将把 ${CMAKE_CURRENT_SOURCE_DIR}/include 添加到头文件搜索路径中。

添加多个目录:

cmake
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/libs/some_library/include
)
这将同时将两个目录添加到头文件搜索路径中。

  • 使用 SYSTEM 参数:

cmake
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/third_party/include)
将 third_party/include 目录添加到系统头文件搜索路径中,这意味着编译器在处理这些头文件时,不会生成警告信息。

  • 控制目录添加的位置:

cmake
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/include)
将 include 目录添加到所有其他目录之前搜索,而不是默认的添加方式(即在后面添加)。

  • 在子目录中使用:

cmake
add_subdirectory(some_subdir)

在子目录中使用 include_directories
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/some_subdir/include)
当在主 CMakeLists.txt 中包含子目录时,可以在子目录的 CMakeLists.txt 文件中使用 include_directories 来添加子目录的头文件路径。

  • 注意事项
    推荐使用 target_include_directories: 尽管 include_directories 可以直接影响整个项目的头文件搜索路径,但推荐的做法是在 target_include_directories 中将头文件路径与特定的目标(如可执行文件或库)关联起来。这样做可以更精确地控制每个目标的头文件路径,并使得依赖关系更清晰。

相对路径和绝对路径: 可以使用相对路径或绝对路径来指定目录,具体取决于项目的组织结构和构建系统的需求。

注意搜索顺序: CMake 搜索头文件的顺序基本上遵循添加路径的顺序,可以使用 AFTER 和 BEFORE 来控制搜索路径的优先级。

通过有效使用 include_directories 函数,可以确保在 CMake 项目中正确地包含和管理头文件路径,从而顺利地构建和编译项目。

1 target_link_libraries

在 CMake 中,target_link_libraries 函数用于将一个或多个库链接到目标(如可执行文件、共享库或静态库)上。这个函数是非常重要的,因为它帮助定义了编译链接过程中的依赖关系。

基本语法
cmake
target_link_libraries(target_name
library1
library2

libraryN
)
target_name 是你的目标的名称,比如可执行文件的名称(使用 add_executable 定义)、库的名称(使用 add_library 定义)等。
library1, library2, …, libraryN 是需要链接到目标上的库的名称,可以是库的名称、变量或表达式。
示例用法

  • 链接一个库:

cmake
target_link_libraries(my_executable_name my_library_name)
将 my_library_name 链接到 my_executable_name 上,其中 my_library_name 是一个通过 add_library 定义的库。

  • 链接多个库:

cmake
target_link_libraries(my_executable_name
my_library_name1
my_library_name2
)
将 my_library_name1 和 my_library_name2 链接到 my_executable_name 上。

  • 链接系统库:

cmake
target_link_libraries(my_executable_name
pthread
dl
)
在Linux系统上,pthread 和 dl 是一些标准的系统库,可以直接链接到你的目标中。

使用变量和表达式:

cmake
set(MY_LIBRARIES my_library_name1 my_library_name2)
target_link_libraries(my_executable_name ${MY_LIBRARIES})
可以通过变量来存储需要链接的库的名称,然后在 target_link_libraries 中使用变量。

  • 链接第三方库:

cmake
find_package(Boost REQUIRED COMPONENTS filesystem)
target_link_libraries(my_executable_name Boost::filesystem)
使用 find_package 找到第三方库(比如 Boost),然后使用 target_link_libraries 将找到的组件(如 Boost::filesystem)链接到你的目标上。

注意事项
目标顺序: 在 target_link_libraries 中,你可以指定多个库,它们将按照你列出它们的顺序链接到目标中。通常,先列出主库,再列出依赖的其他库。

系统库和框架: 在不同的操作系统和框架下,链接的方法和库名称可能有所不同。比如在 Windows 下,使用 target_link_libraries 可能会需要指定完整的库文件名,而在 macOS 上,可能需要使用框架名称。

使用 PUBLIC, PRIVATE, INTERFACE 限定符: 通过这些限定符可以精确控制链接库的传递性。例如,PUBLIC 表示链接到目标后也传递到目标的使用者,PRIVATE 只在当前目标内部可见,INTERFACE 只影响目标的使用者而不影响目标本身。

通过合理使用 target_link_libraries 函数,你可以有效管理 CMake 项目中的库依赖关系,确保在构建时正确链接所需的库,从而顺利生成可执行文件或库文件。

在 CMake 的 target_link_libraries 命令中,并没有直接使用 -L 和 -l 这两个命令行参数的对应形式。这两个参数通常是在传统的编译链命令中使用的,例如在 gcc/g++ 编译器的命令行中。

让我们来理解一下它们的含义:

-L 参数:

-L 参数用于指定编译器在链接时搜索库文件的路径。例如,-L/path/to/libs 会告诉编译器在 /path/to/libs 目录中寻找库文件。

在 CMake 中,你不需要显式地使用 -L 参数来指定库文件的路径。相反,CMake 使用 find_library 和 find_package 等命令来自动查找所需的库文件和路径。当你使用 target_link_libraries 函数时,CMake 已经包含了正确的库路径信息。

-l 参数:

-l 参数用于指定链接时需要的库的名称,例如 -lmylib 表示链接名为 libmylib.so 或 libmylib.a 的库文件(具体文件名可能会根据系统和平台有所不同)。

在 CMake 中,当你使用 target_link_libraries 函数时,只需指定库的逻辑名称即可,而不需要包含 -l 前缀。CMake 会根据逻辑名称自动确定正确的库文件(例如 .so 或 .a 文件)以及路径,并将其添加到链接命令中。

示例:
如果你想链接一个名为 mylib 的库,而不使用 -L 和 -l 参数,你应该这样写:

cmake
add_executable(my_executable main.cpp)
target_link_libraries(my_executable mylib)
这里的 mylib 应该是通过 add_library(mylib …) 定义的库名称。CMake 将根据 mylib 的逻辑名称找到并链接正确的库文件。

因此,在 CMake 中,不需要直接使用 -L 和 -l 参数,因为 CMake 会自动处理和管理这些库的查找和链接路径。

$ 变量

在 CMake 脚本中,$ 符号有特定的意义,通常用于引用变量或者表达式。以下是几种常见的用法:

变量引用:

在 CMake 中,变量使用 语法来引用。例如, {} 语法来引用。例如, 语法来引用。例如,{CMAKE_SOURCE_DIR} 表示引用名为 CMAKE_SOURCE_DIR 的变量的值。这种语法在 target_link_libraries 中并不直接使用,但在其他部分的 CMake 脚本中非常常见。

cmake
add_executable(my_executable main.cpp)
target_link_libraries(my_executable M Y L I B R A R I E S ) 在这个例子中, {MY_LIBRARIES}) 在这个例子中, MYLIBRARIES)在这个例子中,{MY_LIBRARIES} 是一个变量,其值是一个包含要链接的库的列表。

命令替换:

CMake 支持使用 $() 语法执行命令,并将其结果分配给变量。这种形式在 add_custom_command 和 add_custom_target 等命令中经常使用。

cmake
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/output.txt
COMMAND generate_output > C M A K E C U R R E N T B I N A R Y D I R / o u t p u t . t x t ) 在这个例子中, {CMAKE_CURRENT_BINARY_DIR}/output.txt ) 在这个例子中, CMAKECURRENTBINARYDIR/output.txt)在这个例子中,{CMAKE_CURRENT_BINARY_DIR} 表示当前构建目录的路径。

环境变量:

在 CMake 中,可以使用 $ENV{VAR_NAME} 语法来引用环境变量的值。

cmake
message(“Path: $ENV{PATH}”)
这将打印出当前环境中 PATH 变量的值。

总之,$ 符号在 CMake 中主要用于变量引用和命令替换,是一个很重要的语法元素,用于动态地获取和使用值。

在 CMake 中,使用 target_link_libraries 命令来链接目标(例如可执行文件或库)到其他库时,并不需要像传统的编译器命令行那样使用 -l 来指定库的名称。这是因为 CMake 在背后会自动处理这些细节,使得整个构建过程更加简洁和跨平台。

具体来说,当你在 CMake 脚本中使用 target_link_libraries 指令时,可以直接引用之前通过 set 命令设置过的局部变量作为依赖项,而不需要在变量名前加上 -l

例如,假设你有一个库变量 MY_LIBRARY:

cmake
set(MY_LIBRARY mylib)
然后,在链接到目标时,可以这样写:

cmake
target_link_libraries(my_target ${MY_LIBRARY})
CMake 会自动解析 MY_LIBRARY 的值,然后在链接时正确地使用 -lmylib(或其等效的平台特定格式)。这种方式使得 CMake 脚本更加清晰和易于维护,同时也避免了直接使用编译器命令行选项所面临的平台差异和复杂性。

总之,CMake 在设计上是为了尽可能隐藏底层的构建系统细节,提供一个统一和简洁的界面来管理依赖项和构建过程,因此 target_link_libraries 中直接使用变量名即可引用并链接库,无需加上 -l 前缀。

相关推荐

  1. makefile规则

    2024-07-12 22:02:06       19 阅读
  2. [C++] Makefile的语法规则

    2024-07-12 22:02:06       55 阅读
  3. CMakeLists.txt语法规则:部分命令说明三

    2024-07-12 22:02:06       36 阅读
  4. 开发规范工具

    2024-07-12 22:02:06       48 阅读
  5. <span style='color:red;'>Makefile</span>

    Makefile

    2024-07-12 22:02:06      51 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-12 22:02:06       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-12 22:02:06       72 阅读
  3. 在Django里面运行非项目文件

    2024-07-12 22:02:06       58 阅读
  4. Python语言-面向对象

    2024-07-12 22:02:06       69 阅读

热门阅读

  1. 固体物理学习笔记(持续更新

    2024-07-12 22:02:06       15 阅读
  2. 使用 docker-compose 部署和使用 Yapi

    2024-07-12 22:02:06       21 阅读
  3. 力扣 202快乐数

    2024-07-12 22:02:06       24 阅读
  4. 跨越数据边界:域适应在目标检测中的革新作用

    2024-07-12 22:02:06       25 阅读
  5. 在linux x86服务器安装jdk

    2024-07-12 22:02:06       20 阅读
  6. 中国专利文献编号系统方案

    2024-07-12 22:02:06       21 阅读
  7. LanceDB:开源的向量搜索引擎

    2024-07-12 22:02:06       19 阅读