Brian Lovin
/
Hacker News
Daily Digest email

Get the top HN stories in your inbox every day.

dijit

I cant speak much about the system, it just works, but the community was really nice when I interacted with them over IRC

I had the plan to build oasis with bazel for some immutable OS images that could run as kubernetes nodes. I succeeded with a little pointing.

malux85

Thats a cool idea! Will you open source it or make it available somehow? I would like to play with it for running Atomic T

eek2121

"it just works" so you are doing the tech support when it doesn't, right?

EDIT: that was meant to be a joke, I forgo HN doesn't support emojies.

xenophonf

As an aside, emoticons work just fine. ;)

gravypod

Have you shared your BUILD files upstream?

dijit

No, they were quite happy with Samurai

colatkinson

If you don't mind I'm super curious as to what approach you ended up taking. Did you use rules_foreign_cc to build the ninja files they generate? Or generating BUILD files directly? Or something completely different? Sounds like a really cool project!

dieortin

Same, I’m curious too!

public_void

Why did you need to use bazel?

dijit

I didnt need to use bazel, I like bazel and want to learn more about it.

I also have a small, but burning, passion for reproducible builds, distributed compilation and distributed caching.

Being able to build an entire OS and essentially anything I want on top in a reproducible and relatively organic way (with incremental compilation) is pretty dope.

i-use-nixos-btw

You sound like the perfect Nix cult memb… erm, user. It’s everything you describe and more (plus the language is incredibly powerful compared with starlark).

But you speak from sufficient experience that I presume Nix is a “been there, done that” thing for you. What gives?

yx827ha

You should check out the ChromeOS Bazelification project[1]. It has those exact same goals. Not all packages are reproducible though because they embed timestamps.

[1]: https://chromium.googlesource.com/chromiumos/bazel/+/HEAD/do...

MuffinFlavored

> I cant speak much about the system, it just works,

What systems don't just work by this criteria?

Just because something is statically linked vs dynamically linked, as long as you are within "normal expected operating conditions", does it really make a "just works vs doesn't work" quality difference?

Koshkin

Read after the comma:

> it just works, but...

Qwertious

...but the community was really nice.

That still doesn't tell us how low the parent commenter's standards for "just works" are. It's irrelevant.

kentonv

Doesn't linking everything statically imply that the base image -- and memory, at runtime -- will be bloated by many copies of libc and other common libraries? I do like the simplicity of static linking but it sort of seems to go against the idea of avoiding "bloat".

jezze

A linker typically only includes the parts of the library it needs for each binary so some parts will definately have many copies of the same code when you statically link but it will not make complete copies.

But I wouldnt consider this bloat. To me it is just a better seperation of concerns. To me bloat would be to have a system that has to keep track of all library dependencies instead, both from a packaging perspective but also in runtime. I think it depends where you are coming from. To me static linking is just cleaner. I dont care much for the extra memory it might use.

jvanderbot

Dynamic linking served us when OS upgrades came infrequently, user software was almost never upgraded short of mailing out new disks, and vendors had long lead times to incorporate security fixes.

In the days of fast networks, embedded OSs, emphemeral containers, and big hard drives, a portable static binary is way less complex and only somewhat less secure (unless you're regularly rebuilding your containers/execs in which case it's break even security wise or possibly more secure, simply because each exec may not include vulnerable code)

bscphil

> In the days of fast networks, embedded OSs, emphemeral containers, and big hard drives, a portable static binary is way less complex and only somewhat less secure

If what you're trying to do is run a single program on a server somewhere, then yes absolutely a static binary is the way to go. There are lots of cases, especially end user desktops, where this doesn't really apply though.

In my opinion the debate over static vs dynamic linking is resolved by understanding that they are different tools for different jobs.

gnramires

As far as I can see, it would be unwise to roll back 30 years of (Linux) systems building with dynamic linking in favor of static linking. It mostly works very well and does save some memory, disk, and has nice security properties. Both have significant pros and cons.

