记录一次踩坑过程(clion + cmake + vcpkg)
首先结论放这里:编写 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 中,你就需要在如下图位置指定:

那么问题就来了,由于楼主需要分别使用 msvc
和 gcc
编译,所以需要定义 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
中的值是否有问题
