首页 > 其他分享 >CMake学习2024.12.7问AI的问题记录

CMake学习2024.12.7问AI的问题记录

时间:2024-12-07 19:33:45浏览次数:7  
标签:2024.12 CMakeLists include CMake AI add MyLibrary txt 目录

iwtbf: target_include_directories(&{PROJECT_BINARY_DIR})

是什么

GitHub Copilot: target_include_directories 是 CMake 中的一个命令,用于为目标添加包含目录。&{PROJECT_BINARY_DIR} 是一个变量,表示项目的二进制目录。

语法如下:

target_include_directories(<target> [SYSTEM] [AFTER|BEFORE] <INTERFACE|PUBLIC|PRIVATE> [items1...])

例如:

target_include_directories(my_target PRIVATE ${PROJECT_BINARY_DIR})

这行代码的意思是将 ${PROJECT_BINARY_DIR} 目录添加到 my_target 目标的私有包含路径中。

iwtbf: target_include_directories(Tutorial PUBLIC "${PROJECT_BINARY_DIR}")

GitHub Copilot: 这行代码的意思是将 ${PROJECT_BINARY_DIR} 目录添加到 Tutorial 目标的公共包含路径中。

具体解释如下:

  • target_include_directories 是 CMake 命令,用于为目标添加包含目录。
  • Tutorial 是目标名称。
  • PUBLIC 指定包含目录的可见性,表示该目录对目标及其依赖项都是可见的。
  • "${PROJECT_BINARY_DIR}" 是包含目录的路径,表示项目的二进制目录。

完整示例:

target_include_directories(Tutorial PUBLIC "${PROJECT_BINARY_DIR}")

这行代码将 ${PROJECT_BINARY_DIR} 目录添加到 Tutorial 目标的公共包含路径中,使得该目录中的头文件可以被 Tutorial 及其依赖项访问。

iwtbf: 什么是项目的二进制目录

GitHub Copilot: 项目的二进制目录(PROJECT_BINARY_DIR)是指 CMake 构建系统生成的所有构建文件(如编译后的目标文件、可执行文件、库文件等)所在的目录。这个目录通常是在运行 CMake 配置命令时指定的。

例如,在使用 CMake 构建项目时,通常会执行以下步骤:

  1. 创建一个构建目录:

    mkdir build
    cd build
    
  2. 运行 CMake 配置命令,指定源代码目录和生成的二进制文件目录:

    cmake ../path/to/source
    

在这个例子中,build 目录就是项目的二进制目录,CMake 会在这个目录中生成所有的构建文件。

在 CMakeLists.txt 文件中,可以使用 PROJECT_BINARY_DIR 变量来引用这个目录。例如:

message("Binary directory: ${PROJECT_BINARY_DIR}")

这行代码会输出项目的二进制目录路径。

iwtbf: 公共包含路径是什么

GitHub Copilot: 公共包含路径是指在构建系统中指定的包含目录,这些目录中的头文件可以被目标及其依赖项访问。在 CMake 中,通过 target_include_directories 命令可以为目标添加包含目录,并指定其可见性(INTERFACEPUBLICPRIVATE)。

  • INTERFACE:仅对依赖该目标的其他目标可见。
  • PUBLIC:对目标本身及其依赖项都可见。
  • PRIVATE:仅对目标本身可见。

例如:

target_include_directories(Tutorial PUBLIC "${PROJECT_SOURCE_DIR}/include")

这行代码将 ${PROJECT_SOURCE_DIR}/include 目录添加到 Tutorial 目标的公共包含路径中,使得该目录中的头文件可以被 Tutorial 及其依赖项访问。

总结:

  • 公共包含路径是对目标及其依赖项都可见的包含目录。
  • 在 CMake 中,通过 target_include_directories 命令并使用 PUBLIC 关键字来指定公共包含路径。

iwtbf: 包含路径是什么

GitHub Copilot: 包含路径是编译器在编译源代码时查找头文件(.h.hpp 文件)的位置。通过指定包含路径,编译器可以找到并包含这些头文件,从而使得源代码能够正确编译。

在 CMake 中,可以使用 target_include_directories 命令为目标添加包含路径。包含路径可以分为三种可见性:INTERFACEPUBLICPRIVATE

  • INTERFACE:仅对依赖该目标的其他目标可见。
  • PUBLIC:对目标本身及其依赖项都可见。
  • PRIVATE:仅对目标本身可见。

例如:

target_include_directories(MyTarget PUBLIC "${CMAKE_SOURCE_DIR}/include")

这行代码将 ${CMAKE_SOURCE_DIR}/include 目录添加到 MyTarget 目标的公共包含路径中,使得该目录中的头文件可以被 MyTarget 及其依赖项访问。

总结:

  • 包含路径是编译器查找头文件的位置。
  • 在 CMake 中,可以使用 target_include_directories 命令为目标添加包含路径,并指定其可见性。

iwtbf: configure_file(TutorialConfig.h.in TutorialConfig.h)

GitHub Copilot: configure_file 是 CMake 中的一个命令,用于从模板文件生成配置文件。它会读取一个输入文件(通常带有 .in 后缀),替换其中的变量,然后将结果写入到输出文件中。

例如:

configure_file(TutorialConfig.h.in TutorialConfig.h)

这行代码的作用是:

  1. 读取 TutorialConfig.h.in 文件。
  2. 替换文件中的变量(例如 ${PROJECT_NAME}${VERSION} 等)。
  3. 将替换后的内容写入到 TutorialConfig.h 文件中。

假设 TutorialConfig.h.in 文件内容如下:

#define PROJECT_NAME "@PROJECT_NAME@"
#define VERSION "@VERSION@"

在 CMakeLists.txt 中定义变量:

set(PROJECT_NAME "Tutorial")
set(VERSION "1.0")

执行 configure_file 后,生成的 TutorialConfig.h 文件内容如下:

#define PROJECT_NAME "Tutorial"
#define VERSION "1.0"

总结:

  • configure_file 命令用于从模板文件生成配置文件。
  • 它会替换模板文件中的变量,并将结果写入到指定的输出文件中。

iwtbf: 模板文件和配置文件的位置如何决定的

GitHub Copilot: 在使用 configure_file 命令时,模板文件和配置文件的位置是相对于当前的 CMake 构建目录和源目录来决定的。

  1. 模板文件的位置
    模板文件的位置通常是相对于 CMakeLists.txt 文件所在的源目录。你需要在 configure_file 命令中指定模板文件的相对路径或绝对路径。

    例如,如果你的模板文件 TutorialConfig.h.in 位于项目的源目录中,你可以这样指定:

    configure_file(${CMAKE_SOURCE_DIR}/TutorialConfig.h.in ${CMAKE_BINARY_DIR}/TutorialConfig.h)
    
  2. 配置文件的位置
    配置文件的位置通常是相对于 CMake 的二进制目录(构建目录)。你需要在 configure_file 命令中指定配置文件的相对路径或绝对路径。

    例如,如果你希望生成的配置文件 TutorialConfig.h 位于构建目录中,你可以这样指定:

    configure_file(${CMAKE_SOURCE_DIR}/TutorialConfig.h.in ${CMAKE_BINARY_DIR}/TutorialConfig.h)
    

