bash
# 1. 最低 CMake 版本要求(建议写 3.16+,兼容大部分系统)
cmake_minimum_required(VERSION 3.10 )
# 2. 项目定义(项目名、版本、语言)
project(
OpenCV_Demo
VERSION 1.0.0
LANGUAGES CXX
)
# 3. 设置 C++ 标准(比如 C++17)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# -----------------------------------------------------------
# 3. 选项开关:是否启用 CUDA
# -----------------------------------------------------------
# 在 cmake 配置时可以通过 -DENABLE_CUDA=ON 来开启
option(ENABLE_CUDA "Enable NVIDIA CUDA support" OFF)
# 把 ENABLE_CUDA 定义传给 C++ 编译器
if(ENABLE_CUDA)
add_definitions(-DENABLE_CUDA) # 这一行必须加!
endif()
# 输出目录设置
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
# -----------------------------------------------------------
# 4. 查找 OpenCV
# -----------------------------------------------------------
find_package(OpenCV REQUIRED)
if(OpenCV_FOUND)
message(STATUS "OpenCV found: ${OpenCV_VERSION}")
message(STATUS "OpenCV libs: ${OpenCV_LIBS}")
endif()
# -----------------------------------------------------------
# 5. 配置 ONNX Runtime
# -----------------------------------------------------------
if(WIN32)
# --- 根据你的实际路径修改这里 ---
# 如果想切换 CPU/GPU,直接改这个路径或者用 CMake 变量传入
if(ENABLE_CUDA)
# GPU 版本路径
set(ONNXRUNTIME_ROOTDIR "E:/FindJob/onnxruntime-win-x64-gpu-1.14.1")
message(STATUS ">>> 使用 ONNX Runtime GPU 版本")
else()
# CPU 版本路径
set(ONNXRUNTIME_ROOTDIR "E:/FindJob/onnxruntime-win-x64-1.14.1")
message(STATUS ">>> 使用 ONNX Runtime CPU 版本")
endif()
else()
# Linux 路径示例
set(ONNXRUNTIME_ROOTDIR "/usr/local/onnxruntime")
endif()
# 包含头文件目录
target_include_directories(${PROJECT_NAME} PRIVATE ${ONNXRUNTIME_ROOTDIR}/include)
# 链接库目录
target_link_directories(${PROJECT_NAME} PRIVATE ${ONNXRUNTIME_ROOTDIR}/lib)
# 核心库
set(ONNXRUNTIME_LIBS onnxruntime)
# 如果开启 CUDA,需要额外链接 Provider 库
if(ENABLE_CUDA)
# 注意:GPU 版本需要链接这两个额外的库
list(APPEND ONNXRUNTIME_LIBS onnxruntime_providers_cuda)
list(APPEND ONNXRUNTIME_LIBS onnxruntime_providers_shared)
endif()
# -----------------------------------------------------------
# 6. 生成可执行文件 (关键修复:必须在 target_link_libraries 之前)
# -----------------------------------------------------------
add_executable(${PROJECT_NAME} main.cpp)
# -----------------------------------------------------------
# 7. 链接库
# -----------------------------------------------------------
target_link_libraries(${PROJECT_NAME}
PRIVATE
${OpenCV_LIBS}
${ONNXRUNTIME_LIBS}
)
# -----------------------------------------------------------
# 8. Windows DLL 自动拷贝 (非常重要,否则运行找不到 dll)
# -----------------------------------------------------------
if(WIN32)
# 拷贝核心 DLL
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${ONNXRUNTIME_ROOTDIR}/lib/onnxruntime.dll"
$<TARGET_FILE_DIR:${PROJECT_NAME}>
)
# 如果开启了 CUDA,还需要拷贝 Provider 的 DLL
if(ENABLE_CUDA)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${ONNXRUNTIME_ROOTDIR}/lib/onnxruntime_providers_cuda.dll"
"${ONNXRUNTIME_ROOTDIR}/lib/onnxruntime_providers_shared.dll"
$<TARGET_FILE_DIR:${PROJECT_NAME}>
)
# 注意:运行 GPU 版本还需要系统环境变量中有 CUDA 的 cudnn.dll 和 cublas.dll 等
endif()
endif()
cmake_minimum_required(VERSION 3.10)
- 含义:声明运行此 CMake 脚本所需的最低版本。如果用户的 CMake 版本低于 3.10,CMake 会报错并停止运行。
- 作用:确保脚本中使用的语法特性在当前环境中受支持。
- 当前状态:你的电脑上安装的 CMake 版本必须 ≥ 3.10。
project(OpenCV_Demo VERSION 1.0.0 LANGUAGES CXX)
- 含义:定义项目名称、版本号、语言。这是 CMake 脚本中最重要的指令之一,它会初始化一系列变量。
- 关键字 :
OpenCV_Demo:这是你给项目起的名字。VERSION 1.0:项目的版本号。
- 生成的变量 :
PROJECT_NAME:值为"OpenCV_Demo"。PROJECT_VERSION:值为"1.0"。PROJECT_SOURCE_DIR:包含此文件的根目录。
总结:给项目起名字
告诉 CMake:我用的语言是 C++
让 CMake 检查 C++ 编译器是否存在
set(CMAKE_CXX_STANDARD 17)
- 含义:告诉 CMake 使用 C++17 标准来编译代码。
- 作用 :相当于在 g++ 编译器后面加了
-std=c++17参数。这让你可以使用现代 C++ 的特性(如auto、filesystem等)。
set(CMAKE_CXX_STANDARD_REQUIRED ON)
- 含义:强制要求编译器支持 C++17。
- 作用 :如果编译器太老(不支持 C++17),CMake 会直接报错,而不是悄悄降级使用旧标准(如 C++98),避免莫名其妙的编译错误。
大白话翻译:"我指定的 C++ 版本是必须的!编译器不支持就别编译了!"
set(CMAKE_CXX_EXTENSIONS OFF)
工程化细节。这行代码告诉编译器不要使用编译器特有的扩展(比如 GCC 的 -std=gnu++17),而是严格遵循标准(-std=c++17)。这能保证你的代码在不同编译器(GCC, Clang, MSVC)上表现一致,避免"在我的电脑上能跑,换个环境就挂了"的问题。
CUDA 开关与宏定义
cmake
option(ENABLE_CUDA "Enable NVIDIA CUDA support" OFF)
if(ENABLE_CUDA)
add_definitions(-DENABLE_CUDA) # 这一行必须加!
endif()
-
option(ENABLE_CUDA ...): 这是一个交互式开关。- 当你运行
cmake ..时,默认是 OFF。 - 如果你想用 GPU,只需运行
cmake .. -DENABLE_CUDA=ON。这比修改代码去切换版本要专业得多。
- 当你运行
-
add_definitions(-DENABLE_CUDA): 这是连接 CMake 和 C++ 代码的桥梁。-
作用 :它会在编译时给编译器传入一个
-DENABLE_CUDA参数。 -
代码里的体现 :在你的
main.cpp里,你可以这样写:cpp#ifdef ENABLE_CUDA // 初始化 CUDA Provider OrtCUDAProviderOptions cuda_options; session_options.AppendExecutionProvider_CUDA(cuda_options); #endif -
如果没有这一行,即使你链接了 CUDA 库,你的 C++ 代码里关于 CUDA 的初始化代码也不会被编译进去,导致程序实际还是在跑 CPU。
-
查找 OpenCV
cmake
find_package(OpenCV REQUIRED)
if(OpenCV_FOUND)
message(STATUS "OpenCV found: ${OpenCV_VERSION}")
message(STATUS "OpenCV libs: ${OpenCV_LIBS}")
endif()
find_package(OpenCV REQUIRED): CMake 会自动去系统路径(如/usr/local或环境变量OpenCV_DIR)找 OpenCV 的配置文件。REQUIRED: 强制要求。如果没装 OpenCV,CMake 直接报错停止,防止后续出现莫名其妙的错误。message(STATUS ...): 在配置阶段打印出找到的 OpenCV 版本和库列表,方便排查"为什么链接不上"的问题。
此处本人是使用vcpkg 部署的opencv
配置 ONNX Runtime(跨平台处理)
cmake
# 5. 配置 ONNX Runtime
if(WIN32)
# --- Windows 特有逻辑 ---
if(ENABLE_CUDA)
set(ONNXRUNTIME_ROOTDIR "E:/FindJob/onnxruntime-win-x64-gpu-1.14.1")
message(STATUS ">>> 使用 ONNX Runtime GPU 版本")
else()
set(ONNXRUNTIME_ROOTDIR "E:/FindJob/onnxruntime-win-x64-1.14.1")
message(STATUS ">>> 使用 ONNX Runtime CPU 版本")
endif()
else()
# --- Linux 特有逻辑 ---
set(ONNXRUNTIME_ROOTDIR "/usr/local/onnxruntime")
endif()
target_include_directories(${PROJECT_NAME} PRIVATE ${ONNXRUNTIME_ROOTDIR}/include)
target_link_directories(${PROJECT_NAME} PRIVATE ${ONNXRUNTIME_ROOTDIR}/lib)
if(WIN32): 区分操作系统。Windows 下通常使用预编译的压缩包(zip),路径是固定的;Linux 下通常是安装到系统目录。target_include_directories: 告诉编译器去哪里找onnxruntime_cxx_api.h等头文件。target_link_directories: 告诉链接器去哪里找.lib(Windows) 或.so(Linux) 文件。- 注:虽然现代 CMake 推荐用
find_library,但在部署特定版本的 ONNX Runtime 时,直接指定路径(硬编码或变量)往往更直接有效。
- 注:虽然现代 CMake 推荐用
include_directories 和target_include_directories什么关系
一句话终极结论
include_directories = 全局生效(老写法,不推荐)
target_include_directories = 只给某个目标生效(现代 CMake,必须用)
1. 先讲清楚:它们是亲戚关系,但地位完全不同
include_directories是老一辈的命令target_include_directories是现代 CMake 的标准
它们的目的完全一样:
告诉编译器:去哪里找 .h 头文件!
2. 核心区别(最关键)
🔴 include_directories(xxx)
作用范围:整个项目所有目标
- 你写了这一行
- 后面所有
add_executable/add_library - 全部都能找到这个头文件路径
缺点:污染全局!容易冲突!
🟢 target_include_directories(目标 ...)
作用范围:只给这一个目标
- 只让你指定的程序/库能找到头文件,当你在代码中写 #include <myheader.h> 时,编译器会去这个目录下查找。
- 别的目标完全不受影响
优点:干净、安全、现代、无冲突!
3. 举个超级大白话例子
假设你有:
项目
├─ A.exe
└─ B.exe
你只想让 A 能用 OpenCV 的头文件,B 不能用。
✅ 现代正确写法(推荐)
cmake
add_executable(A a.cpp)
# 只给 A 用
target_include_directories(A
PRIVATE
${OpenCV_INCLUDE_DIRS}
)
❌ 老写法(全局污染,不推荐)
cmake
# 全局加路径 → A 和 B 全都能找到
include_directories(${OpenCV_INCLUDE_DIRS})
add_executable(A a.cpp)
add_executable(B b.cpp) # B 也能找到,这可能不是你想要的
4. 最关键的三个关键字
target_include_directories 后面必须跟三个之一:
1) PRIVATE
→ 路径仅给当前目标用
→ 别人链接你时看不到
→ 90% 的情况都用这个!
2) PUBLIC
→ 自己用 + 别人链接你时也能用
→ 给库用
3) INTERFACE
→ 自己不用,只给别人用
→ 纯头文件库用
链接库(CPU vs GPU)
cmake
# 核心库
set(ONNXRUNTIME_LIBS onnxruntime)
# 如果开启 CUDA,需要额外链接 Provider 库
if(ENABLE_CUDA)
# 注意:GPU 版本需要链接这两个额外的库
list(APPEND ONNXRUNTIME_LIBS onnxruntime_providers_cuda)
list(APPEND ONNXRUNTIME_LIBS onnxruntime_providers_shared)
endif()
set(ONNXRUNTIME_LIBS onnxruntime): 初始化库变量,包含最基础的onnxruntime.lib。list(APPEND ...): GPU 部署的坑点 。- ONNX Runtime 的 GPU 实现是模块化的。如果你要用 CUDA,必须链接
onnxruntime_providers_cuda。 - 如果不加这两行,编译可能通过,但运行时会报错
Failed to load shared library或者回退到 CPU 模式。
- ONNX Runtime 的 GPU 实现是模块化的。如果你要用 CUDA,必须链接
生成目标与链接
cmake
# 6. 生成可执行文件
add_executable(${PROJECT_NAME} main.cpp)
# 7. 链接库
target_link_libraries(${PROJECT_NAME}
PRIVATE
${OpenCV_LIBS}
${ONNXRUNTIME_LIBS}
)
add_executable: 生成.exe或可执行文件。注意 :这行必须在target_link_libraries之前,因为链接是依附于目标的。PRIVATE: 这是一个作用域修饰符。表示这些库只用于编译当前项目,不会传递给依赖当前项目的其他库(虽然这里是顶层项目,但加上是个好习惯)。${OpenCV_LIBS}: CMake 会自动展开成opencv_world4xx.lib或者opencv_imgproc;opencv_core等一堆库。
Windows DLL 自动拷贝(工程化神器)
cmake
# 8. Windows DLL 自动拷贝
if(WIN32)
# 拷贝核心 DLL
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${ONNXRUNTIME_ROOTDIR}/lib/onnxruntime.dll"
$<TARGET_FILE_DIR:${PROJECT_NAME}>
)
# 如果开启了 CUDA,还需要拷贝 Provider 的 DLL
if(ENABLE_CUDA)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${ONNXRUNTIME_ROOTDIR}/lib/onnxruntime_providers_cuda.dll"
"${ONNXRUNTIME_ROOTDIR}/lib/onnxruntime_providers_shared.dll"
$<TARGET_FILE_DIR:${PROJECT_NAME}>
)
endif()
endif()
- 为什么需要这个?
- 在 Windows 上,编译出来的
.exe运行时需要同目录下有.dll文件。 - 如果不拷贝,你每次编译完还得手动去把 dll 复制到
bin目录,非常低效。
- 在 Windows 上,编译出来的
add_custom_command(... POST_BUILD ...):- 这是一个构建后钩子。意思是:当你的代码编译链接完成后,CMake 会自动执行后面的命令。
copy_if_different: 智能拷贝。只有当源文件比目标文件新(或者目标文件不存在)时才拷贝,避免每次都无脑覆盖,节省时间。$<TARGET_FILE_DIR:...>: 这是一个生成器表达式,它会自动解析成你的.exe所在的目录(比如bin/Release)。
关于set(CMAKE_EXPORT_COMPILE_COMMANDS ON)的使用
这行代码是连接"构建系统"与"开发工具"的桥梁。简单来说,它的作用是告诉 CMake 在编译时生成一个名为 compile_commands.json 的文件。
这个文件是编译数据库 ,记录了项目中每一个源文件编译时的完整命令 (包括编译器路径、所有的 -I 头文件路径、-D 宏定义等)。
💡 什么时候需要它?
如果你只是单纯在命令行里用 make 或 ninja 编译运行,这个选项不是必须的。
但在以下 3 种"工程化"场景 中,它是必选项:
1. 使用 VS Code / CLion 进行开发(最常用)
当你使用 VS Code 写 C++ 代码时,插件(如 C/C++ 或 Clangd)需要知道你的头文件在哪里,定义了哪些宏。
- 没有它 :编辑器只能瞎猜。它会报一堆红色的波浪线报错(比如
#include <opencv2/...> file not found),即使你的项目明明能编译通过。代码跳转(Go to Definition)也会失效。 - 有了它 :编辑器读取
compile_commands.json,精准还原编译环境,代码补全、跳转、错误检查瞬间变准。
2. 使用静态代码分析工具
如果你想在项目中集成 clang-tidy 或 cppcheck 来检查代码质量。
- 这些工具需要知道完整的编译参数(比如你用了
-std=c++17或者定义了ENABLE_CUDA),否则它们无法正确解析代码,导致误报。
3. 排查复杂的编译错误
有时候编译报错很奇怪,你不知道编译器到底用了什么参数。
- 你可以直接打开这个 JSON 文件,查看对应
.cpp文件的那一行命令,看看是不是漏了什么宏定义或者路径。
🛠️ 如何正确使用?
有两种方式开启,推荐方式二。
方式一:在 CMakeLists.txt 中写死(不推荐)
cmake
# 写在 project() 之前
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
缺点: 每次配置都会生成,哪怕你只是想简单编译一下。而且如果要把代码提交给不需要这个文件的人,会显得多余。
方式二:在命令行配置时开启(推荐 ✅)
这是最灵活的做法,只在需要时生成。
bash
# 在 cmake 配置阶段加上这个参数
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..
总结
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 是现代 C++ 开发(特别是配合 IDE)的标配。 它能极大提升你的编码体验,让你告别"能编译但编辑器一片红"的痛苦。
对于当前项目是否要加set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
非常需要!强烈建议加上。
结合你正在做的 YOLO 部署项目(涉及 OpenCV、ONNX Runtime、CUDA 跨平台切换),加上这行配置会让你的开发体验提升一个档次。
以下是为什么你的项目特别需要它的三个理由:
1. 解决 VS Code 的"爆红"问题(最重要)
你的项目中使用了大量的条件编译 和自定义路径:
- 路径复杂 :你硬编码了
E:/FindJob/onnxruntime...这样的路径。如果不生成compile_commands.json,VS Code 的 IntelliSense 引擎很难猜到你的头文件在这些非标准目录下,会导致#include <onnxruntime_cxx_api.h>报红,即使能编译通过。 - 宏定义复杂 :你用了
if(ENABLE_CUDA)和add_definitions(-DENABLE_CUDA)。- 如果不加 :VS Code 不知道
ENABLE_CUDA被定义了,它会把#ifdef ENABLE_CUDA里面的代码(比如 CUDA 初始化代码)当成注释或者无效代码,导致代码高亮失效、跳转失效。 - 加了之后:编辑器会精准识别:"哦,原来这个宏定义了,那我就要检查这段 CUDA 代码的语法错误。"
- 如果不加 :VS Code 不知道
2. 调试 ONNX Runtime 源码
做部署时,你经常会遇到 ONNX Runtime 报错(比如 OrtStatus 报错)。
- 有了这个文件,配合 VS Code,你可以直接跳转到 ONNX Runtime 的头文件定义处 ,查看
SessionOptions到底有哪些参数可以调,而不需要去浏览器搜文档。
3. 跨平台开发的"后悔药"
你现在可能在 Windows 上开发,以后可能要部署到 Linux。
- 当你把代码迁移到 Linux 时,加上这行配置,配合 VS Code 的 WSL 或 Remote-SSH 插件,它能自动帮你检测 Linux 环境下的路径对不对。如果配置错了,编辑器会立刻提示,而不需要你等到编译报错才发现。
🚀 怎么加?(推荐做法)
不要修改你的 CMakeLists.txt 文件(保持它的纯净性),而是在配置命令里加上它。
Windows (PowerShell/CMD) 用户:
powershell
# 在运行 cmake 配置时加上这个参数
cmake -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
Linux 用户:
bash
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..
💡 加完之后的一步操作
生成后,compile_commands.json 会出现在 build 目录下。
为了让 VS Code 读取到它,你需要在 VS Code 的设置(.vscode/c_cpp_properties.json)里加一行:
json
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**"
],
"compileCommands": "${workspaceFolder}/build/compile_commands.json"
// 👆 加上这一行,指向你的生成位置
}
]
}
总结: 加上它,你的代码提示、跳转、错误检查将瞬间变得精准,这是专业 C++ 开发的标配。
源文件配置方式选择
采用
add_executable(${PROJECT_NAME} main.cpp)方式
还是
file(GLOB SOURCES "${PROJECT_SOURCE_DIR}/src/*.cpp")
add_executable({PROJECT_NAME} {SOURCES})
将 main.cpp 替换为 file(GLOB ...) 是管理多文件项目的常见做法,但这里有一个巨大的"坑",如果不注意,会让后续开发中非常抓狂。
我们来详细拆解一下这两种写法,并给出工业界最推荐的终极方案。
⚠️ 方案一:file(GLOB ...) 的陷阱
cmake
file(GLOB SOURCES "${PROJECT_SOURCE_DIR}/src/*.cpp")
add_executable(${PROJECT_NAME} ${SOURCES})
优点:
- 省事 :你在
src目录下新建一个utils.cpp,不需要改CMakeLists.txt,直接编译就能自动包含进去。
致命缺点(坑):
- 增量更新失效 :CMake 的
GLOB是在配置阶段 (运行cmake ..时)执行的。- 场景 :你正在写代码,突然新建了一个
new_feature.cpp。 - 现象 :你直接点"编译"或
make,编译会失败 或者找不到新文件的符号。 - 原因 :因为
Makefile是在上一次配置时生成的,它不知道今天多了一个文件。你必须重新运行cmake ..才能让它感知到新文件。这在频繁新建文件的开发初期非常打断心流。
- 场景 :你正在写代码,突然新建了一个
✅ 方案二:现代 CMake 的最佳实践 (target_sources)
工业界更推荐显式管理源文件,或者使用更现代的命令。
1. 显式列出(最稳健)
虽然看起来笨,但对于几百个文件的项目,这是最可控的。
cmake
add_executable(${PROJECT_NAME}
src/main.cpp
src/image_processor.cpp
src/yolo_detector.cpp
)
- 优点:修改文件列表一定会触发 CMake 重新配置,构建系统极其稳定。
- 缺点:文件多了写起来累。
2. 使用 target_sources + GLOB(折中方案)
如果你坚持要用 GLOB 的便利性,建议配合 target_sources 使用,并且必须接受"新建文件后要重新配置"这个设定。
cmake
# 1. 先创建目标
add_executable(${PROJECT_NAME})
# 2. 收集源文件
# 注意:这里建议加上 CONFIGURE_DEPENDS (CMake 3.12+)
# 这会让 CMake 在构建时检查文件变动,解决部分"新建文件不生效"的问题,但会轻微增加配置时间
file(GLOB SOURCES CONFIGURE_DEPENDS "${PROJECT_SOURCE_DIR}/src/*.cpp")
# 3. 添加源文件到目标
target_sources(${PROJECT_NAME} PRIVATE ${SOURCES})
🚀 针对你 YOLO 项目的最终建议
考虑到你的项目结构(src/ 目录下可能有多个 .cpp),我建议你采用 "显式列出 + 变量管理" 的方式。这样既清晰,又不会遇到 GLOB 的坑。
修改后的 CMakeLists.txt 核心部分:
cmake
# -----------------------------------------------------------
# 6. 定义源文件列表 (推荐显式管理)
# -----------------------------------------------------------
# 把 src 目录下的所有 cpp 文件写在这里
# 这样当你删除或重命名文件时,CMake 能立刻感知并报错,避免遗留垃圾代码
set(PROJECT_SOURCES
src/main.cpp
src/image_processor.cpp
# src/yolo_detector.cpp <-- 以后加新文件,在这里加一行即可
)
# -----------------------------------------------------------
# 7. 生成可执行文件
# -----------------------------------------------------------
add_executable(${PROJECT_NAME} ${PROJECT_SOURCES})
# -----------------------------------------------------------
# 8. 包含头文件目录
# -----------------------------------------------------------
target_include_directories(${PROJECT_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${OpenCV_INCLUDE_DIRS}
${ONNXRUNTIME_ROOTDIR}/include
)
# -----------------------------------------------------------
# 9. 链接库
# -----------------------------------------------------------
target_link_directories(${PROJECT_NAME} PRIVATE ${ONNXRUNTIME_ROOTDIR}/lib)
target_link_libraries(${PROJECT_NAME} PRIVATE
${OpenCV_LIBS}
${ONNXRUNTIME_LIBS}
)
总结
- 如果处于快速原型期 (疯狂新建文件):用
file(GLOB SOURCES CONFIGURE_DEPENDS ...),但要记得新建文件后重新运行 CMake。 - 如果处于稳定开发期 (文件结构基本固定):用
set(PROJECT_SOURCES ...)显式列出。这是最专业、最不容易出错的做法。
我的建议 :养成显式列出文件的习惯(方案2)对你的长远发展更有利。
在VSCode中编写CMakeLists.txt 哪些部分是会被高亮显示
我直接给你最清晰、最实用、一看就懂 的答案!
你在 VSCode 里写 CMakeLists.txt ,哪些会高亮、哪些不会,我一次性讲全!
✅ 一定会被高亮的内容(核心)
这些是 CMake 语法的关键字/指令 ,任何 CMake 插件都会高亮:
1. CMake 命令(蓝色/紫色/绿色)
所有大写/小写命令名都会高亮:
cmake
project()
find_package()
add_executable()
target_link_libraries()
include_directories()
set()
if()
else()
endif()
foreach()
这些是核心语法 → 必高亮
2. 变量(黄色/青色)
以 ${} 包裹的变量:
cmake
${PROJECT_NAME}
${OpenCV_LIBS}
${CMAKE_CXX_STANDARD}
3. 字符串(红色/橙色)
双引号包裹的文本:
cmake
"My Project"
"opencv4"
4. 注释(绿色/灰色)
以 # 开头:
cmake
# 这是注释,一定会高亮
5. 控制流关键字(深蓝色)
cmake
if else endif
while
foreach
function
return
❌ 不会高亮 / 高亮很弱的内容
这些是你自己定义的内容,插件无法识别:
1. 你自己写的 项目名、文件名
cmake
add_executable(
main # 普通颜色,不高亮
main.cpp # 普通颜色,不高亮
)
2. 自定义变量名
cmake
set(MY_VAR 123) # MY_VAR 不高亮
3. 路径、普通数字
cmake
D:/opencv/include
11
20