【问题标题】:mingw ignores '-L' flagmingw 忽略“-L”标志
【发布时间】:2012-12-19 10:07:26
【问题描述】:

我在MinGW 下遇到链接器故障,但我不明白为什么。这是链接命令:

g++ -shared -mthreads -Wl,--out-implib,C:\Users\camm\Syren\libs\libSy_polyMesh.a -o C:\Users\camm\Syren\libs\Sy_polyMesh.dll 调试/Sy_polyMesh.o 调试/moc_Sy_polyMesh.o 调试/qrc_Sy_polyMesh.o -L"c:\Qt\4.8.4\lib" -lglu32 -lopengl32 -lgdi32 -luser32 -LC:\Users\camm\Syren/libs -lSyren -lglew32 -lboost_system -lQtSvgd4 -lQtSqld4 -lQtOpenGLd4 -lQtGuid4 -lQtCored4

undefined reference 错误来自Syren dll(我应该声明该命令是由qmake 自动生成的)。 -LC:\Users\camm\Syren/libs 在我看来格式不正确,因为混合了正斜杠和反斜杠,但如果我手动将它们设置为一种或另一种方式 - 它不会更改编译器输出。

我之前遇到了我需要的第 3 方库(特别是 GLEW 和 Boost)的问题,但因为它们相对“恒定”,所以我将它们放在我的 C:\MinGW\lib 目录中没有问题。但这真的不是我的插件的选择。

我发现 MinGW docs 状态在几个位置:

...因为可以始终使用 -L 指定合适的搜索路径 选项。

...但是 GCC 本身提供了有效的默认值,通过提供 适当的 -L 选项。

但是,C:\Users\camm\Syren\libsSyren.dll 所在的位置!

编辑:这是我的.pro 文件中的 LIBS 声明:

LIBS += -L$(SYREN_PATH)/libs \
    -lSyren
win32 {
    LIBS += -lglew32 \
            -lboost_system
}

$(SYREN_PATH) 扩展为C:\Users\camm\Syren。我还可以看到Syren.dll 中的“缺失”符号,例如:

