CMake 生成的程序无法在 Windows 上链接:尝试链接到不存在的文件

Posted

技术标签:

【中文标题】CMake 生成的程序无法在 Windows 上链接:尝试链接到不存在的文件【英文标题】:CMake generated program fails to link on Windows: tries to link to non-existent file 【发布时间】:2018-12-11 12:13:33 【问题描述】:

我正在尝试在 Windows 上编译一个非常简单的测试程序并不断收到链接器错误。要链接的程序如下:

#include <boost/asio/io_context.hpp>

int main()

    boost::asio::io_context context;

虽然 CMakeLists.txt 看起来像这样:

cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(windows-test)

SET(CMAKE_CXX_STANDARD 17)

find_package(Boost 1.6.7 COMPONENTS system)

include_directories("$Boost_INCLUDE_DIRS")
add_executable(windows-test main.cpp)
target_link_libraries(windows-test Boost::system)

使用 nmake 构建它时,它会失败并显示以下输出:

-- Boost version: 1.67.0
-- Found the following Boost libraries:
--   system
-- Configuring done
-- Generating done
-- Build files have been written to: Z:/windows-test/build
[ 50%] Linking CXX executable windows-test.exe
LINK Pass 1: command "C:\PROGRA~2\MICROS~1\2017\BUILDT~1\VC\Tools\MSVC\1414~1.264\bin\Hostx64\x64\link.exe /nologo @CMakeFiles\windows-test.dir\objects1.rsp /out:windows-test.exe /implib:windows-test.lib /pdb:Z:\windows-test\build\windows-test.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console C:\local\boost_1_67_0\lib64-msvc-14.1\boost_system-vc141-mt-gd-x64-1_67.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:CMakeFiles\windows-test.dir/intermediate.manifest CMakeFiles\windows-test.dir/manifest.res" failed (exit code 1104) with the following output:
LINK : fatal error LNK1104: cannot open file 'libboost_system-vc141-mt-gd-x64-1_67.lib'
NMAKE : fatal error U1077: '"C:\Program Files\CMake\bin\cmake.exe"' : return code '0xffffffff'
Stop.
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Tools\MSVC\14.14.26428\bin\HostX64\x64\nmake.exe"' : return code '0x2'
Stop.
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Tools\MSVC\14.14.26428\bin\HostX64\x64\nmake.exe"' : return code '0x2'
Stop.

文件'libboost_system-vc141-mt-gd-x64-1_67.lib'在系统上确实不存在,但我不知道它来自哪里,因为它没有出现在链接器命令中它正在执行。链接器命令显示文件 C:\local\boost_1_67_0\lib64-msvc-14.1\boost_system-vc141-mt-gd-x64-1_67.lib,它确实存在。

为什么哦,为什么它会尝试链接到一个丢失的文件,而链接器命令中却没有出现该文件?在这里我觉得我的深度不够,因为我已经有将近 20 年没有使用过 Windows 并且以前从未移植到它。

【问题讨论】:

看我的回答。另外,您是否安装了正确版本的 boost? 你写"文件'libboost_system-vc141-mt-gd-x64-1_67.lib'确实不存在" 然后"... boost_system -vc141-mt-gd-x64-1_67.lib,确实存在”。那么它存在还是不存在?你编译了boost吗?问题标题也与问题描述不符。 @VTT 注意lib 前缀的存在/不存在;它们是两个不同的文件名。 标题有误。这是我在链接 $Boost_LIBRARIES 而不是 Boost::system 时遇到的错误。我现在已经纠正了这一点。您提到的文件名不同。一个包含“lib”前缀,另一个不包含。该文件仅存在没有前缀。链接器命令也只包含不带前缀的版本。 有lib前缀的应该是静态库,没有lib前缀的应该是导入库。但是,如果您正确构建了 boost,它们都应该存在。我怀疑静态库版本是通过 boost 源代码中的指令隐式链接的,因为链接库的静态版本是 Windows 上 boost 的默认行为。您可以尝试定义BOOST_ALL_DYN_LINK 以强制它使用库的动态版本或BOOST_ALL_NO_LIB 以强制它不与链接器设置混淆。 【参考方案1】:

Boost 标头包含 Windows 上的链接器命令,因此 Boost 库在包含适当的标头时会自动链接。但是,您的设置似乎对库使用了不同的命名方案,这使得它们无法链接。

您可以通过定义预处理器宏 BOOST_ALL_NO_LIB 来禁用 Boost 自动链接功能。像这样:

target_compile_definitions(windows-test PRIVATE BOOST_ALL_NO_LIB)

【讨论】:

这确实解决了它。我想知道我的命名方案有什么问题。我从 sourceforge.net/projects/boost/files/boost-binaries 安装了预编译的 boost 库,我尝试从源代码编译,但在 Windows 上速度非常慢,编译大约需要 3 天。 @MartijnOtto 根据 VTT 的评论,它看起来像是静态/动态库不匹配。

以上是关于CMake 生成的程序无法在 Windows 上链接:尝试链接到不存在的文件的主要内容,如果未能解决你的问题,请参考以下文章

Cmake 无法正确生成 assimp 解决方案 [Windows 10]

如何使用cmake在mac上链接OpenGL相关库?

Cmake是啥?有啥用?在WINDOWS下如何用

从现有 cmake 应用程序导入的 Netbeans 项目无法在 Windows 上构建并出现文件系统错误

cmake 在Windows 命令行怎么指定编译器

cmake 不使用 QT4_automoc 生成 Qt moc 文件