V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zcion
V2EX  ›  C++

记录一次踩坑过程(clion + cmake + vcpkg)

  •  
  •   zcion · 20 天前 · 1462 次点击

    首先结论放这里:编写 cmake 文件时,project(xxx) 放在越后边越好,避免在它之后定义和构建相关的宏变量

    好的,下边是踩坑经历: 楼主在写一个程序时,突发奇想的想分别使用 vs 工具链和 mingw 工具链跑下代码,所需要的库文件都是用 vcpkg 下载的。

    CMAKE_TOOLCHAIN_FILE 举例,使用 vcpkg + cmake,就需要定义这个值(指明你的 vcpkg.cmake 放在哪个路径下,通常是 xxx/vcpkg/scripts/buildsystems/vcpkg.cmake)。要定义这个值,要么就是在执行 cmake 构建命令时加上 -DCMAKE_TOOLCHAIN_FILE 参数,要么就是直接在 cmake 文件中指定。第二种方法很好理解,直接在 cmake 文件定义就行( clion 在构建时会将其添加进 cache variable),而第一种,如果是在 clion 中,你就需要在如下图位置指定:

    那么问题就来了,由于楼主需要分别使用 msvcgcc 编译,所以需要定义 VCPKG_TARGET_TRIPLET 来选用 vcpkg 中库文件的 triplet ,第一次用 msvc 编译项目,没有任何问题,但换成 mingw 后就出现莫名其妙的问题(例如 cmake 构建不成功,构建成功但链接时找不到对应的 lib )。在进行了一系列的排查发现,虽然我在 cmake 中指定了 set(VCPKG_TARGET_TRIPLET x64-mingw-dynamic),但 clion 的 cache variable 中的 VCPKG_TARGET_TRIPLET 的值雷打不动的为 x64-windows(因为先用的是 vs 工具链的,所以 clion 一直用的是缓存的值)。在经过很长一段时间的折磨后,我突发奇想的将所有设计 vcpkg 的宏定义提到了 cmake 文件的最前边,然后问题就解决了。

    # 从原先的这样
    cmake_minimum_required(VERSION 3.30)
    project(myproject)
    set(CMAKE_TOOLCHAIN_FILE "D:/development-tool/vcpkg/scripts/buildsystems/vcpkg.cmake")
    set(VCPKG_TARGET_TRIPLET x64-mingw-dynamic)
    # ...
    
    # 变成这样
    cmake_minimum_required(VERSION 3.30)
    set(CMAKE_TOOLCHAIN_FILE "D:/development-tool/vcpkg/scripts/buildsystems/vcpkg.cmake")
    set(VCPKG_TARGET_TRIPLET x64-mingw-dynamic)
    # ...
    project(myproject)
    # ...
    

    最后想通了,在 project() 前定义宏,这些宏就能够在项目在构建前使用,这样 clion 就能够先写入 cache variable,这样就确保项目构建的行为是根据 cmake 文件中来的。反之在 project() 后定义,这些宏就变为在项目构建过程中才能使用,这就导致了 clion 需要在构建前指定 vcpkg 某些宏找不到,所以 clion 用的是缓存的值。

    相信有一部分人和我一样,在开始写 cmake 时,喜欢用默认的模板来写,而默认模板的 project() 又是最先写的,等到项目逐渐的开发,需要往 cmake 中假如越来越多东西,这些东西很容易就加到 project() 后,然后一些在构建前需要用到的宏无法被识别,从而引发一系列问题。

    这个点可能是 cmake 很常规的一个点,但如果忽略了,就可能像我一样,在 google->ai 后陷入“明明都是按照语法来的,怎么死活就跑不起来”,然后无能狂怒数个小时的情况。

    最后再分享点心得,如果什么都看着正常,但项目就是跑不起来,可以看看 cache variable 中的值是否有问题

    5 条回复    2025-08-15 10:02:26 +08:00
    ashong
        1
    ashong  
       20 天前 via iPhone
    VCPKG_TARGET_TRIPLET 设置强制就可以了

    用 presets 更省事
    hwdq0012
        2
    hwdq0012  
       20 天前
    文档里好像有要求要写在前面吧,我找找
    hwdq0012
        3
    hwdq0012  
       20 天前
    @hwdq0012 #2 https://learn.microsoft.com/zh-cn/vcpkg/get_started/get-started?pivots=shell-powershell
    文档变好快, 这个 preset 我之前都不知道, 不过我一般都用清单模式不同的项目的依赖编译到不同的目录,再手动设置进去,cmake_toolchain_file 我一般都指向自己的交叉编译工具链文件
    hwdq0012
        4
    hwdq0012  
       20 天前
    hwdq0012
        5
    hwdq0012  
       20 天前
    @hwdq0012 #3
    CMake Presets:由 CMake 从 3.19+ 支持。
    vcpkg 官方推荐使用 Presets:大约从 2023 年开始逐步推广,2024–2025 的官方文档中明确使用示例。
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1048 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 18:37 · PVG 02:37 · LAX 11:37 · JFK 14:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.