(C/C++) 如何生成可以在Windows和Linux上运行的可执行文件?
我是编程新手。据我所知,在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 可执行文件结合起来?是否可以生成可以在两个平台上运行的单个可执行文件?
谢谢。
I'm new in programming. From what i know, a program that is compiled in Linux should not be able to run in Windows. So, if we want to run the same program in both platform, we need to compile the source code under both platform, and create 2 different executable files.
Recently I am studying the source code of an open source, cross-platform Java GUI application. I'm surprised to find that the backend engine of that GUI application is a small executable file generated from C++ codes. No matter users use that application in Windows or Linux, the Java GUI will call the same executable file in the bin folder.
I just want to know, how can that executable file run on both Windows and Linux?
I'm also interested to create a cross-platform Java GUI application using a C++ program as the engine. That C++ program is only available for Linux only. I've been googling for a while and i found that I need to use Cygwin to port it to Windows. However, if i use Cygwin, i will end up having 2 different executable files.
How can i combine the Windows executable file with the Linux executable file? Is it possible to generate a single executable file that can run on both platform?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
好吧,孩子们。
是的,您可以编写多平台二进制文件,但这很困难。它被称为 Fat Binary,它在 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 仍将运行这些文件,您似乎可以创建通用二进制文件。我不能肯定地说这会起作用,但似乎是合理的。
另一个警告:通常您需要在代码的开头放置一个跳转,以跳过其他操作系统的入口点、标头等,因为您无法在那里找到您的代码(显然)。
现代计算中的问题是大多数防病毒软件会错误地将其识别为病毒。过去,病毒通常会通过在可执行文件的开头插入这样的跳转来攻击二进制文件,该跳转会跳转到二进制文件的末尾,将自己的代码附加到二进制文件的末尾,然后插入另一个跳转回主可执行文件代码。由于您需要做一些或多或少类似的事情来在一个二进制文件中支持多个平台,因此大多数反病毒软件都会试探性地将其识别为病毒并隔离您的可执行文件。
简而言之:是的,它可以针对(某些)平台组合来完成。这并非不可能,但你必须发疯才能做到这一点。
Ok, kids.
Yes, you CAN write a multi-platform binary, but it's difficult. It's called a Fat Binary, and it used to common enough in the 1980's although I haven't seen it done in decades. https://en.wikipedia.org/wiki/Fat_binary
Basically, you compile the machine code for each platform you want to run on and then hand-link the code with different entry points. While the Wikipedia article merely describes packing different architectures into the same binary, its actually possible to make one binary that runs on different operating systems so long as the entry points for the operating systems don't collide.
Some executable formats were intentionally designed to allow this. For example, MZ, NE, LX and PE can be overlaid. Old OS/2 programs sometimes did this... they rarely contained an entire program for both operating systems, but when run on DOS would print a message telling you that you were using the wrong operating system for the program.
As far as Linux and Windows in one binary: While you can't do an ELF and PE, I believe it might be doable with a PIE or a COFF and a PE or COM. Older Linux will run COFF binaries, which PE is descended from, so it seems you might be able to create a universal binary if newer versions of Linux will still run these. I can't say for sure this would work, but it seems plausible.
Another caveat: Usually you need to put a jump in the code right at the beginning to skip past the other operating system's entry point, headers, etc. because you can't locate your code there (obviously).
The problem with this in modern computing is that most anti-virus software will incorrectly identify this as a virus. It used to be common that viruses would attack binaries by inserting such a jump at the beginning of an executable that jumped to the end of the binary, tacking their own code onto the end of the binary, then inserting another jump back to the main executable code. Since you need to do something more-or-less similar to support multiple platforms in one binary, most AV software will heuristically identify this as a virus and quarantine your executable.
So in short: YES it can be done for (some) combinations of platforms. It is not impossible, but you would have to be insane to do it.
简单的答案是,你不能。
PE (Windows) 和 ELF (Linux) 二进制可执行文件格式完全不同。
更不用说 C/C++ 程序需要链接到在两个平台上同时可用的库。
但是,您可以在 Linux 上使用 Wine 来运行 Windows 可执行文件,前提是它不尝试进行特殊的 Windows 特定调用。
或者您可以选择使用更“通用”的跨平台语言,例如 .NET for Windows 和 Mono for linux/其他支持的 CLI 语言(C#/IronPython/Java 等)。
The simple answer is, is that you can't.
The PE (Windows) and ELF (Linux) binary executable formats are totally different.
Not to mention that a C/C++ Program requires linking to libraries that won't be available on either platform simultaneously.
However, you could use Wine on Linux to run the Windows executable providing it doesn't attempt exotic Windows specific calls.
Or you could choose to use a more "common" cross-platform language such as a CLI language (C#/IronPython/Java etc.) that .NET for Windows and Mono for linux/others supports.
无法从 C++ 源代码编译出一个可在不同平台上运行的本机可执行文件。我不相信您在 Windows 和 Linux 上运行相同的可执行文件,正如您在第二段中所述。
There is no way to have a single native executable compiled from C++ source that works on different platforms. I don't believe you that the same executable file is run on Windows and Linux, as you state in your second paragraph.
简而言之,不可能在不同平台上运行相同的可执行文件。对于 Windows、Linux 或任何其他 UNIX 平台都是如此。
拥有单个可执行文件的想法并不是什么新鲜事,也是 Java 运行时和 Windows .Net(Mono for Linux)背后的想法。它们本身依赖于在特定机器上编译的不同可执行文件。
他们可能只是使用这些可执行文件的相关路径,并且这些可执行文件可能是在不同平台上单独编译的。不看代码很难判断。
Cygwin 是 Windows 上的命令行界面,提供 UNIX 外观。
可以尝试的一个选择是 Wine,它是一个用于 Linux 的程序,可以在 Linux 上运行 Windows 程序。
Simply put, it is not possible to run the same executable on different platforms. It is true for Windows, Linux, or any other UNIX platform.
The idea of having a single executable is nothing new and is the idea behind Java Runtime and Windows .Net (Mono for Linux). These themselves rely on different executables compiled on the specific machines.
They might simply be using relavant paths to these executables, and these executables are probably compiled separately on different platforms. Hard to tell without looking at the code.
Cygwin is a command line interface on windows that provides UNIX look and feel.
One option to try would be Wine which is a program for Linux to run windows programs on Linux.
如果操作系统位于同一平台上,这是可能的。
然而,Linux 可以在具有不同处理器的各种平台上运行:VAX、MAC、PC、Sun 等。
一个问题是可执行文件包含特定于处理器的汇编(机器代码)指令。使用 ARM 处理器添加寄存器的机器代码可能与 Motorola、Intel 或 Sun 处理器不同。因此,在这种情况下,可能无法保证一个可执行文件在不同平台上运行。
另一个问题是运行时库还可能调用特定的操作系统功能(如文件打开、显示文本等)。某些操作系统可能不提供相同的功能;而其他人有不同的方法来执行相同的功能。嵌入式平台上的操作系统可能不支持文件系统。 Windows Vista 可能会阻止来自不安全的 MSDOS 请求的调用。
其他语言通过生成由“虚拟机”执行的代码而变得独立于平台。该代码不直接由处理器执行。
移植C和C++方法的传统方法是提供源代码并让客户在他们的平台上构建软件。其他交付流程是为每个支持的平台创建可执行文件;这成为维护的噩梦。
It may be possible, if the OSes are on the same platform.
However, Linux can run on a variety of platforms with different processors: VAX, MAC, PC, Sun, etc.
One problem is that an executable contains assembly (machine code) instructions specific to a processor. The machine code for adding a register using ARM processor may be different than a Motorola, Intel or Sun processor. So with this context, one executable may not be guaranteed to run on different platforms.
Another issue is that the Run-Time library may also make calls to specific OS functions (like file open, displaying text, etc.) Some operating systems may not supply the same functionality; while others have a different method to execute the same functionality. An OS on an embedded platform may not support a file system. Windows Vista may block calls from unsecure MSDOS requests.
Other languages become platform independent by generating code which is executed by a "virtual machine". The code is not directly executed by a processor.
The traditional method for porting C and C++ methods is to provide the source and let the customers build the software on their platform. Other delivery processes is to create an executable for every supported platform; this becomes a maintenance nightmare.
你不能这样做……即你不能在 Unix 和 Windows 上运行相同的可执行文件。
Windows使用可执行文件,而Unix使用elf文件格式。它们基本上是不同的。与对应的 Java 不同,您可以在两台机器上运行相同的可执行文件(字节码),而后者又使用解释器(JVM)来执行。
现在,你有两个选择......
也许,选项 2 会更适合...这是你的决定...
问候,
You can't do that....i.e. you can't run the same executable on both Unix as well as Windows.
Windows uses executable files, while Unix used elf file format. They are basically different. Unlike the counterpart Java where you can run the same executable( bytecode) on both machines, which in turn uses an interpreter(the JVM) to execute.
Now, said that you have two options...
Probably, option no 2 would be better suited...Its your call...
Regards,
不能让 C++ 程序使用 #ifdef 加载其各自的现有库吗?
我认为这就是跨平台二进制文件的 C++ 解决方案。但是,需要调整代码才能与两个或所有选定的库一起使用。
然而,如果没有 java 前端或 2 个不同的二进制文件或一个 bat 和一个 sh 或像 wine 这样的程序,您将无法运行相应的二进制文件。
Can't you make a C++ program load it's respective existing libraries using #ifdef?
I think that's the C++ solution to cross platform binaries. However the code needs to be adjusted to work with both or all chosen libraries.
However without a java front end or a 2 different binaries or a bat and a sh or a program like wine you won't be able to run the respective binary.
如果您创建一个表现良好的 MS Windows 应用程序,它可以使用
wine
在 Linux x86 平台上运行,无需修改 实用程序。Wine
是一个兼容层,它提供 Win32 和相关的运行时库调用,以便程序认为它在 MS Windows 上运行,但 wine 层将这些转换为 Linuxisms 非常好表现。更多详细信息,请访问 http://www.winehq.org/
If you create a well behaved MS Windows application, it can run unmodified on Linux x86 platforms using the
wine
utility.Wine
is a compatibility layer which provides Win32 and associated runtime library calls so that the program thinks it is running on MS Windows, but the wine layer translates those into Linuxisms with really good performance.More detail at http://www.winehq.org/