windows 如何用lib.exe捆绑一个静态库和一个导入库(或两个静态库)?

px9o7tmv  于 2023-01-21  发布在  Windows
关注(0)|答案(1)|浏览(115)

Windows上DLL的导入库是一个特殊的东西,它们为链接器提供了必要的粘合剂,以便在生成的PE文件中创建导入存根(无论是命名为.dll还是.exe或其他名称)。
This Q&A provides details关于如何在Unix端捆绑两个静态库。如何在Windows上用Visual C++实现相同的功能?
另外,有没有办法把静态库和导入库结合起来?

2w2cym1i

2w2cym1i1#

虽然这里的其他问答会让您有不同的想法,甚至微软似乎也没有记录这种可能性,但我已经看到了我所说的混合静态/导入库,它分布在某个硬件供应商的SDK中。
一般来说,使用Library Manager(lib.exe)可以很容易地组合/绑定两个静态库,顺便说一下,它只是一个调用link.exe /lib并传递任何参数的浅 Package 器。  by the way   is merely a shallow wrapper invoking link.exe /lib and passing on any arguments. You'd use it like this:

> lib.exe /nologo /out:combined.lib static1.lib static2.lib

很简单。但是反向过程并不简单,因为您需要指定每个.obj文件,包括它们在lib.exe /remove:...中的相对路径。因此,基本上不知道.obj最初属于哪个静态库是一个先决条件。
如果你想组合一个静态库和两个导入库,你可以这样使用lib.exe

> lib.exe /nologo /out:hybrid.lib static.lib dll1.lib dll2.lib
dll2.lib(dll2.dll) : warning LNK4006: __NULL_IMPORT_DESCRIPTOR already defined in dll1.lib(dll1.dll); second definition ignored

在这种特殊情况下,警告是良性的,可以忽略,但它 * 确实 * 告诉我们一件事:* * 如果同一个符号被定义多次,合并两个库可能会导致问题**。我建议 * never * to /ignore:...此警告ever,如果您遵循此问答中的任何示例。
此外,不能合并两个包含相同.obj文件路径的库。
然而,将导入库绑定到混合静态/导入库中要 * 更 * 直接,因为我们应该删除的成员名是DLL名,以摆脱导入库。
所以我们可以这样做:

> lib /nologo /remove:dll1.dll hybrid.lib

但这里有一个潜在的问题,我从来没有尝试过这种情况的所有变化。还记得我们是如何得到这个警告吗?:

dll2.lib(dll2.dll) : warning LNK4006: __NULL_IMPORT_DESCRIPTOR already defined in dll1.lib(dll1.dll); second definition ignored

如果我现在只删除dll1.dll成员,那么hybrid.lib中可能就没有__NULL_IMPORT_DESCRIPTOR了。毫无疑问,当我们试图使用这个混合库构建一个PE文件时,link.exe就会吐出来。但是,如果命令行中有其他导入库提供可用的__NULL_IMPORT_DESCRIPTOR符号,我们可能会很幸运。
使用这个混合的静态/导入库 * 会 * 工作,但是如果你删除了一些零碎的部分,最好是一次删除 * 所有 * 导入库部分。

一些警告

这很可能不是事情的本意。所示的方法有局限性,需要你知道你要做什么:

  • 创建组合(或混合)库的各个部分不能有符号名冲突,除非符号名明确地向链接器提供完全相同的内容(例如,来自任意导入库的__NULL_IMPORT_DESCRIPTOR应该是无害的)
  • 目标文件的名称和路径也不能冲突
  • 导入库的更新版本可能必须用于以后的软件,因此您可能会发现自己无论如何都要拆卸混合库
  • 即使你知道你在做什么,即使你对所有变量有一个Raymond-Chen般的概述,机会是你仍然不想使用这个。可能是因为发现一个导入库合并到一个静态库中是完全令人惊讶的事实。或者是因为你的继任者或未来的开发人员可能不知道所有的细节,并且更侮辱 你忘了记录你的非正统行为。injury   you forgot to document your unorthodox doings ...
更多信息
  • 由Visual C++创建和处理的.lib文件在技术上 * 也只是 * ar归档文件,在Unix上通常就是这种情况
  • 您可以使用像7-Zip这样的工具来解包和检查它们(重新打包它们通常比较困难)。
  • 相反,您可以在Linux上使用ar来处理源自Windows的.lib文件(由于路径分隔符等原因,需要注意一些问题)
  • 在Unix端,包含的.o文件通常是ELF文件,而对于Visual C++,包含的.obj文件是COFF。
  • 您可以使用objconvBinutils工具来操作这些文件,后者必须专门构建以支持COFF和与特定.lib文件相关的架构。

相关问题