c-通过将静态bulid转换为操作系统特定的二进制文件来跨操作系统构建



是否可以用C编写代码,然后静态构建它,并像ELF/PE一样从中生成二进制文件,然后删除它的头和所有不必要的元数据,从而创建一个原始二进制文件,并最终能够将该原始二进制文件放入任何其他特定于操作系统的操作系统中,如(ELF>PE)或(PE>ELF)?!你以前这样做过吗?有可能吗?什么是问题和关注点?这怎么可能?!如果没有,就告诉我为什么不?!!?!

我在理解静态构建时有哪些陷阱?这不意味着它消除了对第三方和标准以及os-libs和headers的任何需求吗?!为什么我们不能删除例如ELF的meta,并放入PE所需的meta和其他规范?

提及:我说,跨操作系统而非跨硬件

[阅读以下内容后再阅读!]正如你所看到的最佳答案,到目前为止(!)继续学习跨平台开发问题!!!这有多疯狂?!感谢哲学!!!

我想说这是可能的,但这个过程必须受到很多细节的影响。

ABI兼容性

首先要考虑的是应用程序二进制接口的兼容性。除非您能够以相同的方式调用函数,否则代码就会被破坏。所以我想(尽管我现在不能检查),在Linux/OSX上用gcc和在Windows上用MinGW-gcc编译代码应该会给出相同的二进制代码,只要没有调用外部函数。这里的问题是,可执行元数据可能依赖于一些ABI假设。

标准库

这似乎是最大的障碍。部分原因是C预处理器可以在某些平台上内联某些过程,而让它们在其他平台上运行。此外,与标准库的跨平台动态互操作几乎是不可能的,尽管理论上可以想象一个代码使用C标准库的有限子集,该子集通过不同平台上的相同ABI公开。

静态构建在很大程度上消除了与其他用户空间代码交互的问题,但与内核接口仍然存在巨大问题:它是x86 Linux上的int $0x80调用,以及一组平台特定的系统调用编号,这些编号不会以任何直接方式映射到Windows。

操作系统特定寄存器的使用

据我所知,Windows使用寄存器%fs来存储一些操作系统范围内的异常处理内容,因此在Linux上编译的二进制文件应该避免将其弄乱。可能还有其他类似的问题。此外,Windows上的C++异常大多与操作系统异常一起完成。

虚拟地址

同样,AFAIK Windows DLL有一些预定义的地址,它们必须加载到进程的虚拟地址空间中,而Linux则为共享库使用与位置无关的代码。因此,除非移植的位置相关代码被重新编译为与位置无关,否则可执行代码和移植代码的重叠区域可能会出现问题。

因此,虽然理论上是可能的,但这种转换在实际情况下必须非常脆弱,并且不可能重新植入整个静态构建代码——有些部分可能完好无损地传输,但必须重新链接到与其他内核正确接口的系统特定代码。

附言:我认为Wine是在完全不同的系统上运行二进制代码的一个很好的例子。它欺骗Windows程序,使其认为自己在Windows环境中运行,并使用相同的机器代码——大多数情况下运行良好(如果程序不使用专用系统低级例程或不可用的库)。

最新更新