
在 CMake 项目中使用动态库本文说明cmake-use-lib如何查找、链接并运行cmake-lib安装的两个动态库以及如何通过compile_commands.json为 clangd 提供语法和跳转支持。动态库的创建和导出过程见使用 CMake 创建并导出动态库。1. 消费关系概览消费流程分为三个阶段cmake-lib构建并安装头文件、DLL、导入库和 CMake 包配置。cmake-use-lib通过find_package(cmake-lib)加载导入目标并完成编译、链接。程序启动时Windows 从可执行文件目录或PATH中查找 DLL。项目使用以下两个导入目标导入目标提供的功能cmake-lib::message_utilsbuild_message()cmake-lib::sort_utils五种返回排序副本的排序函数2. 环境要求Windows 与 PowerShell 7pwshCMake 3.25 或更高版本MinGW 的gcc、g和mingw32-make已加入PATH使用同一套兼容 MinGW 工具链构建并安装的cmake-lib如需代码补全和跳转clangd 可执行文件及 VS Code clangd 扩展虽然两个项目的CMakeLists.txt声明 CMake 3.16但CMakePresets.json使用 schema version 6因此本文的 preset 命令要求CMake 3.25 或更高版本。3. 完整构建和运行流程以下命令从仓库根目录开始执行。3.1 构建并安装动态库Set-Location.\cmake-lib cmake--preset mingw cmake--build--preset mingwbuild cmake--install build/mingw--prefix C:/install/cmake-lib安装完成后至少应存在C:/install/cmake-lib/ ├── bin/ │ ├── libmessage_utils.dll │ └── libsort_utils.dll ├── include/ │ └── cmake-lib/ │ ├── message.h │ └── sort_algorithms.h └── lib/ ├── libmessage_utils.dll.a ├── libsort_utils.dll.a └── cmake/ └── cmake-lib/ ├── cmake-lib-config.cmake ├── cmake-lib-config-version.cmake ├── cmake-lib-targets.cmake └── cmake-lib-targets-debug.cmake3.2 配置并构建消费程序Set-Location..\cmake-use-libcmake--preset mingw cmake--build--preset mingwbuild如果build/mingw以前配置过其他安装前缀应使用cmake --fresh --preset mingw重新生成缓存避免沿用旧的cmake-lib_DIR。mingwpreset 已设置CMAKE_PREFIX_PATH:C:/install/cmake-lib因此配置阶段会在安装前缀下查找cmake-lib的包配置。3.3 配置 DLL 搜索路径并运行$env:PATH C:\install\cmake-lib\bin;$env:PATH.\build\mingw\cmake-use-lib.exe$env:PATH的修改只影响当前 pwsh 进程及其子进程不会永久修改系统环境变量。程序的预期输出为Hello from a CMake subdirectory project built with MinGW. 原始数组: 5 3 8 1 9 2 7 4 6 快速排序: 1 2 3 4 5 6 7 8 9 冒泡排序: 1 2 3 4 5 6 7 8 9 归并排序: 1 2 3 4 5 6 7 8 94. CMake 如何找到并链接动态库4.1CMAKE_PREFIX_PATH指向安装前缀CMAKE_PREFIX_PATH应指向安装根目录而不是bin、lib或具体的.cmake文件CMAKE_PREFIX_PATH └── C:/install/cmake-lib └── lib/cmake/cmake-lib/cmake-lib-config.cmake4.2find_package()加载包配置项目通过以下语句加载安装包find_package(cmake-lib REQUIRED)cmake-lib-config.cmake随后加载cmake-lib-targets.cmake从而创建cmake-lib::message_utils cmake-lib::sort_utils4.3 链接导入目标消费端不硬编码 DLL 或.dll.a的路径而是直接链接导入目标add_executable(cmake-use-lib src/main.cpp) target_link_libraries(cmake-use-lib PRIVATE cmake-lib::message_utils cmake-lib::sort_utils )导入目标会把安装前缀下的 include 目录和 MinGW 导入库传递给cmake-use-lib。由于最终目标是可执行程序使用PRIVATE即可无需继续向下游传播依赖。源码因此可以直接包含安装后的头文件#includecmake-lib/message.h#includecmake-lib/sort_algorithms.h4.4 链接阶段与运行阶段不同构建时链接器使用prefix/lib/*.dll.a。运行时Windows 加载器查找prefix/bin/*.dll。CMAKE_PREFIX_PATH只参与 CMake 配置不会改变 Windows 的运行时 DLL搜索路径。因此即使程序成功链接运行前仍需要配置PATH或者把 DLL 放到可执行文件同一目录。推荐使用当前会话的PATH避免复制出过期 DLL。5. clangd 语法支持5.1 先生成编译数据库CMakePresets.json已开启CMAKE_EXPORT_COMPILE_COMMANDS:ON成功执行下面的配置命令后cmake--preset mingwCMake 会生成cmake-use-lib/build/mingw/compile_commands.json该文件记录真实编译器、C17 参数和 include 搜索路径是 clangd 理解工程的主要依据。更换依赖路径、编译器或 CMake 配置后应重新运行配置命令。5.2.clangd定位编译数据库项目根目录的.clangd包含CompileFlags:CompilationDatabase:build/mingwAdd:--IC:/install/cmake-lib/includeDiagnostics:Suppress:-pp_file_not_foundIndex:Background:BuildCompilationDatabase让 clangd 直接读取build/mingw无需把compile_commands.json复制到项目根目录。Add为安装头文件提供额外的兜底搜索路径。Index.Background: Build开启后台索引。pp_file_not_found被抑制后头文件缺失诊断可能不会显示如果跳转或补全失败仍应检查安装路径和编译数据库而不是把诊断抑制视为依赖已正确加载。正常完成 CMake 配置后导入目标的 include 路径也会进入编译数据库。.clangd中的Add是补充配置不能代替成功安装库和运行 CMake 配置。5.3 VS Code 设置.vscode/settings.json禁用了 Microsoft C/C 扩展的 IntelliSenseC_Cpp.intelliSenseEngine:disabled这样可以避免它与 clangd 同时提供诊断和补全。该设置不会自动安装 clangd仍需保证 clangd 可执行文件和 VS Code clangd 扩展在本机可用。同一设置文件还把 PowerShell 7 路径写为C:\sw\PowerShell-7.4.17\pwsh.exe。如果本机安装位置不同需要调整该终端路径它与 clangd 的工作方式无关。6. 使用自定义安装前缀如果不安装到C:/install/cmake-lib前两个位置必须保持一致安装库时的--prefix消费端配置时的CMAKE_PREFIX_PATH为避免兜底搜索路径继续引用旧版本.clangd中附加的-Iprefix/include也应同步修改或者移除这条冗余的Add。例如使用D:/sdk/cmake-lib以下命令从仓库根目录开始执行$sharedLibPrefixD:/sdk/cmake-libSet-Location.\cmake-lib cmake--preset mingw cmake--build--preset mingwbuild cmake--install build/mingw--prefix$sharedLibPrefixSet-Location..\cmake-use-libcmake--fresh--preset mingw-DCMAKE_PREFIX_PATH$sharedLibPrefixcmake--build--preset mingwbuild$env:PATH $(Join-Path$sharedLibPrefixbin);$env:PATH.\build\mingw\cmake-use-lib.exe同时把.clangd更新为CompileFlags:CompilationDatabase:build/mingwAdd:--ID:/sdk/cmake-lib/include成功配置后导入目标的新 include 路径会进入compile_commands.json。如果没有同步修改.clangdclangd 还会额外搜索旧目录旧安装仍存在时可能出现错误跳转或头文件版本混用。7. 常见问题现象原因与处理CMake 提示找不到cmake-libConfig.cmake先安装cmake-lib确认CMAKE_PREFIX_PATH指向安装根目录切换前缀后用--fresh清除旧的cmake-lib_DIR缓存#include cmake-lib/...飘红确认头文件已安装、重新运行cmake --preset mingw并核对.clangd的-I路径没有compile_commands.json配置尚未成功或查看了错误的 build 目录修改配置后 clangd 仍显示旧结果重新配置 CMake并重启 clangd language server程序启动时提示缺少libmessage_utils.dll或libsort_utils.dll在同一 pwsh 会话中把安装目录的bin加入PATH链接时报未定义符号或文件格式错误确认库和程序使用兼容的 MinGW 工具链、架构及构建配置使用 MSVC 构建失败当前库没有通用的 Windows 导出宏现有流程只验证了 MinGW