简介
- cmake 常用的技巧
vscode中cmake项目配置文件手动修改编译器路径
在 VSCode 中,如果你想为 CMake 项目手动配置编译器路径,可以通过修改 CMakeSettings.json
或者 .vscode/settings.json
文件来实现。以下是配置步骤:
1. 使用 CMakeSettings.json
CMake 支持通过 CMakeSettings.json
来设置不同的构建配置,比如指定编译器路径。创建或修改项目根目录中的 CMakeSettings.json
文件,添加类似下面的配置:
1 | { |
这会告诉 CMake 使用指定的编译器路径。
2. 使用 .vscode/settings.json
你也可以直接在 VSCode 的工作区配置中设置编译器路径,方法是修改 .vscode/settings.json
文件:
1 | { |
这里 cmake.environment
变量用于指定 C 和 C++ 编译器路径。
3. 通过 CMakeLists.txt
文件
你也可以在 CMakeLists.txt
中直接添加设置编译器的指令:
1 | set(CMAKE_C_COMPILER "C:/Path/To/Your/Compiler/gcc.exe") |
4. 使用 cmake-kits.json
VSCode 的 CMake Tools 扩展提供了一种通过 cmake-kits.json
来管理编译器的方式。你可以在 .vscode/cmake-kits.json
中定义编译器路径:
1 | [ |
然后在 VSCode 的 CMake Tools 扩展中选择这个编译器套件。
5. 选择编译器
如果你已经配置了多个编译器,可以通过命令面板(Ctrl+Shift+P
)打开 CMake: Select a Kit
,然后从列表中选择你配置的编译器。
这几种方式都可以帮助你手动指定 CMake 项目的编译器路径。
cmake 静态链接库顺序问题
默认情况下要求被依赖的库放在依赖它的库后面,当一个程序或共享库依赖的静态库较多时,可能会陷入解决链接问题的坑中。如果对静态库不熟悉,需要结构nm等工具来解决顺序问题。
如果去掉顺序的烦恼和痛苦,可以采用如下方法
1
2
3
4
5
6
7
8target_link_libraries(
x
-Wl,--start-group
libX1.a
libX3.a
libX2.a
-Wl,--end-group
)
cmake 设置编译线程数量
在使用 CMake 构建项目时,你可以通过设置编译器选项来指定编译时使用的线程数量。具体步骤如下:
使用
cmake
命令配置项目:
例如,你可以在项目根目录中运行以下命令来生成构建文件:1
cmake -S . -B build
使用
cmake --build
命令进行构建并指定线程数量:
使用--parallel
选项可以指定编译时使用的线程数量。例如,如果你想使用 8 个线程来进行编译,可以运行以下命令:1
cmake --build build --parallel 8
这样,CMake 会根据你指定的线程数量来并行执行构建任务,从而加快编译速度。
完整的流程示例如下:
1 | cmake -S . -B build |
此外,你还可以直接在 make
或 ninja
命令中指定线程数量(假设你使用的是这些生成器):
- 对于
make
生成器:1
make -j8
- 对于
ninja
生成器:1
ninja -j8
CMake 会根据你的项目配置选择合适的生成器并使用相应的构建工具。
CMakeLists.txt 编译性能参数配置
在 CMakeLists.txt
中配置编译性能参数,可以通过一些特定的编译选项和设置来优化编译时间和资源使用。以下是一些常见的方法和配置选项,可以用来提升编译性能:
1. 使用 CMAKE_BUILD_TYPE
通过设置 CMAKE_BUILD_TYPE
可以启用特定的编译器优化选项。例如,在开发过程中可以设置为 Debug
,在发布时设置为 Release
。使用 Release
模式可以启用优化选项,从而减少生成的代码大小和提升执行性能。
1 | set(CMAKE_BUILD_TYPE Release) |
2. 使用 CMAKE_CXX_FLAGS
和 CMAKE_C_FLAGS
可以为编译器指定一些优化选项,比如 -O2
或者 -O3
,这些选项可以启用更多的编译器优化,从而提升生成代码的性能。
1 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2") |
3. 使用 CMAKE_LINKER_FLAGS
对于链接阶段,可以设置 CMAKE_EXE_LINKER_FLAGS
和 CMAKE_SHARED_LINKER_FLAGS
来优化链接器的行为。
1 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed") |
4. 启用并行链接
某些编译器和链接器支持并行链接,可以显著减少链接时间。对于 GNU 链接器,可以使用 -Wl,--parallel
。
1 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--parallel") |
5. 使用 ccache
ccache
是一个编译缓存工具,可以显著减少重复编译的时间。要在 CMake 中启用 ccache
:
1 | find_program(CCACHE_PROGRAM ccache) |
6. 使用 Ninja
生成器
Ninja
是一个快速的构建系统,通常比默认的 Make
更快。要使用 Ninja
,可以在 CMake 配置阶段指定生成器:
1 | cmake -G Ninja .. |
在 CMakeLists.txt
中没有直接指定 Ninja
的方法,但可以通过命令行来指定。
7. 预编译头文件
预编译头文件可以显著减少编译时间,特别是当项目包含大量头文件时。可以通过 target_precompile_headers
指令来设置预编译头文件:
1 | target_precompile_headers(my_target PRIVATE precompiled.h) |
8. 使用编译选项优化
根据不同的编译器,可以启用一些特定的优化选项。例如,针对 GCC,可以启用以下选项:
1 | if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") |
完整示例
以下是一个包含上述多个优化配置的 CMakeLists.txt
示例:
1 | cmake_minimum_required(VERSION 3.14) |
通过在 CMakeLists.txt
中添加这些配置,可以显著提升编译性能并减少系统资源的使用。
cmake 子项目设置二进制文件保存路径
要设置子项目的二进制文件保存路径,你可以在使用 add_subdirectory()
函数添加子项目时,通过第二个参数 binary_dir
来指定。
假设你有如下的项目结构:
1 | project_root/ |
如果你希望将子项目的二进制文件保存在不同的目录中,可以像这样在父项目的 CMakeLists.txt
中设置:
1 | cmake_minimum_required(VERSION 3.10) |
在这个例子中,src
子项目的二进制文件将保存在 project_root/bin/src
目录中,而 test
子项目的二进制文件将保存在 project_root/bin/test
目录中。
如果不指定 binary_dir
参数,子项目的二进制文件将默认保存在子项目目录下的 bin
目录中。
cmake 在子项目中设置头文件包含目录
在 CMake 中,你可以在子项目中使用 target_include_directories()
函数来设置头文件包含目录。这个函数用于为指定的目标(例如库或可执行文件)设置头文件搜索路径。假设你有如下的项目结构:
1 | project_root/ |
在 src/CMakeLists.txt
中,你可以这样设置头文件包含目录:
1 | target_include_directories(my_target_name PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) |
在这个例子中,my_target_name
是你在 src/CMakeLists.txt
中定义的目标名称,${CMAKE_CURRENT_SOURCE_DIR}
表示当前源码目录的路径,${CMAKE_CURRENT_SOURCE_DIR}/include
就是 include
目录的路径。使用 PUBLIC
关键字可以将这个头文件包含目录设置为公开的,这意味着这个目录将会被导出到依赖这个目标的其他目标中。
在 test/CMakeLists.txt
中,你也可以类似地设置头文件包含目录:
1 | target_include_directories(test_target_name PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../src/include) |
在这个例子中,test_target_name
是你在 test/CMakeLists.txt
中定义的目标名称,${CMAKE_CURRENT_SOURCE_DIR}/../src/include
是相对于 test
目录的父目录 src/include
的路径。使用 PRIVATE
关键字可以将这个头文件包含目录设置为私有的,这意味着这个目录只对当前目标有效,不会被导出到依赖当前目标的其他目标中。
cmake 打印目标的头文件路径和编译选项
要打印目标的头文件路径和编译选项,您可以使用 get_target_property
命令来获取目标的属性。以下是一个示例代码,假设您的目标名为 my_target
:
1 | # 获取目标的头文件路径 |
这段代码将打印出目标 my_target
的头文件路径和编译选项。您可以根据需要获取和打印其他属性。
cmake find_package 配置opencv库
配置 OpenCV 库时,通常会使用 CMake 的 find_package
命令。以下是一个简单的示例,展示如何在 CMake 中配置和链接 OpenCV 库:
1 | cmake_minimum_required(VERSION 3.12) |
在上述代码中:
find_package(OpenCV REQUIRED)
用于查找并配置 OpenCV 库。REQUIRED
表示如果找不到 OpenCV 库,将产生一个错误。OpenCV_INCLUDE_DIRS
包含了 OpenCV 库的头文件目录。OpenCV_LIBRARIES
包含了 OpenCV 库的链接库的名称。add_executable
添加了一个可执行文件,并使用target_include_directories
将 OpenCV 库的头文件目录包含进来,使用target_link_libraries
将 OpenCV 库链接到可执行文件中。
确保 OpenCV 已经安装在你的系统中,或者你可以使用 CMake 的 ExternalProject
或其他方法在 CMake 中构建 OpenCV。
此外,find_package
还可以通过指定版本号和特定组件来细化查找过程。例如:
1 | find_package(OpenCV 4.5.1 REQUIRED COMPONENTS core imgproc highgui) |
这将查找并配置 OpenCV 版本为 4.5.1,并确保包含了 core、imgproc 和 highgui 组件。
cmake find_package 配置gflags库
当使用 CMake 的 find_package
配置 gflags
库时,你需要确保 gflags
库的 CMake 模块文件 Findgflags.cmake
被正确找到并使用。以下是一个简单的例子,演示如何在 CMake 中使用 find_package
配置 gflags
库:
1 | cmake_minimum_required(VERSION 3.12) |
在上述代码中:
find_package(gflags REQUIRED)
用于查找并配置gflags
库。REQUIRED
表示如果找不到 gflags 库,将产生一个错误。gflags_INCLUDE_DIRS
包含了gflags
库的头文件目录。gflags_LIBRARIES
包含了gflags
库的链接库的名称。add_executable
添加了一个可执行文件,并使用target_link_libraries
将gflags
库链接到可执行文件中。
确保 gflags
库已经安装在系统中,或者你可以使用 ExternalProject
或其他方法在 CMake 中构建 gflags
。
此外,如果你的项目中还用到其他外部库,可能需要在 find_package
后面添加其他库的查找,以确保这些库的依赖关系也得到正确配置。
最后,记得在 CMakeLists.txt
中引入 main.cpp
或其他源代码文件,以确保它们被编译到可执行文件中。