完整示例:

# 设置项目名称和版本
set(PROJECT_NAME "Tutorial")
set(VERSION "1.0")

# 配置文件生成
configure_file(${CMAKE_SOURCE_DIR}/TutorialConfig.h.in ${CMAKE_BINARY_DIR}/TutorialConfig.h)

在这个示例中:

  • 模板文件 TutorialConfig.h.in 位于源目录中。
  • 生成的配置文件 TutorialConfig.h 位于构建目录中。

总结:

  • 模板文件的位置通常是相对于源目录。
  • 配置文件的位置通常是相对于构建目录。
  • 可以使用 ${CMAKE_SOURCE_DIR}${CMAKE_BINARY_DIR} 变量来指定源目录和构建目录的路径。

iwtbf: configure_file()需要两个文件已经存在,无法创建文件,对吗

GitHub Copilot: 不对。configure_file() 命令只需要模板文件已经存在,而不需要输出文件已经存在。configure_file() 会读取模板文件的内容,进行变量替换,然后生成输出文件。如果输出文件不存在,configure_file() 会自动创建它。

例如:

configure_file(TutorialConfig.h.in ${CMAKE_BINARY_DIR}/TutorialConfig.h)

在这个例子中:

  • TutorialConfig.h.in 是模板文件,必须已经存在。
  • ${CMAKE_BINARY_DIR}/TutorialConfig.h 是输出文件,如果不存在,configure_file() 会自动创建它。

总结:

  • configure_file() 需要模板文件已经存在。
  • configure_file() 会自动创建输出文件,如果输出文件不存在。

iwtbf: Tutorial_VERSION_MAJOR和Tutorial_VERSION_MINOR是什么

GitHub Copilot: Tutorial_VERSION_MAJORTutorial_VERSION_MINOR 通常是用于表示项目的主版本号和次版本号的变量。这些变量可以在 CMakeLists.txt 文件中定义,并在配置文件中使用。

例如,在 CMakeLists.txt 文件中,你可以这样定义版本号:

# 设置项目名称和版本号
set(Tutorial_VERSION_MAJOR 1)
set(Tutorial_VERSION_MINOR 0)

然后,你可以在模板文件(例如 TutorialConfig.h.in)中使用这些变量:

// TutorialConfig.h.in
#define TUTORIAL_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define TUTORIAL_VERSION_MINOR @Tutorial_VERSION_MINOR@

使用 configure_file 命令生成配置文件:

configure_file(TutorialConfig.h.in ${CMAKE_BINARY_DIR}/TutorialConfig.h)

生成的 TutorialConfig.h 文件将包含替换后的版本号:

// TutorialConfig.h
#define TUTORIAL_VERSION_MAJOR 1
#define TUTORIAL_VERSION_MINOR 0

总结:

  • Tutorial_VERSION_MAJORTutorial_VERSION_MINOR 是用于表示项目主版本号和次版本号的变量。
  • 这些变量可以在 CMakeLists.txt 文件中定义,并在模板文件中使用,通过 configure_file 命令生成配置文件。

iwtbf: cmake --build .

GitHub Copilot: cmake --build . 是一个命令,用于在当前目录中构建项目。它会调用生成的构建系统(例如 Makefile、Ninja、Visual Studio 解决方案等)来编译和链接项目。

使用步骤如下:

  1. 创建构建目录(如果还没有创建):

    mkdir build
    cd build
    
  2. 运行 CMake 配置命令,生成构建系统文件:

    cmake ..
    
  3. 构建项目

    cmake --build .
    

在这个例子中:

  • mkdir buildcd build 创建并进入构建目录。
  • cmake .. 命令在构建目录中运行 CMake 配置,生成构建系统文件。
  • cmake --build . 命令在当前构建目录中构建项目。

总结:

  • cmake --build . 命令用于在当前目录中构建项目。
  • 它会调用生成的构建系统来编译和链接项目。

iwtbf: cmake ..\Step1\

GitHub Copilot: cmake ..\Step1\ 命令用于在当前构建目录中运行 CMake 配置,并指定源代码目录为 ..\Step1\。这会生成构建系统文件(例如 Makefile、Ninja 文件、Visual Studio 解决方案等),这些文件用于后续的构建过程。

具体步骤如下:

  1. 创建并进入构建目录

    mkdir build
    cd build
    
  2. 运行 CMake 配置命令,指定源代码目录为 ..\Step1\

    cmake ..\Step1\
    

在这个例子中:

  • mkdir buildcd build 创建并进入构建目录。
  • cmake ..\Step1\ 命令在构建目录中运行 CMake 配置,指定源代码目录为 ..\Step1\

总结:

  • cmake ..\Step1\ 命令用于在当前构建目录中运行 CMake 配置,并指定源代码目录为 ..\Step1\
  • 这会生成构建系统文件,用于后续的构建过程。

iwtbf: library是什么

GitHub Copilot: 在软件开发中,库(library)是一组预编译的代码集合,可以被多个程序或模块共享和重用。库通常包含函数、类、数据结构和其他资源,开发者可以在自己的程序中调用这些库中的功能,而无需重新编写代码。

库可以分为两种主要类型:

  1. 静态库(Static Library)

    • 静态库在编译时被链接到应用程序中,生成一个单一的可执行文件。
    • 静态库的文件扩展名通常是 .lib(Windows)或 .a(Unix/Linux)。
  2. 动态库(Dynamic Library)

    • 动态库在运行时被加载到应用程序中,可以被多个程序共享。
    • 动态库的文件扩展名通常是 .dll(Windows)、.so(Unix/Linux)或 .dylib(macOS)。

在 CMake 中,可以使用 add_library 命令来创建库。例如:

# 创建一个静态库
add_library(MyStaticLib STATIC mylib.cpp)

# 创建一个动态库
add_library(MySharedLib SHARED mylib.cpp)

然后,可以使用 target_link_libraries 命令将库链接到目标:

# 将库链接到可执行文件
add_executable(MyExecutable main.cpp)
target_link_libraries(MyExecutable MyStaticLib MySharedLib)

总结:

  • 库是一组预编译的代码集合,可以被多个程序共享和重用。
  • 库分为静态库和动态库。
  • 在 CMake 中,可以使用 add_library 命令创建库,并使用 target_link_libraries 命令将库链接到目标。

iwtbf: 库由什么组成

