HNHacker News
TopNewBestAskShowJobs

okanat

1,989 karma · joined June 20, 2021

submissionscomments
okanat··on Stop Making TUIs
I don't know much about macOS. I only used other people's stuff and navigating it is really hard for me.

You're wrong about GTK, Qt, WinUI and Electron though. They default to "do nothing" which eliminates the ability to even know that another instance exists. You have to manually program that.

okanat··on Stop Making TUIs
Yeah. This is Unix nerd bs and toxic behavior and silly belief that only terminals deliver complex behavior.

I was visiting a radio test lab in last February for our new product. They use a professional software which was written in WPF. The assistant there was flying with the keyboard shortcuts.

I recommend every self-describing Unix or terminal fan to watch videos of photo or video editors / VFX people on YouTube. They are hella fast.

okanat··on Stop Making TUIs
KDE has a framework based on Qt's QML that works on Android. It is called Kirigami. They have written apps and even a complete Plasma Mobile using it. The apps work both on Android and Linux.

Mobile has significant paradigm changes that makes using both terminals and traditional GUIs harder anyway though. I do expect the need for completely different cross-platform libraries for mobile UIs.

okanat··on Stop Making TUIs
No. When the communication side is actually done thoughtfully, GUIs deliver superior experiences even in remote environments.

VSCode SSH extension is one of the most widely developer-used proof against this. Windows' RDP is the other one where many engineers and POS personnel have experince using them. Many electrical and mechanical engineers still use Windows RDP at my work to run simulations. The connection is responsive enough to survive their home-to-office VPN connection. I set up complex chemical simulation software that is accessed by clients of a HPC cluster over 1000s of kms away.

VScode has a really efficient protocol that communicates only that's required, Windows RDP can declaratively send UI component changes as long as one uses Win32 or WPF. It can also reasonably compress the data to even survive dial-up levels of bad data.

We use multi-attendant video conferencing day to day with whiteboarding extensions. If there is will, efficient and amazing remote-GUIs are easy.

okanat··on Solo – a .so loader for static Linux binaries
THERE IS NO STANDARD, AGREED ON, RFC'd or EVEN BEHAVIORALLY DOCUMENTED ABI FOR MUSL TO FOLLOW!

It's not Musl's fault that Glibc has an undocumented, badly designed, tightly coupled implementation. It's not Musl's fault when they decide to not follow Glibc's design which they have to reverse engineer and rewrite from scratch. Then Glibc can break it in a future version anyway. They give 0 guarantees and have a track record of breaking things.

