我可以将一个编译生成的目标文件链接到另一个编译的目标文件吗?

时间:2011-04-20 09:22:29

标签: c++ compiler-construction linker object-files

更具体地说,假设两个编译器都在同一平台上(OS +指令集)。但是,其中一个目标文件是由依赖于编译器的代码构成的。另一方面 - 代码是面向对象的并且尊重封装。

我需要这个我正在制作的一种框架。目标平台是GCC和Java虚拟机的任何系统。实际上,该框架将在每个平台上编译。使用框架用户的编译器取决于他。

4 个答案:

答案 0 :(得分:10)

只要它们使用相同的目标文件格式并定位相同的机器指令集,您就应该能够链接它们。例如,假设您有两个C编译器,每个编译器都有自己的专有语言扩展。您编译两个不同的文件,一个使用编译器A,另一个使用编译器B.每个源文件都使用它各自编译器的语言扩展。只要两个编译器都设置为针对相同的平台和体系结构,例如Linux上的i386指令集,那么您应该能够将文件链接到一个可执行文件中。

See this list of object file formats on wiki

您可能也对此感兴趣:

UNIX tools for exploring object files

修改

根据这篇文章“C++ Standard Library ABI”,有一个行业标准C ++ ABI,您应该能够链接任何符合此标准的编译器的对象文件。你可以在这里看到这个标准:

Itanium C++ ABI

  

本文件由联合制定   非正式的工业联盟   由(按字母顺序排列)组成   CodeSourcery,Compaq,EDG,HP,IBM,   英特尔,红帽和SGI ......

     

在本文档中,我们指定了   C ++的应用程序二进制接口   程序,即目标代码   用户C ++代码与之间的接口   实施提供的系统和   库。这包括记忆   C ++数据对象的布局,包括   预定义和用户定义的数据   类型,以及内部编译器   生成的对象,如虚拟   表。它还包括功能   调用接口,异常处理   接口,全局命名和各种   目标代码约定。

因此,只要您定位相同的指令集,目标文件格式并使用标准C ++ ABI(现在是gcc / g ++中的默认值),您应该没问题,当然假设标准C ++ ABI实际上是标准的并且由大多数在Linux上运行的现代C ++编译器正确实现(这似乎是您所针对的平台)。

编辑2

你应该看看这篇SO帖子:

GCC vs MS C++ compiler for maintaining API backwards binary compatibility

似乎Microsoft没有遵循任何关于其C ++ ABI的一致标准(Itanium或其他),因此如果您使用gcc进行Windows编译,则可能会出现问题。

您可能还想看看这两篇文章:

Policies/Binary Compatibility Issues With C++

Some thoughts on binary compatibility

您可以将用户限制为支持Itanium ABI的编译器,但这取决于您的目标受众。

答案 1 :(得分:7)

这取决于编译器。有些使用相同的ABI,因此生成可以链接在一起的对象,有些则不能,并且对象无法链接。通常 - 事实上,我也不例外 - 当编译器使用不兼容的ABI时,它们也使用不兼容的名称修改,链接阶段失败。

事实上,需要相当多的努力和协调才能将用不同编译器构建的对象链接在一起。曾经有一段时间经常在两个不同版本的gcc之间无法实现。

ABI中的名字比名称更多还多:

  • 对象的精确布局(包括填充,vtable的格式和RTTI信息的格式,......)

  • 进行例外的方式

  • 返回结果的方式

  • 参数的传递方式(寄存器与否,寄存器,this

  • 谁保存了不用于结果/参数的寄存器(来电者,被叫者......)

  • 处理模板的方式(例如静态数据成员)

  • 使用的标准库版本

  • ...

为了了解ABI的复杂性,here是一份详细描述Itanium上使用的ABI的文档。 IIRC,它是对描述C ABI的类似文件的补充。它通过gcc在其他目标上使用(对于非机器相关部件)。

答案 2 :(得分:2)

编译后,目标文件只包含不依赖于编译器的明确定义的目标代码,即使源文件使用了编译器相关的代码。

确保使用相同的对象格式,但您已经知道使用了相同的指令集,因此请不要担心。

答案 3 :(得分:0)

简单的答案是否定的。可以链接两个目标文件 只有它们是二进制兼容的。 (更准确地说 声明:可能会或可能不会将它们连接在一起,但是 即使他们链接,结果程序也无法工作。)这 意味着它们以相同的方式传递参数(适用于所有类型 参数),以相同的方式传递任何隐藏的参数(例如 this),以相同的方式布局所有数据结构(包括 你看不到的东西,比如vtable),以及所有的类和 两个目标文件使用的对象具有相同的定义。

这适用于C,通常是因为大多数(如果不是全部)平台 为C指定二进制API。这几乎不适用于C ++, 因为几乎没有平台为其指定二进制API C ++ - 一个值得注意的例外是Itanium,它就是 规范要么不完整要么不受尊重。在 实际上,实际上,你不仅要使用同样的东西 编译器,但你必须编译相同的代码 选项:例如,g ++和VC ++都有两种不同 std::vector和。std::string等不兼容的实现 {{1}},根据编译器选项选择。