【问题标题】:Can I link object files made by one compile to those made by another one?我可以将一个编译器制作的目标文件链接到另一个编译器制作的目标文件吗?
【发布时间】:2011-04-20 09:22:28
【问题描述】:

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

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

【问题讨论】:

  • 你使用什么编译器?
  • 好吧,对于框架 GCC。程序员将使用什么是他的选择,我需要知道我是否必须警告他。

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


【解决方案1】:

只要它们使用相同的目标文件格式并针对相同的机器指令集,您就应该能够链接它们。例如,假设您有两个 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、康柏、EDG、惠普、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

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

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

Policies/Binary Compatibility Issues With C++

Some thoughts on binary compatibility

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

【讨论】:

  • @anatolyg:查看我的编辑。 g++ 从版本 3 开始支持行业标准 C++ ABI。请参阅:codesourcery.com/public/cxx-abi/abi.html
  • 我面向所有可以找到 GCC 和 JVM 的平台 - 包括使用 MSVC 作为第二个编译器的 Windows。但是,主要使用的编译器应该是GCC。
  • @Rusty Horse:Windows 使用与 Linux 不同的目标文件格式,因此您可能需要为这两个平台使用单独的目标文件。
  • 当然。框架将由 GCC 在每个目标平台上编译。
  • 安腾有一个标准的 C++ 二进制 API。大多数其他系统都没有:例如,您无法将使用 g++ 编译的 C++ 代码链接到使用 Sun CC 在 Solaris 下编译的代码,并且您无法将使用 g++ 编译的 C++ 代码链接到使用 VC++ 在 Windows 下编译的代码。事实上,很多时候,您无法将使用某个版本的编译器编译的 C++ 代码链接到使用早期版本编译的代码。
【解决方案2】:

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

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

ABI 中的内容远不止名称修饰:

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

  • 进行异常的方式

  • 返回结果的方式

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

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

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

  • 使用的标准库版本

  • ...

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

【讨论】:

  • 有一个行业标准 C++ ABI,自版本 3 以来一直是 gcc 中的默认设置。我不确定它的实施范围有多广,但该标准确实存在,并且至少得到以下支持: CodeSourcery、康柏、EDG、惠普、IBM、英特尔、红帽和 SGI
【解决方案3】:

是的。

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

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

【讨论】:

  • 好的,我该如何检查?我在哪里可以找到这些信息?
  • 好吧,例如对于 gcc,google is your friend.
  • 要考虑的不仅仅是指令集和目标文件格式,尤其是对于 C++。
【解决方案4】:

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

这通常适用于 C,因为大多数(如果不是所有)平台 为 C 指定二进制 API。这几乎不适用于 C++, 因为几乎没有平台指定二进制 API C++——一个值得注意的例外是 Itanium,它是 规范要么不完整,要么不被尊重。在 练习,其实不仅要使用相同的 编译器,但你必须用相同的方式编译代码 选项:例如,g++ 和 VC++ 都有两个不同的 std::vectorstd::string,根据编译器选项选择。

【讨论】:

  • 这很有趣,所以您是说在实践中仅针对相同的指令集、目标文件格式和 ABI 标准是不够的?你如何解释 dll(在 Windows 上)和 Linux 上可以从各种编译器中使用的共享对象文件?我曾经(多年前)在 Borland Builder 中编译 dll,然后在 Visual Studio 中使用它们,反之亦然……如果一个编译器的目标文件永远无法链接到另一个编译器的目标文件,那么你基本上只有一个 C++ 编译器允许在任何特定平台上使用。
  • @Robert:GCC 使用稍微不同的格式(其中,名称 mangling 不同),因此与 Visual C++ 工具链不兼容。如果 Borland builder 像你说的那样工作,我假设它要么使用 Visual C++ 链接器,要么符合完全相同的 ABI/目标文件格式。不能混合目标文件并不意味着不同的工具链不能通过不同类型的中间步骤(=目标文件)创建可用的二进制文件。
  • @Robert 仅当该标准存在(大多数系统并非如此)并且它涵盖了您正在做的所有事情(例如,std::vector 的实现)时,针对相同的 ABI 标准才有效,如果您使用的是std::vector)。你通常得到的只是一个涵盖 C 的 ABI 标准,即便如此,通常也有一些编译器选项会破坏这一点。
  • 请注意,对于 DLL,通常有一些方法(在 Windows 下默认情况下大部分是活动的)屏蔽 DLL 中的所有内容,除了您明确导出的内容。如果 ABI 规范(通常只是纯 C)涵盖了您明确导出的内容,那么您可以链接使用不同编译器编译的 DLL。例如,Firefox 并没有为其插件强加任何特定的编译器。但是您必须考虑到这一点来设计和构建应用程序。
猜你喜欢
  • 2012-05-11
  • 1970-01-01
  • 1970-01-01
  • 2012-01-10
  • 1970-01-01
  • 2015-11-03
  • 1970-01-01
  • 1970-01-01
  • 2023-03-06
相关资源
最近更新 更多