I've been thinking (not a Linux expert by any means) the ideal solution would be to have better dependency management: I think a solution could be if say binaries themselves carried dependency information. That way you get the benefits of dynamic and static linking by just distributing binaries with embedded library requirements. Also, I think there should be a change of culture in library development to clearly mark compatibility breaks (I think something like semantic versioning works like that?).

That way, your software could support any newer version up to a compatibility break -- which should be extremely rare. And if you must break compatibility there should be an effort to keep old versions available, secure and bug free (or at least the old versions should be flagged as insecure in some widely accessible database).

Moreover, executing old/historical software should become significantly easier if library information was kept in the executable itself (you'd just have to find the old libraries, which could be kept available in repositories).

I think something like that could finally enable portable Linux software? (Flatpak and AppImage notwithstanding)

nequo

> Dynamic linking served us when OS upgrades came infrequently, user software was almost never upgraded

Even today, dynamic linking is not only a security feature but also serves convenience. A security fix in OpenSSL or libwebp can be applied to everything that uses them by just updating those libraries instead of having to rebuild userland, with Firefox, Emacs, and so on.

teaearlgraycold

Yeah I’d prefer we just use another gigabyte of storage than add so much complexity. Even with what is a modest SSD capacity today I have a hard time imagining how I’d fill my storage. I’m reminded of my old workstation from 8 years ago. It had a 500GB hard drive and a 32GB SSD for caching. I immediately reconfigured to just use the SSD for everything by default. It ended up being plenty.

manmal

Apple has been pushing dynamic libraries for a while, but now realized that they really like static linking better. The result is they found a way to convert dynamic libraries into static ones for release builds, while keeping them dynamic for debug builds: https://developer.apple.com/documentation/xcode/configuring-...

chaxor

I'm not versed in this, so apologies for the stupid question, but wouldn't statically linking be more secure, if anything? Or at least have potentially better security?

I always thought the better security practice is statically linked Go binary in a docker container for namespace isolation.

jhallenworld

>A linker typically only includes the parts of the library it needs for each binary so some parts will definately have many copies of the same code when you statically link but it will not make complete copies.

Just to add to what you said: in the old days the linker would include only the .o files in the .a library that were referenced. Really common libraries like libc should be made to have only a single function per .o for this reason.

But modern compilers have link time optimization, which changes everything. The compiler will automatically leave out any items not referenced without regard to .o file boundaries. But more importantly, it can perform more optimizations. Perhaps for a given program a libc function is always called with a constant for a certain argument. The compiler could use this fact to simplify the function.

I'm thinking that you might be giving up quite a lot of performance by using shared libraries, unless you are willing to run the compiler during actual loading.

Even without lto, you can have the same results in C++ by having your library in the form of a template- so the library is fully in the /usr/include header file, with nothing in /usr/lib.

inkyoto

> Just to add to what you said: in the old days the linker would include only the .o files in the .a library that were referenced.

It was not exactly like that. Yes, the .o file granularity was there but the unused code from that .o file would also get linked in.

The original UNIX linker had a very simple and unsophisticated design (compared to its contemporaries) and would not attempt to optimise the final product being linked. Consider a scenario where the binary being linked references A from an «abcde.o» file, and the «abcde.o» file has A, B, C, D and E defined in it, so the original «ld» would link the entire «abcde.o» into the final product. Advanced optimisations came along much later on.

inkyoto

> A linker typically only includes the parts of the library it needs for each binary […]

It is exactly the same with the dynamic linking due to the demand paging available in all modern UNIX systems: the dynamic library is not loaded into memory in its entirety, it is mapped into the process's virtual address space.

Initially, there is no code from the dynamic library loaded into memory until the process attempts to access the first instruction from the required code at which point a memory fault occurs, and the virtual memory management system loads the required page(s) into the process's memory. A dynamic library can be 10Gb in size and appear as a 10Gb in the process's memory map but only 1 page can be physically present in memory. Moreover, under the heavy memory pressure the kernel can invalidate the memory page(s) (using LRU or a more advanced memory page tracking technique) and the process (especially true for background or idlying processes) will reference zero pages with the code from the dynamic library.

Fundamentally, dynamic linking is the deferred static linking where the linking functions are delegated to the dynamic library loader. Dynamic libraries incur a [relatively] small overhead of slower (compared to statically linked binaries) process startup times due to the dynamic linker having to load the symbol table, the global offset table from the dynamic library and performing the symbol fixup according to the process's own virtual memory layout. It is a one-off step, though. For large, very large and frequently used dynamic libraries, caching can be employed to reduce such overhead.

Dynamic library mapping into the virtual address space != loading the dynamic library into memory, they are two disjoint things. It almost never happens when the entire dynamic library is loaded into memory as the 100% code coverage is exceedingly rare.

akira2501

> It is a one-off step, though.

Yes, but often a one off step that sets all your calls to call through a pointer, so each call site in a dynamic executable is slower due to an extra indirection.

> For large, very large and frequently used dynamic libraries, caching can be employed to reduce such overhead.

The cache is not unlimited nor laid out obviously in userspace, and if you have a bunch of calls into a library that end up spread all over the mapped virtual memory space, sparse or not, you may evict cache lines more than you otherwise would if the functions were statically linked and sequential in memory.

> as the 100% code coverage is exceedingly rare.

So you suffer more page faults than you otherwise have to in order to load one function in a page and ignore the rest.

rwmj

You should be keeping track of those library dependencies anyway if you want to know what you have to recompile when, say, zlib or openssl has a security problem.

ithkuil

Well, you have to do that anyways

giljabeab

Can’t file systems de dupe this now

1vuio0pswjnm7

I have seen this sort of statement on HN before. I am guessing that the persons who propagate this idea have never actually experimented with replacing dynamically-linked programs having numerous dependencies with statically-compiled ones. It's a theory that makes sense in the abstract, but they have not actually tested it.

Though it is not a goal of mine to save storage space by using static binaries, and I actually expect to lose space as a tradeoff, I have actually saved storage space in some cases by using static binaries. This comes from being able to remove libraries from /usr/lib. TBH, I am not exactly sure why this is the case. Perhaps in part because one might be storing large libraries containing significant numbers of functions that one's programs never use.

For me using static binaries works well. Even "common" libraries can be removed in some cases by using a multi-call/crunched binary like busybox. This might not work for everyone. I think much depends on what selection of programs the computer owner prefers. (Namely, the dependencies required by those programs.)

Shorel

In a world where Docker and Kubernetes exist, where whole copies of operating systems are added to each running service...

This seems a weird thing to complain about =)

