【问题标题】:Linking object files from different C compilers链接来自不同 C 编译器的目标文件
【发布时间】:2016-08-11 17:06:22
【问题描述】:

假设我有两个编译器,甚至是一个带有两个不同选项集的编译器。每个编译器都将一些 C 代码编译成一个对象,我尝试用一​​个通用链接器链接这两个 .o 文件。这会成功吗?

我最初的想法是:并非总是如此。如果编译器使用相同的目标文件格式并且具有兼容的选项,那么它将成功。但是,如果编译器有冲突的选项,或者(这是一个简单的选项)使用两种不同的目标文件格式,它将无法正常工作。

有没有人对此有更深入的了解?目标文件需要遵守哪些标准才能获得对其有效的信心?

【问题讨论】:

标签: c compiler-construction linker


【解决方案1】:

大多数 *nix 操作系统都有很好的定义和打开 ABI 并且大多使用 ELF 对象文件格式,所以对于 *nix 来说根本不是问题。

Windows 的定义不太严格,不同的编译器在某些调用约定上可能会有所不同(例如,某些编译器可能不支持 __fastcall 或可能有不同的行为,请参阅https://en.wikipedia.org/wiki/X86_calling_conventions)。但是主要的调用约定集(__stdcall、_cdecl 等)足够标准,可以确保一个编译器从另一个编译器编译的函数成功调用,否则程序将根本无法工作,因为与 Linux 不同,Windows 中的每个系统调用都被包装通过你需要成功调用的DLL中的函数。

另一个问题是目标文件没有标准的通用格式。虽然大多数工具(MS、Intel、GCC (MinGW)、Clang)使用 COFF 格式,但有些可能使用 OMF (Watcom) 或 ELF (TinyC)。

另一个问题是所谓的“名称修改”。虽然引入它是为了支持重载具有相同名称的 C++ 函数,但它被 C 编译器采用以防止使用不同调用约定定义的函数的链接。例如,函数 int _cdecl fun(void);将获得编译名称 _fun 而 int __stdcall fun(void);将获得名称 _fun@0。有关名称修改的更多信息,请参见此处:https://en.wikipedia.org/wiki/Name_mangling

最后,某些编译器的默认行为可能会有所不同,所以是的,选项可能会阻止成功链接不同编译器甚至同一编译器生成的目标文件。例如,TinyC 使用默认约定 _cdecl,而 CLang 使用 __stdcall。带有默认选项的 TinyC 可能不会生成可能与其他代码链接的代码,因为它不会在名称前加下划线符号。为了使其可交叉链接,它需要 -fleading-underscore 选项。

但请记住,上述代码可能会成功混合。例如,我成功地将 Visual Studio、Intel Parallel Studio、GCC (MinGW)、Clang、TinyC、NASM 生成的代码链接在一起。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-03
    • 1970-01-01
    • 1970-01-01
    • 2010-10-06
    • 1970-01-01
    • 2013-08-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多