This is a major roadblock for commercial third-parties that would like to distribute ports of their software for Linux.
gcc -arch i386 -arch ppc -arch x86_64 -isysroot <SDK path> example.c -o example
Done. > file example
example: Mach-O universal binary with 3 architectures
example (for architecture i386): Mach-O executable i386
example (for architecture ppc7400): Mach-O executable ppc
example (for architecture x86_64): Mach-O 64-bit executable x86_64
I can even transparently run PPC binaries on my x86 Mac.Universal binaries are a core component of this easy-to-use (for developers and users alike) architecture independence.
No, what I'm demonstrating is an end-to-end architecture-transparent platform, which includes a complete userspace toolchain, a universal binary format, and necessary kernel and dynamic linker support.
What was suggested above is an improvement by not requiring meddling with the kernel
I'm not sure I understand how "meddling" in the kernel is a bad thing when it provides for user-transparent execution of multi-architecture binaries, including transparent emulation of binaries that lack support for the host architecture.
It's not as if it's complex or dangerous to parse the Mach-O or FatELF formats, and if you take a page from Mac OS X or qemu, you can even do transparent emulation in userspace.
Nothing prevents a userland toolchain for Linux from supporting what you are describing above without kernel modifications.
How is it useful to build an easy-to-use multi-architecture binary if the kernel can't actually execute it?
Why are you afraid of doing simple parsing[1] of the binary? The kernel already does this -- how do you think ELF loading and shell script execution works?
I can imagine this conversation 30 years ago[2] -- "Why should we add shell script shebang parsing/execution support to the kernel? Why not just glue together loader executables that load the shell script"
[1] The dead simple Mach-O universal binary loading code: http://fxr.watson.org/fxr/source/bsd/kern/kern_exec.c?v=xnu-...
[2] The introduction of shebang in UNIX: http://www.in-ulm.de/~mascheck/various/shebang/sys1.c.html
The motivation, though, was not just to make things easier for the ISVs, but also to make things easy for the ISVs' customers. Simplifying the process of buying and installing software was the real thrust of the endeavor. [1] There is real economic value in making things easy for customers.
Why, for example, would web sites offer 1-Click ordering, when entering a credit card number is just a few more keystrokes? Because simplicity makes money flow, and is good for a market.
The Year of the Linux Desktop will never come until these issues become important to the community. Which is to say that it will never happen, because the community, as a whole, has no economic incentive to lower the bar for customers like this.
Ryan Gordan probably could have figured that out sooner, but I'm glad he was an optimist for a little while, at least.
[1] There was also a secondary benefit for system administrators. You could install a single copy of a 4-way-fat-binary on an NFS share and a workstation running NeXTstep of any architecture could launch it over the network.
FWIW, I used Debian/PPC at home for years. But, then, I was also among the small set of people who actually ran NeXTSTEP on a "gecko" PA-RISC machine and a SPARC laptop made by Tadpole. That's the story behind my perspective, anyway.
You can produce all important functionality of the fat_elf patches with a single simple shell script.
Remember that stuff in kernel works outside memory protection. Moving complex stuff away from the kernel is a win pretty much always when there are no pressing performance reasons to do otherwise. This code will only run once every time a program is started, so performance is certainly not a good reason to put it in kernel.
What I really want to reiterate here is that using fat_elf:s would in absolutely no way make shipping stuff to multiple different linux platforms easier. The reason it is hard is because when someone says linux, pretty much the only guarantee you have about the system is that it runs a linux kernel, and even that can potentially be so old or be so strange that you can't trust anything about it. All fat_elf gives us is stuffing multiple binaries in a single file, and we can do this already without much fuss. It does not in any way give us true "Universal Binaries", because to do so, we would have to either agree on a common subset of libraries a linux system should always ship (and agree on indefinite binary compability for those libraries), or ship a meaningful portion of the entire platform in every binary.
If you want what fat_elf gives, you can get it with a 20-line shell script you concatenate into a bunch of binaries, and it could be argued that it is the cleaner and better place to put it in, considering it's only an ugly hack anyway. It's just that people look at fat_elf and see something that isn't there.
Or, perhaps even better, adopt a small, architecture-neutral IR like LLVM-BC and a workstation of any architecture could choose to compile it just-in-time at launch, or at install time.
Either way, the greatest tragedy here is small thinking. I would love to see Linux rise to the level where users don't need to know what an instruction-set architecture is.
Universal/fat binaries made sense on the Macintosh because there is no concept of program installation on these systems. While I think that eschewing installation is generally a better design, one drawback is that if you want to be able to support multiple architectures in one application you have to do the architecture check when the program is loaded.
Central to Linux and Windows is the idea of program installation, either through packages or installer programs. No one is interested in making it so that you can drag and drop items in Program Files or /usr/bin between systems and expect them to run, which is the only thing that using fat binaries really gets you over other solutions.
Nearly all of the commercial binary-only software I have seen in Linux (and other Unixes) uses an installer program, just like windows. There is no technical reason why such an installer couldn’t determine the architecture to install.
The problem can be solved in two ways:
1) Distributing through a repository and have the package manager auto-select the architecture. However this is highly distribution-specific. If you want to build a single tar.gz that works on the majority of the Linux distros then you're out of luck.
2) Compile binaries for multiple architectures and bundle everything into the same package, and have a shell script or whatever select the correct binary.
While (2) is entirely doable and does not confuse the end user, it does make the developer's job harder. He has to compile binaries multiple times and spend a lot of effort on packaging. Having support for universal binaries throughout the entire system, including the developer toolchain, solves not only confusion for the end user but also hassle for the developer. On OS X I can type "gcc -arch i386 -arch ppc" and it'll generate a universal binary with two architectures. I don't have to spend time setting up a PPC virtual machine with a development environment in it, or to setup a cross compiler, just to compile binaries for PPC; everything is right there.
I think the ultimate point is not to make impossible things possible, but to make already possible things easier, for both end users and app developers.
Regarding point two, the developer is stuck with the packaging hassle regardless. The binary goes one place, config files and man pages in others, maybe you want a launcher in the gnome and kde menus... You are stuck with writing an install script anyway.
And yes, the developer must take care of packaging anyway. But that doesn't mean packaging can't be made easier. If I can skip the step "setup a cross compiler for x86_64" then all the better.
Neither the compiler nor the emulator are perfect. Somebody has to test and debug your packaged app on actual PPC hardware.
Our Xcode-supported unit tests transparently run three times -- once for x86_32, once for x86_64, and once for PPC. The PPC run occurs within Rosetta (ie, emulated).
If the tests pass, we can be reasonably sure everything is A-OK. In addition, we can do local regression testing under Rosetta (but it's rarely necessary -- usually everything just works).
The only native PPC testing we do is integration testing once we reach the end of the development cycle.