TL;DR: 简单来说是 CLion 的问题; 解决方法就是避免使用 clang-cl 工具链.

2023/02/24 更新: 最新的 CLion EAP 似乎已经修正了这个问题.


昨天比较闲, 就给 vcpkg 里的包都升级了一下, 自然是要重新构建 (大概花了 4 个小时). 说来最近 vcpkg 好像会自动清理掉构建过程的缓存了, 可能是觉得, 对于大多数用户, 或者说作为一款包管理器, 留着 buildtrees 的实际价值不大吧, 毕竟需要自行修改代码进行构建的用户可能也不会从包管理器里面去安装依赖.

升级完后, 自然是想体验一下, 于是打开 CLion 新建一个项目, 引入 Boost 依赖, 找一个简单的 demo 试一下能不能用, 然后就遇到了问题.

"C:\Program Files\CMake\bin\cmake.exe" --build D:\repos\boost-demos\cmake-build-debug --target bt -j 6
[1/2] Building CXX object CMakeFiles\bt.dir\bt.cpp.obj
[2/2] Linking CXX executable bt.exe
FAILED: bt.exe
cmd.exe /C "cd . && "C:\Program Files\CMake\bin\cmake.exe" -E vs_link_exe --intdir=CMakeFiles\bt.dir --rc="D:\Windows Kits\10\bin\10.0.22621.0\x64\rc.exe" --mt="D:\Windows Kits\10\bin\10.0.22621.0\x64\mt.exe" --manifests  -- "D:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\Llvm\x64\bin\lld-link.exe" /nologo CMakeFiles\bt.dir\bt.cpp.obj  /out:bt.exe /implib:bt.lib /pdb:bt.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console  D:\repos\vcpkg\installed\x64-windows\debug\lib\boost_program_options-vc140-mt-gd.lib  kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cmd.exe /C "cd /D D:\repos\boost-demos\cmake-build-debug && C:\Users\Henry\AppData\Local\Microsoft\WindowsApps\pwsh.exe -noprofile -executionpolicy Bypass -file D:/repos/vcpkg/scripts/buildsystems/msbuild/applocal.ps1 -targetBinary D:/repos/boost-demos/cmake-build-debug/bt.exe -installedDir D:/repos/vcpkg/installed/x64-windows/debug/bin -OutVariable out""
LINK Pass 1: command "D:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\Llvm\x64\bin\lld-link.exe /nologo CMakeFiles\bt.dir\bt.cpp.obj /out:bt.exe /implib:bt.lib /pdb:bt.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console D:\repos\vcpkg\installed\x64-windows\debug\lib\boost_program_options-vc140-mt-gd.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:CMakeFiles\bt.dir/intermediate.manifest CMakeFiles\bt.dir/manifest.res" failed (exit code 1) with the following output:
lld-link: error: undefined symbol: void __cdecl boost::throw_exception(class std::exception const &)
>>> referenced by D:\repos\vcpkg\installed\x64-windows\include\boost\function\function_template.hpp:761
>>>               CMakeFiles\bt.dir\bt.cpp.obj:(public: void __cdecl boost::function1<void, int const &>::operator()(int const &) const)
>>> referenced by D:\repos\vcpkg\installed\x64-windows\include\boost\program_options\detail\value_semantic.hpp:62
>>>               CMakeFiles\bt.dir\bt.cpp.obj:(class std::basic_string<char, struct std::char_traits<char>, class std::allocator<char>> const & __cdecl boost::program_options::validators::get_single_string<char>(class std::vector<class std::basic_string<char, struct std::char_traits<char>, class std::allocator<char>>, class std::allocator<class std::basic_string<char, struct std::char_traits<char>, class std::allocator<char>>>> const &, bool))
>>> referenced by D:\repos\vcpkg\installed\x64-windows\include\boost\program_options\detail\value_semantic.hpp:66
>>>               CMakeFiles\bt.dir\bt.cpp.obj:(class std::basic_string<char, struct std::char_traits<char>, class std::allocator<char>> const & __cdecl boost::program_options::validators::get_single_string<char>(class std::vector<class std::basic_string<char, struct std::char_traits<char>, class std::allocator<char>>, class std::allocator<class std::basic_string<char, struct std::char_traits<char>, class std::allocator<char>>>> const &, bool))
>>> referenced 2 more times
ninja: build stopped: subcommand failed.

CMakeLists 如下:

cmake_minimum_required(VERSION 3.22)
project(Boost-Demos)set(CMAKE_CXX_STANDARD 14)find_package(Boost REQUIRED COMPONENTS program_options)message("Boost libraries: ${Boost_LIBRARIES}")add_executable (bt "bt.cpp")
target_link_libraries(bt Boost::boost ${Boost_LIBRARIES})