GitHub Copilot: 库(library)通常由以下几个部分组成:

  1. 头文件(Header Files)

    • 头文件通常以 .h.hpp 作为扩展名。
    • 头文件包含函数、类、宏和数据结构的声明。
    • 头文件用于定义库的接口,供其他程序使用。
  2. 源文件(Source Files)

    • 源文件通常以 .c.cpp.cc 等作为扩展名。
    • 源文件包含函数、类和其他代码的实现。
    • 源文件在编译时生成目标文件(.o.obj),然后这些目标文件被打包成库文件。
  3. 库文件(Library Files)

    • 库文件是编译后的二进制文件,包含了源文件的实现。
    • 静态库文件通常以 .lib(Windows)或 .a(Unix/Linux)作为扩展名。
    • 动态库文件通常以 .dll(Windows)、.so(Unix/Linux)或 .dylib(macOS)作为扩展名。
  4. 元数据和配置文件(Metadata and Configuration Files)

    • 有些库可能包含元数据和配置文件,用于描述库的版本、依赖关系、编译选项等。
    • 这些文件可以帮助构建系统(如 CMake)正确地使用和链接库。

示例:
假设我们有一个名为 MyLibrary 的库,它包含以下文件:

  • 头文件:

    • MyLibrary.h
  • 源文件:

    • MyLibrary.cpp
  • 静态库文件:

    • MyLibrary.lib(Windows)
    • libMyLibrary.a(Unix/Linux)
  • 动态库文件:

    • MyLibrary.dll(Windows)
    • libMyLibrary.so(Unix/Linux)
    • libMyLibrary.dylib(macOS)

在 CMake 中,可以这样定义和使用这个库:

# 定义库
add_library(MyLibrary STATIC MyLibrary.cpp)
# 或者
add_library(MyLibrary SHARED MyLibrary.cpp)

# 将库链接到可执行文件
add_executable(MyExecutable main.cpp)
target_link_libraries(MyExecutable MyLibrary)

总结:

  • 库由头文件、源文件、库文件以及可能的元数据和配置文件组成。
  • 头文件定义接口,源文件实现功能,库文件包含编译后的二进制代码。
  • 在 CMake 中,可以使用 add_librarytarget_link_libraries 命令来定义和使用库。

iwtbf: 将库链接到可执行文件是什么意思

GitHub Copilot: 将库链接到可执行文件是指在编译过程中,将库中的函数、类和其他符号与可执行文件中的引用进行匹配和绑定的过程。这个过程确保可执行文件在运行时能够正确调用库中的功能。

链接过程分为两种类型:

  1. 静态链接(Static Linking)

    • 在编译时,将静态库的代码复制到可执行文件中。
    • 生成的可执行文件包含所有依赖的库代码,因此不需要在运行时依赖外部库文件。
    • 优点:可执行文件独立,不需要额外的库文件。
    • 缺点:可执行文件体积较大,更新库时需要重新编译可执行文件。
  2. 动态链接(Dynamic Linking)

    • 在运行时,将动态库加载到内存中,并将其符号与可执行文件中的引用进行匹配。
    • 生成的可执行文件较小,但在运行时需要依赖外部的动态库文件。
    • 优点:可执行文件体积较小,更新库时不需要重新编译可执行文件。
    • 缺点:需要在运行时确保动态库文件存在。

在 CMake 中,可以使用 target_link_libraries 命令将库链接到可执行文件。例如:

假设我们有一个名为 MyLibrary 的库和一个名为 MyExecutable 的可执行文件:

# 定义库
add_library(MyLibrary STATIC MyLibrary.cpp)
# 或者
add_library(MyLibrary SHARED MyLibrary.cpp)

# 定义可执行文件
add_executable(MyExecutable main.cpp)

# 将库链接到可执行文件
target_link_libraries(MyExecutable MyLibrary)

在这个例子中:

  • add_library 命令定义了一个名为 MyLibrary 的库。
  • add_executable 命令定义了一个名为 MyExecutable 的可执行文件。
  • target_link_libraries 命令将 MyLibrary 库链接到 MyExecutable 可执行文件。

总结:

  • 将库链接到可执行文件是指在编译过程中,将库中的符号与可执行文件中的引用进行匹配和绑定。
  • 链接过程分为静态链接和动态链接。
  • 在 CMake 中,可以使用 target_link_libraries 命令将库链接到可执行文件。

iwtbf: Once the library is created, it is connected to our executable target with target_include_directories() and target_link_libraries().

为什么要用到target_include_directories()

GitHub Copilot: target_include_directories() 命令用于指定目标的包含目录(include directories),这些目录包含头文件(header files),编译器在编译源文件时会在这些目录中查找头文件。

当你创建一个库并将其链接到可执行文件时,通常需要包含库的头文件,以便在可执行文件的源代码中使用库的功能。target_include_directories() 命令确保编译器能够找到这些头文件。

例如,假设你有一个库 MyLibrary,它的头文件位于 include 目录中:

# 定义库
add_library(MyLibrary STATIC MyLibrary.cpp)

# 指定库的包含目录
target_include_directories(MyLibrary PUBLIC ${CMAKE_SOURCE_DIR}/include)

然后,你有一个可执行文件 MyExecutable,需要使用 MyLibrary 库:

# 定义可执行文件
add_executable(MyExecutable main.cpp)

# 将库链接到可执行文件
target_link_libraries(MyExecutable MyLibrary)

在这个例子中:

  • target_include_directories(MyLibrary PUBLIC ${CMAKE_SOURCE_DIR}/include) 命令指定了 MyLibrary 库的包含目录。
  • PUBLIC 关键字表示包含目录对 MyLibrary 及其依赖项(如 MyExecutable)都是可见的。
  • 当编译 MyExecutable 时,编译器会在 include 目录中查找头文件。

总结:

  • target_include_directories() 命令用于指定目标的包含目录,确保编译器能够找到头文件。
  • 在将库链接到可执行文件时,使用 target_include_directories() 命令可以使可执行文件的源代码中正确引用库的头文件。

# iwtbf: target_include_directories()执行目标可以是什么

GitHub Copilot: target_include_directories() 命令的执行目标可以是任何由 add_library()add_executable() 命令创建的目标。这些目标可以是静态库、动态库或可执行文件。

具体来说,target_include_directories() 命令用于为指定的目标添加包含目录,使得在编译该目标时,编译器能够找到并包含这些目录中的头文件。

以下是一些示例,展示了如何使用 target_include_directories() 命令:

示例 1:为库添加包含目录

# 定义一个静态库
add_library(MyLibrary STATIC MyLibrary.cpp)

# 为库添加包含目录
target_include_directories(MyLibrary PUBLIC ${CMAKE_SOURCE_DIR}/include)

示例 2:为可执行文件添加包含目录

# 定义一个可执行文件
add_executable(MyExecutable main.cpp)

# 为可执行文件添加包含目录
target_include_directories(MyExecutable PRIVATE ${CMAKE_SOURCE_DIR}/include)

示例 3:为可执行文件链接库并添加包含目录

# 定义一个静态库
add_library(MyLibrary STATIC MyLibrary.cpp)

# 为库添加包含目录
target_include_directories(MyLibrary PUBLIC ${CMAKE_SOURCE_DIR}/include)

# 定义一个可执行文件
add_executable(MyExecutable main.cpp)

# 将库链接到可执行文件
target_link_libraries(MyExecutable MyLibrary)

