9

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

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

4

4 回答 4

10

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

请参阅 wiki 上的目标文件格式列表

您可能也对此感兴趣:

用于探索目标文件的 UNIX 工具

编辑

根据这篇文章“ C++ 标准库 ABI ”,有一个行业标准 C++ ABI,您应该能够链接任何符合该标准的编译器的目标文件。您可以在此处查看该标准:

安腾 C++ ABI

本文档由一个非正式的行业联盟联合开发,该联盟由(按字母顺序排列)CodeSourcery、Compaq、EDG、HP、IBM、Intel、Red Hat 和 SGI...

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

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

编辑 2

你应该看看这个 SO 帖子:

用于维护 API 向后二进制兼容性的 GCC 与 MS C++ 编译器

微软似乎没有遵循任何关于他们的 C++ ABI 的一致标准(安腾或其他),所以如果你用 gcc for Windows 编译它可能会成为一个问题。

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

C++ 的策略/二进制兼容性问题

关于二进制兼容性的一些想法

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

于 2011-04-20T09:26:05.900 回答
7

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

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

除了名称修饰之外,ABI 中还有很多内容:

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

  • 异常进行的方式

  • 返回结果的方式

  • 传递参数的方式(在寄存器中与否,哪些寄存器,在哪里this

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

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

  • 使用的标准库版本

  • ...

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

于 2011-04-20T09:27:14.743 回答
2

是的。

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

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

于 2011-04-20T09:26:07.230 回答
0

简单回答是不。只有二​​进制兼容的两个目标文件才能链接在一起。(更准确地说:可能会将它们链接在一起,也可能不会,但即使它们链接,生成的程序也不会工作。)这意味着它们以相同的方式传递参数(对于所有类型的参数),以相同的方式传递任何隐藏的参数(例如 this),以相同的方式布置所有数据结构(包括你看不到的东西,如 vtable),并且两个目标文件使用的所有类和对象都具有相同的定义。

这通常适用于 C,因为大多数(如果不是所有)平台都为 C 指定了二进制 API。这几乎从不适用于 C++,因为几乎没有平台为 C++ 指定二进制 API——一个值得注意的例外是 Itanium,它是规范要么不完整,要么不被尊重。实际上,实际上,您不仅必须使用相同的编译器,而且还必须使用相同的选项来编译代码:例如,g++ 和 VC++ 对于std::vector和 之类的东西都有两种不同的不兼容实现std::string,根据选择编译器选项。

于 2011-04-20T11:09:23.913 回答