palata

> This seems a weird thing to complain about =)

On the contrary, I find it relevant: I think that the modern way is wasting way, way too much.

Shorel

On that respect, we agree.

lnxg33k1

Yeah but there I can still update vulnerable libraries independently, to be a statically linked system just means that if there is a bug in libpng then I have to recompile everything?

colonwqbang

Not recompile I guess, but you need to relink everything.

Oasis seems to have a good way of doing that, with the whole system being built in a single tree by an efficient build tool (my recollection from last time it was posted).

A dynamic executable needs to relink every time it's run, which also takes time.

nordsieck

> if there is a bug in libpng then I have to recompile everything?

You say that as if it's such a burden. But it's really not.

I'm somewhat sympathetic to the space argument, but a package manager/docker registry means that updating software is very easy. And it happens all the time for other reasons today anyhow.

Shorel

I was under the impression only Gentoo users recompile everything.

In a statically linked system, your dependency manager will update more packages.

And if your program is written in C/C++/Go/Rust, then yes, it will be recompiled.

bzzzt

Yes, although it very much depends on how big 'everything' is if that's a problem.

greyw

In most cases relinking is enough.

kentonv

I mean, if you ran every single executable on your desktop in a separate container I think you'd see problems. There are a pretty large number of programs running on most desktops, plus all the programs that get called by shell scripts, etc.

Running a handful of containers representing major applications is more reasonable and the memory wastage may be worth it to avoid dependency conflicts.

drakenot

You've just described Qubes OS!

Gabrys1