# 为可执行文件添加包含目录(如果需要额外的包含目录)
target_include_directories(MyExecutable PRIVATE ${CMAKE_SOURCE_DIR}/extra_include)

在这些示例中:

  • MyLibrary 是一个静态库目标。
  • MyExecutable 是一个可执行文件目标。
  • target_include_directories() 命令为这些目标添加了包含目录。

关键字 PUBLICPRIVATEINTERFACE 用于指定包含目录的可见性:

  • PUBLIC:包含目录对目标本身及其依赖项都可见。
  • PRIVATE:包含目录仅对目标本身可见。
  • INTERFACE:包含目录仅对依赖该目标的其他目标可见。

总结:

  • target_include_directories() 命令的执行目标可以是由 add_library()add_executable() 创建的任何目标。
  • 该命令用于为目标添加包含目录,使得编译器能够找到头文件。

add_subdirectory()的格式是什么

add_subdirectory() 的格式如下:

add_subdirectory(<source_dir> [<binary_dir>] [EXCLUDE_FROM_ALL])

参数说明

  • <source_dir>:必需。包含 CMakeLists.txt 文件的子目录路径。通常相对于当前 CMakeLists.txt 文件的位置。
  • <binary_dir>:可选。子目录的二进制输出目录。默认情况下,二进制目录与源目录同名。
  • EXCLUDE_FROM_ALL:可选。如果指定,子目录不会包含在默认构建目标中。

示例

基本用法

假设项目结构如下:

ProjectRoot/
├── CMakeLists.txt
└── src/
    ├── CMakeLists.txt
    └── main.cpp

ProjectRoot/CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(MyProject)

add_subdirectory(src)

ProjectRoot/src/CMakeLists.txt

add_executable(MyExecutable main.cpp)

指定二进制目录

add_subdirectory(src build/src)
  • src:源目录。
  • build/src:二进制目录。

排除子目录

add_subdirectory(src EXCLUDE_FROM_ALL)

此命令添加 src 子目录,但不会将其包含在 all 目标中。

总结

  • add_subdirectory() 用于将子目录添加到构建过程中。
  • 可以指定源目录和可选的二进制目录。
  • 通过 EXCLUDE_FROM_ALL 控制是否包含在默认构建目标中。

默认的src的二进制输出目录是ProjectRoot/src吗

默认情况下,add_subdirectory(src) 不会将生成的二进制文件直接输出到 ProjectRoot/src 目录。相反,CMake 使用二进制目录(build directory)来存放所有生成的构建文件,以保持源代码目录的整洁。

具体说明

  1. 构建目录与源代码目录分离
    通常,推荐使用外部构建(out-of-source build),即在源代码目录之外创建一个单独的构建目录。例如:

    ProjectRoot/
    ├── CMakeLists.txt
    ├── src/
    │   ├── CMakeLists.txt
    │   └── main.cpp
    └── build/
    
  2. 使用 add_subdirectory
    ProjectRoot/CMakeLists.txt 中添加子目录:

    cmake_minimum_required(VERSION 3.10)
    project(MyProject)
    
    add_subdirectory(src)
    
  3. 默认的二进制输出目录
    当你在 build 目录中运行 cmake .. 时,CMake 会在 build 目录下为每个子目录创建相应的二进制输出目录。

    ProjectRoot/
    ├── CMakeLists.txt
    ├── src/
    │   ├── CMakeLists.txt
    │   └── main.cpp
    └── build/
        ├── CMakeCache.txt
        ├── CMakeFiles/
        └── src/
            ├── CMakeFiles/
            └── Makefile
    

    在这种情况下,src 子目录的二进制输出目录为 build/src,而不是 ProjectRoot/src

  4. 指定自定义二进制目录(可选)
    如果需要,可以在 add_subdirectory 命令中指定自定义的二进制目录。例如:

    add_subdirectory(src build/src_bin)
    

    这样,src 子目录的二进制输出目录将是 build/src_bin

总结

  • 默认行为add_subdirectory(src) 会在二进制目录中创建一个与源目录同名的子目录(例如 build/src),而不是将二进制文件放在源代码目录 ProjectRoot/src 中。
  • 推荐实践:使用外部构建目录(例如 build/)来分离源代码和构建文件,保持项目结构清晰。
  • 自定义二进制目录:可以通过在 add_subdirectory 中指定第二个参数来自定义二进制目录的位置。

这样做有助于维护项目的整洁性,避免在源代码目录中混杂生成的构建文件。

add_subdirectory()的功能是什么

add_subdirectory() 是 CMake 中的一个命令,用于将子目录添加到当前的构建过程。通过使用 add_subdirectory(),你可以组织项目结构,将不同的模块或组件分开管理,确保构建系统能够正确地识别和构建这些子项目。

格式

add_subdirectory(<source_dir> [<binary_dir>] [EXCLUDE_FROM_ALL])

参数说明

  • <source_dir>必需。包含 CMakeLists.txt 文件的子目录路径。路径通常相对于当前 CMakeLists.txt 文件的位置。
  • <binary_dir>可选。指定子目录的二进制输出目录。如果不指定,默认会在构建目录中创建一个与源目录同名的子目录。
  • EXCLUDE_FROM_ALL可选。如果指定,子目录不会包含在默认的 all 目标中。这意味着该子目录只有在明确指定时才会被构建。

功能

  1. 组织项目结构

    • 将项目划分为多个模块或组件,每个模块有自己的源代码和 CMakeLists.txt 文件,便于维护和管理。
  2. 继承和扩展设置

    • 子目录可以继承父目录中的设置,如编译选项、包含目录等,同时可以根据需要添加或覆盖这些设置。
  3. 控制构建流程

    • 通过 EXCLUDE_FROM_ALL 等选项,可以灵活控制哪些子目录在默认构建时被包含,哪些不被包含。

示例

假设项目结构如下:

ProjectRoot/
├── CMakeLists.txt
├── src/
│   ├── CMakeLists.txt
│   └── main.cpp
└── lib/
    ├── CMakeLists.txt
    └── library.cpp

ProjectRoot/CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(MyProject)

# 添加 src 子目录
add_subdirectory(src)

# 添加 lib 子目录,并排除在默认构建之外
add_subdirectory(lib EXCLUDE_FROM_ALL)

ProjectRoot/src/CMakeLists.txt

add_executable(MyExecutable main.cpp)

# 链接库(假设库名为 MyLibrary)
target_link_libraries(MyExecutable PRIVATE MyLibrary)

ProjectRoot/lib/CMakeLists.txt

add_library(MyLibrary STATIC library.cpp)

# 指定包含目录
target_include_directories(MyLibrary PUBLIC ${CMAKE_SOURCE_DIR}/include)

使用场景

  • 大型项目:将项目划分为多个子模块,每个子模块负责不同的功能,便于团队协作和代码管理。
  • 复用代码:通过子目录管理独立的库或组件,实现代码复用。
  • 第三方库集成:将第三方库的源码添加为子目录,便于统一管理和构建。

