With a unified compiler it will be easier to develop 32-bit apps on 64-bit Haiku, but most of the work for supporting them is on the kernel side.
I support revitalization with llvm-gcc2; it will eliminate system build problems, facilitate 32-bit ports without the need for patches, simplify compilations, and allow these old tickets below to be closed:
No one bothered to make a patch to change the default path and hut the secondary arch first.
We went for maximal compatibility with BeOS (including drivers, applications, add-ons), because that’s the main reason people would still be running a 32 bit version of Haiku. The gcc4/2 hybrid is less compatible with BeOS for various reasons (problems with paths, incompatiple add-ons, …) and no one is interested in solving those problems. So we went with the cheapest solution.
I do not think that is it true anymore. Main reason to run 32 bit version of Haiku is use of still functional 32 bit x86 hardware, not running BeOS binaries.
I actually don’t use the 64 bit version of Haiku in my setup yet. And that is mainly for three reasons:
- I actually still run Gobe Productive, and have many (legacy) documents there. I don’t use it for new things anymore, though.
- I haven’t found a simple migration path, and I don’t want to have to setup my system again.
- There is no pressing need, as almost everything I use it for, still works with the 32-bit version.
Personally, I like the idea, especially if LLVM would adopt it, and commit to maintain it for the next years.
Besides the points you already made, it even has some more benefits:
- No more incompatible add-ons
- No need to install many libraries twice
- The support for a secondary architecture could be dropped completely from Haiku (packagefs), and HaikuPorts
- and that also makes the file system hierarchy cleaner, and the whole system easier to understand
Instead of requiring a legacy GCC 2, we would require clang instead.
I don’t see any downsides to this, but if anyone has any contra arguments, please make yourself heard.
Of course, this all depends on our willingness to continue to support BeOS compatibility in the future. I’d still like us to do this, but that doesn’t mean it’ll happen. And ultimately, it would only really be useful for everyone if it worked on top of x64 as well in the future, which then might need the whole two archicteures support again.
They are likely to adopt it if there is support from the Haiku community from this RFC, and if they do, I will volunteer as the maintainer. The way the GCC2 backend is designed makes it easy to inherit new development from Clang with minimal changes required on the compatibility backend side.
Even better, we could potentially build everything with Clang, including the GCC4+ side - maybe even just the host Clang, if this proposal gets through.
None of these benefits work out, unless you effectively deprecate the “modern” x86 arch entirely. That means all Haiku applications compiled for the modern arch (which is almost all of them) will cease to work.
(And in Addition, secondary arch design is a choice we could also just reorganize some stuff right now and remove it. We just chose not to. And In additon Haikuports does not even need _gcc2, as apps for that era are already compiled. Those should simply be dealt with with a seperate repository. Either apps get open sourced, and then no longer need _gcc2 or they remain closed and then there does not need to be a recipe to build them for _gcc2)
I don’t think that removing the entire 32bit userland compatibility of the last 15ish years makes sense in the guise of… making our development slightly easier.
In addition this now locks in everyone to using clang on 32bit, they can no longer choose to use gcc. The new hybrid arch is effectively incompatible with the old arch.
gcc 2.9 can’t compile modern C++ code, but can compile for a subset of this new ABI
the “modified” clang can compile modernc c++ code for this modified ABI
modern gcc cannot compile for this modified ABI
In effect only the modified clang would remain as an option.
The entire reason for this effort in the first place was to decrease our maintenance burden by making it possible to use some slightly more modern C++ constructs that gcc does not quite understand.
I don’t grasp how this simplification has somehow turned into a proposal to delete our entire modern userland and start with a new hybrid ABI. If the goal is to keep ABI compat why would you choose to delete the new, standard, Itanium ABI, thereby breaking alll Haiku apps of the last years and then instead keep the gcc2 ABI? By now the applications for our new ABI far outweigh those for the old ABI. If we are serious about ABI compat, and not beeing a linux-like where the answer to everything is “lol just recompile, no source compat? well then just fix the app before recompiling!” we should not remove the x86 arch, especially not before 2038.
Could Haiku not “simply” tell legacy applications that it’s the year 2001, forever? It’s technically incorrect, but I don’t consider it a meaningful inconvenience for the user.
It can compile code for any ABI, depending on what flags you pass it to. In fact, for the code I currently have, it emits Itanium by default.
There is a reason we have not made a release yet. We already do break compatibility from time to time – just not with BeOS, because that would be a bug. Most apps would be compiled with HaikuPorter anyway. Current Haiku userland is still built with GCC 2.95 for the most part (in tree). For my part, breaking compatibility would be acceptable here, as is locking the userland to clang for the time being, as it reduces superfluous complexity. But that’s just my opinion, anyway. And no one would hinder anybody at adding the same ABI to current GCC, either.
Having to touch each and every HaikuPorter recipe might a very good counterargument to that plan, too, though.
In any case, what other way do you imagine to solve the issue with supporting the two ABIs at once?
I highly doubt GCC is designed to support this without too many downstream patches.
Don’t we do that from time to time as part of routine maintenance such as updating app versions?
While doing that, we can also simplify the recipe to build with Clang for all targets and remove the $secondaryArchSuffix.
The number of _x86 packages should be easily trackable in a package repository file. Once most packages have been migrated from _x86 as part of routine maintenance, we can have a more coordinated effort to purge the rest (possibly done automatically using scripts) and complete the transition.
Clang is surely slower than GCC2, and memory intensive. I see this more as an alternative to GCC 2.95.
IMO having GCC on x86_64 and Clang on x86_gcc2 make things more difficult to maintain haikuports. At least _x86 and x86_64 are consistent.
I’m also not sure how ASM tools like nasm or yasm will handle the change.
In the end, it also doesn’t bring Golang, OpenJDK, Rust to x86, or more memory to build WebKit/Webengine. Looks like a side quest ![]()
Well, in any case. I think removing this ABI is a strong negative indicator, as this would be a new ABI we then have to support basically indefinetely (and one that does not match the BeOS one precisely)
If we ever support 32bit BeOS apps on 64bit Haiku we are then also locked into clang for that support.
I’d still much prefer the way of a dedicated compat library that provides this ABI, and otherwise deprecate the BeOS compatible one… we already removed compat for drivers and such for example
Can we not use Clang for all architectures? Is it also a known fact that Clang is slower than modern GCC?
These tools should produce object files from assembly, right? So, if I am not mistaken, the C++ toolchain should be irrelevant?
What are the blockers? Don’t many of these large projects use Clang instead of GCC?
For .NET, I would see this making it possible to port the runtime to x86_gcc2 if there is ever demand.
We are as locked into Clang in that case as we are locked into GCC2 today.
We use GCC2 today because that is the only compiler that works.
I propose Clang because it is the only compiler mature enough to handle standard C/C++ and modular enough to easily extend to the GCC2 ABI.
Theoretically we are not “locked into” anything - any implementation that can understand and generate the target ABI should work.
Isn’t this pretty much the status quo?
We currently have a set of libraries with the GCC2 ABI (the entire GCC2 ABI userland) that works with the rest of the system through a stable C ABI (libroot.so).
Under the “compat library” idea we will still need:
- Two sets of libraries (normal libraries and “compat” glue libraries).
- Support for two ABIs.
- Special tooling that understands the legacy ABI (either GCC2 itself, this Clang port, or some weird nonstandard polyglot tool that can magically translate between Itanium and GCC2).
- A robust way to indicate when to use or not use these compat libraries (i.e.
setarch).
Hmm, no not really. We have one code base that we compile with two compilers, that means it has to work with both. A “smaller” compat library could leave most business logic to the “modern” lib while providing a frontend for exactly the ABI surface we want to expose, and not more. This would effectively freeze the surface and not add more, like the Itanium compat in your example would do.
Yes, I suppose this would need a compiler that can do both, but that is exactly the thing where clang could work. I’d just much rather see a fixed compat library we can later on also use on 64bit Haiku, while staying with the modern ABI, and not have a needless diversion from other operating systems.
I’d solve this with a library that connects to both ends, not an ABI translation as such. this would not require setarch, that command only specifies compilers, in this scenario you would never need the gcc2 compiler variant except for building the compat library… it could even live outside the Haiku tree if wanted
Right - so essentially you agree to adopt Clang if it magically supports the GCC2 ABI, and reject the rest of the RFC (the part that involves migration to GCC2 ABI), am I correct?
I don’t understand this part. setarch sets an environment so that a binary requesting something such as libroot.so gets the correct version.
Without a setarch-style tool, how would you ensure a BeOS binary gets the ABI it needs when it requests libroot.so on a GCC4 primary environment?
Even with a frozen ABI surface, we would either need to duplicate hundreds of functions or tag them with weird macros or something similar so that the tool could recognize and generate the code we want.
That is not to mention the complex marshalling implementation, as we are escalating from two ABIs on one OS installation to two ABIs on one team. All of this needs to be maintained somewhere in the Haiku ecosystem, even if it is put out of tree (and manage not to bitrot).
The whole spirit of this RFC is for fewer hacks to float around Haiku and its apps, not more. Everything should just work the way it is meant to work, not through a fragile shim.
Kinda. The “original” idea was to use clang for the gcc2 abi, and compile the _gcc2 variant of the userland with it. Without the Itanium modifiaction to the ABI, and without removing the other architecture I would be Okay with that original plan.
setarch is a commandline tool, I don’t understand how this would work, this is never ran when starting a gcc2 based GUI application. the runtime loader is the application which should select the correct variant for you. iirc setarch is primarily for setting the right include paths for your compiler, the right $PATH etc.
(though looking at the code it seems to only set the path, i guess the rest is known by the compiler?)
The functions would need to be in the compat library once for the frozen ABI, similar to how we now do this with explicit mangling, (i.e the whole extern C stuff to keep stuff in the right position)
If you call ::Draw for example this will just use the ::Draw() in the gcc2 abi, and the implementation would call the ::Draw() from the Itanium abi, but with any BeOS specific nuanced dealt with beforehand. This should reduce the ammount of “hacks” we need in our normal code and allow us to move it to the BeOS compat library.
I don’t see how this proposal would decrease the ammount of hacks?
For example, we cannot build a recent ICU version on gcc2, and we need to build DIFFERENT versions of ICU on gcc2 and gcc > 2 systems. Since we implement our public API on top of ICU, in certain cases we can’t expose the same API on gcc2 and > gcc2 systems.
Same problem with other libraries. This would be solved with this approach, if I understood correctly