Each electron app is like that

Gazoche

I'll take bloat over dependency hell every day of the week. Feels like every single app is a bundled web browser these days anyways.

nerpderp82

Dynamic Library hell is why Docker exists. If operating systems had less global state and less ambient authority, our systems would be vastly more tractable. Instead we still create environments that look like replicas of whole hosts.

Might as well go all in and use something with pervasive virtualization like Qubes.

https://www.qubes-os.org/

palata

To be fair, QubesOS does not really solve the problem of bad libraries creating dependency hell. If you need to ship every app with its own rootfs because you can't handle dependencies, then you will have to do that on QubesOS as well (you don't want one VM per app).

Also the biggest problem I had with QubesOS is that it doesn't support GPU (for security reasons). It feels like that was a big cause for the reduced performance. I wish there was a solution for the GPU, and then I would love to daily-drive QubesOS.

IshKebab

Exactly this. Windows apps aren't distributed as Docker images. Guess why...

undefined

[deleted]

palata

> dependency hell

Dependency hell comes from bad dependencies that don't do semver properly. Choose your deps carefully, and that's perfectly fine.

> Feels like every single app is a bundled web browser these days anyways.

Yep, that's apparently the best way to use the bad libraries people want to use and not give a damn about semver.

avgcorrection

It seems impossible to solve this by just everyone adopting a manifesto that one GitHub guy wrote many years ago and which has been adopted in some communities but not in many others. And besides there is plenty of (1) human judgement about what is breaking and not (which goes against machine-readability), and (2) worrying about the minutiae of what is a “patch” and a “feature”, and (3) weird implicit social taboos about doing major releases “too often” (?).[1][2]

Most things might be solved by everyone doing SemVer. And for all I know some communities might be running like greased pigs in a chute exactly because they use SemVer (I don’t tend to hear about the everyday everything-is-working stories on HN). But also doing static linking a bit more seems like it would help a lot with the same problem.

[1] All based on discussions I’ve seen. Not really personal experience.

[2] Again, making a spec/manifesto which is both about machine-readability and about shaming people for vague things is very muddled. Although I don’t know how much the latter is about the culture around it rather than the spec itself.

IshKebab

There are various kinds of "dependency hell". To be honest I can't think of any that are due to not doing semver properly. Usually it's:

1. Software depending on versions of libraries that are newer than the latest version available on the distro you have to use (cough RHEL 8). E.g. this very day I ran into a bug where some Asciidoctor plugin craps out with an error because my version of Ruby isn't new enough. Ruby's advice for how to install Ruby is "use your package manager; you will get an old version btw fuck you".

90% of the time it's bloody glibc. Every Linux user has run into the dreaded glibc version error dozens of times in their career.

2. Software that can't install multiple versions of the same package, leading to diamond dependency issues. Python is very bad for this.

hn_go_brrrrr

Semver is nearly impossible to do "properly" because of https://xkcd.com/1172. With a sufficient number of users, all bug fixes are breaking changes. If the behavior can possibly be observed in any way, some user will be depending on it, deliberately or otherwise.

arghwhat

Static linked binaries are a generally lot smaller than a dynamically linked library and its dependencies, especially with link-time optimizations and inlining.

You wouldn't want have 100 tools statically link the entirety of chromium, but for normal C library sizes you don't get bloat. The preference for dynamic libraries in Linux distros is just so they can roll out patch updates in one place instead of rebuilding dependents.

marwis

But dynamically linked library only needs to be loaded to RAM once whereas with static linking you'd be loading the same code many times (unless you compile everything to single binary like BusyBox). This also gets you better cache utilization.

Also I think inlining would typically increase the total size of output rather than decrease it.

arghwhat

Static linking gives you better instruction cache utilization as you are executing local code linearly rather than going through indirection with more boilerplate. This indirection costs a few cycles too.

Inlining external code reduces the size not only by saving the call, PLT and and stack dance, but also through specialization (removal of unused conditional, pruning of no longer referenced symbols) as the code is locally optimized. This further reduction in size further improves cache behavior and performance.