Sorry but I feel like you're trying to excuse Glibc out of their terrible design. Glibc didn't ask anybody for standardization. Glibc didn't document their behavior. Musl doesn't need to follow any undocumented behavior. Musl has its own implementation of thread_local variable and it works only for Musl dynamic binaries (which you cannot load with Glibc's ld-linux.so either). You need to tell your compiler to generate code that Musl prefers not Glibc. So effectively we have two ABIs.

There is no standard and any design that tightly couples the system binary loader to the C standard library is just extremely terrible design. Both Musl and Glibc do it. Both of them are terrible. Glibc was first and it set the horrible, binary hostile behavior "have no standards, trust Glibc, and recompile your programs again" as the "standard".

The entire Linux userspace depends on Glibc's terrible design. Due to Hyrum's Law, the exact needs of the complex and emergent behavior can only be surfaced via making a better designed, completely independent system loader and a completely independent libc and then fixing the entire tens of thousands of userspace libraries in the upcoming decades. It is just Sisyphean work to fix Linux userspace.

There is no simple "let libc-X obey the standard S" solution. There is no standard. Linux Standard Base project tried to set a standard. It failed.

I'll won't further discuss this with you. Maybe you have good intentions, maybe you're playing dumb. I'm not sure anymore. If you're the former, I'm not going to deliver every single bit of information. I provided enough resources and you can learn.

okanat··on Solo – a .so loader for static Linux binaries
Why? What kind of single-responsibility-principle that predicates the C standard library to become the both syscall interface and the binary loader as well?

What happened to the Unix principle "do one thing and do it well"? Windows solved this quite modularly and it works perfectly well.

Glibc is terribly designed and it is the core component of almost any Linux userspace app today. Let's not try to find excuses for horrible designs.

okanat··on Solo – a .so loader for static Linux binaries
It's not insane. Many people who were in the GNU organisation wanted the OS to be as hostile against binaries as possible to prevent people distributing proprietary software with GNU. That GNU became the userspace layer.

It isn't that this is 2026 and it was a bug that hasn't been fixed since. The userspace of GNU is designed against what you consider as basic functionality.

okanat··on Fixing a bricked Framework laptop
The UEFI spec is open. The way to load Intel ME payload isn't. You need to do it otherwise the Intel CPU is as good as a brick. It will shut down automatically in 30 mins, none of the TPM functions will work, no power management will work.

It is not just payment. Without being "big enough" and guaranteeing some big volumes of CPU sales, Intel won't give you the specs. AFAIK only ODMs and BIOS makers like AMI has the full low-level CPU bootstrap spec.

This is just the CPU. Now add the other peripherals like HDMI controllers. You'd see the problem now.

okanat··on Solo – a .so loader for static Linux binaries
It kind of does but in a "it is an implementation detail that you cannot access and it doesn't matter" sense. Unlike ELF, PE32+ files do not have an "interpreter" that you can specify.

csrss.exe handles some of the loading functionality: https://en.wikipedia.org/wiki/Client/Server_Runtime_Subsyste...

okanat··on Solo – a .so loader for static Linux binaries
You can completely skip all CRTs on Windows and still have a program that can call dynamic loader and other Win32 APIs. Here is a tutorial: https://nullprogram.com/blog/2023/02/15/

When you link with UCRT your specific program just gets a "view" of standard C functions. You can load DLLs that were linked with MSVCRT from a UCRT program. It just works

okanat··on Solo – a .so loader for static Linux binaries
> Can't be done. The libc is legacy, it can't be changed without breaking everything... Every other OS forces a C runtime.

Windows never had this problem. If you really want it, you can actually skip CRT completely on Windows. Only thing you need is the initialization code that's statically linked anyway: https://nullprogram.com/blog/2023/02/15/ . You can still make Win32 calls with it. CRT is there as a convenience.

And since Linux distros are compiling everything from source anyway, this makes Linux a prime candidate for complete libc and complete ABI replacement. Thanks to stable kernel ABI, we can also use the same kernel even with Docker etc! Musl did it. Why can a completely modularized libc not?

Will it break a lot of programs in the userspace? YES! Hyrum's Law exists.

Will it be rejected by a significant part of user base? YES! They rejected systemd as well.

Will it take one or more decades to have something working? HELL YES! This is Linux we're talking about. Everybody has seen how Wayland played out. However, maybe if Valve has enough motivation to fix Linux binary problem, we maybe can get finally a binary-compatible distro in a decade or half a decade.

okanat··on Solo – a .so loader for static Linux binaries
> Wasn't Linux Standard Base supposed to fix this? I cannot imagine any reason why glibc would break at a rate that you can't keep the current version binary compatible for years.

Guess what happened with LSB? Some distros like Debian never adopted it. It also broke backwards compatibility at random times. It is now abandoned.

> Or do the MS thing, and ship multiple versions like msvcrt

MS can do that since the CRT is decoupled from the system DLL loader and Windows ABI is designed to isolated loaded DLLs into their own symbol namespaces. So your program can load DLLs that depend on a different CRT version.

Glibc's design tightly couples the system loader with the specific libc. Moreover symbols in ELF files are loaded into a single global namespace. You cannot ship shared libraries that are compiled with a different version of Glibc or Musl libc.

okanat··on Solo – a .so loader for static Linux binaries
Here read it from the lion's mouth: https://wiki.musl-libc.org/design-concepts

> Then, what is the exact reason a library compiled against glibc must be loaded by a specific ld-linux? I could see that this is true for C++ perhaps, or when you use very special features, but I do not see this for C.

You still have functionality like `dlopen` with C or `pthreads` with C. ld-linux.so is the thing that prepares the stack frame, or the segment pointers (FS_BASE on x86_64).

When you have your main loaded __libc_start_main_impl is called from glibc and if you disassemble it you'll see this line:

call 0x7ffff7c28790 <_dl_audit_preinit@plt>

Guess where _dl_audit_preinit lives?

(gdb) info symbol _dl_audit_preinit _dl_audit_preinit in section .text of /lib64/ld-linux-x86-64.so.2

Moreover glibc has "magic" sections like .init_first. Only ld-linux.so that is compiled from glibc source knows how to handle that. https://elixir.bootlin.com/glibc/glibc-2.44.9000/source/csu/...

> I often compiled programs against one version of glibc and run it against a different version, so I know there is not a tight coupling. So please be specific in explaining in what scenarios this would break.

It didn't break, since glibc hasn't broken backwards compatibility of ld-linux.so and glibc combination lately. Last time they broke it was in 2024 for a really specific subset: https://sourceware.org/pipermail/libc-alpha/2024-December/16...

A breakage hasn't been observed doesn't mean that there is no tight-coupling between ld-linux.so and glibc that is compiled from glibc source.

If you want a really specific scenario:

- Write a very simple C file that contains a global (volatile if you want to stop the compiler optimizations) thread_local variable with C23 syntax

- Compile a simple .so file on a GNU distro targetting glibc ABI with GCC (pass -std=c23)

- start up a Musl distro (e.g. Alpine Docker image), copy that .so file in

- Write a C program that dlopens the GNU .so file

- Try accessing the thread_local variable you defined

- Watch the world burn

okanat··on Solo – a .so loader for static Linux binaries
There is no libc independent ABI. ABI doesn't purely mean just calling conventions.

When you compile libc, you also get a binary loader ld-linux.so with it. They are not two independent components of a system.

Basically all .so files compiled with glibc require the ld-linux.so that's also generated by that glibc (or a later version, if they didn't break the binary compatibility).

