(C/ c++)如何生成可以在Windows和Linux上运行的可执行文件

(C/C++) How to generate executable file that can run on both Windows and Linux?

本文关键字:Linux Windows 运行 可执行文件 c++ 何生成      更新时间:2023-10-16

我是编程新手。据我所知,在Linux上编译的程序应该不能在Windows上运行。因此,如果我们想在两个平台上运行相同的程序,我们需要在两个平台上编译源代码,并创建两个不同的可执行文件。

最近我正在研究一个开源、跨平台的Java GUI应用程序的源代码。我惊讶地发现,该GUI应用程序的后端引擎是一个由c++代码生成的小可执行文件。无论用户在Windows还是Linux中使用该应用程序,Java GUI都将调用bin文件夹中相同的可执行文件。

我只是想知道,这个可执行文件怎么能在Windows和Linux上同时运行?

我还对使用c++程序作为引擎创建一个跨平台的Java GUI应用程序感兴趣。那个c++程序只适用于Linux。我已经在谷歌上搜索了一段时间,我发现我需要使用Cygwin将其移植到Windows。但是,如果我使用Cygwin,我最终会有两个不同的可执行文件。

如何将Windows可执行文件与Linux可执行文件合并?是否有可能生成可以在两个平台上运行的单个可执行文件?

谢谢。

简单的答案是,你不能。

PE (Windows)和ELF (Linux)二进制可执行格式是完全不同的。

更不用说C/c++程序需要链接到无法同时在两个平台上使用的库。

然而,你可以在Linux上使用Wine来运行Windows可执行文件,只要它不尝试特殊的Windows特定调用。

或者你可以选择使用更"通用"的跨平台语言,如CLI语言(c#/IronPython/Java等),Windows的。net和linux的Mono/其他支持。

好了,孩子们。

是的,你可以写一个多平台的二进制文件,但是很难。它被称为脂肪双星,在20世纪80年代很常见,尽管我已经有几十年没见过了。https://en.wikipedia.org/wiki/Fat_binary

基本上,您为要运行的每个平台编译机器码,然后将代码与不同的入口点手工链接。虽然维基百科的文章仅仅描述了将不同的体系结构打包到同一个二进制文件中,但实际上只要操作系统的入口点不冲突,就可以使一个二进制文件在不同的操作系统上运行。

一些可执行格式被有意设计为允许这样做。例如,MZ、NE、LX和PE可以叠加。旧的OS/2程序有时会这样做…它们很少包含两个操作系统的完整程序,但是当在DOS上运行时,会打印一条消息告诉您,您使用了错误的操作系统。

就Linux和Windows在一个二进制文件:虽然你不能做一个ELF和PE,我相信它可能与PIE或COFF和PE或COM是可行的。旧的Linux将运行COFF二进制文件,PE是从COFF二进制文件派生而来的,因此,如果新版本的Linux仍将运行这些二进制文件,那么您似乎可以创建一个通用二进制文件。我不能肯定这是否可行,但它似乎是合理的。

另一个警告:通常你需要在代码的开头添加一个跳转,以跳过其他操作系统的入口点、头文件等,因为你无法在那里找到你的代码(很明显)。

在现代计算中,这个问题是大多数杀毒软件会错误地将其识别为病毒。过去,病毒攻击二进制文件的常见方式是,在可执行文件的开头插入跳转到二进制文件末尾的代码,将自己的代码添加到二进制文件的末尾,然后插入另一个跳转到主可执行代码。因为你需要做一些或多或少类似的事情来在一个二进制文件中支持多个平台,大多数反病毒软件会启发式地将此识别为病毒并隔离你的可执行文件。

所以简而言之:是的,它可以用于(某些)平台组合。这并非不可能,但你必须疯了才会去做。

没有办法从c++源代码编译一个在不同平台上工作的本机可执行文件。我不相信你在Windows和Linux上运行相同的可执行文件,正如你在第二段所说的。

简单地说,不可能在不同的平台上运行相同的可执行文件。对于Windows、Linux或任何其他UNIX平台都是如此。

拥有单个可执行文件的想法并不新鲜,这是Java运行时和Windows。net (Linux的Mono)背后的想法。它们本身依赖于在特定机器上编译的不同可执行文件。

无论用户在Windows或Linux中使用该应用程序,Java GUI将调用bin文件夹中相同的可执行文件。

他们可能只是使用了这些可执行文件的相关路径,并且这些可执行文件可能在不同的平台上单独编译。不看代码很难分辨

Cygwin是windows上的一个命令行接口,提供UNIX的外观和感觉。

一个可以尝试的选择是Wine,这是一个在Linux上运行windows程序的Linux程序。

如果操作系统在同一平台上,这可能是可能的。

然而,Linux可以运行在各种不同处理器的平台上:VAX、MAC、PC、Sun等。

一个问题是可执行文件包含特定于处理器的汇编(机器代码)指令。使用ARM处理器添加寄存器的机器码可能与摩托罗拉、英特尔或Sun处理器不同。因此,在这种情况下,一个可执行文件可能不能保证在不同的平台上运行。

另一个问题是运行时库也可能调用特定的操作系统函数(如文件打开,显示文本等),一些操作系统可能不提供相同的功能;而其他人有不同的方法来执行相同的功能。嵌入式平台上的操作系统可能不支持文件系统。Windows Vista可能会阻止来自不安全MSDOS请求的调用。

其他语言通过生成由"虚拟机"执行的代码而独立于平台。代码不是由处理器直接执行的。

移植C和c++方法的传统方法是提供源代码,让客户在他们的平台上构建软件。其他交付过程是为每个支持的平台创建可执行文件;这将成为维护的噩梦。

…也就是说你不能这么做。你不能在Unix和Windows上同时运行同一个可执行文件。

Windows使用可执行文件,Unix使用elf文件格式。它们基本上是不同的。与对应的Java不同,您可以在两台机器上运行相同的可执行文件(字节码),而这反过来又使用解释器(JVM)来执行。

现在,说你有两个选择…

  1. 或者你可以在windows和linux(unix)上安装C编译器,然后在它们上编译你的代码。
  2. 或者你可以安装'Wine',这是一个linux上的移植软件,它可以通过windows仿真在linux上实际运行windows可执行文件。

可能,选项2更适合…你说了算……

Regards

你不能让一个c++程序使用#ifdef来加载它各自的现有库吗?我认为这就是跨平台二进制文件的c++解决方案。然而,需要调整代码以使用两个或所有选定的库。

但是,如果没有java前端或两个不同的二进制文件或bat和sh或wine之类的程序,您将无法运行各自的二进制文件。

如果您创建了一个性能良好的MS Windows应用程序,它可以使用wine实用程序在Linux x86平台上不加修改地运行。

Wine 是一个兼容层,它提供了Win32和相关的运行库调用,使程序认为它是在MS Windows上运行,但是wine层将这些转换为具有良好性能的linux系统。

详情见http://www.winehq.org/