是老生常谈的 undefined symbol (未定义符号), 然后一看似乎是 Boost 库里的符号, 那么也许是少链接了某个 Boost 的库吧? 毕竟 Boost 目前好像还没有官方正式的 CMake 支持, vcpkg 也有出问题的可能. 因此, 猜测可能是 CMake Target 有些 bug 的地方.

但是直接查相应的错误, 然而发现没有结果. 由于看到 vcpkg 前几天刚推出的 Release, 所以也怀疑过是 vcpkg 的问题, 但是看到 Boost 库的 port 好像是几个月前更新的了, 这么长时间也没有用户提出相关的 issue, 应该 vcpkg 本身没问题.

差点就冲动去给 vcpkg 提 issue 了, 虽然解决问题的过程中间实在找不到办法的时候还是发了个 discussion.

于是只能从自己这边找问题.

先是尝试在 CMakeLists.txt 里面给目标多链接一个 Boost 的 throw_exception 库, 结果也没有任何变化.

首先在其他地方重新安装了一份 vcpkg, 发现没有问题, 同时还在 WSL 2 Ubuntu 上进行了测试, 构建十分顺滑没有问题, 于是排除了项目的 CMakeLists.txt 以及 Boost 和 vcpkg 自身的问题.

并且, 通过检测生成的构建脚本, 发现确实只链接了 program_options 这一个库. 根据报错信息里边的构建命令发现, 实际上也是指定了要链接这个库.

这样一来就说明, CMake 所解出的要链接的库, 以及生成的链接命令都没有差错, 那么可能存在问题的地方就只剩下编译器工具上了.

可笑的是, 笔者直到这时才想起来换一下构建工具试试. 先是换了 IDE, 打开 Visual Studio, 其默认使用的是自己的 MSVC 构建工具链, 结果成功构建没有问题, 更换 Clang for MSVC 也没有问题; 打开 Visual Studio Code, 然而 CMake Tools 插件从生成到构建也没有问题.

这样一来就是施展控制变量法的好时机了. 在 CLion 和其他工具中使用相同的工具集, 也就是 clang-cl, 即 Clang (MSVC CLI) for MSVC, 然后比对不同环境下 CMake 生成的 CMakeCache.txt, 发现 CMAKE_C_FLAGSCMAKE_CXX_FLAGS 变量的值有蹊跷: CLion 生成的CMake 缓存里面, CMAKE_C_FLAGS 等变量处只有 -m64, 而缺失了 /DWIN32 /D_WINDOWS /W3 /GR /EHsc 等参数.

既然发现 CMakeCache.txt 这里有问题, 那问题应该就出在这之前的步骤, 也就是 CMake 的生成步骤. 通过比较不同 IDE 所执行的 CMake 命令发现, CLion 这边多传递了 -DCMAKE_C_FLAGS=-m64-DCMAKE_CXX_FLAGS=m64 这两个选项给 CMake.

而观察 Visual Studio 生成的 CMake 缓存, 发现虽然附加了 -m64 这个参数 (进行 CMake 生成时候也提示拾取了这两个环境变量), 但是也有上面提到的 “缺失” 的参数.

笔者更换了一个 CLion 的版本, 发现情况一致: 即, 在使用 clang-cl 时, CLion 就会给出这两个选项, 而使用 GNU 风格命令行选项版本的 Clang (GNU CLI) for MSVC (clang) 时, CLion 就不会传递这两个选项.

目前笔者并不清楚是 CLion 自身的问题还是笔者本人的配置问题, 抑或是 MSVC 的问题, 但是目前感觉可能主要是 Visual Studio MSVC 的问题, 而 CLion 在识别并应用 Visual Studio 工具链的方式导致了问题的发生.

感觉是 Visual Studio 和 CLion 的处理方式不同, Visual Studio 是把环境中的 C/C++ 编译器选项参数附加到了 CMake 生成的缓存里, 而 CLion 是直接认为这个参数应该覆盖掉 CMake 的选项. 而之所以认为是 BUG, 是因为 -m64 并不是 CMD 风格的命令行选项.

毕竟, 对于不需要链接外部库的项目来说, 这些选项存在与否好像没有什么影响. 而在笔者把这些缺失的命令行选项手动加回到 CMake 缓存后, CMake 生成的构建脚本就能正常构建并链接到 Boost 库了.

遗憾的是, 笔者暂时没有更多时间精力去调查清楚, 比如实验一下对于其他的外部库是否存在该问题, 还有研究一下 CLion 使用 Visual Studio 开发环境的方式, 找出来到底是那个环节出了问题.

总而言之, 目前的解决办法是, 使用 clang 而不是 clang-cl.