Duplication can be an issue (not necessarily for performance, but for total binary size), but compilers have heuristics for that. Even just having the symbol local saves some space and call overhead though (no PLT).

The case for the shared library having better caching implies multiple processes that are distinct executables (otherwise they share program memory regardless of linkage) trying to hammer it at once, sharing the continued caching, but such scenario is hurt by the call overhead and lower optimization opportunities, negating the result.

jhallenworld

So you only need to load duplicated code for each different statically linked program. If there are many processes running the same program, they will all share the same physical pages for the code. So for example, having 100s of "bash" instances running does not use that much memory.

You can see this by running "pmap <pid> -XX" (the output is very wide- probably load it into an editor). Look at the shared vs. private pages.

Also: There is another way to automatically share pages between different programs: de-duplication. This would require common libraries to be statically linked on page boundaries. The OS would quickly de-duplicate during loading by hashing the pages. VMs use this technique to increase effective memory when there are many guest OS running.

zshrc

musl is significantly smaller and "less bloat" than glibc, so even with a statically linked program, it still remains small in both system memory and storage.

jacquesm

Not necessarily. Bloat is one reason why originally dynamic linking was rolled out but the bigger benefit (to manufacturers) was to be able to update libraries without updating the applications. This has been the source of much trouble (dependency hell) and statically linked binaries suffer none of these issues. It's not like every application uses all of every library and an efficient linker is able to see which parts of the library it needs to link and which parts it can safely leave out.

javierhonduco

Once it’s loaded in memory, if Kernel Samepage Merging is enabled it might not be as bad, but would love to hear of somebody has any thoughts https://docs.kernel.org/admin-guide/mm/ksm.html

LegionMammal978

From the link:

> KSM only merges anonymous (private) pages, never pagecache (file) pages.

So it wouldn't be able to help with static libraries loaded from different executables. (At any rate, they'd have to be at the same alignment within the page, which is unlikely without some special linker configuration.)

javierhonduco

Had completely missed that line — great point!

sylware

For a real statically-linked linux system, the main issue is GPU support: you must relink all apps _really using_ a GPU, that to include the required GPU drivers.

With sound, alsa, it is fine since there is IPC/shared-memory based mixing that whatever the playback/capture devices [dmix/dsnoop]. Static linking is reasonable. (pulseaudio[012] IPC interfaces are bloaty kludges, hardly stable in time, 0..1..2.., not to be trusted compared to the hardcore stability of alsa one able to do a beyond good enough job *and* _real_ in-process low latency hardware access at the same time).

x11 and wayland are IPC based, then no issue here neither.

But for the GPU, we would need a wayland vulkan3D-inspired set of IPC/shared-memory interfaces (with a 3D enabled wayland compositor). For compute, the interfaces would be de-coupled from the wayland compositor (shared dma-buffers).

The good part of this would be to free our system interfaces from the ultra complex ELF (one could choose an excrutiatingly simple executable file format, aka a modern executable file format, but will need compilers/linkers support to help legacy support).

There is a middle ground though: everything statically linked, except the apps requiring the GPU driver (for that ELF is grotesquely overkill), still provided as a shared library.

AshamedCaptain

I ponder which kind of malaise would push one to dismiss ELF as "ultra complex" and at the same time propose pervasive IPC through the entire system including Vulkan calls through IPC.

stefan_

To be fair ELF is complex mostly because of relocations, which are not purely to support shared libraries but also the nowadays ubiquitous PIE. But GPU drivers is a good point; I don't believe you can even statically link them today, you would only be statically linking a shim that tries to find the real driver at runtime.

sylware

I am exploring an executable file format of my own (excrutiatingly simple, basically userland syscalls) which is only PIE, and until now, the main real "issue" (not really) is actually the lack of support from compilers for static relative global data init (handled by ELF... which is not there anymore).

About the shared libs, well, they are the utility shared libs, and the system interface shared libs. With a mostly statically linked elf/linux distro, all the utility libs would be statically linked, and the system interface shared libs would be statically linked if they have an IPC/shared-mem interface. In the end, only the GPU driver is an issue, namely would stay a shared libs.