注意事项

  • 路径正确性:确保 <source_dir> 路径正确,避免因路径错误导致找不到 CMakeLists.txt 文件。
  • 依赖管理:子目录之间的依赖关系需要通过 target_link_libraries() 等命令显式管理,确保构建顺序正确。
  • 构建目录分离:推荐使用外部构建(out-of-source build)方式,即在源代码目录之外创建一个独立的构建目录,以保持源代码目录的整洁。

总结

add_subdirectory() 命令在 CMake 中起到了组织和管理项目结构的重要作用。通过合理使用 add_subdirectory(),可以将复杂的项目划分为多个独立且可维护的子模块,提高项目的可扩展性和可维护性。

add_subdirectory()之后是否可以直接使用subdirectory中定义的内容

是的,在使用 add_subdirectory() 之后,可以直接使用子目录中定义的内容,如目标(库、可执行文件)和变量。add_subdirectory() 会将子目录的 CMakeLists.txt 包含到主项目中,使得子目录中定义的目标和设置在主项目中可见和可用。

示例

假设项目结构如下:

ProjectRoot/
├── CMakeLists.txt
├── src/
│   ├── CMakeLists.txt
│   └── main.cpp
└── lib/
    ├── CMakeLists.txt
    └── MyLibrary.cpp

ProjectRoot/CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(MyProject)

# 添加子目录 lib
add_subdirectory(lib)

# 添加子目录 src
add_subdirectory(src)

ProjectRoot/lib/CMakeLists.txt

# 定义静态库 MyLibrary
add_library(MyLibrary STATIC MyLibrary.cpp)

# 指定包含目录
target_include_directories(MyLibrary PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)

ProjectRoot/src/CMakeLists.txt

# 定义可执行文件 MyExecutable
add_executable(MyExecutable main.cpp)

# 链接库 MyLibrary
target_link_libraries(MyExecutable PRIVATE MyLibrary)

ProjectRoot/src/main.cpp

#include "MyLibrary.h"

int main() {
    myFunction();
    return 0;
}

ProjectRoot/lib/MyLibrary.cpp

#include "MyLibrary.h"
#include <iostream>

void myFunction() {
    std::cout << "Hello from MyLibrary!" << std::endl;
}

ProjectRoot/lib/include/MyLibrary.h

#pragma once

void myFunction();

解释

  1. 添加子目录

    • CMakeLists.txt 使用 add_subdirectory(lib)add_subdirectory(src)libsrc 子目录添加到构建过程中。
  2. 定义库

    • lib/CMakeLists.txt 中,使用 add_library(MyLibrary STATIC MyLibrary.cpp) 定义了一个名为 MyLibrary 的静态库。
    • 使用 target_include_directories(MyLibrary PUBLIC ...) 指定了库的头文件目录,使得链接该库的目标可以找到相应的头文件。
  3. 定义可执行文件并链接库

    • src/CMakeLists.txt 中,使用 add_executable(MyExecutable main.cpp) 定义了一个可执行文件。
    • 使用 target_link_libraries(MyExecutable PRIVATE MyLibrary)MyLibrary 库链接到 MyExecutable 可执行文件。
  4. 使用库

    • main.cpp 中包含了 MyLibrary.h 并调用了 myFunction(),这是子目录 lib 中定义的函数。

注意事项

  • 目标可见性

    • 使用 PUBLICPRIVATEINTERFACE 来设置包含目录和链接库的可见性。例如,上述示例中 MyLibrary 使用 PUBLIC,意味着链接 MyLibrary 的目标(如 MyExecutable)也可以访问其包含目录。
  • 构建顺序

    • add_subdirectory() 确保子目录在主目录的构建过程中被正确处理,允许主目录使用子目录中定义的目标。
  • 变量作用域

    • 子目录中的变量默认不会影响父目录,除非使用 set(... CACHE ...) 或其他方法显式传递变量。

总结

通过 add_subdirectory(),可以将子目录中的目标和设置集成到主项目中,从而实现模块化和代码复用。这样,子目录中定义的库、可执行文件等内容可以在主项目及其他子目录中直接使用和链接。

链接库使用的是源文件(.cpp),包含目录使用的是头文件(.hpp)对吗

是的,基本上可以这样理解:

  • 链接库 使用的是库文件(如 .lib.a.dll.so 等),这些库文件是由源文件(.cpp)编译生成的。
  • 包含目录 指定的是存放头文件(如 .h.hpp)的路径,编译器在编译时会在这些目录中查找头文件。

详细说明

  1. 源文件 (.cpp)

    • 包含库的实现代码。
    • 在编译过程中,这些源文件会被编译成目标文件(.o.obj),然后打包成库文件(静态库 .lib.a,动态库 .dll.so 等)。
  2. 头文件 (.h, .hpp)

    • 包含库的接口声明,如函数声明、类定义等。
    • 通过 target_include_directories() 指定包含目录,确保在使用库的代码中可以正确引用这些头文件。
  3. 库文件

    • 静态库(如 .lib.a):在编译时链接到可执行文件中,生成的可执行文件包含所有需要的库代码。
    • 动态库(如 .dll.so):在运行时加载,生成的可执行文件依赖于外部的库文件。

示例

假设有一个库 MyLibrary,结构如下:

MyLibrary/
├── include/
│   └── MyLibrary.hpp
└── src/
    └── MyLibrary.cpp

CMakeLists.txt

# 定义库
add_library(MyLibrary STATIC src/MyLibrary.cpp)

# 指定包含目录
target_include_directories(MyLibrary PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)

使用库的可执行文件

MyExecutable/
├── main.cpp
└── CMakeLists.txt

MyExecutable/CMakeLists.txt

add_executable(MyExecutable main.cpp)
target_link_libraries(MyExecutable PRIVATE MyLibrary)

main.cpp

#include "MyLibrary.hpp"

int main() {
    myFunction();
    return 0;
}

总结

  • 源文件 (.cpp) 用于实现库的功能,编译后生成库文件。
  • 头文件 (.h, .hpp) 用于声明库的接口,通过包含目录让使用者能够访问这些声明。
  • 链接库 时,使用的是编译生成的库文件,而不是源文件。

这样,编译器在编译可执行文件时,会通过包含目录找到头文件,使用库文件中的实现代码进行链接,确保程序能够正确调用库中的功能。

既然add_subdirectory()是将子目录的CMakeLists.txt包含到主项目中,那理论上是否可以直接将子目录中的CMakeLists.txt中的内容进行路径方面的修正后直接替换顶层CMakeLists.txt中相应的add_subdirectory(),然后删除子目录中的CMakeLists.txt从而整个项目仅保留一个顶层CMakeLists.txt

是的,理论上,您可以将子目录中的 CMakeLists.txt 文件的内容整合到顶层的 CMakeLists.txt 中,调整相关的路径,然后删除子目录中的 CMakeLists.txt,使整个项目仅保留一个顶层的 CMakeLists.txt。然而,这种做法在实际项目中有一些优缺点需要考虑。

