Brace yourselves, this question will likely appear naive and/or foolish, seeing as I am relatively new to the inner workings of unix like systems, and programming in general.
Ready? Ok! I will go through about 3 levels of ludicrosity, increasing as I go along.
We have two systems with similar hardware (main point being the processor, let us say a standard intel core 2 duo).
One is running (insert your linux distro here: Ubuntu will be used henceforth), and the other is running let’s say Mac OS X.
One compiles an equivalent program, Let us say something like:
int main()
{
int cat = 33;
int dog = 5*cat;
return dog;
}
The code is extremely simple, because I don’t want to consider the implications of shared libraries yet.
When compiled on the respective systems. Is not the main difference between the output a matter of ELF vs Mach-O? If one were to strip each binary of the formatting, leaving a flat binary, wouldn’t the disassembled machine instructions be the same? (with perhaps a few differences depending on the compilers habits/tendencies).
1.) If one were to develop a program to repackage the flat binary produced from our Ubuntu system, in the Mach-O formatting, would it run in the Mac OS X system? Then, if one only had the compiled binary of the supposed program above, and one had this mystical tool for repackaging flat binaries, would simple programs be able to run on the Mac OS X system?
Now let us take it a bit further.
We now have a program with source such as:
#include <stdio.h>
int main()
{
printf("I like tortoises, but not porpoises");
return 0;
}
2.)Assuming this program is compiled and statically linked, would our magical program still be able to repackage the raw binary in the Mach-O format and have it work on mac os X? Seeing as it would not need to rely on any other binaries, (for which the mac system would not have in this case)
And now for the final level;
3.)What if we used this supposed program to convert all of the necessary shared libraries to the Mach-O format, and then instead compiled the program above with dynamic linking. Would the program still succeed to run?
That should be it for now, obviously each step of absurdity relies on the previous base, to even make sense. so If the very first pillar gets destroyed, I doubt there would be much merit to the remaining tiers.
I definitely would not even go as far as to think of this with programs with GUI’s in mind. Windowing systems would likely be a whole other headache. I am only considering command line programs at this stage.
Now, I invite the world to correct me,and tell me everything that is wrong with my absurd line of thinking.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
You forget one crucial thing, namely that your program will have to interact with the operating system to do anything interesting.
The conventions are different between Linux and OS X so the same binary cannot run as-is without essentially having a chunk of operating system dependent code to be able to interact with it. Many of these things are provided through libraries, which you then need to link in, and that means your program needs to be linkable, and linking is also different between the two systems.
And so it goes on and on. What on the surface sounds like doing the same thing is very different in the actual details.
Method 2
This is doable if someone wants to spend enough time to make it happen. The Darling project is attempting this, though as of this writing, it’s in a pretty primitive state.
It’s been done successfully before on other platforms:
-
Solaris and UnixWare include a helper program called
lxrunwhich works something likesudo: you pass your executable name and parameters to the helper and it fixes things up dynamically so that the executable can talk to the OS. The official site (down, archive link) says it’s bitrotted. - Linux’s kernel once had a feature called iBCS that did the reverse, except that it didn’t need a helper because the kernel recognized the “foreign” binaries directly. It fell into disrepair during the kernel 2.3 development series, most likely because the small Unix server battle was essentially over once 2.4 came out.
-
FreeBSD’s kernel can be configured to recognize Linux binaries and run them as if they were native. This feature appears to be in better shape than the above two.
OpenBSD and NetBSD have similar features.
OS X has a lot of FreeBSD in it, so porting its Linux support might be straightforward.
Method 3
I pretty much agree with everyone, but I want to add that, while this would take a significant amount of time and effort, it wouldn’t be nearly as much as it has taken to develop Wine.
Much of the difficultly in Wine development is that they are porting a binary format from a closed source operating system and MANY of the system calls are undocumented. They had to essentially reverse engineer the operating system.
If someone were to do this from one open OS to another open OS, they could likely get it done in 1/10 of the time, since the compatibility layer could quite conceivably be copy/pasted from the other OS if an equivalent native system call doesn’t exist. Of course, in most cases across the POSIX world, there will be a native call available.
Another project of note is ReactOS, where they’re essentially creating a full binary-compatible version of Windows… no need for Wine.
Method 4
It is technically doable in macOS but not without significant effort, although some of the effort is already done for us.
- Both macOS and a rebranded Red Hat Enterprise Linux have been certified UNIX 03. This means in principle POSIX calls should have the same API.
- Both macOS and Linux uses System V ABI for amd64 platform. This means that for amd64 macOS and Linux should have compatible ABI and API.
- macOS uses Mach-O as its native executable format while Linux uses ELF. This does make things easier, as the executable file format can be used to distinguish whether the compatibility layer should be called. This would require something like
binfmt_miscthough. - There exists a third party macOS kernel extension that provides exactly that. Now we have a way to load convince macOS to load ELF, we need our special
ld-linux.sowhich itself is a Mach-O executable that would load our ELF and run it.
Now what we need is at least a special ld-linux.so that can do the following:
- Be a Mach-O executable or
dylditself, - Can load Linux ELF files into memory at the correct address,
- Hopefully has the ability to map Linux soname to macOS ones (example
/lib/libc.so.6to/lib/libSystem.B.dylib) and load corresponding Mach-O when a matching ELF is not found, so we can reuse macOS libraries
With just that loader above ELF that does not make direct syscalls has a good chance of working, but ELF with syscalls might not work. A second component that might be useful would be a kernel extension that catches those Linux syscalls and maps them to macOS ones. As of desktop uses, special mesa implementation is needed to map Linux graphics calls to OpenGL.framework and Metal.framework.
Method 5
There are a number of specialized Linux apps for which this would be a great help. On the FPGA side, Quartus and Vivado are good examples of programs that run under Linux and there is unlikely to be source code available for them or similar programs that target the latest FPGAs.
I think the simple answer to your question is: recompile on MacOS where you have the source and form a group to provide the capability if you have the time–and it will be a time consuming task.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0