There are a lot of stuff that's executed by ld-linux.so and glibc that are not explicitly documented but they are absolutely necessary for your program to start and correctly initialize things like global variables or signal handling or loading other dynamic libraries. Some of that functionality sits in ld-linux.so and some of that in glibc. They have circular dependencies to each other. glibc expects ld-linux.so to put things in certain order but ld-linux.so also must load glibc first to have access to certain APIs. They are not part of System V ABI. They are not documented.

Musl maybe can implement this but it is simply reverse engineering what glibc did and then playing a game of cat and mouse. There is no independent ABI standard.

okanat··on Solo – a .so loader for static Linux binaries
You'd expect that but, no. That's why you cannot load glibc-linked binaries in a Musl distro. Edit: that's why the hacks like the original post is needed, as well.

The ABI is strongly dependent on explicit libc implementation in current Linux systems. There is no libc independent ABI on Linux.

okanat··on Solo – a .so loader for static Linux binaries
It is not just compatibility. You cannot load them into the memory with your system dynamic loader. You need to also ship ld-linux.so with the new version of glibc you have, if you were to distribute your program independently.

On Windows you don't need to ship a new binary loader. I can just ship Windows 10 UCRT DLL (which is the new libc of Windows) to Vista and my binaries will work. The binary loader isn't interlinked with the libc.

okanat··on Solo – a .so loader for static Linux binaries
> The C compiler doesn't really care as much.

Until you define a thread local variable (C11) or use atomics (also C11) or define a global with an initial value. Then it happily generates code that depends on "whatever my target glibc + ld-linux.so needs".

okanat··on Solo – a .so loader for static Linux binaries
See https://news.ycombinator.com/item?id=49355262 .

Yes glibc has some backwards compat but you cannot load a binary compiled with a newer version of glibc using an older ld-linux.so. That's because the interdependency. Nor you can load binaries that depend on different libc.so files with glibc systems

I cannot comment on macOS, I have never used it. However this is not a problem with Windows. You can ship a newer CRT or you can install it as a system component using Microsoft's MSI. The dependency is one way on Windows. CRT purely depends on Win32. Moreover the loader is completely independent and DLLs are loaded into their own unique scoped namespace unlike Linux that loads them in global symbol namespace. That's why you can mix and match DLLs compiled for different CRT versions.

okanat··on Solo – a .so loader for static Linux binaries
BSD also did it. They did it better. Maybe more modern but AOSP also did it but at a different level of binary: instead of ELF, using compiled Java bytecode archives.
okanat··on Solo – a .so loader for static Linux binaries
See: https://news.ycombinator.com/item?id=49355262

How libstdc++ initializes global variables absolutely depends on glibc and ld-linux.so. That is part of C++ ABI.

okanat··on Solo – a .so loader for static Linux binaries
When you compile GCC you need to provide a full glibc installation as your target. It is also a dependency of libstdc++.

