catkin cmake官方教程解读以及资料补充

这里写目录标题

  • 报错
  • cmakei下载
  • cmake 官方教程
  • 教程1
    • step1
      • 最低版本
    • 报错
    • 报错2 vscode 路径没有配置好
    • setting.json
      • 通过该方式打开的似乎是一个全局的文件,可以为本工作文件夹下设置一个本地的吗
    • 报错3
    • 配置cmake工具链
    • 准确的流程
    • 报错4 cpp中main函数返回值
    • 问题结果
  • 官方教程2 specifying the c++ standard
    • cmakelists
    • atof stod
    • sqrt
    • cstdlib
  • exercise 3 Adding a Version Number and Configured Header File
    • 编辑的文件
      • 总结
    • 解释
    • 解释2
    • 解释3
  • step2 adding a library
    • exercise 1 creating a library
    • PROJECT_BINARY_DIR和PROJECT_SOURCE_DIR都指向当前工程目录吗
    • add library
    • add subdirectory
      • 指定路径
    • .so .a .lib
  • step2 exercise2 adding an option
    • -D option -d 小d是调试工具选项,输出详细调试信息
    • target source
  • cmake -
  • compiler 和kit
    • kit
    • 两者是并行的嘛
    • kit默认配置好的嘛,我都没配置就直接用了
  • gcc和mingw
  • Linux系统介绍
    • 命令

报错

target include libraries 应当在add_executable(cmake cmake.cpp)后面

cmakei下载

https://cmake.org/download/

我下载了 zip版本的,直接解压缩就行。

解压缩的步骤如下:

  1. 首先,你需要将下载好的 ZIP 压缩包解压缩到你想要存放 CMake 可执行文件和相关资源的目录中。这个目录可以任意选定,只要有足够的空间存放 CMake 文件即可。

  2. 解压后,你可以在目录中看到一个名为 “cmake-x.x.x-win64-x64” 的文件夹(其中“x.x.x”代表 CMake 的版本号),打开该文件夹即可看到 CMake 的可执行文件和其他必需的资源文件,如下所示:

bin/
doc/
share/
LICENSE.txt
README.html
  1. 如果你希望在命令行中使用 CMake 命令,那么你需要将解压缩后的 “bin” 目录添加到系统环境变量的 Path 中。具体操作方法可以参考以下步骤:

    • 右键点击桌面左下角的“开始”按钮,选择“系统”。

    • 在系统设置面板上,选择“关于”选项卡,并记录下自己的电脑名称和系统版本号。

    • 在搜索框中输入“环境变量”并选择“编辑系统环境变量”命令。

    • 在弹出的“系统属性”对话框中,选择“高级”选项卡,然后点击下方的“环境变量”按钮。

    • 在环境变量对话框中,找到“Path”变量并双击打开编辑对话框。

    • 点击“新建”按钮,然后输入刚才解压缩出来的 CMake 可执行文件所在的完整路径,例如:C:\Program Files\cmake-x.x.x-win64-x64\bin

    • 点击“确定”按钮,保存设置并关闭所有对话框。

至此,你已经成功地将 CMake 安装到了你的 Windows 操作系统中,并且可以在命令行中使用 CMake 命令进行项目构建管理等操作。

cmake 官方教程

https://cmake.org/documentation/

教程1

step1

创建一个cmakelists.txt文件,最基本的,需要三个命令

add_executable()

cmake_minimum_required(VERSION 2.4)

project()

完善后直接执行以下指令

mkdir Step1_build
cd Step1_build
cmake ../Step1  到上一级目录的 step1目录下查找cmakelists文件,然后使用 cmake 命令来执行 CMakeLists.txt 中的构建脚本,并将生成的构建系统文件(如 Makefile 或 Ninja 构建文件)保存到当前目录中。执行完这个指令后,可以使用 make 或 ninja 命令来对代码进行编译和构建。具体的构建流程和命令可能会因项目而异,但一般情况下,上述步骤就可以让我们成功地使用 CMake 来管理和构建项目了。

cmake --build . 在当前目录下编译
`cmake --build .` 是一个在命令行中使用 CMake 构建系统进行构建的指令。它会自动识别当前目录下的构建系统文件(如 Makefile 或 Ninja 构建文件),并执行相应的构建过程来生成可执行文件或库文件等。

具体来说,`.` 表示当前目录,也就是 CMake 构建脚本所在的目录。执行 `cmake --build .` 后,CMake 会查找当前目录下的构建系统文件,并使用默认的构建方式,例如 Makefile 时就会使用 `make` 命令进行构建,Ninja 时则会使用 `ninja` 命令进行构建。

需要注意的是,执行 `cmake --build .` 前,需要先使用 `cmake` 命令来生成构建系统文件。如果没有在当前目录下生成构建系统文件,则会出现构建失败的情况。

此外,在构建过程中,还可以通过添加一些参数来指定编译选项、目标类型、生成路径等信息。例如,可以使用 `-j` 参数来指定构建线程数,同时也可以使用 `--target` 参数来指定要构建的目标类型,以及使用 `-DCMAKE_BUILD_TYPE` 参数来指定构建类型等。

总之,`cmake --build .` 可以帮助我们自动执行构建过程,而不需要手动执行 Makefile 或其他构建系统文件。但是,在使用这个命令前,需要确保当前目录下已经存在构建系统文件,并且可以进行正确的编译和构建。

`--build` 是 CMake 命令行工具中的一个参数,用于在构建系统中进行构建和生成输出文件。

这个参数可以让 CMake 自动识别当前目录下的构建系统文件(如 Makefile 或 Ninja 构建文件),并执行相应的构建操作。

当使用 `cmake` 命令创建构建系统文件后,我们可以执行 `cmake --build` 命令来直接进行编译、链接和打包等操作。例如,可以使用以下命令来进行构建:

cmake --build . 在当前目录下编译 链接 操作 相当于mingw


上述命令中的 `.` 表示当前目录,CMake 会自动根据当前目录中的 CMakeLists.txt 文件生成对应的构建系统文件,然后执行默认的构建方式(如 Makefile 时就会执行 make 命令)。

除了指定目录外,`--build` 还支持其他一些可选参数,例如:

- `--target`: 指定要构建的目标名称。
- `--config`: 指定要构建的配置类型(如 Debug 或 Release)。
- `--clean-first`: 在构建之前首先清除输出目录。
- `-j`: 指定多线程构建时使用的线程数等。

总之,`--build` 参数可以让我们更便捷地执行构建操作,并且可以快速的在命令行中生成可执行文件或库文件等输出结果。




最低版本

这里的 <min> 指的是在 cmake_minimum_required() 命令中指定的最低 CMake 版本号。当 <min> 的值大于 2.4 时,cmake_minimum_required() 命令会隐式地调用 cmake_policy(VERSION <min>[...<max>]) 命令,以根据指定的版本范围设置 CMake 策略(policies)。

反之,当 <min> 的值小于或等于 2.4 时,cmake_minimum_required() 命令会隐式地调用 cmake_policy(VERSION 2.4[...<max>]) 命令,以启用与 CMake 2.4 及以下版本的兼容性特性。

因此,这段话的意思是:当在 cmake_minimum_required() 命令中指定的最低 CMake 版本号 <min> 大于 2.4 时,cmake_minimum_required() 命令会隐式地调用 cmake_policy(VERSION <min>[...<max>]) 命令;而当 <min> 小于或等于 2.4 时,cmake_minimum_required() 命令会隐式地调用 cmake_policy(VERSION 2.4[...<max>]) 命令。

最低为2.4, 如果低于2.4,比方说你给了个2.3,他会隐式的调用2.4.

报错

具体为cmake configuration报错

"D:\Microsoft VS Code\mingw64\bin\gcc.exe" 命令未找到
mingw32-make 命令未找到
首先,关于第一个问题,它表示你的系统缺少 GCC 编译器或者它的路径未正确添加到 PATH 环境变量中。你需要确认你的系统上已安装了 GCC 编译器,并且它的路径被正确地添加到 PATH 环境变量中。你可以在终端中运行 gcc --version 命令来验证 GCC 是否正确安装并设置好了环境变量。

其次,关于第二个问题,它表示你的系统缺少 mingw32-make 工具或者它的路径未正确添加到 PATH 环境变量中。你需要确认你的系统上已经安装了 MinGW 并且它的路径被正确地添加到 PATH 环境变量中。你可以在终端中运行 mingw32-make --version 命令来验证 MingGW 是否正确安装并设置好了环境变量

两个都是存在的

系统已经正确安装了 GCC 编译器和 MinGW 并且它们的路径也被正确地添加到 PATH 环境变量中。因此出现报错的原因就不是因为缺少这两个组件。