Rochus

Interesting, but what is the use case?

What is the advantage of using the croc C compiler instead of e.g. TCC?

I wasn't aware of Netsurf (https://www.netsurf-browser.org/); this is really amazing. But it seems to use Duktape as the JS engine, so performance might be an issue.

helloimhonk

cproc supports C11, tcc only goes up to c99. There is also something to be said for cproc using QBE which is slowly growing backends like risc-v etc which tcc doesnt support afaik.

Rochus

Ok, thanks, that makes sense. QBE looks interesting, but I'm missing 32 bit support. So currently I'm trying to reuse the TCC backend, which is far from trivial.

helloimhonk

There seems to have been a little progress on that recently, I saw someone working on a ppc 32bit port here: https://bsd.network/@tobhe/111756322928965195 and I also saw somewhere someone working on a 68000 port, but I don't remember where.

I'd like an arm 32bit port, which might be a bit easier with this ppc port as an example of 32bit qbe. It'd be nice to try run some hare programs on a gameboy advance :)

willy_k

Tangential, but the trailing “/“ in the URL you gave seems to include the “);” in the hyperlink, giving a “Not Found” error.

Working link: https://www.netsurf-browser.org

cpach

AFAICT it could be useful for embedded devices.

mike_hock

https://www.netsurf-browser.org/documentation/

Every single link on that page is dead.

https://www.netsurf-browser.org/about/screenshots/

Judging by the screenshots, it can render BBC, its own website, and Wikipedia. Well, it might be able to render others, we just can't tell from the shots. But we can tell those three websites work with all sorts of different window decorations.

Rochus

> Every single link on that page is dead

Unfortunately, as it seems. On the start page they say "Last updated 2 January 2007". But version 3.11 was released on 28 Dec 2023.

schemescape

Does anyone know how big the base installation is? I couldn't find an answer anywhere, and the link to the QEMU image appears to be broken, currently.

I'm curious how it compares to, say, Alpine with a similar set of packages.

jackothy

I have an old (2020) .qcow2 lying around that's about 360MB

ratrocket

There's a (dead) comment lamenting that you can't access Github with javascript turned off. The Oasis repo seems to be mirrored on sourcehut, though, so if that's more acceptable:

https://git.sr.ht/~mcf/oasis

__s

michaelforney was also who did the wayland port of st: https://github.com/michaelforney/st

oasis's predecessor would be https://dl.suckless.org/htmlout/sta.li

sigsev_251

Michaelforney has also built croc [1], a qbe based C compiler. Really impressive!

[1]: https://github.com/michaelforney/cproc

Koshkin

Not as "impressive" as TCC, I'd say. Why? TCC has its own backend, and it has the preprocessor built in. (But QBE is indeed impressive.)

trealira

The assembly generated by cproc is more efficient than that generated by TCC, which is not great.

rice7th

Yes but cproc supports c11

hkt

This is very very cool. I love the bloat free nature of the thing, especially velox (the WM). Samurai (build system) also looks pretty interesting. I've not managed to work out quite how samurai works, or truthfully, why it differs from ninja, but this project is exactly the kind of brain food I intend on learning a lot from.

Many, many props to Michael Forney.

eterps

Interesting choices, finally something that isn't just another Linux distribution.

sluongng

What is the comparison between using musl and traditional glibc?

Is there performance differences between the two?

I have been seeing musl used more and more in both Rust and Zig ecosystems lately.

digikata

One of the reasons I've switched some builds over to musl over glibc, is that I found that glibc linking is brittle if you're going to run a binary over multiple distros in various container environments. Particularly if you want one binary to work on linux across RH and Debian/Ubuntu derived distros or even different ages of distro.

skywal_l

raverbashing

As much as I think about Linux compared to the competition in desktop the more I realize this is right

"If it's a bug people rely on it's not a bug, it's a feature" Let me guess, he was thinking of the memcpy issue that broke flash. Or maybe something else. And I agree, nobody cares

