在MinGW上是否可以使用“ -Wl,-soname”?

问题描述

我正在尝试使用MINGW在Windows上构建DLL。

一个很好的总结(在我看来)可以在以下位置找到: https://www.transmissionzero.co.uk/computing/building-dlls-with-mingw/

甚至有一个基本项目可用于本讨论的目的: https://github.com/TransmissionZero/MinGW-DLL-Example/releases/tag/rel%2Fv1.1

请注意,此项目中存在一个外观错误,这将使它开箱即用:Makefile不会创建“ obj”目录-要么调整Makefile,要么手动创建它。

这是真正的问题。 如何更改Windows DLL名称,使其与实际的DLL文件名不同? 本质上,我试图在Windows上实现,在Linux上对此效果进行了很好的描述: https://www.man7.org/conf/lca2006/shared_libraries/slide4b.html

最初,我尝试更改用于创建DLL的资源文件中的“ InternalName”和“ OriginalFilename”,但这不起作用。

第二步,我尝试在执行最终链接的命令上添加“ -Wl,-soname,SoName.dll”,以更改Windows DLL名称

但是,这似乎并没有达到预期的效果(我使用的是MingW 7.3.0,x86_64-posix-seh-rev0)。 两件事让我这么说:

1 /测试可执行文件仍然有效(我希望它会失败,因为它试图找到SoName.dll但找不到它)。

2 /“ pexports.exe AddLib.dll”产生以下输出,其中库名未更改:

LIBRARY "AddLib.dll"
EXPORTS
Add
bar DATA
foo DATA

我做错什么了吗?我的期望也许不对吗?

感谢您的帮助! 大卫

解决方法

首先,我想说重要的是使用.def文件指定导出的符号,或使用__declspec(dllexport) / __declspec(dllimport),但切勿混用这两种方法。还有一种使用-Wl,--export-all-symbols链接器标志的方法,但是我认为这很丑陋,只有在您想要快速而肮脏的情况下才应使用。

可以告诉MinGW使用与库名不匹配的DLL文件名。在链接步骤中,使用-o指定DLL,并使用-Wl,--out-implib,指定库文件。

让我通过展示如何将chebyshev构建为静态库和共享库来进行说明。其来源仅包含2个文件:chebyshev.hchebyshev.c

  1. 编译
gcc -c -o chebyshev.o chebyshev.c -I. -O3
  1. 创建静态库
ar cr libchebyshev.a chebyshev.o
  1. 创建一个.def文件(因为没有提供文件,也没有使用__declspec(dllexport) / __declspec(dllimport))。请注意,此文件不包含带有LIBRARY的行,允许链接程序稍后指定DLL文件名。 如果项目未提供.def文件,有几种方法可以做到这一点:

3.1。从.h文件中获取符号。这可能很难,因为有时您需要区分类型定义(例如typedefenumstruct)与需要导出的实际函数和变量之间的区别;

echo "EXPORTS" > chebyshev.def
sed -n -e "s/^.* \**\(chebyshev_.*\) *(.*$/\1/p" chebyshev.h >> chebyshev.def

3.2。使用nm列出库文件中的符号并过滤出所需的符号类型。

echo "EXPORTS" > chebyshev.def
nm -f posix --defined-only -p libchebyshev.a | sed -n -e "s/^_*\([^ ]*\) T .*$/\1/p" >> chebyshev.def
  1. 将静态库链接到共享库。
gcc -shared -s -mwindows -def chebyshev.def -o chebyshev-0.dll -Wl,libchebyshev.dll.a libchebyshev.a

如果您有一个使用__declspec(dllexport) / __declspec(dllimport)的项目,事情会容易得多。您甚至可以使链接步骤使用.def链接器标记生成-Wl,--output-def,文件,如下所示:

gcc -shared -s -mwindows -o myproject.dll -Wl,myproject.dll.a -Wl,myproject.def myproject.o

此答案基于我对C的经验。对于C ++,您确实应该使用__declspec(dllexport) / __declspec(dllimport)

,

我相信我已经找到一种在Windows上实现的机制,https://www.man7.org/conf/lca2006/shared_libraries/slide4b.html

中针对Linux所描述的效果

这涉及dll_tool

example Makefile中最初有以下行:

gcc -o AddLib.dll obj/add.o obj/resource.o -shared -s -Wl,--subsystem,windows,libaddlib.a

我只是将其替换为下面的2行:

dlltool -e obj/exports.o --dllname soname.dll -l libAddLib.a obj/resource.o obj/add.o
gcc -o AddLib.dll obj/resource.o obj/add.o obj/exports.o -shared -s -Wl,windows

确实,关键似乎是使用dlltool创建的导出文件与 dllname 一起使用。此导出文件与构成DLL主体的目标文件链接,并处理DLL与外界之间的接口。请注意,dlltool还会同时创建“导入库”

现在我得到了预期的效果,并且我可以看到“内部DLL名称”(不确定正确的术语是什么)已发生变化:

第一证据:

>> dlltool.exe -I libAddLib.a
soname.dll

第二证据:

>> pexports.exe AddLib.dll
LIBRARY "soname.dll"
EXPORTS
Add
bar DATA
foo DATA

第三种证据:

>> AddTest.exe
Error: the code execution cannot proceed because soname.dll was not found.

尽管达到了预期的效果,但这似乎仍是一种解决方法。我的理解(但我很可能错了)是gcc选项“ -Wl,-soname”应该实现完全相同的功能。至少它在Linux上可以,但是在Windows上可能会被破坏吗?

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...