你可以尝试在 VS Code 中打开终端窗口,进入到 CMakeLists.txt 所在的目录下,然后执行以下命令来进行编译:


cmake -G "MinGW Makefiles" .    
mingw32-make


第一条命令 cmake -G "MinGW Makefiles" . 是用来生成 Makefile 文件,并指定了使用 MinGW 生成器,同时“.”表示当前目录,即 CMakeLists.txt 所在的目录。

第二条命令 mingw32-make 是用来执行编译操作的,它会根据 Makefile 文件中的指令进行编译。需要注意的是,在使用 mingw32-make 命令之前,你需要确保当前工作目录已经是包含 Makefile 文件的目录。因此,. 表示当前目录,也就是 Makefile 文件所在的目录。

总而言之,这两条命令的组合就是先通过 CMake 生成 Makefile 文件,然后再使用 mingw32-make 命令进行编译。


报错2 vscode 路径没有配置好

到这里再次 cmake configuration

[proc] Executing command: "D:\Microsoft VS Code\mingw64\bin\gcc.exe" -v
[proc] The command: "D:\Microsoft VS Code\mingw64\bin\gcc.exe" -v failed with error: Error: spawn D:\Microsoft VS Code\mingw64\bin\gcc.exe ENOENT
[proc] The command: mingw32-make --version failed with error: Error: spawn mingw32-make ENOENT
[main] Unable to determine what CMake generator to use. Please install or configure a preferred generator, or update settings.json, your Kit configuration or PATH variable. Error: No usable generator found.
[main] Configuring project: cmake 

vscode没有配置好
根据你提供的信息,报错信息显示 CMake 在执行命令行时无法找到对应的程序,可能是因为 GCC 或者 MinGW 没有正确安装或者其路径没有被正确地添加到环境变量中。具体来说,ENOENT 错误代码表示系统找不到指定文件路径的程序。

你可以尝试按照以下步骤进行排查:

  1. 确认 GCC 和 MinGW 已经成功安装在你的电脑上,且安装路径已经添加到 PATH 环境变量中。可以在终端中分别执行 gcc --versionmingw32-make --version 命令来检查 GCC 和 MinGW 的版本信息。

  2. 如果你使用的是 VS Code,可以在 VS Code 的“设置”中搜索“Path”关键字,然后在“Terminal > Integrated > Env: Path”选项中添加 GCC 和 MinGW 的安装路径。这样做可以确保终端窗口能够正确识别到 GCC 和 MinGW 的安装路径。

  3. 如果你使用的是其他 IDE 或编辑器,可以查看对应软件的文档,了解如何添加环境变量或者指定 GCC 和 MinGW 的路径。

如果上述方法仍然不能解决问题,可以重新安装 GCC 和 MinGW 并确保其正确添加到 PATH 环境变量中。

Unable to determine what CMake generator to use. Please install or configure a preferred generator, or update settings.json, your Kit configuration or PATH variable. 是不是跟这个有关,我需要配置相关文件

是的,这个错误提示与 CMake 的生成器配置有关。通过这个错误提示,我们可以得知 CMake 无法自动识别所使用的生成器,需要手动进行配置。

你可以尝试更改 CMakeLists.txt 文件中的 project() 命令后面所跟随的参数,以指定所需要的 CMake 生成器。例如,以下命令将指定使用 MinGW 作为代码编译器:

project(MyProject CXX)
set(CMAKE_C_COMPILER "D:/mingw64/bin/gcc.exe")
set(CMAKE_CXX_COMPILER "D:/mingw64/bin/g++.exe")

其中,CMAKE_C_COMPILERCMAKE_CXX_COMPILER 是用来指定 GCC 和 G++ 编译器路径的变量,你需要将其指定为你所使用的编译器的实际路径。在这个示例中,我们将编译器安装在 D:/mingw64/bin/ 目录下,因此需要指定相应的路径。

另外,还可以通过修改 VS Code 的 settings.json 文件来指定所使用的 CMake 生成器。你可以在该文件中添加以下设置:

{
    "cmake.generator": "MinGW Makefiles"
}

这里,“MinGW Makefiles”表示使用 MinGW 作为 CMake 生成器。你也可以根据实际情况选择其他合适的生成器类型。

setting.json

另外,还可以通过修改 VS Code 的 settings.json 文件来指定所使用的 CMake 生成器。如何调出setting.json,ctrl+shift+p吗

是的,您可以使用快捷键 Ctrl + Shift + P 来打开 VS Code 的命令面板,然后输入 “Open Settings (JSON)” 或者 “打开设置(JSON文件)” 来打开 settings.json 文件。

在打开的 JSON 配置文件中添加以下内容,就可以指定 CMake 使用 MinGW 作为生成器:

{
    "cmake.generator": "MinGW Makefiles"
}

保存文件后,关闭并重新打开 VS Code,CMake 就会自动识别并使用 MinGW 作为默认的生成器来构建项目。请注意,如果您在 CMakeLists.txt 中明确指定了其他的生成器,那么这个设置将被覆盖。

通过该方式打开的似乎是一个全局的文件,可以为本工作文件夹下设置一个本地的吗

是的,您可以设置一个本地的 Workspace 设置来覆盖全局设置,这样就只会影响当前工作区域中的所有文件。以下是具体步骤:

  1. 在 VS Code 中打开您的工作文件夹,并右键单击左侧的资源管理器窗口中的 .vscode 文件夹。

  2. 在弹出的上下文菜单中,选择 “新建文件”(New File) 选项,创建一个名为 settings.json 的新文件。

  3. 在新文件中添加以下内容:

{
    "cmake.generator": "MinGW Makefiles"
}
  1. 保存文件后,关闭并重新打开 VS Code。

现在,VS Code 将会使用您在本地设置文件中指定的 CMake 生成器。如果您想要清除本地设置并恢复全局设置,只需要删除 .vscode 文件夹下的 settings.json 文件即可。

报错3

你上面让我cmake -G “MinGW Makefiles” . 相当于避开了这个问题吗,他是怎么做到的

是的,使用 cmake -G "MinGW Makefiles" . 命令可以直接指定使用 MinGW 作为 CMake 的生成器,从而避免了无法确定生成器的问题。

这个命令通过 -G 参数指定了生成器类型,后面的参数 . 表示当前目录。执行这个命令之后,CMake 就会自动在当前目录下生成适合 MinGW 编译器的 Makefile 文件,并以此来进行代码的编译和构建。

相比于手动修改 CMakeLists.txt 文件或者 VS Code 的 settings.json 文件来设置生成器,使用命令行指定生成器可以更加简单快捷,不需要修改配置文件。只要保证 MinGW 的安装路径已经添加到 PATH 环境变量中,就可以直接在终端中运行上述命令,完成编译工作。

配置cmake工具链

The kit “GCC 8.1.0 x86_64-w64-mingw32” references a non-existent compiler binary [D:\Microsoft VS Code\mingw64\bin\gcc.exe]. What would you like to do?这什么意思

这意味着您使用的 CMake 工具链中指定了一个不存在的编译器二进制文件 “D:\Microsoft VS Code\mingw64\bin\gcc.exe”。

您需要检查该路径下是否存在 “gcc.exe” 可执行文件,如果没有,可能是由于 MinGW 工具链未正确安装或配置所致。请尝试重新安装 MinGW 工具链,并确保将其添加到 PATH 环境变量中。

如果 “gcc.exe” 文件存在,但仍然无法被找到,请检查 CMake 工具链文件是否正确配置。您可以在 CMake 插件的设置页面中检查和修改 CMake 工具链配置。

如果还有其他问题,请提供更多信息以便我能够帮助您解决问题。

配置 CMake 工具链的方法如下:

  1. 打开 VS Code 中的 CMake 工具链设置页面。您可以通过侧边栏中的 “CMake” 图标打开,或者在 VS Code 菜单中选择 “File” -> “Preferences” -> “Settings”,然后搜索 “cmake.toolchain”。

  2. 找到 “cmake.toolchain” 设置项,并点击 “Edit in settings.json” 按钮进行编辑。

  3. 在 “cmake.toolchain” 的值域中添加工具链文件的路径和名称,例如:

"cmake.toolchain": "/path/to/mytoolchain.cmake"
  1. 打开指定的工具链文件(如上例中的 mytoolchain.cmake),并按照需要配置编译器和相关工具的路径、编译选项、链接选项等信息。例如:
SET(CMAKE_C_COMPILER /path/to/gcc)
SET(CMAKE_CXX_COMPILER /path/to/g++)
SET(CMAKE_AR /path/to/ar)
SET(CMAKE_RANLIB /path/to/ranlib)

