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

时间:2011-09-15 15:45:31

标签: c++ c windows linux cross-platform

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

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

我只是想知道,该可执行文件如何在Windows和Linux上运行?

我也有兴趣使用C ++程序作为引擎创建一个跨平台的Java GUI应用程序。该C ++程序仅适用于Linux。我已经谷歌搜索了一段时间,我发现我需要使用Cygwin将其移植到Windows。但是,如果我使用Cygwin,我将最终拥有2个不同的可执行文件。

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

感谢。

8 个答案:

答案 0 :(得分:9)

简单的答案是,你不能。

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

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

但是,您可以在Linux上使用Wine来运行Windows可执行文件,前提是它不会尝试异乎寻常的Windows特定调用。

或者您可以选择使用更常用的跨平台语言,例如.NET语言(C#/ IronPython / Java等),.NET for Windows和Mono for linux / Others支持。

答案 1 :(得分:8)

无法从C ++源编译的单个本机可执行文件在不同平台上运行。我不相信你在Windows和Linux上运行相同的可执行文件,正如你在第二段中所述。

答案 2 :(得分:3)

简单地说,不可能在不同的平台上运行相同的可执行文件。适用于Windows,Linux或任何其他UNIX平台。

拥有单个可执行文件的想法并不是什么新鲜事,而且是Java Runtime和Windows .Net(Mono for Linux)的理念。这些本身依赖于在特定机器上编译的不同可执行文件。

  

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

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

Cygwin是Windows上的命令行界面,提供UNIX外观。

尝试的一个选项是Wine,这是Linux在Linux上运行Windows程序的程序。

答案 3 :(得分:2)

如果操作系统位于同一平台上,则有可能。

但是,Linux可以在具有不同处理器的各种平台上运行:VAX,MAC,PC,Sun等。

一个问题是可执行文件包含特定于处理器的程序集(机器代码)指令。使用ARM处理器添加寄存器的机器代码可能与Motorola,Intel或Sun处理器不同。因此,使用此上下文,可能无法保证一个可执行文件在不同平台上运行。

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

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

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

答案 4 :(得分:1)

好,孩子们。

是的,您可以编写一个多平台的二进制文件,但这很困难。它被称为“胖二进制”(Fat Binary),它在1980年代曾经很常见,尽管几十年来我还没有看到它。 https://en.wikipedia.org/wiki/Fat_binary

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

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

就Linux和Windows而言,它是一个二进制文件:虽然您无法进行ELF和PE,但我相信可能可以与PIE或COFF一起使用PE或COM。旧版Linux将运行PE派生的COFF二进制文件,因此,如果新版本的Linux仍将运行这些二进制文件,则您似乎可以创建通用二进制文件 。我不确定这是否行得通,但这似乎是合理的。

另一个警告:通常,您需要在代码的开始处添加一个跳转,以跳过其他操作系统的入口点,标头等,因为(显然)您无法在此处找到代码。

现代计算中存在的问题是,大多数防病毒软件都会错误地将其识别为病毒。通常,病毒会通过以下方式攻击二进制文件:在可执行文件的开头插入一个跳转,跳转到二进制文件的末尾,将自己的代码附加到二进制文件的末尾,然后再将另一个跳转回主可执行文件码。由于您需要执行某种或多或少的类似操作以在一个二进制文件中支持多个平台,因此大多数视音频软件都会试探性地将其识别为病毒并隔离可执行文件。

因此,简而言之:是的,可以针对(某些)平台组合使用。这并非不可能,但您必须疯了。

答案 5 :(得分:0)

你不能这样做......即。你不能在Unix和Windows上运行相同的可执行文件。

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

现在,说你有两个选择......

  1. 您可以在Windows和Linux(unix)上实际安装C编译器,然后在两者上编译代码。
  2. 或者你可以在linux上安装'Wine',这是一个移植软件,它可以通过windows仿真在linux上实际运行Windows可执行文件。
  3. 可能选项2号更适合......它的召唤......

    此致

答案 6 :(得分:0)

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

然而,如果没有java前端或2个不同的二进制文件或bat和sh或像wine这样的程序,您将无法运行相应的二进制文件。

答案 7 :(得分:0)

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

Wine 是一个兼容层,它提供Win32和相关的运行时库调用,以便程序认为它在MS Windows上运行,但是wine层将它们转换为非常好的Linux主义性能

http://www.winehq.org/

的详细信息