C:\Users\camm\Documents\Syren\Sy_polyMesh_debug/../Sy_polyMesh/src/Sy_polyMesh.cpp:341: 对 `Sy_GLBuffer::unbind()' 的未定义引用

可以看作是:

6c500bd6 T _ZN11Sy_GLBuffer6unbindEv

编辑2

在链接器阶段添加详细标志后,我注意到链接器正在遍历每个搜索路径,然后遍历每个库命名约定,并使用它可以打开的第一个。

attempt to open C:\Users\camm\Syren/libs/libSyren.dll.a failed
attempt to open C:\Users\camm\Syren/libs/Syren.dll.a failed
attempt to open C:\Users\camm\Syren/libs/libSyren.a succeeded

假设libSyren.a 可能已损坏,我将其重命名以强制链接器使用.dll

attempt to open C:\Users\camm\Syren/libs/libSyren.dll.a failed
attempt to open C:\Users\camm\Syren/libs/Syren.dll.a failed
attempt to open C:\Users\camm\Syren/libs/libSyren.a failed
attempt to open C:\Users\camm\Syren/libs/Syren.lib failed
attempt to open C:\Users\camm\Syren/libs/libSyren.dll failed
attempt to open C:\Users\camm\Syren/libs/Syren.dll succeeded

但我仍然收到完全相同的错误消息!

【问题讨论】:

  • 您使用的是哪个构建系统?编译器本身应该理解两者,但 shell 和 make 不理解。
  • 您可以在项目文件中发布您的“LIBS”声明吗??
  • @JanHudec 我正在运行 Qt 的 MinGW,不涉及 cygwin。
  • @cmannett85:我什至没有想到 cygwin。我的意思不是它是手动编写的makefile还是cmake生成的还是qmake生成的,以及你是否有MSYS(这是mingw的unix shell;cygwin是不同的东西)
  • @JanHudec 这是qmake-生成的。大概 Qt Creator 使用 MSYS 作为外壳,我从两者得到相同的输出。

标签: qt gcc mingw qmake


【解决方案1】:

如果您正在链接正确的 DLL,并且链接器没有抱怨缺少文件,则 dll 可能缺少导出以允许链接。

如果 MinGW 链接器正确导出符号,它可以直接链接到 DLL,尽管仍然建议链接到名为 lib*.alib*.dll.a 的导入库(应在 qmake 构建中创建) .我相信链接器会寻找带有和不带有 libprefix 的变体,但我不确定,应该自己测试一下。

您可以使用 objdump 和/或 nm 检查 DLL 导出的符号。

【讨论】:

  • 我在.dll 的同一目录中有lib*.a 变体,所以它不应该使用它吗?
  • @cmannett85 是的,那么你可能是。检查.a.dll 文件是否显示链接器找不到的符号。
  • 是的,我可以看到 objdumpnm 缺少的符号 - 我真的很难理解现在发生了什么......
  • 我在我的问题中添加了更多细节,你能看看它是否暗示了你可能知道的其他任何事情吗?
  • 我相信 DLL 导出的函数会变成__imp_*original_name*,并且这些符号需要与您找到的符号一起出现。对于 Windows DLL,您需要使用 dllimport/dllexport 机制才能正常工作。似乎您正在静态构建 Syren。您是否检查过libSyren.a 中是否存在缺失符号?
【解决方案2】:

如果链接器没有抱怨无法加载Syren dll,则表示文件已正确加载...符号只是缺少到Syren dll(未导出?)...为什么没有更多信息很难判断

当您构建 Syren 库时,您是否有任何关于缺少原型的警告? Syren lib 使用什么,没有什么不可移植或需要 Windows dll? 你能给出缺失符号的列表吗?

编辑:你如何编译Syren.dll?你用的是明威吗?您将什么选项传递给编译器/链接器? 我建议阅读这两个链接:

如果要导出 C++ 函数,则必须在程序和 DLL 之间使用相同的编译器。或者您可以使用 C 风格的包装函数来封装 C++ ABI。

关于这个主题的一篇非常好的文章:http://www.codeproject.com/Articles/28969/HowTo-Export-C-classes-from-a-DLL

【讨论】:

  • 我认为你是对的,如果我将Syren.dlllibSyren.a 文件复制到MinGW/lib 中,它仍然不起作用。我正在将这个应用程序从 Linux 移植到 Windows(像这样的东西“正常工作”),所以我在某处缺少一些特殊的选项来添加符号吗?这种行为肯定是默认的吗?另一个奇怪的是(调试)共享库比 Linux 版本大 100MB!
  • 首先缺少哪些符号?与这些符号关联的函数如何声明到 Syren lib 中?
  • Syren 链接到我在 MinGW 中成功构建的 GLEW 和 boost,以及预构建的 Qt 库。我没有丢失原型警告(my 代码库在两个操作系统之间没有改变)。大约有 230 个缺失符号,它们全部来自我编写的代码,全部来自 Syren.dll。
  • 没有给出至少一个例子,我能做的唯一猜测是 C 和 C++ 代码之间的接口问题,但是我们甚至没有这个信息......你试过这个建议了吗@rubenvb : 在 dll 上使用 objdump 查看是否列出了所需的符号
  • 是的,我可以看到 objdumpnm 缺少的符号 - 我真的很难理解现在发生了什么......
【解决方案3】:

$(SYREN_PATH) 替换为$${SYREN_PATH} 会发生什么? 因为前面的符号$() 表示environment variable at the time Makefile is executed. 的内容

qmake variable reference.

【讨论】:

  • 没什么,但SYREN_PATH 是一个环境变量——这正是我想要的。
猜你喜欢
  • 2019-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-15
  • 2021-01-27
相关资源
最近更新 更多