SET(CMAKE_C_FLAGS "-Wall -O2")
SET(CMAKE_CXX_FLAGS "-Wall -O2")

SET(CMAKE_EXE_LINKER_FLAGS "-L/path/to/libs -lmylib")
  1. 配置完毕后,保存工具链文件并重新打开 CMake 插件的界面,让插件重新扫描项目并尝试使用指定的生成器和编译器来构建项目。

如果您遇到任何问题,请告诉我。
如果您在 VS Code 的设置中没有找到 “cmake.toolchain” 配置项,可能是因为您当前没有打开 CMake 项目或者缺少必要的扩展插件。

请确保您已经安装了 CMake Tools 扩展插件,该插件提供了 CMake 项目的关键功能,并且支持用户配置 CMake 工具链。

如果您已经安装了 CMake Tools 插件,但仍然无法找到 “cmake.toolchain” 配置项,请尝试使用以下方法进行配置:

  1. 在 CMake 项目文件夹下创建一个名为 “toolchain.cmake” 的文件,用于指定特定的编译器、链接器和其他构建工具的路径、选项等信息。例如:
SET(CMAKE_C_COMPILER /path/to/gcc)
SET(CMAKE_CXX_COMPILER /path/to/g++)
SET(CMAKE_AR /path/to/ar)
SET(CMAKE_RANLIB /path/to/ranlib)

SET(CMAKE_C_FLAGS "-Wall -O2")
SET(CMAKE_CXX_FLAGS "-Wall -O2")

SET(CMAKE_EXE_LINKER_FLAGS "-L/path/to/libs -lmylib")
  1. 在 VS Code 中打开 CMake 项目文件夹,然后在状态栏中单击 “Configure” 按钮。如果状态栏中没有 “Configure” 按钮,则可以通过菜单 “View” -> “Command Palette” -> “CMake: Configure” 来达到同样的效果。

  2. 在弹出的 “Configure” 对话框中,选择 “Advanced” 选项卡,并在 “CMake toolchain file” 选项中指定工具链文件的路径,例如:

-D CMAKE_TOOLCHAIN_FILE=/path/to/toolchain.cmake
  1. 点击 “Configure” 按钮,进行 CMake 配置。

  2. 在配置完成后,您可以在状态栏中单击 “Build” 按钮开始构建项目。如果状态栏中没有 “Build” 按钮,则可以通过菜单 “View” -> “Command Palette” -> “CMake: Build” 来达到同样的效果。

如果您仍然遇到问题,请提供更多详细信息以便我能够更好地帮助您解决问题。

准确的流程

在build文件夹下


PS F:\cmake\steo1_build> cmake -G "MinGW Makefiles" ..

PS F:\cmake\steo1_build> mingw32-make
[ 50%] Building CXX object CMakeFiles/cmake.dir/cmake.cpp.obj
[100%] Linking CXX executable cmake.exe
[100%] Built target cmake
PS F:\cmake\steo1_build> cd ..
PS F:\cmake> ./cmake
1000

报错4 cpp中main函数返回值

cpp中main函数必要要有一个返回值
是的,C++ 中程序的入口函数 main() 必须要有一个 int 类型的返回值。这个返回值指示程序的运行状态,可以用来告诉操作系统程序是否正常结束。

在 C++ 标准中规定,main() 函数的返回类型必须是 int,不能是其他类型。一般情况下,如果程序正常运行并且没有出现错误,我们可以将返回值设置为 0,表示程序正常结束。如果程序出现了某些错误,可以返回其他非零的整数值,以便向操作系统表明程序发生了错误并且退出了。

所以在您的代码中,如果 main() 函数没有返回任何值,或者返回了一个非整数值,都会导致编译错误。要解决这个问题,只需要将 main() 函数的返回类型改为 int,并在函数末尾添加 return 0; 即可。

问题结果

一开始进去 会提示你来自cmake tool的配置cmake 工程

这个时候点击配置 就会报错,因为他默认会有一个错误的路径,他会到这个错误的路径下查找什么 gcc,它上面也告诉你了,
The kit “GCC 8.1.0 x86_64-w64-mingw32” references a non-existent compiler binary [D:\Microsoft VS Code\mingw64\bin\gcc.exe]. What would you like to do?

这个时候点击 remove去除,再次配置就成功了,他会默认生成build文件夹。
这个时候 单纯的cmake什么的命令就没问题了

官方教程2 specifying the c++ standard

cmake有一些特殊的变量,都各自有意义,通常以CMAKE_ 开头,这里介绍两个

CMAKE_CXX_STANDARD

CMAKE_CXX_STANDARD_REQUIRED

set()

需要编辑两个文件:

CMakeLists.txt

tutorial.cxx



在cpp文件中添加了c++11所需要的特征指令
  // TODO 4: Replace atof(argv[1]) with std::stod(argv[1])
  const double inputValue = atof(argv[1]);
#include <cstdlib> // TODO 5: Remove this line


# TODO 6: Set the variable CMAKE_CXX_STANDARD to 11
#         and the variable CMAKE_CXX_STANDARD_REQUIRED to True
  // TODO 6: Replace sqrt with mathfunctions::sqrt

  // calculate square root
  const double outputValue = sqrt(inputValue);



cmakelists

确保 cmake cxx standard声明在 add executable() 前面

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

atof stod

atof()std::stod() 都是将字符串转换成浮点数的函数。但它们有以下不同:

  1. 标准库函数 std::stod() 是 C++11 引入的,而 atof() 则是 C 标准库里的函数,它们所属的语言和标准不同。

  2. atof() 只能将字符串转换成 double 类型的浮点数,而 std::stod() 可以将字符串转换成任意精度的浮点数类型(如 floatdoublelong double 等)。

  3. atof()std::stod() 对于不合法的输入字符串的处理方式不同。atof() 无法检测输入字符串是否合法,如果输入字符串不是有效的浮点数格式,则会返回一个未定义值。而 std::stod() 会抛出 std::invalid_argument 异常或 std::out_of_range 异常,以指示输入字符串无效。

  4. std::stod() 支持多种进制的浮点数转换,可以指定参数 base 来指定转换进制。而 atof() 仅支持十进制的浮点数转换。

  5. std::stod() 能够实现更好的精度控制,例如可以设置输出精度和舍入模式等。而 atof() 无法进行更细致的精度控制。

总之,在 C++11 及以上版本的项目中,推荐使用 std::stod() 函数来进行浮点数字符串转换操作,因为它更加安全、灵活和易于维护。如果您在 C 语言项目中使用,则只能使用 atof() 或者自行实现一个浮点数字符串转换函数。

sqrt

sqrt() 函数是标准 C++ 库定义的一个函数,用于计算一个 double 类型数的平方根。而 mathfunctions::sqrt() 是一个自定义的命名空间 mathfunctions 中定义的函数,也是用于计算 double 类型数的平方根。

两者在功能上并没有本质上的差别,都可以进行浮点数的开根运算。但是 mathfunctions::sqrt() 是由用户自定义的函数,可以自行实现和修改,比如可以添加更多的参数检查、异常处理等功能。而标准库函数 sqrt() 则是由 C++ 标准委员会制定的规范,具有较高的通用性和可移植性。

此外,如果您使用了命名空间 using namespace std;,则可以直接调用标准库函数 sqrt(),而省略前缀 std::。但是如果您的代码中使用了其他自定义的函数或变量,可能会出现名字冲突的问题,建议使用 namespace 前缀来明确指定函数的来源。

cstdlib

cstdlib 是 C++ 标准库中的一个头文件,其中定义了一些与标准 C 库函数相关的常量、类型、函数等。该头文件在 C 和 C++ 中都可以使用。

其中包含的一些常用函数有:

  • std::atoi():将字符串转换为整型数,其功能与 C 标准库的 atoi() 函数相同。
  • std::atof():将字符串转换为浮点型数,其功能与 C 标准库的 atof() 函数相同。
  • std::rand():生成一个随机数,其功能与 C 标准库的 rand() 函数相同。
  • std::exit():结束程序,并返回一个指定的退出码,其功能与 C 标准库的 exit() 函数相同。
  • std::system():调用系统命令,其功能与 C 标准库的 system() 函数相同。

此外,cstdlib 还定义了一些常量,例如 EXIT_SUCCESSEXIT_FAILURE 表示程序正常执行和执行失败时的退出码。

总之,cstdlib 头文件提供了一些实用的 C 标准库函数和常量,方便我们在 C++ 程序中进行系统调用、字符串处理、数字转换等操作。