CLion 使用 clang-cl 工具链时未正确链接 vcpkg 中的 Boost 外部库相关推荐

  1. c语言int64编译时错误,错误:编译C程序时未在此作用域中声明uint64_t

    我正在尝试一个简单的程序来打印steady_clock的时间戳值,如下所示: #include #include using namespace std; int main () { cout < ...

  2. php magic quotes 选项为 on,PHP:当Magic Quotes为ON时,如何(正确)删除数组中的转义引号...

    如您所知,当Magic Quotes为ON时,单引号会在值和键中转义.大多数在运行时删除Magic Quotes的解决方案只能取消值,而不是键.我正在寻找一种能够解决关键和价值观的解决方案-- 我在P ...

  3. gcc mips64编译后无法运行在octeon上运行_编译工具链

    软件的编译过程由一系列的步骤完成,每一个步骤都有一个对应的工具.这些工具紧密地工作在一起,前一个工具的输出是后一个工具的输入,像一根链条一样,我们称这些工具为工具链. Linux系统上,通常只需要使用 ...

  4. 研发平台演进:从工具链到开放平台

    在数字化的转型浪潮中,开发人员的生产力越来越被企业重视,提升团队研发效能.缩短TTM成为了实现企业战略目标的重要措施.企业中的研发团队从每个团队各自试验.探索,逐步整合基础设施.最佳实践.企业规范等, ...

  5. Android开发工具链ppt,介绍Android原生开发工具包r14

    原标题:介绍Android原生开发工具包r14 现在,可以下载最新版本 Android 原生开发工具包 (NDK)--Android NDK r14.也可以通过 Android Studio 在 SD ...

  6. linux centos7 使用 crosstool-ng 构建 交叉编译 工具链 即构建各cpu架构平台的gcc编译器

    简介 crosstool-ng,全称是crosstool Next Generation,即下一代crosstool.crosstool是个交叉编译器的制作工具,但是做的不够好,于是有人(Yann E ...

  7. Buildroot构建指南——工具链

    Linux系统的交叉编译工具链用来将源代码变成bin文件或者库文件的一个软件.一般大家默认工具链等于gcc或者arm-linux-gcc,但是实际上,gcc只是工具链的编译器部分,不是全部,制作一个工 ...

  8. linux 编译工具链,Linux工具链for TKStudio下载_Linux工具链for TKStudio官方下载-太平洋下载中心...

    Linux工具链for TKStudio是一款支持TKStudio IDE集成开发环境的辅助LINUX交叉编译工具链软件,交叉编译就是跨架构编译,编译出来的程序不能在本机执行(当然有例外情况).所以这 ...

  9. 交叉编译工具链建立与常识

    交叉编译工具链的命名规则 arch [-vendor] [-os] [-(gnu)eabi] arch – 体系架构,如ARM,MIPS,对于MIPS可能还分大端模式mips或者小端模式mipsel: ...

最新文章

  1. SpringBoot同时集成Redis和Guava作为缓存组件--进一步分析代码
  2. 阿里8亿加持B端智能化后,本地生活服务更好做了吗?
  3. Google Chrome —— 离线安装/安装包下载解决方案
  4. “数学的重要性及其应用“系列公益讲座01
  5. 如何看Cortex-M系列处理器差异与共性?技术老司机Joseph带你飞
  6. 单列多行转单行单列合并oracle_oracle中多行转单行的两种方法
  7. 教育部推出首批490门“国家精品在线开放课程”
  8. 单片机自动调光C语言,51单片机触控调光程序C语言
  9. 【Python-3.3】使用while循环实现列表间数据移动
  10. Intellij IDEA 修改默认配置
  11. 【Caffe代码解析】Layer网络层
  12. 使用虚拟机备份软件备份云宏Winghong CNware虚拟机
  13. Chirp信号基础知识及matlab实现
  14. Tomcat Get请求中文乱码
  15. postman压力测试
  16. 微信的Linux版本,ubuntu16.04安装微信,linux原生版
  17. MoveIt与RobotStudio
  18. sap中re凭证是什么意思_SAP财务模块内有哪些凭证类型
  19. 夜宿祝国寺(文:元哲)
  20. 2019年9月Leetcode每日训练日志

热门文章

  1. 初学者必看,提供海星检测项目从零开始小目标检测sota算法(ppyoloe-sod)
  2. SQL 笔记 By 华仔
  3. !!!!!!!!!!!!!!!!!!!!1哥!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  4. msm8660 add lcd driver
  5. 去掉Visual Studio 2019绿色波浪线
  6. linux下恢复win10启动,重装win10后原来的ubuntu系统启动项丢失恢复方式
  7. Go1.8 泛型简单上手使用
  8. MySQl数据库-批量添加数据的两种方法
  9. Windows注册表互换Caps Lock、Shift、Ctr l键
  10. 初学Java的安装和环境配置全教程