本文主要是介绍【问题记录】c++编译报错~/bin/ld.exe: cannot find 0,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
构建环境
windows 11
cmake 3.29.0-rc2
MinGW 8.1.0
先说结论
推测这应该是MinGW和cmake版本的部分不兼容导致的,尝试使用旧一点的cmake或新一些的MinGW或许会解决这个问题。
诡异的 0
是怎么来的
首先这个程序没有链接任何外部库,也没导出任何库;
我通过添加cmake -- VERBOSE=1
参数查看详细信息后发现问题出在build.make
文件中的这一句命令
F:/MinGW/bin/c++.exe -g \
-Wl,--whole-archive CMakeFiles/print_hello_world.dir/objects.a \
-Wl,--no-whole-archive -o print_hello_world.exe \
-Wl,--out-implib,"" \
-Wl,--major-image-version,0,--minor-image-version,0 @CMakeFiles/print_hello_world.dir/linkLibs.rsp
经过分析问题是在--out-implib,""
这个参数,不明白cmake为什么会生成这一句,似乎这个版本的c++.exe
没有将""
识别为空 ,并且又把--major-image-version
后面的主版本号0
识别为了一个库,所以才出现了这个链接错误,删除-Wl,--out-implib,""
或主版本号0后恢复正常,这里肯定是选择删除-Wl,--out-implib,""
才符合语义。
另外如果链接了第三方库,反而不会出问题。
修正前报错~/bin/ld.exe: cannot find 0
F:/MinGW/bin/c++.exe -g \
-Wl,--whole-archive CMakeFiles/print_hello_world.dir/objects.a \
-Wl,--no-whole-archive -o print_hello_world.exe \
-Wl,--out-implib,"" \
-Wl,--major-image-version,0,--minor-image-version,0 @CMakeFiles/print_hello_world.dir/linkLibs.rsp
修正后正常
F:/MinGW/bin/c++.exe -g \
-Wl,--whole-archive CMakeFiles/print_hello_world.dir/objects.a \
-Wl,--no-whole-archive -o print_hello_world.exe \
-Wl,--major-image-version,0,--minor-image-version,0 @CMakeFiles/print_hello_world.dir/linkLibs.rsp
链接gtest静态库后
源码结构没有变化,但该行参数变成了-Wl,--out-implib,libtest_print_hello_world.dll.a
F:/MinGW/bin/c++.exe -g \
-Wl,--whole-archive CMakeFiles/test_print_hello_world.dir/objects.a \
-Wl,--no-whole-archive -o test_print_hello_world.exe \
-Wl,--out-implib,libtest_print_hello_world.dll.a \
-Wl,--major-image-version,0,--minor-image-version,0 @CMakeFiles/test_print_hello_world.dir/linkLibs.rsp
gtp4给出的解释是这样的:
连接器(linker)被指令以特定的方式处理静态库和生成的输出。这不仅仅关于链接gtest.a。让我们逐一分析参数:
-Wl,--whole-archive CMakeFiles/test_print_hello_world.dir/objects.a -Wl,--no-whole-archive
: 这一段指示连接器将指定的静态库(objects.a
)中所有的目标文件全部加入到最终的可执行文件中。--whole-archive
选项强制链接器不忽略任何目标文件,哪怕它们看起来并没有被使用。这通常用来确保库中可能会被程序运行时动态引用的对象都将被包含进来。-o test_print_hello_world.exe
: 这指示生成的输出是一个名为test_print_hello_world.exe
的可执行文件。-Wl,--out-implib,libtest_print_hello_world.dll.a
: 这段指示连接器创建一个导入库(import library),名字叫做libtest_print_hello_world.dll.a
。在Windows平台,当你创建一个DLL的时候,你通常也会生成一个关联的导入库,它用于从DLL中链接函数。即使你的意图是创建一个可执行文件,连接器也可以生成这样一个导入库,它可以被其他的DLL或可执行文件使用,来链接到你的程序(尽管这在实际中并不常见)。
后缀.dll.a
是在MinGW或Cygwin环境中使用的,它表示这是一个用于链接DLL的导入库。与.lib
文件相比(通常在Native Windows环境中用作导入库),.dll.a
的格式略有不同,以符合GCC工具链的预期。
如果你的目标确实是生成一个独立的可执行文件,你可能不需要 --out-implib
参数,除非你打算将你的可执行程序输出一些接口给其他程序动态链接使用。只有在生成DLL时,--out-implib
通常才是必要的。
如果有进一步的混淆,你可以检查CMakeList.txt中的设置,或者是和其他库或目标的交互方式,来确定为什么这个命令行被这样配置。这可能需要你具体了解项目的构建系统配置。
这篇关于【问题记录】c++编译报错~/bin/ld.exe: cannot find 0的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!