exercise 3 Adding a Version Number and Configured Header File

在你的源代码文件中有一个你在cmakelists里定义的变量,该做法优势会很有用。

一个做法是使用一个配置的 header 文件。 创建一个输入文件,里面包含多个用于替换的变量。
这些变量有特别的语法,看起来像 @VAR@
使用 configure_file()命令来将输入文件拷贝至一个给定的输出文件,并替换这些变量在cmakelist文件里的值
虽然我们可以直接在源代码中编辑版本,但使用这个特性更加推荐,因为它可以创建一个单一的真相源,避免重复。

编辑的文件

CMakeLists.txt

tutorial.cxx


<PROJECT-NAME>_VERSION_MAJOR

<PROJECT-NAME>_VERSION_MINOR

configure_file()

target_include_directories()



创建1个头文件 xxx.h 定义了版本数字,他会接收由configure file传递过来的变量

project(Tutorial VERSION 1.0)   CMake defines Tutorial_VERSION_MAJOR and Tutorial_VERSION_MINOR behind the scenes.
configure_file(TutorialConfig.h.in TutorialConfig.h)  通过· 来分隔数字

target_include_directories(Tutorial PUBLIC      
                           "${PROJECT_BINARY_DIR}"
                           ) 
  在示例中,Tutorial 是指示要创建的目标名称,PUBLIC 则指示这个搜索路径将作为其接口的一部分公开,即在编译目标时需要包括此目录。  public是默认的可以省略
创建 头文件

引入头文件
#include "TutorialConfig.h"
增加代码直接使用变量
 if (argc < 2) {
    // report version
    std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
              << Tutorial_VERSION_MINOR << std::endl;
    std::cout << "Usage: " << argv[0] << " number" << std::endl;
    return 1;
  }

创建一个 xxx.h.in作为输入文件,输出文件会根据你的路径创建出
输出文件里 @ @中的变量被替代了

// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@

总结

相当于设置变量 让cmakelist里的变量传入 代码文件

解释

是的,CMake 在定义 project(Tutorial VERSION 1.0) 的同时,会根据版本号自动定义两个变量 Tutorial_VERSION_MAJORTutorial_VERSION_MINOR,其值分别为版本号中的主版本号和次版本号。

例如,如果设置 project(Tutorial VERSION 1.2.3),则会自动生成下面两个变量:

set(Tutorial_VERSION_MAJOR 1)
set(Tutorial_VERSION_MINOR 2)

这些自动生成的变量可以在 CMakeLists.txt 文件中使用,比如生成一个带有版本号的头文件。通常做法是使用 configure_file() 函数,将一个包含 ${Tutorial_VERSION_MAJOR}${Tutorial_VERSION_MINOR} 的头文件模板复制到构建目录,并将其中的变量替换为实际的版本号,然后将生成的头文件添加到源代码中。

例如,假设我们有一个包含版本号的头文件模板 version.h.in:

// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@

然后可以在 CMakeLists.txt 文件中添加以下语句:

configure_file(version.h.in ${PROJECT_BINARY_DIR}/version.h)
include_directories(${PROJECT_BINARY_DIR})

这段代码会将 version.h.in 复制到构建目录中的 version.h,并将其中的变量替换为实际的版本号。然后通过将 ${PROJECT_BINARY_DIR} 添加到 include_directories() 中,可以确保头文件能够被正确地包含在项目中。

是的,您说得对,我犯了一个错误。project(Tutorial VERSION 1.2.3) 定义的不仅仅是一个版本号,而是一个包含三个数字的完整版本号,其中 1 是主版本号,2 是次版本号,3 是修订号。

CMake 在定义 project() 的同时,自动为项目定义了以下变量:

  • ProjectName_VERSION:等于指定的版本号,即 “1.2.3”。
  • ProjectName_VERSION_MAJOR:等于指定的主版本号,即 “1”。
  • ProjectName_VERSION_MINOR:等于指定的次版本号,即 “2”。
  • ProjectName_VERSION_PATCH:等于指定的修订号,即 “3”。
  • ProjectName_VERSION_TWEAK:如果指定了第四个数字,则等于该数字,否则没有定义(也就是说,该变量只有当版本号中包含四个数字时才会被定义)。

需要注意的是,这些变量的名称始终是全部大写的,并且是自动生成的,因此在 CMakeLists.txt 文件中无需手动定义它们。我们可以在项目中使用这些变量来包含版本信息、生成带版本号的文件名等。

示例:

# 指定项目名称和版本号
project(Tutorial VERSION 1.2.3)

# 生成带版本号的可执行文件
add_executable(MyApp_${PROJECT_NAME}_${PROJECT_VERSION} main.cpp)

# 输出项目版本信息
message("MyApp version: ${PROJECT_VERSION}")

解释2

在 CMake 中,可以使用 configure_file() 命令将一个输入文件中的内容复制到另一个输出文件中,并且可以根据变量的值修改输入文件中的内容。在 configure_file() 命令中,@ 符号和 ${} 语法用于引用 CMake 变量。而 .in 则是作为输入文件的后缀名称。

configure_file(version.h.in ${PROJECT_BINARY_DIR}/version.h) 为例,version.h.in 是一个输入文件,其中包含了一些占位符,例如:

#define PROJECT_VERSION "@PROJECT_VERSION@"

在运行 configure_file() 命令时,CMake 会读取 version.h.in 文件的内容,并将 @PROJECT_VERSION@ 替换为实际的项目版本号。然后,CMake 会将修改后的内容写入 ${PROJECT_BINARY_DIR}/version.h 文件中。

因此,version.h.in.in 后缀只是为了表示这是一个输入文件,以便 CMake 正确地处理它。在实际使用中,我们可以将输入文件命名为任何字符串,只要在调用 configure_file() 命令时正确指定即可。例如,您也可以将 version.h.in 改为 version_template.h,并使用以下命令进行配置:

configure_file(version_template.h ${PROJECT_BINARY_DIR}/version.h)

这样也是可以的。

是的,在运行 configure_file() 命令时,CMake 会自动创建输出文件 ${PROJECT_BINARY_DIR}/version.h 并将修改后的内容写入其中。${PROJECT_BINARY_DIR} 是 CMake 内置的变量,表示构建目录的绝对路径。

需要注意的是,如果输出文件所在的目录不存在,则 CMake 会自动创建该目录。如果您希望输出文件的目录与输入文件的目录结构相同,则可以在命令中使用 ${CMAKE_CURRENT_SOURCE_DIR} 变量,该变量表示当前正在处理的 CMakeLists.txt 所在的目录。例如:

configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h)

这样,CMake 将根据 version.h.in 文件在 ${CMAKE_CURRENT_BINARY_DIR} 目录下创建一个名为 version.h 的文件,并将修改后的内容写入其中。

总之,在运行 configure_file() 命令时,CMake 会自动创建输出文件并写入其中,不需要用户手动创建。

解释3

include_directories() 命令用于向 CMake 项目中添加包含文件的搜索路径。${PROJECT_BINARY_DIR} 是 CMake 内置的变量,表示构建目录的绝对路径。因此,这个命令可以将 ${PROJECT_BINARY_DIR} 目录添加到包含文件的搜索路径中,以便在源代码中引用生成的 version.h 文件。

具体来说,如果在 CMakeLists.txt 文件中添加了以下代码:

project(MyProject VERSION 1.0)

configure_file(version.h.in ${PROJECT_BINARY_DIR}/version.h)
include_directories(${PROJECT_BINARY_DIR})

则 CMake 将处理 version.h.in 文件并生成 ${PROJECT_BINARY_DIR}/version.h 文件,并将 ${PROJECT_BINARY_DIR} 目录添加到包含文件的搜索路径中。在源代码中,可以使用 #include "version.h" 来引用 version.h 文件中定义的宏 PROJECT_VERSION

例如,在一个名为 main.c 的源代码文件中,可以编写以下代码来使用 PROJECT_VERSION 宏:

#include <stdio.h>
#include "version.h"

int main()
{
    printf("Project version: %s\n", PROJECT_VERSION);
    return 0;
}

这样,CMake 将自动在构建期间为该项目生成版本号,并将其定义为 PROJECT_VERSION 宏,供源代码中的其他部分使用。然后,当您构建项目并运行生成的可执行文件时,它将输出您在 CMakeLists.txt 文件中指定的项目版本号。

因此,include_directories(${PROJECT_BINARY_DIR}) 命令实际上将 ${PROJECT_BINARY_DIR} 目录添加到包含文件的搜索路径中,以便在源代码中引用生成的 version.h 文件。

step2 adding a library

exercise 1 creating a library