The spec says that because it was the 70s and nobody had thought better of that or how things would work 30 yrs on, and going with it does not make sense.

And I feel the pain of this hardheadedness when any library deprecates an API when they didn't need. "Oh but it's cleaner now" Again, nobody cares

o11c

The real comparison is: musl does not provide any preprocessor macro to tell you what libc you're using.

And it has so many weird quirks that you need to work around.

***

Static linking makes linking more painful, especially regarding global constructors (which are often needed for correctness or performance). This is not a musl-specific issue, but a lot of people are interested in both.

Just do your builds on the oldest supported system, and dynamic linking works just fine. You can relative-rpath your non-libc dependencies if they would be a pain to install, though think twice about libstdc++.

***

The major advantage of MUSL is that if you're writing a new OS, it's much easier to port.

yjftsjthsd-h

> musl does not provide any preprocessor macro to tell you what libc you're using.

> And it has so many weird quirks that you need to work around.

I was under the impression that musl stuck closely to the standard, and glibc frequently did its own thing, so 1. it's not musl that's quirky, 2. if you need to detect something, just detect glibc.

o11c

The standard is uselessly incomplete and vague.

There are places where MUSL implements a broad set of GLIBC extensions in order to actually be useful. However, it does not indicate that in any way, and sometimes violates the conditions that GLIBC documents. This requires workarounds.

There are places where MUSL implements a standard interface in a particular way. If you're lucky, this "just" means giving up on performance if you don't know you're using MUSL.

Sometimes MUSL implements its own ABI-incompatible extensions. The time64 transition, for example, is a huge mess regardless, but musl provides no blessed way to figure out what's going on. The only reason it's not an even bigger disaster is that almost nobody uses musl.

znpy

> What is the comparison between using musl and traditional glibc?

you get weird bugs and failures that don't happen with glibc (like the incomplete dns resolving routines that would fail under some conditions) but you can brag about saving 30-40 mb of disk space.

this project seems to be compromising on quality overall, in the name of having smaller size.

Even BearSSL, by their own website is beta-quality: "Current version is 0.6. It is now considered beta-quality software" (from https://bearssl.org/).

ghotli

https://musl.libc.org/releases.html

I maintain a large codebase, widely deployed, cross compiled to many cpu architecures that's built atop musl. You're right that historically in the context of people blindly using alpine for their container base that sort of thing might be the case. The newest version of musl solves the thing you're describing and in general most of the complaints about malloc perf or otherwise have been addressed. Avoiding musl to me seems like an outdated trope, but there was a time wherein that take was valid indeed.

NewJazz

malloc performance is still sub-par IMO. It is not nearly as terrible as it was, but scudo, memalloc, and glibc's malloc are better.

electroly

> incomplete dns resolving routines

They eventually did fix this, as of musl 1.2.4.

o11c

While not an issue for musl-centric distros if they keep updated, note that e.g. Debian stable doesn't have that version yet, so good luck testing.

undefined

[deleted]

raesene9

A small point on that last bit. The bearssl authors are pretty conservative when it comes to development milestones, I'd guess that their 0.6 would be pretty solid :)

znpy

> I'd guess that their 0.6 would be pretty solid :)

Would you accept that kind of reasoning for software running on your pacemaker, or on your insuline pump?

I think we should respect the developers here: they're not claiming production quality level (they're claiming beta-quality level) so it's not correct to use that library in any kind of product and claim any kind of production-level quality.

fullspectrumdev

30-40mb of disk space is absolutely huge in some environments even today though

ComputerGuru

Speaking from heavy experimentation and experience, [0] glibc has some more optimized routines but musl has significantly less bloat. If you are haphazardly calling libc functions left and right for everything and have a generally unoptimized code base, your code may fare better better with glibc. But musl’s smaller codebase is a win for faster startup and micro optimizations otherwise - and that’s without lto where it stands to gain more.

[0]: https://neosmart.net/blog/a-high-performance-cross-platform-...

Edit:

Sorry, the correct link is this one: https://neosmart.net/blog/using-simd-acceleration-in-rust-to...