如何操作

  1. 整合内容

    • 打开子目录中的 CMakeLists.txt 文件。
    • 复制其中定义的库、可执行文件、包含目录等命令。
    • 将这些内容粘贴到顶层的 CMakeLists.txt 中,确保调整所有相对路径,使其相对于顶层目录正确。
  2. 调整路径

    • 更新所有源文件和头文件的路径。例如,将 src/main.cpp 调整为 subdir/src/main.cpp,如果子目录在顶层目录中的位置有所不同。
  3. 删除子目录的 CMakeLists.txt

    • 确保所有必要的配置都已迁移到顶层 CMakeLists.txt 后,可以删除子目录中的 CMakeLists.txt 文件。
  4. 移除 add_subdirectory()

    • 从顶层 CMakeLists.txt 中删除 add_subdirectory(subdir) 命令,因为子目录的配置已被整合。

示例

假设项目结构如下:

ProjectRoot/
├── CMakeLists.txt
├── src/
│   ├── CMakeLists.txt
│   └── main.cpp
└── lib/
    ├── CMakeLists.txt
    └── MyLibrary.cpp

原顶层 CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(MyProject)

add_subdirectory(src)
add_subdirectory(lib)

子目录 src/CMakeLists.txt

add_executable(MyExecutable main.cpp)
target_link_libraries(MyExecutable PRIVATE MyLibrary)

子目录 lib/CMakeLists.txt

add_library(MyLibrary STATIC MyLibrary.cpp)
target_include_directories(MyLibrary PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)

整合后的顶层 CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(MyProject)

# 定义库
add_library(MyLibrary STATIC lib/MyLibrary.cpp)
target_include_directories(MyLibrary PUBLIC ${CMAKE_SOURCE_DIR}/lib/include)

# 定义可执行文件并链接库
add_executable(MyExecutable src/main.cpp)
target_link_libraries(MyExecutable PRIVATE MyLibrary)

优缺点分析

优点

  1. 简单性

    • 对于小型项目,使用单一的 CMakeLists.txt 文件可能更为简洁,减少了文件数量。
  2. 易于理解

    • 所有构建配置集中在一个文件中,便于新手或初学者理解项目的构建流程。

缺点

  1. 可维护性差

    • 随着项目规模的增大,单一的顶层 CMakeLists.txt 会变得臃肿,难以管理和维护。
  2. 缺乏模块化

    • 分离的子目录和独立的 CMakeLists.txt 文件有助于模块化设计,每个模块或组件可以独立开发和测试。
  3. 团队协作不便

    • 在多团队成员协作的情况下,分离的 CMakeLists.txt 文件有助于团队成员各自负责不同模块,减少冲突。
  4. 复用性降低

    • 独立的子目录和 CMakeLists.txt 文件更容易被其他项目复用,通过 add_subdirectory() 直接引入。

推荐做法

虽然将所有内容整合到顶层 CMakeLists.txt 中在技术上是可行的,但在实际开发中,推荐保持使用 add_subdirectory() 并保留子目录中的 CMakeLists.txt 文件。这种方式有助于:

  • 模块化和分层设计:每个子模块或组件有独立的构建配置,便于管理和扩展。
  • 提高可维护性:更清晰的项目结构,便于定位和修改特定模块的构建设置。
  • 增强复用性:子模块可以更方便地被其他项目引用和复用。

总结

虽然可以通过调整路径和整合 CMakeLists.txt 内容,将子目录的配置合并到顶层文件中,但这种做法在项目规模增大或需要模块化管理时会带来诸多不便。保持子目录中的 CMakeLists.txt 文件,并使用 add_subdirectory() 来组织项目结构,是更为推荐和实践的构建方式,尤其适用于中大型项目和团队协作开发。

我注意到add_subdirectory(src) add_subdirectory(lib)中lib是在src后面添加的,但是src中的CMakeLIsts却使用了lib中的内容

您观察到的问题确实涉及到 add_subdirectory() 的调用顺序在 CMake 项目中的重要性。让我们详细解释一下这一点,以及如何正确组织项目结构以避免问题。

问题描述

假设您的顶层 CMakeLists.txt 如下:

cmake_minimum_required(VERSION 3.10)
project(MyProject)

add_subdirectory(src)
add_subdirectory(lib)

而在 src/CMakeLists.txt 中,您尝试链接 lib 中定义的库:

add_executable(MyExecutable main.cpp)
target_link_libraries(MyExecutable PRIVATE MyLibrary)

这种情况下,由于 lib 子目录在 src 之后添加,CMake 在处理 src/CMakeLists.txt 时,尚未定义 MyLibrary 库,导致链接失败或找不到目标错误。

原因分析

CMake 的解析顺序是自上而下的。当 CMake 处理 add_subdirectory() 时,会立即进入并解析指定子目录中的 CMakeLists.txt。因此:

  1. add_subdirectory(src) 被调用

    • 进入 src/CMakeLists.txt
    • 尝试链接 MyLibrary,但 lib 子目录尚未添加,MyLibrary 尚未定义。
    • 导致错误。
  2. add_subdirectory(lib) 之后被调用

    • 定义 MyLibrary
    • 但是在 src 中已经尝试链接,出错已发生。

解决方案

要确保 src 子目录能够正确链接 lib 中定义的库,您需要先添加 lib 子目录,再添加 src 子目录。这样,lib 中的库在 src 之前被定义,src 中的 CMakeLists.txt 能够正确引用 MyLibrary

修改后的顶层 CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(MyProject)

# 先添加 lib 子目录,确保 MyLibrary 被定义
add_subdirectory(lib)

# 再添加 src 子目录,允许 src 链接到 MyLibrary
add_subdirectory(src)

目录结构示例

假设项目结构如下:

ProjectRoot/
├── CMakeLists.txt
├── src/
│   ├── CMakeLists.txt
│   └── main.cpp
└── lib/
    ├── CMakeLists.txt
    └── MyLibrary.cpp

lib/CMakeLists.txt

# 定义库 MyLibrary
add_library(MyLibrary STATIC MyLibrary.cpp)

# 指定包含目录
target_include_directories(MyLibrary PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)

src/CMakeLists.txt

# 定义可执行文件 MyExecutable
add_executable(MyExecutable main.cpp)

# 链接库 MyLibrary
target_link_libraries(MyExecutable PRIVATE MyLibrary)

总结

  • 调用顺序重要:在顶层 CMakeLists.txt 中,先添加被依赖的子目录(如 lib),再添加依赖它的子目录(如 src)。

  • 目标可见性:使用 PUBLICPRIVATEINTERFACE 关键字在 target_include_directories()target_link_libraries() 中正确设置目标的可见性,确保依赖关系正确传递。

  • 模块化管理:保持子目录中的 CMakeLists.txt 文件独立有助于模块化管理,便于维护和扩展项目。