怎么在工程中使用库
使用 add library()并确认加入什么代码文件
可以增加一个cmakelist并增加多个代码文件
并在顶层的cmakelist里面使用add subdirectory增加子目录
一旦库被建立,可以通过target include directories 和 target link libraries来连接可执行的目标文件
在这里插入图片描述
可以看他的文件目录结构

add_library()

add_subdirectory()

target_include_directories()

target_link_libraries()

PROJECT_SOURCE_DIR



add_library(MathFunctions MathFunctions.cxx mysqrt.cxx) 在里面的cmakelist里面添加
第一个参数是库的名称


add_subdirectory(MathFunctions) 在外层的cmakelist添加
target_link_libraries(Tutorial PUBLIC MathFunctions) 连接库与可执行文件
target_include_directories(Tutorial PUBLIC								确认库的头文件的位置
                          "${PROJECT_BINARY_DIR}"
                          "${PROJECT_SOURCE_DIR}/MathFunctions"
                          )


在mian.cpp中加入
#include "MathFunctions.h"



文件如下:
#pragma once

namespace mathfunctions {
double sqrt(double x);
}


最后修改参数
const double outputValue = mathfunctions::sqrt(inputValue);

PROJECT_BINARY_DIR和PROJECT_SOURCE_DIR都指向当前工程目录吗

PROJECT_BINARY_DIRPROJECT_SOURCE_DIR 变量分别指向当前 CMake 工程的构建目录和源代码目录。

其中,PROJECT_BINARY_DIR 是构建目录,指编译产生的二进制文件、库文件等输出目录。而 PROJECT_SOURCE_DIR 则是源代码目录,通常包含了 CMakeLists.txt 文件、头文件、源文件等等。

需要注意的是,PROJECT_BINARY_DIRPROJECT_SOURCE_DIR 可能不总是指向当前工程的根目录。这两个变量的值是由 project() 命令的第一个参数指定的项目名称得出的。如果在 project() 命令中指定了项目子目录,那么 PROJECT_BINARY_DIRPROJECT_SOURCE_DIR 就会相应地指向子目录。

例如,在以下工程结构中,

MyProject/
├── CMakeLists.txt
├── build/
│   ├── CMakeFiles/
│   └── Makefile
└── src/
    ├── CMakeLists.txt
    ├── main.cpp
    └── sub/
        ├── CMakeLists.txt
        ├── lib.cpp
        └── lib.h

当我们在 MyProject/CMakeLists.txt 中调用 project(MyProject) 命令时,PROJECT_BINARY_DIRPROJECT_SOURCE_DIR 分别指向 MyProject/buildMyProject/src 目录。

如果我们在 MyProject/src/CMakeLists.txt 中再次调用 project(SubProject) 命令并添加一个子目录 sub,那么 PROJECT_BINARY_DIRPROJECT_SOURCE_DIR 就会相应地指向 MyProject/build/subMyProject/src 目录。

因此,需要根据具体情况来使用 PROJECT_BINARY_DIRPROJECT_SOURCE_DIR 变量。

add library

add_library() 是 CMake 中的一个命令,用于向项目中添加一个库文件。它的语法如下:

add_library(<name> [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL]
            source1 [source2 ...])

其中,<name> 是要创建的库文件的名称,STATICSHAREDMODULE 是可选的构建类型,其意义分别是创建静态库、共享库和模块库。EXCLUDE_FROM_ALL 用于将这个库从默认的构建目标列表中排除。source1source2 等参数则是编译库文件所需的源代码文件。

add_library() 命令可以创建多种类型的库文件,具体取决于使用的构建类型。使用 STATIC 构建类型创建的库文件是静态库(也称为归档库),它将在链接时与应用程序一起链接。使用 SHARED 构建类型创建的库文件是共享库(也称为动态库),它将在应用程序运行时加载。而使用 MODULE 构建类型创建的库文件是模块库,它通常用于插件式架构,可在运行时动态加载和卸载。

CMake 在生成构建系统时会自动根据操作系统和编译器等信息选择库文件的适当构建类型和后缀名,例如 .a.lib.so

使用 add_library() 命令可以将多个源文件合并为一个库文件。这种库文件通常包含一组相关的类、函数或对象,也可以将其用作其他源代码文件的依赖项。

总之,add_library() 命令是 CMake 中用于创建库文件的命令,它允许将多个源代码文件合并成一个库文件,并可选择不同的构建类型,例如静态库、共享库或模块库等。

add subdirectory

add_subdirectory()target_link_libraries() 都是 CMake 中与库文件相关的命令,但它们的作用是不同的。

add_subdirectory(MathFunctions) 命令用于向 CMake 项目中添加一个子目录,并在该目录中构建一个新的 CMake 项目。这个子目录中的 CMakeLists.txt 文件可以包含一些其他的 add_library()add_executable() 等命令来定义新的库或可执行文件。当使用 add_subdirectory() 命令添加一个子目录后,CMake 将会为这个子目录构建一个新的 Makefile 或者其他生成方法所需的构建系统。

target_link_libraries(Tutorial PUBLIC MathFunctions) 命令则是用于将目标文件与一个或多个库文件进行链接。在本例中,Tutorial 是由 add_executable() 命令创建的可执行文件的名称。PUBLIC 关键字告诉 CMake 该链接库应该同时应用于 Tutorial 及其公共依赖关系。MathFunctions 则是指用于链接的库文件名。

这两个命令通常在不同的 CMakeLists.txt 文件中使用,它们的作用也是不同的。add_subdirectory() 用于在一个 CMake 项目中添加一个子目录,并构建其中定义的新的库或可执行文件。而 target_link_libraries() 则用于将一个或多个库文件链接到一个目标文件中(例如可执行文件或者其他库文件)。

因此,在一个 CMake 项目的根目录中,我们可以使用 add_subdirectory() 命令添加子目录,并在这些子目录的 CMakeLists.txt 文件中使用 add_library() 命令创建库文件。然后我们可以在需要使用这些库文件的目标文件(例如可执行文件)的 CMakeLists.txt 文件中使用 target_link_libraries() 命令将这些库文件链接起来。这样就可以方便地管理和构建整个项目。

指定路径

注意,在使用 add_subdirectory() 命令添加子目录时,CMake 会自动将子目录中定义的库文件添加到当前项目中,并将其编译成为共享库或静态库,具体取决于 add_library() 命令中的参数。因此,在使用 target_link_libraries() 命令时,可以直接将库文件名作为参数传递给该命令,而不需要指定库文件的路径。如果需要指定库文件的位置信息,可以使用变量来表示路径等信息。

在使用 target_link_libraries() 命令时,可以通过指定库文件的路径或者使用变量来表示库文件的位置信息。下面分别介绍这两种方式:

  1. 指定库文件的路径

如果库文件位于当前目录下的子目录中,可以使用相对路径来指定库文件的位置。例如,如果要将名为 libMyLib.a 的静态库文件链接到当前目标文件中,可以使用以下命令:

target_link_libraries(MyTarget PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/libs/libMyLib.a)

其中 ${CMAKE_CURRENT_SOURCE_DIR} 是一个 CMake 变量,表示当前 CMakeLists.txt 文件所在的目录。${CMAKE_CURRENT_SOURCE_DIR}/libs/libMyLib.a 表示该库文件所在的目录为 libs 目录,文件名为 libMyLib.a

如果库文件位于外部目录中,可以使用绝对路径或者相对路径来指定库文件的位置。例如,如果要链接 /home/user/mylibs/libMyLib.so 动态库文件,可以使用以下命令:

target_link_libraries(MyTarget PUBLIC /home/user/mylibs/libMyLib.so)
  1. 使用变量来表示库文件的位置信息

除了使用绝对路径、相对路径来指定库文件的位置信息外,还可以使用变量来表示库文件的位置信息。例如,可以使用 set() 命令来定义一个变量,并在 target_link_libraries() 命令中使用该变量来表示库文件的位置信息。示例如下:

set(MY_LIBS_DIR /home/user/mylibs)

target_link_libraries(MyTarget PUBLIC ${MY_LIBS_DIR}/libMyLib.so)

在这个示例中,我们使用 set() 命令定义了一个名为 MY_LIBS_DIR 的变量,并给它赋值 /home/user/mylibs。然后,在 target_link_libraries() 命令中使用 ${MY_LIBS_DIR} 变量来表示库文件的位置信息。这样做的好处是,如果将来库文件位置发生变化,只需要修改变量的值即可,而不需要修改多次出现在 target_link_libraries() 命令中的路径信息。

.so .a .lib