jart

If you want an optimized Musl, try Cosmopolitan in `make toolchain MODE=tinylinux`, since it's based on Musl, and its string routines go 2x faster.

ComputerGuru

I don’t think that was around back then but I can add it to the backlog of things to try for next round. Does that play nice with rust? Presumably I’d have to at least build the standard library from scratch (which I’d want to do against musl as a separate benchmark anyway since it’s now a single environment variable away).

(Not that the codebase makes much string function usage.)

scns

> in addition to its direct usage of AVX2 functions and types, it also made a call to the BZHI and LZCNT intrinsics/asm instructions – which rustc/llvm do not recognize as being supported via the avx2 feature! So although (to the best of this developer’s knowledge) there does not exist a processor on the face of this planet that supports AVX2 but doesn’t support BZHI and LZCNT

Looks like a "bug" or better put needed enhancement to LLVM.

skywal_l

glibc is LGPL. Static linking your application implies some obligation on your part. Musl being MIT is less restrictive.

actionfromafar

Not very tough obligations, but it can be a practical hassle. This answer describes it quite well I think:

https://opensource.stackexchange.com/questions/13588/how-sho...

Zambyte

[flagged]

bigstrat2003

No it doesn't. The MIT license is objectively less restrictive than the LGPL. Whether it's a good or bad thing to be less restrictive is a matter of opinion, but whether or not it is less restrictive is a matter of fact.

nightowl_games

Can someone explain a couple use cases for something like this?

ghotli

I routinely get embedded linux devices at $dayjob that need my time and attention and they basically never have the tooling I need to get my job done. I'm a pro at looking at how Alpine builds a tool and then just making my own statically linked / minimal size tool to drop in place on the device. The allure of something like this is that I can just potentially grab a drop-in binary and get on with my day. I simply don't attempt to link to libraries already on the device since they're all built in wildly different ways, old tools, old compilers.

Hopefully that's helpful context. Overall since I did linux from scratch half a lifetime ago I've always wondered why something like Oasis hasn't gotten more traction. It's got some ambitious ideas in the README so maybe others have other nice use-cases atop all that. I just see small, statically linked and think 'oh boy if i never have to build my own tools again for some weird board'. If so, I'm here for it.

8organicbits

> grab a drop-in binary

This is a cool approach on Docker as well.

    FROM some:thing AS bins
    FROM debian:latest
    COPY --from=bins /bin/foo /bin/

ghotli

Agreed, if the binary is statically linked. If you run `file` on the output from that and it shows 'dynamically linked' then you're playing games with porting over libraries, changing the library loading path, or just going full chroot like linux from scratch does with the bootstrapping part of the install. I find static binaries simplest to work with in that context but agreed I use that pattern too with docker and generally build ad-hoc tools within containers like that. If only these devices could run docker but I'm left to my own tooling to figure out per device.

nightowl_games

I still don't understand.

Is oasis the "drop in binary" you would use? Or do you use oasis to build the tool that you would use?

"The allure of something like this is I could potentially grab a drop in binary"

From where?

enriquto

> Can someone explain a couple use cases for something like this?

At this point, it would be more useful if someone explained a couple of use cases for dynamic linking.

pjmlp

Plugins, unless you want to have one process per plugin.

Which in the days of running Kubernetes clusters on laptops maybe isn't a big deal.

enriquto

You can still call dlopen from your static binary, if you really want to.

pjmlp

You miss UNIX developer experience until mid-1980's, before shared objects came to be.

mech422

Heh...rebuilding gcc on slackware to enable shared libs was an adventure - but that wasn't till the late 90s(??). I think I spent like a week bootstrapping the new gcc, rebuilding glibc and rebuilding all the stuff I used.

pjmlp

UNIX System V 4.0 was the one that kind of uniformized existing parallel solutions from UNIX variants, alongside ELF in the late 1980's.

ekianjo

immutable images

Daily Digest email

Get the top HN stories in your inbox every day.

Oasis – a small, statically-linked Linux system - Hacker News