进一步优化建议

  1. 使用相对路径:确保在不同子目录中引用路径时使用相对于顶层或当前子目录的相对路径,避免路径混乱。

  2. 保持清晰的依赖关系:明确各模块之间的依赖关系,避免循环依赖。例如,lib 不应该依赖于 src,以确保编译顺利进行。

  3. 分离构建目录:推荐使用 外部构建目录(out-of-source build),保持源代码目录的整洁。例如:

    mkdir build
    cd build
    cmake ..
    cmake --build .
    

通过遵循上述原则,您可以确保 CMake 项目结构清晰、依赖关系明确,避免因 add_subdirectory() 顺序问题导致的构建错误。

源文件与头文件在同一个目录的情况下,使用这些源文件构成的library和链接了该library的可执行文件是否需要进行target_include_directirues()以包含这些头文件

在源文件和头文件位于同一个目录的情况下,是否需要使用 target_include_directories() 来包含这些头文件,取决于头文件的使用场景和编译器的查找路径。

情况分析

  1. 库的头文件在同一目录

    • 如果头文件和源文件在同一个目录,并且头文件仅在库的源文件中使用,那么在定义库时不需要额外的 target_include_directories()
  2. 可执行文件需要访问库的头文件

    • 如果可执行文件需要访问库的头文件(例如,在可执行文件的源代码中包含库的头文件),则需要使用 target_include_directories() 将库的头文件目录添加到可执行文件的包含路径中。

示例

假设项目结构如下:

ProjectRoot/
├── CMakeLists.txt
├── src/
│   ├── MyLibrary.cpp
│   ├── MyLibrary.hpp
│   └── main.cpp

顶层 CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(MyProject)

add_subdirectory(src)

src/CMakeLists.txt

# 定义库 MyLibrary
add_library(MyLibrary MyLibrary.cpp)

# 定义可执行文件 MyExecutable
add_executable(MyExecutable main.cpp)

# 链接库 MyLibrary 到 MyExecutable
target_link_libraries(MyExecutable PRIVATE MyLibrary)

# 如果 MyExecutable 需要访问 MyLibrary.hpp,则需要添加包含目录
target_include_directories(MyExecutable PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})

src/MyLibrary.hpp

#pragma once

void myFunction();

src/MyLibrary.cpp

#include "MyLibrary.hpp"
#include <iostream>

void myFunction() {
    std::cout << "Hello from MyLibrary!" << std::endl;
}

src/main.cpp

#include "MyLibrary.hpp"

int main() {
    myFunction();
    return 0;
}

解释

  1. 定义库

    • add_library(MyLibrary MyLibrary.cpp) 定义了一个名为 MyLibrary 的库,包含 MyLibrary.cpp 源文件。
  2. 定义可执行文件

    • add_executable(MyExecutable main.cpp) 定义了一个名为 MyExecutable 的可执行文件,包含 main.cpp 源文件。
  3. 链接库

    • target_link_libraries(MyExecutable PRIVATE MyLibrary)MyLibrary 库链接到 MyExecutable 可执行文件。
  4. 包含目录

    • target_include_directories(MyExecutable PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})src 目录添加到 MyExecutable 的包含路径中,使得 main.cpp 能够找到并包含 MyLibrary.hpp 头文件。

总结

  • 库的头文件在同一目录:如果头文件仅在库的源文件中使用,不需要额外的 target_include_directories()
  • 可执行文件需要访问库的头文件:如果可执行文件需要包含库的头文件,则需要使用 target_include_directories() 将头文件目录添加到可执行文件的包含路径中。

通过这种方式,可以确保编译器在编译可执行文件时能够正确找到并包含库的头文件,从而避免编译错误。

target_link_libraries()的格式是很忙

target_link_libraries() 是 CMake 中用于将库链接到目标(如可执行文件或另一个库)的命令。它的格式和用法如下:

格式

target_link_libraries(<target> [<PRIVATE|PUBLIC|INTERFACE>] <library>...)

参数说明

  • <target>:必需。要链接库的目标名称(如可执行文件或库)。
  • <PRIVATE|PUBLIC|INTERFACE>:可选。指定链接库的可见性和传播方式。
    • PRIVATE:仅对当前目标可见,不传播到依赖该目标的其他目标。
    • PUBLIC:对当前目标和依赖该目标的其他目标都可见。
    • INTERFACE:仅对依赖该目标的其他目标可见,当前目标不可见。
  • <library>:必需。要链接的库或目标,可以是多个。

示例

假设项目结构如下:

ProjectRoot/
├── CMakeLists.txt
├── src/
│   ├── CMakeLists.txt
│   ├── MyLibrary.cpp
│   ├── MyLibrary.hpp
│   └── main.cpp

顶层 CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(MyProject)

add_subdirectory(src)

src/CMakeLists.txt

# 定义库 MyLibrary
add_library(MyLibrary MyLibrary.cpp)

# 定义可执行文件 MyExecutable
add_executable(MyExecutable main.cpp)

# 链接库 MyLibrary 到 MyExecutable
target_link_libraries(MyExecutable PRIVATE MyLibrary)

# 如果 MyExecutable 需要访问 MyLibrary.hpp,则需要添加包含目录
target_include_directories(MyExecutable PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})

解释

  1. 定义库

    • add_library(MyLibrary MyLibrary.cpp) 定义了一个名为 MyLibrary 的库,包含 MyLibrary.cpp 源文件。
  2. 定义可执行文件

    • add_executable(MyExecutable main.cpp) 定义了一个名为 MyExecutable 的可执行文件,包含 main.cpp 源文件。
  3. 链接库

    • target_link_libraries(MyExecutable PRIVATE MyLibrary)MyLibrary 库链接到 MyExecutable 可执行文件。
    • PRIVATE 关键字表示 MyLibrary 仅对 MyExecutable 可见,不传播到依赖 MyExecutable 的其他目标。

可见性关键字

  • PRIVATE

    • 仅对当前目标可见,不传播到依赖该目标的其他目标。
    • 适用于库仅在当前目标内部使用的情况。
  • PUBLIC

    • 对当前目标和依赖该目标的其他目标都可见。
    • 适用于库在当前目标和依赖该目标的其他目标中都需要使用的情况。
  • INTERFACE

    • 仅对依赖该目标的其他目标可见,当前目标不可见。
    • 适用于库仅在依赖该目标的其他目标中使用的情况。

示例:使用 PUBLIC

如果 MyLibrary 的头文件需要在 MyExecutable 和依赖 MyExecutable 的其他目标中都可见,可以使用 PUBLIC

target_link_libraries(MyExecutable PUBLIC MyLibrary)

总结

  • target_link_libraries() 用于将库链接到目标。
  • 格式为 target_link_libraries(<target> [<PRIVATE|PUBLIC|INTERFACE>] <library>...)
  • 可见性关键字 PRIVATEPUBLICINTERFACE 控制库的可见性和传播方式。
  • 根据具体需求选择合适的可见性关键字,确保库的正确链接和使用。

一个源文件被包含为一个库之后,这个源文件#include的头文件也在这个库里吗