是的,动态库通常使用 .so (Shared Object)扩展名,静态库通常使用 .a (Archive)扩展名。这是因为在大多数 Unix 系统中,动态库使用的扩展名为 .so,而静态库使用的扩展名为 .a

.a 文件实际上就是一个简单的归档文件,可以将多个目标文件打包成一个文件供链接器使用,以便生成可执行程序。当创建一个静态库时,编译器会将所有的源文件编译成目标文件(.o),然后使用 ar 命令将它们打包成一个 .a 文件。静态库在链接时会被完整地复制到可执行文件中,因此可执行文件运行时与静态库没有任何关系。

.so 文件是一种共享库,它涵盖了许多不同的功能,并且可以在多个应用程序之间共享使用。动态库在链接时不会被完全复制到可执行文件中,而是在运行时动态加载到内存中。这意味着多个程序可以共享同一个库,从而节省系统资源并简化程序的管理和维护。

需要注意的是,不同的操作系统、编译器和开发环境可能会使用不同的扩展名来表示库文件,例如 Windows 系统下的动态库通常使用 .dll 扩展名,而静态库通常使用 .lib 扩展名。

总之,.so 通常指动态库,.a 通常指静态库,它们是不同类型的库文件,具有不同的用途和链接方式。

.lib 是在 Windows 操作系统下表示静态库文件的扩展名,与在 Unix/Linux 系统下使用的 .a 扩展名类似。它是 Microsoft Visual Studio 编译器生成的静态库文件的标准扩展名。

在 Visual Studio 中,静态库文件可以使用命令行工具 LIB.EXE 或在 IDE 中的属性页中进行创建。与 Unix/Linux 系统下的静态库一样,.lib 文件实际上也是一个归档文件,其中包含了一个或多个目标文件(即编译后的代码)。在链接可执行程序时,链接器会将需要的目标文件从库文件中提取出来,并将其复制到可执行文件中。

在 Windows 平台上,.dll 文件是动态库文件的标准扩展名,和在 Unix/Linux 平台上使用的 .so 扩展名相当。.dll 文件和 .lib 文件是不同类型的文件,.dll 文件常用于动态链接,而.lib 文件则常用于静态链接。

总之,在 Windows 操作系统中,.lib 扩展名通常表示静态库文件,其中包含了目标文件,可以通过链接器静态地将其连接到可执行程序中。

step2 exercise2 adding an option

https://cmake.org/cmake/help/latest/guide/tutorial/Adding%20a%20Library.html

在MathFunctions库中添加一个选项,允许开发人员选择自定义平方根实现或内置标准实现。虽然对于教程来说,确实没有必要这样做,但对于较大的项目来说,这是常见的情况。

CMake可以使用option()命令执行此操作。这为用户提供了一个变量,用户可以在配置cmake构建时更改该变量。此设置将存储在缓存中,这样用户就不需要每次在构建目录上运行CMake时都设置该值。

if()

option()

target_compile_definitions()

cmake ../Step2 -DUSE_MYMATH=OFF
cmake --build .
步骤如下:
 		MathFunctions/CMakeLists.txt. This option will be displayed in the cmake-gui and ccmake with a default value of ON that can be changed by the user. 		
option(USE_MYMATH "Use tutorial provided math implementation" ON) 第二个为说明信息
if (USE_MYMATH)
  target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")
endif()
ON的话就会设置是否编译


然后再 mathfunctions.cxx中定义
#ifdef USE_MYMATH
  return detail::mysqrt(x);
#else
  return std::sqrt(x);
#endif                                    Next, we need to include mysqrt.h if USE_MYMATH is defined.加入头文件

#ifdef USE_MYMATH    头文件也要看情况加入
#  include "mysqrt.h"
#endif

#include <cmath> 如果为off, mysqrt.cxx文件不会被用到,但仍然会被编译,因为 MathFunctions target has mysqrt.cxx listed under sources.
There are a few ways to fix this. The first option is to use target_sources() to add mysqrt.cxx from within the USE_MYMATH block. Another option is to create an additional library within the USE_MYMATH block which is responsible for compiling mysqrt.cxx. For the sake of this tutorial, we are going to create an additional library.
他这里选了第二种

内部的cmakelist
  add_library(SqrtLibrary STATIC
              mysqrt.cxx
              )
  target_link_libraries(MathFunctions PUBLIC SqrtLibrary)
上面这两个都是要在if() endif中 

add_library(MathFunctions MathFunctions.cxx) 从一开始的删掉mysrt.cpp



外部的
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
target_include_directories(Tutorial PUBLIC
                           "${PROJECT_BINARY_DIR}"
                           )



-D option -d 小d是调试工具选项,输出详细调试信息

-D 是 CMake 工具的一个选项,用于定义一个 CMake 变量,并为其指定一个值。

在 CMake 中,变量可用于存储和传递信息,比如控制编译选项、设置版本号、指定构建路径等等。在 CMakeLists.txt 文件中使用 -D 选项可以方便地在命令行上设置变量值,避免了手动编辑 CMakeLists.txt 文件的麻烦。

例如,以下是一个简单的 CMakeLists.txt:

cmake_minimum_required(VERSION 3.0)

project(MyProject)

option(USE_MYMATH "use my math library" ON)

if(USE_MYMATH)
    add_subdirectory(mymath)
    list(APPEND EXTRA_LIBS mymath)
endif()

add_executable(MyApp main.cpp)
target_link_libraries(MyApp ${EXTRA_LIBS})

其中,option() 命令会定义一个名为 USE_MYMATH 的选项变量,初始值为 ON。如果 -DUSE_MYMATH=OFF 被传给 cmake 命令,那么 CMake 会将 USE_MYMATH 变量的值设置为 OFF,从而跳过构建 mymath 库并且不链接 mymath 库到 MyApp 可执行文件中。这样,我们就可以在命令行上方便地修改相应的选项。

因此,-D 选项是非常有用的,它方便开发者在命令行上动态地设置 CMake 变量,从而轻松控制编译选项,增强 CMake 的灵活性。

target source

CMake 中没有 target_source() 命令,可能您想问的是 target_sources() 命令。

target_sources() 是 CMake 提供的一个命令,用于向指定的一个或多个目标添加源文件。其常见语法如下:

target_sources(<target> [PRIVATE|PUBLIC|INTERFACE] [items1...]
               [PRIVATE|PUBLIC|INTERFACE] [items2...] ...)

其中,<target> 表示添加源文件的目标名称,可以是库或可执行文件。

[PRIVATE|PUBLIC|INTERFACE] 是可选的关键字,用于指定后面的源文件列表是属于 PRIVATEPUBLIC 还是 INTERFACE。具体含义如下:

  • PRIVATE 表示仅对当前目标可见的源文件,不会被链接到依赖该目标的其他目标中;
  • PUBLIC 表示既对当前目标可见,也会被链接到依赖该目标的其他目标中;
  • INTERFACE 表示不对当前目标可见,只会被链接到依赖该目标的其他目标中。

[items1...][items2...] 等表示要添加的源文件列表,可以是相对于当前 CMakeLists.txt 文件的路径或者源文件名。

例如,以下是一个简单的例子:

add_library(MyLib STATIC)
target_sources(MyLib PRIVATE src/foo.cpp)

首先,我们创建了一个名为 MyLib 的静态库,然后使用 target_sources() 命令向它添加了 src/foo.cpp 源文件。由于使用了 PRIVATE 关键字,因此该源文件只会对 MyLib 目标可见,不会被链接到依赖该目标的其他目标中。

使用 target_sources() 命令可以方便地管理源文件,避免了手动编写链接器脚本的繁琐操作,并且提高了 CMake 项目的可维护性。

cmake -

-build 和 mingw
cmake --build .make 命令类似,都是用于执行编译和链接操作的命令。不过它们之间还是有一些区别的。

make 是一个独立的构建工具,它使用 Makefile 文件来描述项目的组织结构以及如何进行编译、链接和安装等操作。

cmake 则是一个跨平台的构建系统生成器,它可以根据不同操作系统和编译器生成对应的构建系统文件(如 Makefile 或 Ninja 构建文件),提供相应的接口和API来进行项目的编译、测试、打包和安装等操作。

执行 cmake --build . 命令时,CMake 会自动识别当前目录下的构建系统文件,并执行默认的构建方式(如 Makefile 时就会执行 make 命令)来进行编译和链接操作。

make 相比,cmake --build . 可以自动进行一些跨平台的处理,例如在 Windows 平台中会自动使用 MSVC 编译器,而在 Linux 平台则会自动使用 GCC 或 Clang 等编译器。

