14

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.

  • 1
    It would be most helpful to know which open source application you've been studying so we could see it as well. – Mark Ransom Sep 15 '11 at 16:07
  • Hi Mark, thank you. You can download that application here: http://xjperf.googlecode.com/files/jperf-2.0.2.zip. –  Sep 15 '11 at 16:10
  • 1
    This question: http://stackoverflow.com/questions/2082336/has-anyone-been-able-to-create-a-hybrid-of-pe-coff-and-elf has the closest thing possible – Flexo Sep 15 '11 at 16:37
  • 1
    What's about JNI ? http://javablog.co.uk/2007/05/19/making-jni-cross-platform/ – willll Sep 15 '11 at 17:57
  • Unless you are need high performance, much like turtles, you should go Java all the way down. Also, there a few CAD programs that have 1 JAVA GUI that chooses between Windows and Linux files, both of which are distributed. – Mikhail Apr 03 '13 at 07:38

8 Answers8

11

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.

NoDeadCode
  • 131
  • 1
  • 3
  • 1
    Technically speaking, all modern windows PE binaries are a fat binary that would print a message about lack of compatibility on DOS. Not that its very useful. – user1937198 Mar 22 '21 at 22:41
  • 3
    someone has actually gone and done this. does that mean justine is insane @NoDeadCode? =) https://github.com/jart/cosmopolitan – billywhizz Jul 30 '21 at 23:09
11

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.

Adam Leyshon
  • 131
  • 6
10

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.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • The question states that the observed application is C++, not Java, it's just being started via a Java front end. And I thought there have been executable files that could run on both Windows and Mac. – Mark Ransom Sep 15 '11 at 16:02
  • @Mark Same executable on Windows and Mac? I don't think so. – David Heffernan Sep 15 '11 at 16:03
3

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.

No matter users use that application in Windows or Linux, the Java GUI will call the same executable file in the bin folder.

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.

fasih.rana
  • 1,645
  • 1
  • 14
  • 27
3

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.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
  • Creating an executable for every supported platform is in no way a maintenance nightmare. This is common practice for almost every program out there, commercial or not. Building these executables is an easily automated process. – B T Sep 01 '14 at 18:50
  • @BT There are far more platforms out there than you seem to have thought of when making that comment. Any reasonably portable C program inherently supports CPU and operating system combinations that you won't have compilers for and can't run or emulate easily, but you could still reasonably say "any system with a hosted C89 implementation is supported". Solaris 10 on SPARC, Linux compiled for RISCV, UniVAC and their modern emulation hardware.. From where I'm looking, the common practice for "almost every program out there" is a source tarball and binaries for maybe 2-6 most common platforms. – mtraceur Jan 06 '23 at 14:51
  • As a concrete example: last I checked, all sorts of software that I use - Git, Node.js, Go, curl, never offered pre-built binaries for Linux on ARMv7 CPUs with software floating point (I think at one point some of those had an ARMv6 build which assumed hardware floating point support), and yet I was able to compile it just fine for ARMv7 with software floating point (or rather if I remember right I just needed the *ABI* that was initially designed for ARM systems without hardware floating point) and neither of those projects would have rejected me with "not supported" if I filed a bug report. – mtraceur Jan 06 '23 at 15:01
0

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.

0

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/

wallyk
  • 56,922
  • 16
  • 83
  • 148
0

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...

  1. Either you can actually install C compilers on both windows and linux(unix) and then compile your code on both of them.
  2. Or you can install 'Wine', a porting software on linux which will be able to actually run windows executable file on linux by windows emulation.

Probably, option no 2 would be better suited...Its your call...

Regards,

Vineet Menon
  • 728
  • 2
  • 9
  • 25