当一个源文件被包含为一个库之后,这个源文件 #include 的头文件是否也在这个库里,取决于头文件的具体位置和库的组织方式。通常情况下,头文件和源文件是分开管理的,头文件用于声明接口,源文件用于实现功能。

头文件和库的关系

  1. 头文件的作用

    • 头文件(.h.hpp)包含函数、类、宏和数据结构的声明。
    • 头文件用于定义库的接口,供其他代码使用。
  2. 源文件的作用

    • 源文件(.c.cpp)包含函数和类的实现。
    • 源文件被编译成目标文件(.o.obj),然后打包成库文件(静态库 .lib.a,动态库 .dll.so 等)。

库的组织方式

通常,库的头文件和源文件是分开管理的。头文件提供接口,源文件实现功能。头文件通常放在一个 include 目录中,而源文件放在一个 src 目录中。

示例

假设项目结构如下:

ProjectRoot/
├── CMakeLists.txt
├── include/
│   └── MyLibrary.hpp
└── src/
    ├── CMakeLists.txt
    └── MyLibrary.cpp

include/MyLibrary.hpp

#pragma once

void myFunction();

src/MyLibrary.cpp

#include "MyLibrary.hpp"
#include <iostream>

void myFunction() {
    std::cout << "Hello from MyLibrary!" << std::endl;
}

src/CMakeLists.txt

# 定义库 MyLibrary
add_library(MyLibrary MyLibrary.cpp)

# 指定包含目录
target_include_directories(MyLibrary PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../include)

顶层 CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(MyProject)

add_subdirectory(src)

解释

  1. 头文件和源文件分开管理

    • 头文件 MyLibrary.hpp 放在 include 目录中。
    • 源文件 MyLibrary.cpp 放在 src 目录中。
  2. 定义库

    • add_library(MyLibrary MyLibrary.cpp) 定义了一个名为 MyLibrary 的库,包含 MyLibrary.cpp 源文件。
  3. 指定包含目录

    • target_include_directories(MyLibrary PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../include)include 目录添加到 MyLibrary 的包含路径中,使得编译器能够找到 MyLibrary.hpp 头文件。

总结

  • 当一个源文件被包含为一个库之后,这个源文件 #include 的头文件通常不在库文件中,而是单独管理的。
  • 头文件用于声明接口,源文件用于实现功能。
  • 通过 target_include_directories() 命令,可以将头文件所在的目录添加到库的包含路径中,使得编译器能够找到并包含这些头文件。
  • 这种组织方式有助于模块化管理和代码复用,确保头文件和源文件的清晰分离。

标签:2024.12,CMakeLists,include,CMake,AI,add,MyLibrary,txt,目录
From: https://www.cnblogs.com/l25428455/p/18592571

相关文章

  • 腾讯终于出手了,发布的AI 视频生成模型!完全免费开源,生成质量高!HunyuanVideo AI文生视频
    腾讯发布超强AI视频生成模型!完全免费开源,生成质量极高!HunyuanVideo模型,一、下载链接1、邀请你一起来体验腾讯元宝的应用【AI视频】,让每个创意瞬间生动。点击以下链接:【抢先体验手机APP版本】:https://yuanbao.tencent.com/bot/app/share/chat/VR8O83A/videoTrafficDiv......
  • CMakeTutorial_Step1_CMakeLists.txt
    #TODO1:SettheminimumrequiredversionofCMaketobe3.10cmake_minimum_required(VERSION3.10)#TODO2:CreateaprojectnamedTutorialproject(TutorialVERSION1.0)#TODO7:Settheprojectversionnumberas1.0intheaboveprojectcommand#Wh......
  • 2025年AI游戏行业的14大趋势:引领未来娱乐的新纪元
    随着技术的飞速发展,2025年的AI游戏行业正站在一个转折点上。这一年不仅标志着AI3D、代理和游戏的“元年”,还预示着一系列深刻影响游戏设计、开发以及用户体验的趋势。以下是经过优化整理的2025年AI游戏行业的14大趋势,旨在为读者提供深入洞察。一、新一代皮克斯的崛起利用AI......
  • 从技术概念到场景落地 联想百应撬动AI长尾
    一面是科技企业,不断宣传AI的价值和低门槛:零代码,零技术门槛,任何人都能用AI,AI将重构一切。一面是茫然的数以万计的中小企业:AI很诱惑,但我到底该怎么搭上AI的大船呢?显然,在AI技术与中小企业的价值实现之间,需要一辆便捷的“直通车”。徘徊在AI门外的长尾从2024年起,我们看到AI的关注......
  • 【OpenAI 】从获取OpenAI API Key到实现数据分类Demo的完整教程(超详细)!
    文章目录一、初识OpenAIAPI1.1获取API-Key(两种方案)1.2安装OpenAI库二、Python调用OpenAIAPI的基础设置2.1设置API密钥和BaseURL2.2参数详解三、构建一个简单的聊天应用3.1创建聊天请求3.2参数详解3.3处理响应四、完整代码示例1.Python示例代码(基础)2.Python......
  • AI工具推荐——Cherry Studio
    CherryStudio介绍CherryStudio是一款支持多模型服务的Windows/macOSGPT客户端。它的主要特点如下:多样化的大型语言模型提供商支持☁️主要的大型语言模型云服务:OpenAI、Gemini、Anthropic等......
  • 详细介绍 NVIDIA GeForce RTX 系列,各显卡配置参数(长期更新 - 2024.12)
    NVIDIAGeForceRTX系列是NVIDIA面向消费级市场的高性能GPU产品线,注重提供高性能的图形处理能力和游戏特性。主要面向游戏玩家和普通用户,同时也被广泛用于深度学习推理和训练等计算密集型任务。主要GPU产品有:50Series、40Series、30Series、20Series、10Seri......
  • 电动车Ai头盔穿戴识别系统方案
    电动车Ai头盔穿戴识别系统方案利用高清摄像头捕捉电动车骑行者的画面,电动车Ai头盔穿戴识别系统方案实现对头盔佩戴情况的实时监测。当系统检测到未佩戴头盔的骑行者时,会立即启动智能提醒功能。这包括发出声音警报,提醒骑行者注意安全,及时佩戴头盔。同时,系统还会通过视觉警报,如LED显......
  • c++ 中异步闲谈:async,await,future, promise的使用和注意事项
    《C++异步妙韵》C++异步展新章,async开启并行航。函数异步去闯荡,不必同步苦守望。future犹如希望光,异步结果有处藏。等待之时心不慌,获取成果见真章。promise把诺来担当,结果设定不迷茫。与future紧捆绑,异步流程稳起航。await恰似静候郎,future前面来......
  • 探索 LangChain 0.2.0 版本中的最新改变:如何适应和转型
    探索LangChain0.2.0版本中的最新改变:如何适应和转型引言在快速发展的编程世界中,库和框架的更新是不可避免的。这篇文章将帮助您理解和适应LangChain0.2.0版本带来的重要变更。本次更新注重使LangChain变得更加集成不可知,这意味着用户需要明确指定使用的模型和工具......