总之,cmake --build . 命令可以让我们更方便地执行 CMake 构建系统,自动生成构建文件和进行编译、链接和打包等操作。而 make 则是常用的 Linux 系统中的构建工具,用于编译、链接和构建 Makefile 构建文件所描述的项目。

compiler 和kit

在 Windows 和 Linux 中,Compiler 和 Kit 都是关键的概念,用于构建和编译应用程序。下面我会逐一介绍这两个概念的具体内容:

  1. Compiler(编译器)

编译器是将源代码转换为可执行文件或库文件的工具。在编译过程中,编译器会将源代码翻译成计算机可以理解的机器码,然后生成可执行文件或库文件。在 Windows 中,常见的编译器包括 Visual Studio 的 MSVC 编译器和 MinGW 编译器;而在 Linux 中,则常见的编译器有 GCC 和 Clang。

  1. Kit(构建工具链)

Kit 是 CMake 中的一个重要概念,表示一组用于构建和编译应用程序的工具集合。在 Windows 上,一个 Kit 可以包括 C++ 编译器、构建工具(如 Ninja 或 Visual Studio)、调试器和其他相关的工具;在 Linux 上,一个 Kit 则可以包括 C++ 编译器、构建工具(如 Makefile 或 Ninja)、调试器和其他相关的工具。

Kit 对于交叉编译非常有用。例如,在 Windows 系统上开发嵌入式 Linux 应用程序时,我们需要使用一个 Linux 交叉编译工具链,这样才能将应用程序编译为 Linux 可执行文件。使用 CMake 的 Kit 功能,我们可以轻松切换不同的工具链(如 Linux 交叉编译工具链或本地编译工具链),从而为我们提供了一个可靠的交叉编译环境。

总之,编译器和 Kit 是 CMake 中非常重要的概念,通过它们可以构建和编译不同平台的应用程序。无论是 Windows 还是 Linux 系统下,都需要选择合适的编译器和 Kit 来满足不同的需求。

在 CMake 中,Kit 是一组参数的集合,它描述了如何为不同的目标平台编译和构建项目。一个 Kit 是由一组工具链、编译器、构建器、环境变量等参数组成的。

具体来说,Kit 是一个用于定义构建环境的抽象概念,包括了编译器、构建器、调试工具、部署工具以及相关的路径、变量、选项等等。通常情况下,一个 Kit 会对应一个特定的编译器和一些相关的构建、编译和部署工具。

在使用 CMake 进行交叉编译时,通过创建不同的 Kit,可以为不同的目标平台选择不同的编译器、工具链和构建选项等。这样可以使得我们的项目能够在不同的平台上进行编译和构建,并生成相应的可执行文件或库文件。

总之,CMake 中的 Kit 是一个非常重要的概念,通过它可以指定编译器、构建工具等参数,从而为不同的目标平台定制构建环境。

kit

在 CMake 中,Kit 是一组工具集合,用于指定构建和编译应用程序的工具链。使用 Kit 功能的主要优点是可以实现跨平台交叉编译,同时也可以进行本地编译,从而简化了开发人员的工作。

要使用 CMake 的 Kit 功能,需要先定义一个 Kit。在定义 Kit 时,需要指定以下几个关键参数:

  • 工具链类型:例如 GNU、Clang 等
  • 工具链版本:例如 GCC 5.3.0、Clang 9.0.0 等
  • 构建器类型:例如 Ninja、Visual Studio 等
  • 构建器版本:例如 Ninja 1.5.3、Visual Studio 2015 等
  • 附加项:例如编译选项、链接选项等

定义好 Kit 后,我们就可以在项目中使用这个 Kit 了。在 CMakeLists.txt 文件中,我们可以通过指定 Kit 来设置构建选项和参数。例如,假设我们使用的 Kit 名称为 “MyKit”,那么可以通过以下方式设置构建选项:

cmake_minimum_required(VERSION 3.12)
project(MyProject)

# 指定 Kit
set(CMAKE_TOOLCHAIN_FILE /path/to/mykit.cmake)

# 其他构建选项
...

在上述示例中,我们通过 set(CMAKE_TOOLCHAIN_FILE ...) 指定了使用的 Kit,然后可以设置其他构建选项。在执行 CMake 命令时,就可以使用 -DCMAKE_TOOLCHAIN_FILE=/path/to/mykit.cmake 选项来指定 Kit 所在的文件路径。

总之,Kit 是 CMake 中非常有用的功能,可以帮助我们实现跨平台交叉编译和本地编译,从而提高开发效率。

两者是并行的嘛

在 CMake 中,Kit 和 Compiler 并不是类似于两种并行的工具,而是在构建和编译过程中扮演不同的角色。

Kit 主要用于指定构建、编译和链接应用程序的工具链,即在 CMake 构建时使用哪个编译器、链接器以及其他相关工具(如 make、ninja 等)。如果我们需要在不同平台上进行编译,或者需要使用不同版本的编译器、不同的编译器选项等,可以通过 Kit 来管理。

而 Compiler 则是 CMake 在查找和选择编译器时使用的过程。它会尝试在系统环境变量 PATH 中查找可用的编译器,并且根据编译器的类型、版本、路径等信息来选择合适的编译器。

可以说,Kit 和 Compiler 是在不同的层次上发挥作用的。Kit 主要用于指定编译过程中使用的工具链,与编译器本身并没有直接关联。而 Compiler 则是在工具链确定之后,用于确定最终使用哪个编译器来进行编译。

因此,在使用 CMake 进行构建时,需要同时考虑 Kit 和 Compiler 的使用。对于复杂的项目,可能需要同时管理多个 Kit 和 Compiler,并根据实际需求进行配置和选择。

kit默认配置好的嘛,我都没配置就直接用了

在默认情况下,CMake 会使用系统安装的工具链来构建应用程序,因此不需要手动配置 Kit。也就是说,如果您直接运行 cmake 命令进行构建,则默认使用系统提供的编译器、链接器以及其他相关工具,而不需要手动指定 Kit。

但是,在一些特定场景下,可能需要手动配置 Kit,例如:

  • 进行交叉编译,需要使用不同于系统默认的编译器和工具链。
  • 在不同操作系统上构建不同版本的应用程序,需要使用不同的工具链。
  • 针对特定的硬件平台进行开发,需要使用特定的编译器和工具链等。

在这些情况下,需要手动配置 Kit,并且将其与 CMakeLists.txt 文件中的构建选项和参数结合使用,来确保应用程序可以正确地编译和构建。

总之,CMake 中的 Kit 可以帮助我们管理工具链,减少构建过程中的问题,并提高构建的可移植性。虽然默认情况下不需要手动配置 Kit,但在某些特定场景下,手动配置 Kit 是非常有必要的。

gcc和mingw

是的,GCC 和 MinGW 都是编译器,它们都可以将源代码编译成可执行文件或库文件。GCC 是 GNU Compiler Collection 的缩写,是一个开源的编译器集合,支持多种编程语言和多个平台,包括 C、C++、Objective-C、Ada、Fortran 和 Java 等。MinGW 则是一个 Windows 下的 GCC 移植版本,提供了一组可移植的 GNU 工具链,可以在 Windows 平台上编译开源项目和应用程序。

需要注意的是,GCC 和 MinGW 之间有一些区别。具体来说,MinGW 是针对 Windows 平台而设计的,因此它提供了更好的 Windows API 支持和更好的兼容性,同时也包含了一些 Windows 下所需要的工具和库。而 GCC 则是一款跨平台的编译器,在多个平台上通用,但是在 Windows 下使用时需要特别注意一些问题,例如需要手动配置环境变量和路径等。

总之,无论是使用 GCC 还是 MinGW,它们都是编译器,可以将源代码转换为可执行文件或库文件。根据具体需求和平台特点,我们可以选择合适的编译器和工具链来进行开发和编译。

GCC 和 MinGW 的主要区别在于它们的目标平台和使用场景。GCC 是跨平台的编译器,可以在多个操作系统上都使用,并且支持多种编程语言和多种目标平台。MinGW 则是专门针对 Windows 平台的 GCC 移植版本,提供了一套工具集,方便在 Windows 上构建本地程序和移植的开源代码。

关于生成 makefile 文件的问题,实际上不是由 GCC 和 MinGW 决定的。makefile 文件是一种用于自动化构建的脚本文件,在 make 工具的帮助下,开发人员可以自动执行编译、链接等一系列操作,从而生成最终的可执行文件。无论是使用 GCC 还是 MinGW,我们都可以使用 make 工具来完成自动化构建的过程,并且生成 makefile 文件。