C++ global/static variable initialization depends on the specific version of glibc (they don't usually break compat, but they can and they did in the past) which also provides ld-linux.so that loads those global variable placeholders in the correct manner such that glibc and libstdc++ can initialize them correctly.

This is just one example. Thread local variables and behavior of things like pthreads with signal, fork etc all depend on glibc.

okanat··on Solo – a .so loader for static Linux binaries
Because glibc and GNU set a terrible precedent. On GNU/Linux systems the shared binary interpreter / loader, GCC compiler, the C library and the system C/C++ ABI all depend into each other. You cannot change any of them independently. All shared libraries depend on the specific glibc version to load them into memory to be able to use that specific glibc version as their C library and make calls like dlopen.

Shared libraries have always been broken in Linux. Unfortunately many things like GPU drivers, graphics libraries and NSS need shared libraries to dynamically load certain runtimes (because you don't want to load all possible GPU drivers in existence to your RAM). So an ecosystem has been developed on top of terrible ABI and architecture GNU/glibc provided.

okanat··on Fixing a bricked Framework laptop
The bootloader part of UEFI FW is quite straightforward. It requires updates due to vulnerabilities found in it and also to update certificates.

However modern FW of PC clones don't only contain a bootloader and a "simple" hardware initializer. Modern laptops have tens of sensors, power measuring parts, power controllers, completely remote management (Intel ME / AMD PSP), embedded controller code for fingerprint, embedded controller code for keyboard etc.

Companies ship a new product line every single year. This churn causes nothing but shitty FW to be developed. Moreover the component manufacturers also slightly change things every single year. That's why sleep sucks with PCs. That's why Fn shortcuts don't always work correctly. That's why batteries drain.

Everything is fixed in the 6 months to a year following the launch in PC industry. Then they start to work on the new model and only supply security updates.

okanat··on Fixing a bricked Framework laptop
Probably they depend on some "obscure" contactor which is one of the ODMs here: https://en.wikipedia.org/wiki/List_of_laptop_brands_and_manu... .

Intel / AMD and BIOS vendors simply do not expose their designs to everyone. So you have to go through an ODM to have an Intel chip-based motherboard design. The silicon industry is completely rotten at this point. Framework could simply be too small to get access to secret sauce.

okanat··on Beware Management Consultants
Human beings are quite rational. But they are not rational in the classical economics sense. Human beings recognize social aspects. They also have their own social status they want to improve. They also know that they can exploit their social status and gain advantages, favors, mates and power over other human beings. They know that openly backstabbing one of your key players may discourage other ones from obeying your power, so they let others do the stabbing take the blame.
okanat··on Protobuf has LSP support
It is generally correct. When both implementations are completely in the same language Protobuf will win. Instead of a pure-JS implementation one can also make a FFI module for Protobuf.

The comparison that's being made is equivalent to implementing quick sort in Python and bubble sort in C++ and then declaring bubble sort is the better alternative.

Anyone with a healthy understading of computer science and programming experience will not make bullshit claims like that.

okanat··on Protobuf has LSP support
Protobuf simply encode things way more efficient that JSON can define a single object. You're quite frankly spewing bullshit in this whole thread.
okanat··on I hate packaging my software for Linux
It is not ironic. Windows is designed from ground up to make independent software deployment by proprietary software vendors as easy as possible. Easy deployment is Windows' raison d'être. It is the antithesis of Unix which is hostile to that. That's what was behind "Developers! Developers! Developers!".
okanat··on I hate packaging my software for Linux
It's a solved problem until you want to display the local user name, make queries through OS name resolution service not Go's custom from scratch DNS implementation. Try accessing a system on mDNS that's not on a global DNS server and your nice statically linked Go app doesn't work anymore.

It is hopeless. There is a reason why systemd-resolved exists and there is a good reason why people say that only way to sanely interact with a Go program is through a network socket.

okanat··on I hate packaging my software for Linux
You're trying to force Linux-style packaging where declaratively specified dependencies from a single(-ish) repository and shared DLLs are a necessity due to intentionally hostile architecture of GNU/Linux for shipping binary-only software. You have to build everything as one single OS, because that's how Unix people did in 80s. Unix people weren't designing an OS for general binary software distribution.

You need to give up Linux-style thinking first. Windows-native tools like Visual Studio, WiX, MSI etc. make it nice and easy to vendor your own DLLs. They are designed for closed-source and binary-distribution first. And if the libraries are designed for this ecosystem, you just import them in VS.

If you don't want to give up Linux-style dependency management you can use source-based build systems. You can use `conan` as a source package manager to get something closer and then export every single binary dependency `conan install . --deploy=runtime_deploy --output-folder=dist`.

← PreviousPage 2 of 28Next →