至于生成可执行文件的问题,这实际上是由编译器和链接器来决定的。编译器会将源代码编译成目标文件(如 .o 或 .obj),而链接器则会将目标文件合并成最终的可执行文件或库文件。因此,无论是使用 GCC 还是 MinGW,它们都可以生成目标文件和最终的可执行文件,只是在使用上可能有一些细节上的差异。

Linux系统介绍

linux 多用户多任务
windows 单用户 多任务

linux 一切都是文件

创建文件 ,编辑文件,保存文件,关闭文件,重命名文件,删除文件,恢复文件

在这里插入图片描述
root 管理员
在这里插入图片描述

命令

命令 空格 【选项】 空格 【操作对象】
ls -a -l -h 等效于 ls -alh

owner group other 三个对象的权限
chmod 777

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/31121.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Verilog基础:标识符的向上向下层次名引用

相关文章 Verilog基础&#xff1a;表达式位宽的确定&#xff08;位宽拓展&#xff09; Verilog基础&#xff1a;表达式符号的确定 Verilog基础&#xff1a;数据类型 Verilog基础&#xff1a;位宽拓展和有符号数运算的联系 Verilog基础&#xff1a;case、casex、ca…

如何在Microsoft Excel中使用TRUNC函数

Excel 中有多种删除小数点和缩短数值的方法。在本文中,我们将解释如何使用 TRUNC 函数,以及它与其他技术的不同之处。 TRUNC函数 什么是 TRUNC 功能如何使用 TRUNC 函数从日期时间戳中删除时间什么是 TRUNC 功能 TRUNC 函数将数字截断为指定的小数位数。使 TRUNC 不同于其他…

概率论与数理统计教程第五章节笔记

参考书籍&#xff1a;概率论与数理统计教程第三版 茆诗松 程依明 濮晓龙 编著 文章声明&#xff1a;如有错误还望批评指正 文章目录 ξ 5.1 \xi5.1 ξ5.1总体与样本 ξ 5.2 \xi5.2 ξ5.2样本数据的整理与显示Python绘制直方图Python绘制茎叶图 ξ 5.3 \xi5.3 ξ5.3统计量及其分…

基於Hadoop HA 在kerberos中配置datax

概要 提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 概要 前言一、基於HADOOP HA 搭建datax二、基於HADOOP HA 配置好的datax去配置kerberos1.在datax的配置文件中進行配置2.在shell腳本中加入認證語句 总结 前言…

layui框架学习(27:弹出层模块_其它用法)

除了前几篇文章介绍的弹出框类型外&#xff0c;layui的layer弹出层模块还支持相册框和tab框&#xff0c;所谓相册框即点击图片或按钮后会出现一个类似相册的页面单独浏览、切换图片&#xff0c;而tab框是指弹出框的显示形式类似于Winform中的TabControl控件&#xff0c;能以选项…

【Spring Security】的RememberMe功能流程与源码详解

文章目录 前言原理 基础版搭建初始化sql依赖引入配置类验证 源码分析 进阶版集成源码分析疑问1疑问2 鉴权 升级版集成初始化sql配置类验证 源码分析鉴权流程 扩展版 前言 之前我已经写过好几篇权限认证相关的文章了&#xff0c;有想复习的同学可以查看【身份权限认证合集】。今…

MIT 6.S081 Lab Four

MIT 6.S081 Lab Four 引言trapsRISC-V assembly (easy)代码解析 Backtrace(moderate)代码解析 Alarm(Hard)test0: invoke handler(调用处理程序)test1/test2(): resume interrupted code(恢复被中断的代码)代码解析issue解答 可选的挑战练习 引言 本文为 MIT 6.S081 2020 操作…

JDBC BasicDAO详解(通俗易懂)

目录 一、前言 二、BasicDAO的引入 1.为什么需要BasicDAO&#xff1f; 2.BasicDAO示意图 : 三、BasicDAO的分析 1.基本说明 : 2.简单设计 : 四、BasicDAO的实现 0.准备工作 : 1.工具类 : 2.JavaBean类 : 3.BasicDAO类 / StusDAO类 : 4.测试类 : 一、前言 第七节内容…

Jenkins+Docker 实现一键自动化部署项目!步骤齐全,少走坑路

大家好&#xff0c;我是互联网架构师&#xff01; 本文章实现最简单全面的Jenkinsdockerspringboot 一键自动部署项目&#xff0c;步骤齐全&#xff0c;少走坑路。 环境&#xff1a;centos7git(gitee) 简述实现步骤&#xff1a;在docker安装jenkins&#xff0c;配置jenkins基…

数据结构:二叉树经典例题(单选题)-->你真的掌握二叉树了吗?(第一弹)

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下有关二叉树的经典例题&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从入门到精通 数…

Sentinel的限流和Gateway的限流差别?

Sentinel的限流与Gateway的限流有什么差别&#xff1f; 问题说明&#xff1a;考察对限流算法的掌握情况 限流算法常见的有三种实现&#xff1a;滑动时间窗口&#xff0c;令牌桶算法&#xff0c;漏桶算法。gateway则采用基于Redis实现的令牌桶算法。但是我们不会去用&#xff…

ubuntu常用命令

设置root密码 安装好ubuntu后谁也不知道root密码是多少&#xff0c;可以借助于passwd命令来设置root密码。 sudo passwd root 同理修改其他用户只需替换上方用户名即可 换源 备份原始文件 sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak 修改源文件 sudo vim /et…

数据链路层(MAC)、网络层(IP)、传输层(TCP/UDP)抓包分析

目录 OSI七层模型数据包逐层封装头部抓包分析数据包概况数据链路层抓包网络层抓包&#xff08;IP协议抓包&#xff09;UDP抓包数据负载抓包 Linux cooked-mode capture OSI七层模型 OSI模型&#xff08;OSI model&#xff09;&#xff0c;开放式系统互联通信参考模型&#xff…

台电x80HD 安装linux系统,可调电压电源供电,外网访问、3D打印klipper固件

一、系统安装 参照https://blog.csdn.net/gangtieren/article/details/102975027安装 安装过程遇到的问题&#xff1a; 1、试了 linux mint 21 、ubuntu20.04 、ubuntu22.04 都没有直接安装成功&#xff0c;u盘选择安装进入系统后一直黑屏&#xff0c;只有ubuntu18.04 选择后稍…

ChatGPT读PDF、生成思维导图的几种方案

大家好&#xff0c;我是可夫小子&#xff0c;《小白玩转ChatGPT》专栏作者&#xff0c;关注AIGC、读书和自媒体。 日常办公&#xff0c;我们离不开pdf文档读取&#xff0c;思维导图制作&#xff0c;那么ChatGPT能够给我们什么帮助呢&#xff1f; 通常的方法是&#xff1a;我们…

【大数据】大数据相关概念

文章目录 大数据&#xff1a;一种规模大到在获取、存储、管理、分析方面大大超出了传统数据库软件工具能力范围的数据集合&#xff0c;具有海量的数据规模、快速的数据流转、多样的数据类型以及价值密度四大特征。Hadoop&#xff1a;是一个能够对大量数据进行分布式处理的软件框…

华硕天选2ubuntu18.04升级内核后黑屏

https://piaoyun.cc/post/26957.html 1.开机&#xff0c;进入grub画面 2.按’‘‘e’’’ 进入编辑开机指令的模式,同样找到’‘‘quite splash’’,并在后面加上对应的字。 1.Intel 82852/82855 或8系列显示晶片&#xff1a;i915.modeset1或i915.modeset0 2.Nvidia&#xff…

Pytest教程__钩子方法setup、teardown、setup_class、teardown_class(8)

pytest跳过用例执行的用法与unittest跳过用例大致相同。 pytest跳过用例的方法如下&#xff1a; pytest.mark.skip(reason)&#xff1a;无条件用例。reason是跳过原因&#xff0c;下同。pytest.mark.skipIf(condition, reason)&#xff1a;condition为True时跳过用例。 pyte…

设计模式之单例模式

一.单例模式 1.1 定义 我们来解释一下什么是单例模式.在软件系统中有很多对象,他们在同一时刻只能被一个用户或者多个线程访问,如果被共享的word文档在同一时间内,只能由一个用户对其进行写操作. 换一种说法就是 在单例模式中&#xff0c;类自身负责创建自己的唯一实例&#…

从零开始 Spring Boot 47:缓存

从零开始 Spring Boot 47&#xff1a;缓存 图源&#xff1a;简书 (jianshu.com) Spring 提供一个简单但使用的缓存&#xff08;Cache&#xff09;机制&#xff0c;我们可以利用它来优化代码执行效率。 简单示例 老规矩&#xff0c;我们从一个简单示例开始&#xff1a; Serv…