[HN Gopher] Oasis - a small, statically-linked Linux system
       ___________________________________________________________________
        
       Oasis - a small, statically-linked Linux system
        
       Author : smartmic
       Score  : 496 points
       Date   : 2024-01-26 14:11 UTC (1 days ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | __s wrote:
       | 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 wrote:
         | Michaelforney has also built croc [1], a qbe based C compiler.
         | Really impressive!
         | 
         | [1]: https://github.com/michaelforney/cproc
        
           | Koshkin wrote:
           | 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.)
        
       | hkt wrote:
       | 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.
        
       | dijit wrote:
       | 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.
        
         | gravypod wrote:
         | Have you shared your BUILD files upstream?
        
           | dijit wrote:
           | No, they were quite happy with Samurai
        
         | malux85 wrote:
         | 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
        
         | public_void wrote:
         | Why did you need to use bazel?
        
           | dijit wrote:
           | 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 wrote:
             | 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?
        
               | chaxor wrote:
               | Nix has decentralized caching and memorizing?
        
               | i-use-nixos-btw wrote:
               | Decentralised caching, absolutely - unless I'm
               | misunderstanding what you mean there. You can build
               | across many machines, merge stores, host caches online
               | with cachix (or your own approach), etc. I make fairly
               | heavy use of that, otherwise my CI builds would be
               | brutal.
               | 
               | Memorizing isn't a term I'm familiar with in this
               | context.
        
               | chaxor wrote:
               | Sorry - _memoizing_.
               | 
               | I am interested in making a system that can memoize large
               | databases from ETL systems and then serve that on iroh or
               | ipfs/torrent, such that a process that may take a
               | supercomputer a week to process can have the same code
               | run on a laptop and it will notice it's been done my a
               | university supercomputer before already and grab that
               | result automatically from the decentralized network of
               | all people using the software (who downloaded the ETL
               | database).
               | 
               | That way you save compute and time.
        
               | i-use-nixos-btw wrote:
               | Oh I see!
               | 
               | Yes, absolutely doable in Nix.
               | 
               | Derivations are just a set of instructions combined with
               | a set of inputs, and a unique hash is made from that.
               | 
               | If you make a derivation whose result is the invocation
               | of another, and you try and grab the outcome from that
               | derivation, here's what will happen: - it will generate
               | the hash - it will look that hash up in your local
               | /nix/store - if not found it will look that hash up in
               | any remote caches you have configured - if not found it
               | will create it using the inputs and instructions
               | 
               | This is transitive so any missing inputs will also be
               | searched for and built if missing, etc.
               | 
               | So if the outcome from your process is something you want
               | to keep and make accessible to other machines, you can do
               | that.
               | 
               | If the machines differ in architecture, the "inputs"
               | might differ between machines (e.g. clang on Mac silicon
               | is not the same as clang on x86-64) and that would result
               | in a different final hash, thus one computation per
               | unique architecture.
               | 
               | This is ultimately the correct behaviour as guaranteeing
               | identical output on different architectures is somewhat
               | unrealistic.
        
               | chaxor wrote:
               | I see. Perhaps the added benefit I am trying to create
               | with this other system is that _specifying_ remote
               | locations isn 't necessary, and is just inherited as the
               | distributed network. Anytime anyone runs it, they're
               | added to the network, so it scales with the number of
               | users.
        
               | IshKebab wrote:
               | Nix isn't as fine-grained as Bazel as I understand it? I
               | don't think it's incremental within a package, which is
               | presumably what dijit achieved.
        
               | i-use-nixos-btw wrote:
               | Weirdly enough I came across a blog post last week that
               | talked about exactly this. https://j.phd/nix-needs-a-
               | native-build-system/
               | 
               | Nix can be used as a build system in the same way that
               | bazel can. It already has all of the tooling - a
               | fundamental representation of a hermetic DAG, caching,
               | access to any tool you need, and a vast selection of
               | libraries.
               | 
               | The only catch is that no one has used it to write a
               | build system for it in public yet. I've seen it done in a
               | couple of companies, though, as using Nix to only
               | partially manage builds can be awkward due to caching
               | loss (if your unit of source is the entire source tree, a
               | tiny change is an entirely new source).
        
               | gallexme wrote:
               | Nix can do it incremental U could split it into multiple
               | derivations which get built into one package For rust
               | there ist the excellent https://crane.dev/index.html
               | project
               | 
               | Or you can also go to the extreme and do 1:1 source to
               | derivation mapping So for example if ur project has 100
               | source files it could be built from 100 derivations, the
               | language/CLI tools are flexible enough for that
               | 
               | https://discourse.nixos.org/t/distributed-nix-build-
               | split-la... https://discourse.nixos.org/t/per-file-
               | derivations-with-c/19...
               | 
               | Don't know tho if there any well working smart nix tools
               | which can make it well working /efficient, in theory it's
               | very possible, just unsure about practicality/overheads
        
             | yx827ha wrote:
             | 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/+/H
             | EAD/do...
        
         | MuffinFlavored wrote:
         | > 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 wrote:
           | Read after the comma:
           | 
           | > _it just works, but..._
        
             | Qwertious wrote:
             | _...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.
        
         | colatkinson wrote:
         | 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!
        
         | eek2121 wrote:
         | "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 wrote:
           | As an aside, emoticons work just fine. ;)
        
       | eterps wrote:
       | Interesting choices, finally something that isn't just another
       | Linux distribution.
        
       | nightowl_games wrote:
       | Can someone explain a couple use cases for something like this?
        
         | ekianjo wrote:
         | immutable images
        
         | ghotli wrote:
         | 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 wrote:
           | > 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 wrote:
             | 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.
        
               | 8organicbits wrote:
               | Agreed, dynamically linked binaries don't drop in well.
        
               | lloeki wrote:
               | In a way, that's what Nix sets out to do, isolating even
               | dynamically linked libraries: if two derivations depend
               | on the same shared lib derivation then it's reused, if
               | not then they don't conflict. Each leaf derivation can be
               | handled completely independently of the others, and
               | independently of the original system+.
               | 
               | And then when Nix+ is not an option at runtime,
               | dockerTools++ can build a Docker image to do the
               | minimisation+isolation.
               | 
               | That said, Nix might also be completely overkill in some
               | scenarios where static linking would be just fine and
               | very practical. The practical simplicity of a single
               | binary should not be overlooked.
               | 
               | + nixpkgs is sufficient, a full nixos is not needed
               | 
               | ++ https://nixos.org/manual/nixpkgs/stable/#sec-pkgs-
               | dockerTool...
        
               | vacuity wrote:
               | So Nix keeps track of different versions of shared
               | libraries?
        
               | sporeray wrote:
               | Yeah, each package/lib is stored in a unified directory
               | by it's hash https://zero-to-nix.com/concepts/nix-store.
               | Different variation different hash.
        
               | YoshiRulz wrote:
               | You've missed nix-bundle and pkgsStatic, which are much
               | closer to the above idea re: copying to another machine.
        
           | nightowl_games wrote:
           | 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?
        
         | pjmlp wrote:
         | You miss UNIX developer experience until mid-1980's, before
         | shared objects came to be.
        
           | mech422 wrote:
           | 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 wrote:
             | 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.
        
               | mech422 wrote:
               | yeah - I never had access to a 'real' unix. Closest I
               | came was solaris and maybe Irix. Other then that, it's
               | just been Linux. Keep meaning to give *BSD a try...
               | 
               | P.S. - oh! and I had friends that loved HP/UX - another
               | one I never got to try
        
         | enriquto wrote:
         | > 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 wrote:
           | 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 wrote:
             | You can still call dlopen from your static binary, if you
             | really want to.
        
               | pjmlp wrote:
               | Sure lets go back to 1980's UNIX, it was such a great
               | experience.
        
               | mappu wrote:
               | I tried to do this recently at $DAYJOB, but when you
               | statically link a binary with musl, the dlopen() you get
               | is a no-op:
               | 
               | https://github.com/bpowers/musl/blob/master/src/ldso/dlop
               | en....
               | 
               | I tried to hack in a copy of the musl's dynamic loader
               | (and also from old uclibc). But it took a few hours and
               | my only result was segfaults.
               | 
               | Do you have any pointers on making this work?
        
               | enriquto wrote:
               | Have you tried it with glibc? It's harder to build static
               | binaries with it, but it's still possible, and it may
               | work.
               | 
               | To debug your problem, do you have a minimal example at
               | your fingertips to try? Just a "hello world" dynlib that
               | is called from a static program that doesn't do anything
               | else.
        
       | sluongng wrote:
       | 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.
        
         | znpy wrote:
         | > 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 wrote:
           | 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 wrote:
             | 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.
        
               | raverbashing wrote:
               | Yeah, and with glibc you can even LDLIBRARY an
               | alternative glibc, not so much with musl (unless it
               | changed recently)
        
           | raesene9 wrote:
           | 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 wrote:
             | > 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.
        
               | ComputerGuru wrote:
               | I would run away from using glibc on an insulin pump or
               | pacemaker, so I'm not sure what point you're trying to
               | make.
        
               | foul wrote:
               | > Would you accept that kind of reasoning for software
               | running on your pacemaker, or on your insuline pump?
               | 
               | God helps me I wouldn't implant anything so fundamental
               | in my body with hard dependencies on encrypted
               | communication to a remote agent elsewhere, no matter the
               | advantage.
        
           | electroly wrote:
           | > incomplete dns resolving routines
           | 
           | They eventually did fix this, as of musl 1.2.4.
        
             | o11c wrote:
             | 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.
        
               | electroly wrote:
               | At least we have light at the end of the tunnel now. This
               | is a tremendous improvement from the previous status quo
               | of the musl maintainers not even agreeing that it's a
               | problem.
        
               | znpy wrote:
               | This alone "musl maintainers not even agreeing it's a
               | problem" should be a good reason to avoid musl imho
        
               | electroly wrote:
               | What's a better option for static linking? glibc is
               | religiously against it; they have far worse dogmatic
               | beliefs than this musl DNS thing. I'd be happy to choose
               | a better alternative if one exists, but if one does not,
               | I have to live with the options at hand. From where I'm
               | standing, musl seems like the only game in town. uClibc
               | doesn't seem like it's appropriate for general purpose
               | Linux applications on desktop computers (maybe I'm
               | wrong?).
        
               | o11c wrote:
               | Static linking doesn't actually solve any problem. Just
               | use dynamic linking with (probably relative) rpath, and
               | compile against a sufficiently old libc.
               | 
               | There's some common FUD about rpath being insecure, but
               | that only applies if the binary is setuid (or otherwise
               | privileged) _and_ the rpath is writable by someone other
               | than the binary 's owner (all relative rpaths are
               | writable since you can use symlinks; absolute rpaths are
               | writable if they point to /tmp/ or a similar directory,
               | which used to be common on buildbots).
               | 
               | This is really not hard; working around all static
               | linking's quirks is harder.
        
               | schemescape wrote:
               | What are the quirks of static linking you need to work
               | around (in general, not for glibc)?
        
               | o11c wrote:
               | You have to know the internals of your dependencies so
               | you can link them explicitly, recursively. (admittedly,
               | pkg-config helps a ton, but not all libraries ship (good)
               | .pc files)
               | 
               | Global constructors no longer reliably fire unless you
               | are _extremely_ careful with your build system, nor do
               | they run in a predictable order (e.g. you can call a
               | library before it is actually initialized, unlike dynamic
               | linking where only preinit - which nobody uses - is
               | weird), nor can you defer them until dlopen time if you
               | want (which is, admittedly, overdone).
               | 
               | It's possible to link to _parts_ of multiple versions of
               | a library (remember, you have to recurse into your
               | dependencies), as opposed to dynamic libraries where at
               | least you 're guaranteed all-or-nothing (which is much
               | easier to detect).
               | 
               | Linking is slower since it always has to be redone from
               | scratch.
               | 
               | Not resilent against system changes. For example, old
               | versions of `bash-static` (grab them from e.g. Debian
               | snapshot and extract them manually; don't install them)
               | are no longer runnable on modern systems since certain
               | system files have changed formats, whereas the
               | dynamically-linked `bash` packages still run just fine.
               | 
               | It also encourages bad stability habits, leading to the
               | equivalent of NPM hell, which is far worse than DLL hell
               | ever was.
               | 
               | You can't use LD_PRELOAD or other dynamic interception
               | tools.
               | 
               | There are probably more reasons to avoid static linking,
               | but I'm trying to ignore the handful from the popular
               | lists.
        
               | schemescape wrote:
               | Thanks! Most of those seem like a fair trade-off for
               | portability... for an app.
               | 
               | I'm not sure it's a great idea for an OS as in the OP,
               | but I do like that they claim accurate incremental
               | rebuilds, to ensure everything get updated. Certainly an
               | interesting experiment!
               | 
               | Edit: just to clarify, I meant "app" as in "something
               | that isn't part of the OS/distribution".
        
               | o11c wrote:
               | The bash-static example alone is proof that the
               | "usefulness" for apps isn't actually there.
        
               | znpy wrote:
               | > glibc is religiously against it
               | 
               | from my understanding glibc is not "religiously" against
               | it, they're against it for technical reasons. In the
               | sense, this is not a dogma. It's about internal details
               | of their implementations.
               | 
               | See: https://stackoverflow.com/questions/57476533/why-is-
               | statical...
        
           | fullspectrumdev wrote:
           | 30-40mb of disk space is absolutely huge in some environments
           | even today though
        
         | digikata wrote:
         | 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 wrote:
           | Linus Torvald agrees with you:
           | https://youtu.be/Pzl1B7nB9Kc?feature=shared&t=261
        
             | raverbashing wrote:
             | 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_
        
         | skywal_l wrote:
         | glibc is LGPL. Static linking your application implies some
         | obligation on your part. Musl being MIT is less restrictive.
        
           | actionfromafar wrote:
           | 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...
        
         | ComputerGuru wrote:
         | 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 wrote:
           | 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 wrote:
             | 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.)
        
               | jart wrote:
               | It should if everything is static and you're only
               | targeting Linux.
        
           | scns wrote:
           | > 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.
        
         | o11c wrote:
         | 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 wrote:
           | > 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 wrote:
             | 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.
        
         | joveian wrote:
         | Functional differences described here:
         | 
         | https://wiki.musl-libc.org/functional-differences-from-glibc...
        
       | Koshkin wrote:
       | There's also the "suckless" sta.li
        
         | ratrocket wrote:
         | A comment up-thread (currently) says/implies Oasis is a
         | successor to sta.li by the same person.
         | 
         | https://news.ycombinator.com/item?id=39143029
         | 
         | I also thought sta.li when I saw this was about a statically
         | linked linux system...
        
           | lubutu wrote:
           | It's not by the same person -- sta.li was by Anselm R Garbe.
           | It's more like a spiritual successor.
        
             | ratrocket wrote:
             | Ah, thank you for the clarification. I read the linked to
             | (by me) comment too quickly and/or without thinking enough!
             | Cheers!
        
       | Rochus wrote:
       | 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.
        
         | cpach wrote:
         | AFAICT it could be useful for embedded devices.
        
         | helloimhonk wrote:
         | 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 wrote:
           | 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.
        
         | willy_k wrote:
         | 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
        
         | mike_hock wrote:
         | 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 wrote:
           | > _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.
        
       | kentonv wrote:
       | 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".
        
         | zshrc wrote:
         | 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.
        
           | skywal_l wrote:
           | And using LTO[0] can also help.
           | 
           | [0]https://gcc.gnu.org/wiki/LinkTimeOptimization
        
         | Shorel wrote:
         | 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 =)
        
           | kentonv wrote:
           | 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 wrote:
             | You've just described Qubes OS!
        
               | palata wrote:
               | Except that QubesOS uses VMs for their security benefits,
               | which are greater than those of containers.
               | 
               | Containers make a lot of sense to me on servers ("deploy
               | a controlled environment"), but often on Desktop I feel
               | like they are used as a solution to "I don't know how to
               | handle dependencies" or "My dependencies are so unstable
               | that it is impossible to install them system-wide", both
               | of which should be solved by making slightly better
               | software.
        
             | Gabrys1 wrote:
             | Each electron app is like that
        
           | lnxg33k1 wrote:
           | 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?
        
             | bzzzt wrote:
             | Yes, although it very much depends on how big 'everything'
             | is if that's a problem.
        
             | greyw wrote:
             | In most cases relinking is enough.
        
             | Shorel wrote:
             | 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.
        
               | lnxg33k1 wrote:
               | I use Gentoo, so I am not against rebuild everything, but
               | afaik unless you have static-libs USE flag for something,
               | it's dynamically linked so relinking on rebuilding the
               | dependency is enough, with static-libs the dependent
               | package is also rebuilt
        
             | colonwqbang wrote:
             | 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 wrote:
             | > 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.
        
           | palata wrote:
           | > 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 wrote:
             | On that respect, we agree.
        
         | liampulles wrote:
         | It would be bloated, but how big of a problem is that these
         | days? A TB of storage is pretty cheap.
        
           | cmovq wrote:
           | A TB of memory is not
        
         | thanatos519 wrote:
         | KSM could help with that: https://docs.kernel.org/admin-
         | guide/mm/ksm.html
         | 
         | ... oh wait, the apps have to hint that it's possible.
         | Nebbermind.
        
         | jezze wrote:
         | 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 wrote:
           | 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)
        
             | teaearlgraycold wrote:
             | 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.
        
             | gnramires wrote:
             | 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)
        
               | josephg wrote:
               | Yes, if someone actually did dependency management in
               | Linux properly then I agree - dynamic linking would be
               | fine. It works pretty well in Nixos as I understand it.
               | But it's called dependency hell for a reason. And the
               | reason is almost no operating systems handle C
               | dependencies well. There's always weird, complex,
               | distribution specific systems involving 18 different
               | versions of every library. Do you want llvm18 or
               | llvm18-dev or llvm-18-full-dev or something else
               | entirely? Oh, you're on gentoo? Better enable some USE
               | flags. Redhat? It's different again.
               | 
               | If Linux dependency management worked well, there would
               | be no need or appetite for docker. But it works badly. So
               | people just use docker and flatpak and whatnot instead,
               | while my hard drive gently weeps. I don't know about you,
               | but I'm happy to declare bankruptcy on this project. I'd
               | take a 2mb statically linked binary over a 300mb Linux
               | docker image any day of the week.
        
               | StillBored wrote:
               | This isn't really an "operating system" problem.
               | Particularly in the open-source world, there are a number
               | of fairly core libraries that refuse to provide any kind
               | of API compatibility.
               | 
               | Then, when there are a couple dozen applications/etc that
               | depend on that library, it's almost an impossible problem
               | because each of those applications then needs to be
               | updated in lockstep with the library version. There is
               | nothing "clean" about how to handle this situation short
               | of having loads of distro maintainers showing up in the
               | upstream packages to fix them to support newer versions
               | of the library. Of course, then all the distro's need to
               | agree on what those versions are going to be...
               | 
               | Hence containers, which don't fix the problem at all.
               | Instead they just move the responsibility away from the
               | distro, which should never really have been packaging
               | applications to begin with.
        
               | palata wrote:
               | > away from the distro, which should never really have
               | been packaging applications to begin with.
               | 
               | I disagree here: the whole point of a "software
               | distribution" is to "distribute" software. And it does so
               | by packaging it. There is a ton of benefit in having
               | distro/package maintainers, and we tend to forget it.
        
               | palata wrote:
               | > If Linux dependency management worked well, there would
               | be no need or appetite for docker.
               | 
               | I kindly disagree here. Linux dependency management does
               | work well. The problem is the bad libraries that don't do
               | semver properly, and the users who still decide to use
               | bad libraries.
               | 
               | If people stopped using libraries that break ABI
               | compatibility, then the authors of those libraries would
               | have to do it properly, and it would work. The reason it
               | doesn't work is really just malpractice.
        
               | zaphar wrote:
               | If Linux dependency management works well in theory but
               | not in practice then it doesn't work. It works in nix
               | because it can literally use multiple minor versions of a
               | library when it needs to with no problem. Most distro's
               | can't or won't do that.
               | 
               | You can call it malpractice but it's not going to stop so
               | in practice you need a way to deal with it.
        
               | palata wrote:
               | Well, by calling it "malpractice", I say that it works
               | for "true professionals". Then we could say that "it
               | doesn't work in practice if people who don't know what
               | they are doing cannot use it", of course.
               | 
               | The question then is where we want to put the bar. I feel
               | like it is too low, and most software is too bad. And I
               | don't want to participate in making tooling that helps
               | lowering the bar even more.
        
               | palata wrote:
               | And by the way it does work really well for good
               | software. Actually most Linux distros use a system
               | package manager and have been doing it for decades.
               | 
               | So I think it would be more accurate to say that "it
               | doesn't work for lower quality software". And I agree
               | with that.
        
               | SAI_Peregrinus wrote:
               | Semver only controls API compatibility, not ABI
               | compatibility. You can make an ABI break in a Semver
               | minor (or patch) version update. Semver is nice, but it's
               | not enough for ensuring compatibility when dynamic
               | linking.
        
               | kentonv wrote:
               | Everything you describe already exists. Executables _do_
               | list their dependencies, and we have well-defined
               | conventions for indicating ABI breaks. It is entirely
               | normal to have multiple major versions of a library
               | installed for ABI compatibility reasons, and it is also
               | entirely normal to expect that you can upgrade the
               | dependencies out from under a binary as long as the
               | library hasn 't had an ABI break.
               | 
               | The bigger dependency management problem is that every
               | distro has their own package manager and package
               | repository and it's tough for one application developer
               | to build and test every kind of package. But if they just
               | ship a binary, then it's up to the poor user to figure
               | out what packages to install. Often the library you need
               | may not even be available on some distros or the version
               | may be too old.
        
               | rwmj wrote:
               | That's why distros ask you to provide just the sources
               | and we'll do the packaging work for you. The upstream
               | developers shouldn't need to provide packages for every
               | distro. (Of course you can _help_ us downstream packagers
               | by not having insane build requirements, using semantic
               | versioning, not breaking stuff randomly etc).
        
               | kentonv wrote:
               | This is only realistic for established applications with
               | large userbases. For new or very niche apps, distros are
               | understandably not going to be very interested in doing
               | this work. In that case the developer needs to find a way
               | to distribute the app that they can reasonably maintain
               | directly, and that's where containers or statically-
               | linked binaries are really convenient.
        
               | rwmj wrote:
               | This isn't really true, Fedora, Debian and Arch have huge
               | numbers of packages, many very niche. You might well need
               | to make the distro aware that the new program exists, but
               | there are established routes for doing that.
        
               | TimeBearingDown wrote:
               | Arch particularly has the user repository where anyone
               | can submit a package and vote on the ones they use most
               | often to be adopted into the community repository, yes.
               | 
               | It's a great way to start contributing to the
               | distribution at large while scratching an itch and
               | providing a service to individual projects.
        
               | palata wrote:
               | I agree with everything you said up to this. We're
               | talking about a software library, for which the user is a
               | software developer. IMO a software developer should be
               | able to package a library for their own distro (then they
               | can share that package with their community and become
               | this package's maintainer).
               | 
               | As the developer of an open source library, I don't think
               | that you should distribute it for systems that you don't
               | use; someone else who uses it should maintain the
               | package. It doesn't have to be a "distro maintainer".
               | Anyone can maintain a single package. I am not on a very
               | mainstream distro, and I still haven't found a single
               | package that I use and is not already maintained by
               | someone in the community (though I wish I did, I would
               | like to maintain a package). My point is that it really
               | works well :-).
               | 
               | I disagree with the idea that we should build a lot of
               | tooling to "lower the bar" such that devs who don't know
               | how to handle a library don't have to learn how to do it.
               | They should learn, it's their job.
               | 
               | For proprietary software, it's admittedly a bit harder (I
               | guess? I don't have much experience there).
        
               | xorcist wrote:
               | This is not grounded in reality. Look at popcon or
               | something like it. It is a nearly perfect "long tail"
               | distribution. Most software is niche, and it's packaged
               | anyway. It's helped by the fact that the vast majority of
               | software follows a model where it is really easy to
               | build. There are a lot more decisions to take with
               | something like Chromium, which perhaps ironically is also
               | the type of software which tends to package its own
               | dependencies.
        
               | charcircuit wrote:
               | >Executables do list their dependencies
               | 
               | They list paths to libraries, but not the exact version
               | that the executable depends on. It is a common occurrence
               | for executables to load versions of libraries they were
               | not designed to be used with.
        
               | YoshiRulz wrote:
               | If you're talking about ELF for desktop Linux, they for
               | the most part don't contain file paths, and may specify
               | the version but usually just have the major version (to
               | allow for security updates). You can use ldd to read the
               | list of deps and also do a dry run of fulfilling them
               | from the search path, for example:                 $> ldd
               | $(command -v ls)         linux-vdso.so.1
               | (0x00007ffd5b3a0000)         libcap.so.2 =>
               | /usr/lib/libcap.so.2 (0x00007f6bd398c000)
               | libc.so.6 => /usr/lib/libc.so.6 (0x00007f6bd3780000)
               | /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-
               | linux-x86-64.so.2 (0x00007f6bd39e5000)
        
               | charcircuit wrote:
               | Libraries can cause bugs even if they have the same exact
               | version as it may be compiled in a way that is not
               | expected by the program. Ideally the list of libraries
               | should be some form of a hash of the library to ensure it
               | is loading exactly what it expects.
        
               | arghwhat wrote:
               | Linus Torvalds disagrees: https://lore.kernel.org/lkml/CA
               | Hk-=whs8QZf3YnifdLv57+FhBi5_W...
        
               | gnramires wrote:
               | I should have been more balanced or nuanced a bit: I also
               | don't think static linking is to be forbidden or
               | completely shunned. As Linus himself says, a combination
               | of both may be ideal. For basic system libraries like GUI
               | libraries the current approach works well. But you should
               | be free to static link if you want, and if there are
               | serious issues if you don't. Maybe dynamic linking should
               | be focused on a smaller number of well curated libraries
               | and the rest should be left to static. Library archeology
               | seems like a potential serious problem years from now.
               | 
               | I still think better listing dependencies (perhaps with
               | the option to pin an exact version?) would be helpful, as
               | well as better usage of something like semver. Someone
               | mentioned binaries include _paths to dependencies_ , but
               | as far as I know, there is no tool to automatically try
               | to resolve those dependencies or standard interface,
               | maybe some more tooling in this area would help.
               | 
               | Another nice point about how it current works is that I
               | think it relieves work from programmers. The policy of
               | "Don't worry about distribution (just tell us it exists)"
               | from distros seems like one less headache for the creator
               | (and you can provide static linked binaries too if you
               | want).
               | 
               | As most things in life, the ideal is somewhere in the
               | middle...
        
             | bscphil wrote:
             | > 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.
        
               | moffkalast wrote:
               | It applies very much to end user desktops as well, with
               | snap, flatpak, etc. working towards it. Lots of software
               | requires dependencies that aren't compatible with each
               | other and result in absolute dependency hell or even a
               | broken install when you dare to have more than one
               | version of something. Because who would ever need that,
               | right? Especially not in a dev desktop environment...
               | 
               | Windows is basically all self-contained executables and
               | the few times it isn't it's a complete mess with
               | installing VC++ redistributables or the correct Java
               | runtime or whatever that clueless users inevitably mess
               | up.
               | 
               | We have the disk space, we have the memory, we have the
               | broadband to download it all. Even more so on desktop
               | than on some cheap VPS.
        
               | marwis wrote:
               | > Windows is basically all self-contained executables
               | 
               | With the caveat that the "standard library" they depend
               | on is multiple GBs and provides more features than entire
               | Gnome.
               | 
               | Also MS always worked in some tech to avoid library
               | duplication such as WinSxS or now MSIX has autodedupe
               | even at the time of download.
        
               | palata wrote:
               | > when you dare to have more than one version of
               | something. Because who would ever need that, right?
               | 
               | If done properly, you can have multiple major versions of
               | something and that's fine. If one app depends on
               | libA.so.1.0.3, the other on libA.so.1.1.4, and they can't
               | both live with 1.1.4, it means that `libA` did something
               | wrong.
               | 
               | One pretty clear solution to me is that the dev of libA
               | should learn good practice.
        
               | zaphar wrote:
               | Yep, the dev(s) of libA should learn good practice. But
               | they didn't and app1 and app2 still have the problem.
               | Static linking solves it for them more reliably than
               | trying to get the dev of libA to "git gud". Much of the
               | desire to statically link binaries comes from this
               | specific scenario playing out over and over and over.
               | 
               | Heck for a long time upgrading glibc by a minor version
               | was almost guaranteed to break your app and that was
               | often _intentional_.
        
               | palata wrote:
               | > Yep, the dev(s) of libA should learn good practice. But
               | they didn't and app1 and app2 still have the problem.
               | 
               | Sure :-). I just find it sad that app1 and app2 then use
               | the bad libA. Of course that is more productive, but I
               | believe this is exactly the kind of philosophy that makes
               | the software industry produce worse software every year
               | :(.
        
               | zaphar wrote:
               | I used to think the same. But after nearly 30 years of
               | doing this. I no longer think that people will meet the
               | standard you propose. You can either work around it or
               | you can abandon mainstream software entirely and make
               | everything you use bespoke. There are basically no other
               | choices.
        
               | palata wrote:
               | Yeah I try really hard to not use "bad" dependencies.
               | When I really can't, well... I can't.
               | 
               | But still I like to make it clear that the software
               | industry goes in that direction because of quality
               | issues, and not because the modern ways are superior (on
               | the contrary, quite often) :-).
        
               | moffkalast wrote:
               | Wishing that all people will be smart and always do the
               | correct thing is setting yourself up for madness. The
               | dependency system needs to be robust enough to endure a
               | considerable amount of dumbfuckery. Because there will be
               | a lot of it.
        
               | palata wrote:
               | Because I have to live with "malpractice" doesn't mean I
               | should not say it is, IMHO.
               | 
               | I can accept that someone needs to make a hack, but I
               | really want them to realize (and acknowledge) that it is
               | a hack.
        
               | shusfuejdn wrote:
               | It should be noted though that flatpaks and related
               | solutions are NOT equivalent to static linking. They do a
               | lot more and serve a wildly different audience than
               | something like Oasis. They are really much too extreme
               | for non-GUI applications, and I would question the
               | competence of anybody found running ordinary programs
               | packaged in that manner.
               | 
               | I recognize that you probably weren't confused on this
               | I'm just clarifying for others since the whole ecosystem
               | can be a bit confusing.
        
               | StillBored wrote:
               | understanding that they are different tools for different
               | jobs
               | 
               | Right, but this goes against the dogma on both sides and
               | the fact that much of Linux userspace is the wild west.
               | Ideally, there should be a set of core system libraries
               | (ex glibc, openssl, xlib, etc) that have extremely stable
               | API/ABI somatics and are rarely updated.
               | 
               | Then one dynamically links the core libraries and
               | statically links everything else. This solves the problem
               | that a bug/exploit found in something like OpenSSL
               | doesn't require the entire system to be recompiled and
               | updated while allowing libraries that are not stable,
               | used by few packages, etc, to be statically linked to
               | their users. Then, when lib_coolnew_pos has a bug, it
               | only requires rebuilding the two apps linked to it, and
               | not necessarily even then if those applications don't
               | expose the bug.
        
               | palata wrote:
               | > Then one dynamically links the core libraries and
               | statically links everything else.
               | 
               | Agreed, and that is already totally possible.
               | 
               | - If you split your project in libraries (there are
               | reasons to do that), then by all means link them
               | statically.
               | 
               | - If you depend on a third party library that is so
               | unstable that nobody maintains a package for it, then the
               | first question should be: do you really want to depend on
               | it? If yes, you have to understand that you are now the
               | maintainer of that library. Link it dynamically or
               | statically, whichever you want, but you are responsible
               | for its updates in any case.
               | 
               | The fashion that goes towards statically linking
               | everything shows, to me, that people generally don't know
               | how to handle dependencies. "It's simpler" to copy-paste
               | the library code in your project, build it as part of it,
               | and call that "statically linking". And then probably
               | never update it, or try to update it and give up after
               | 10min the first time the update fails ("well, the old
               | version works for now, I don't have time for an update").
               | 
               | I am fine with people who know how to do both and choose
               | to statically link. I don't like the arguments coming
               | from those who statically link because they don't know
               | better, but still try to justify themselves.
        
               | superb_dev wrote:
               | Statically linking does not imply copying the code into
               | the project
        
               | palata wrote:
               | Of course not. My point was that people who say "static
               | linking is better" because the only thing they know
               | (which is copying the code into their project) results in
               | something that looks like static linking are in the
               | wrong.
        
               | jcelerier wrote:
               | > Agreed, and that is already totally possible
               | 
               | How? Take for instance OpenSSL mentioned above. I have a
               | software to distribute for multiple Debian versions,
               | starting from Bullseye which uses OpenSSL 1.x and
               | libicu67. Bookworm the more recent has icu72 and OpenSSL
               | 3.x which are binary-incompatible. My requirement is that
               | I do only one build, not one per distro as i do not have
               | the manpower or CI availability for this. What's your
               | recommendation?
        
               | palata wrote:
               | > How?
               | 
               | Well you build OpenSSL as a static library, and you use
               | that...
               | 
               | > Take for instance OpenSSL mentioned above.
               | 
               | However for something like OpenSSL on a distro like
               | Debian, I really don't get why one would want it: it is
               | most definitely distributed by Debian in the core repo.
               | But yeah, I do link OpenSSL statically for Android and
               | iOS (where anyway the system does not provide it). That's
               | fairly straightforward, I just need to build OpenSSL
               | myself.
               | 
               | > My requirement is that I do only one build
               | 
               | You want to make only one build that works with both
               | OpenSSL 1 and OpenSSL 3? I am not sure I understand...
               | the whole point of the major update is that they are not
               | compatible. I think there is fundamentally no way (and
               | that's by definition) to support two explicitly
               | incompatible versions in the same build...
        
               | formerly_proven wrote:
               | > Right, but this goes against the dogma on both sides
               | and the fact that much of Linux userspace is the wild
               | west. Ideally, there should be a set of core system
               | libraries (ex glibc, openssl, xlib, etc) that have
               | extremely stable API/ABI somatics and are rarely updated.
               | 
               | This is largely true and how most proprietary software is
               | deployed on Linux.
               | 
               | glibc is pretty good about backwards compatibility. It
               | gets shit for not being forwards compatible (i.e. you
               | can't take a binary linked against glibc 2.34 and run it
               | on a glibc 2.17 system). It's not fully bug for bug
               | compatible. Sometimes they'll patch it, sometimes not. On
               | Windows a lot of applications still link and ship their
               | own libc, for example.
               | 
               | xlib et al don't break in practice. Programs bring their
               | own GUI framework linking them and it'll work. Some are
               | adventurous and link against system gtk2 or gtk3. Even
               | that generally works.
               | 
               | OpenSSL does have a few popular SONAMEs around but they
               | have had particularly nastily broken APIs in the past.
               | Many distros offer two or more versions of OpenSSL for
               | this reason. However, most applications ship their own.
               | 
               | If you only need to talk to some servers, you can link
               | against system libcurl though (ABI compatible for like
               | twenty years). This would IMHO be much better than what
               | most applications do today (shipping their own crypto +
               | protocol stack which invariably ends up with holes).
               | While Microsoft ships curl.exe nowadays, they don't
               | include libcurl with their OS. Otherwise that would be
               | pretty close to a universally compatible protocol client
               | API and ABI and you really wouldn't have any _good_
               | reason any more to patch the same tired X.509 and HTTP
               | parser vulnerabilities in each and every app.
        
               | wongarsu wrote:
               | Windows makes up the lion's share of desktop computing,
               | and seems to be doing fine without actually sharing
               | libraries. Lots of dynamic linking going on, but since
               | about the XP days the entire Windows ecosystem has given
               | up on different software linking the same library file,
               | except for OS interfaces and C runtimes. Instead everyone
               | just ships their own version of everything they use, and
               | dynamic linking is mostly used to solve licencing, for
               | developer convenience, or for plugin systems. The end
               | result isn't that different from everything being
               | statically linked
        
             | nequo wrote:
             | > 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.
        
               | plopz wrote:
               | Then why does every steam game need to install a
               | different version of visual c++ redistributable?
        
               | nequo wrote:
               | Because they are not packaged by the distros so they are
               | not guaranteed to have the libraries present that they
               | were linked against? I am just guessing, I haven't used
               | Steam.
        
               | YoshiRulz wrote:
               | Does this happen on Windows too? The reason it happens on
               | Linux is because every game ran via Proton/WINE gets its
               | own virtual C: drive.
        
             | chaxor wrote:
             | 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.
        
               | tyingq wrote:
               | If there is a mechanism to monitor the dependency chain.
               | Otherwise, you may be blissfully unaware that some
               | vulnerability in libwhatever is in some binary you're
               | using.
               | 
               | Golang tooling provides some reasonable mechanisms to
               | keep dependencies up to date. Any given C program might
               | or might not.
        
               | palata wrote:
               | > If there is a mechanism to monitor the dependency
               | chain.
               | 
               | So that would not be _less_ secure, but it would also not
               | make it _more_ secure than dynamic linking with a good
               | mechanism, right?
        
               | tyingq wrote:
               | Personally, I think any inherent security advantage
               | (assuming it has great dependency management) would be
               | very small. This "Oasis" project doesn't seem to call it
               | out at all, even though they are making a fair amount of
               | effort to track dependencies per binary.
               | 
               | They cite the main benefits being this: _" Compared to
               | dynamic linking, this is a simpler mechanism which
               | eliminates problems with upgrading libraries, and results
               | in completely self-contained binaries that can easily be
               | copied to other systems"_.
               | 
               | Even that "easily be copied to other systems" sort of
               | cites one of the security downsides. Is the system you're
               | copying it to going to make any effort to keep the
               | transient statically linked stuff in it up to date?
        
             | manmal wrote:
             | 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/docum
             | entation/xcode/configuring-...
        
               | TimeBearingDown wrote:
               | Very interesting, as of Xcode 15? I wonder if anyone has
               | explored doing this on Linux, and hope this gets a little
               | more attention.
        
               | manmal wrote:
               | Yes, announced last June, Xcode 15
        
           | jhallenworld wrote:
           | >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 wrote:
             | > 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.
        
           | rwmj wrote:
           | 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 wrote:
             | Well, you have to do that anyways
        
           | giljabeab wrote:
           | Can't file systems de dupe this now
        
           | inkyoto wrote:
           | > 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 wrote:
             | > 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.
        
         | bzzzt wrote:
         | I know lots of compilers/linkers don't optimize for it but it
         | should be possible to 'tree shake' libraries so only the parts
         | that are used by an application are included. That would shake
         | off a lot of the 'bloat'.
        
           | volemo wrote:
           | Wait, it's not being done?
        
             | dieortin wrote:
             | It is, major compilers do that by default
        
             | Fronzie wrote:
             | As far as I know, even with LTO, it requires -ffunction-
             | sections -fdata-sections in order to strip out unused
             | functions.
        
         | Gabrys1 wrote:
         | I guess each of the copies of libc can be optimized away and
         | only the functions the specific binary calls will be left (and
         | the compiler should be allowed to optimize past the library
         | boundary), so maybe this balances the issues a bit.
         | 
         | Not that I really know anything about it, ask jart
        
         | Gazoche wrote:
         | 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.
        
           | palata wrote:
           | > 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.
        
             | hn_go_brrrrr wrote:
             | 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.
        
               | Ar-Curunir wrote:
               | Semver defines what is breaking and not-breaking. E.g.,
               | Rust semver says that "code should continue compiling
               | with a minor version bump, but not necessarily for a
               | major version bump"
        
               | steveklabnik wrote:
               | Yes. The very first line of the spec:
               | 
               | > Software using Semantic Versioning MUST declare a
               | public API. This API could be declared in the code itself
               | or exist strictly in documentation. However it is done,
               | it SHOULD be precise and comprehensive.
               | 
               | If it's not in the API, it is not bound by the rules.
               | Many ecosystems come up with various norms, like Rust
               | has, to help guide people in this. But it's almost
               | certainly not a semver violation to make the change
               | described in the XKCD because "handle unknown unknowns"
               | is not possible. That doesn't mean that we should throw
               | out the entire idea of software assisted upgrades to
               | dependencies.
        
               | palata wrote:
               | I would argue that https://xkcd.com/1172 is a case where
               | the user "deserves" the breaking change, because they
               | relied on a hack in the first place.
               | 
               | That's the thing: I feel like people tend to call
               | "dependency hell" what I would consider downright
               | malpractice. "Shared libraries don't work because they
               | require good practice" is, IMO, not a good argument
               | against shared libraries. If you need to design your tool
               | with the constraints that "users will use it wrongly",
               | then it's already lost.
        
               | dwattttt wrote:
               | Semver doesn't stop people from depending on
               | unstable/implementation-specific behaviour; it needs to
               | be coupled with a strong mechanism for defining what
               | behaviour is defined by an API, and the result is that
               | "the bug" is with all those users who depend on un-
               | guaranteed behaviour.
               | 
               | The breaks happen regardless, but you have a principled
               | way of defining whose fault/problem it is.
        
             | IshKebab wrote:
             | 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.
        
               | palata wrote:
               | > Software depending on versions of libraries that are
               | newer than the latest version available on the distro you
               | have to use (cough RHEL 8).
               | 
               | That is a fair point, but it raises a question: if you
               | _absolutely_ need to use software that is not packaged by
               | your distro of choice and that you cannot package
               | yourself (are you sure you can 't maintain a "community"
               | package yourself with RHEL?), maybe you don't want that
               | distro.
               | 
               | Different distros come with different goals. If you take
               | a "super slow but secure" distro, it will be slow and
               | secure. If you take a rolling distro, you get updates
               | very quickly but it has drawbacks. It depends on the use-
               | case, but going for a "slow and secure" distro and then
               | building tooling to work around that choice ("nevermind,
               | I'll ship new and less mature software anyway, statically
               | linked") seems to defeat the purpose of the distro...
               | right?
        
               | IshKebab wrote:
               | > maybe you don't want that distro
               | 
               | Well I definitely don't want RHEL 8 but unfortunately I
               | have to use it because some software I use requires it
               | (RHEL 9 doesn't have _old_ enough versions of some
               | libraries) or is only certified on it (this is for work).
               | 
               | But even if I was using a more modern distro, none of
               | them have _all_ software packaged. And no I obviously don
               | 't want want to become a packager. Some of the software I
               | use is closed source so that's not even an option.
               | 
               | The only real option is Docker (or Apptainer/Distrobox
               | etc), which sucks.
               | 
               | The fundamental model of "we'll just ship all software
               | that exists; all software is open source" that most
               | distros try to use is just fundamentally wrong.
               | 
               | Snap and Flatpak are trying to fix that but in my
               | experience they aren't remotely ready yet.
        
               | palata wrote:
               | > And no I obviously don't want want to become a
               | packager.
               | 
               | That's where I disagree. It's not that hard, and if more
               | people did it, more software would be packaged. Actually
               | I am yet to find a library that I actually need and that
               | is not _already packaged_ and maintained by someone from
               | the community. Then I could finally maintain one myself.
               | 
               | To me, you're basically saying: "I don't want to learn
               | and commit to maintain a package for my distro, because
               | _reason_ , but I am fine spending time with all that
               | tooling that I say "sucks" (Docker/Apptainer/Distrobox)".
               | That's what I don't really get. There is a solution that
               | works well (for me, at least): package the software that
               | is not already available yourself.
               | 
               | > Some of the software I use is closed source so that's
               | not even an option.
               | 
               | I would not want to maintain a package with proprietary
               | binaries that I don't own, that's for sure. But if you
               | need to, you can. As long as the author distributes
               | binaries for your platform, it's not much harder than
               | making an open source package.
        
               | IshKebab wrote:
               | > That's where I disagree.
               | 
               | Well we'll have to agree to disagree on that, but I think
               | if you told most people that the normal way to install
               | third party software for Linux was _to become a package
               | maintainer_ they would rightly laugh you straight to the
               | asylum.
               | 
               | > That's what I don't really get.
               | 
               | The reason is that Docker, Apptainer etc are much easier
               | than creating packages for all the dependencies of the
               | software I want to run. Multiplied by the number of
               | distros I need to use. Pretty obvious no?
        
               | palata wrote:
               | It is pretty obvious indeed, coming from what I get is
               | your point of view. You seem to believe that you _have to
               | become a package maintainer for all the dependencies of
               | the software you want to run_. But I think you have this
               | wrong.
               | 
               | Take it like this: in the current state, I am struggling
               | to find a single interesting library for which I could
               | become a package maintainer for my non-mainstream Linux
               | distro, because there always exists one. Maybe not in the
               | core repo, maybe only in the community repo. But still: I
               | don't maintain a single package today, because I haven't
               | found one that I use and that it not already maintained
               | by somebody else.
               | 
               | Really, if you decide to create packages for all the
               | dependencies of the software you want to run,
               | congratulations: you have just created a new distro from
               | scratch. But even most new distros don't do that :-).
               | 
               | In other words, there are way more developers than
               | libraries that are worth being depended on. So even if we
               | wanted to, not everybody can maintain a single package.
               | There are just not enough packages out there for that, by
               | very, very far.
        
               | TimeBearingDown wrote:
               | I agree with essentially all of this, and I really think
               | the barrier to entry for packaging should be lower. It
               | was deeply helpful to me while learning Linux to be able
               | to write a Bash PKGBUILD, maybe 20-40 lines, to have that
               | clear structure and ease my own update process, while
               | also making it available to others on the Arch User
               | Repository and learning from comments others left. These
               | days I can whip up a simple PKGBUILD for a simple project
               | I discover in just a minute or three, and it led me to so
               | much experience handling build issues and software
               | dependency structure.
               | 
               | I would leap for joy to see Red Hat or Debian or even
               | Gentoo make inroads here, but I haven't looked closely
               | enough and recently at Debian, and .ebuild files hurt my
               | brain. I do believe I recall Gentoo requiring more work
               | to get my packages available and listed anywhere.
        
               | palata wrote:
               | Yeah I do agree, I find Arch's PKGBUILDs and Alpine's
               | APKBUILDs much easier to write than e.g. a debian
               | package. Not that the debian package is impossible, but
               | it's not as straightforward.
        
               | xorcist wrote:
               | With traditional Linux distributions like Red Hat, you
               | can sometimes take a package from a newer release (or
               | something like Fedora) in _source form_ and rebuild it
               | for your release. When it works, it 's literally just one
               | command, which does everything to give you a binary
               | package. If there is some problematic patch, you can
               | often take it out, but also put in patches from the old
               | version. It's usually documented enough to make it
               | obvious.
               | 
               | It's usually straightforward with end user applications,
               | such as bash or git or ruby. Things more likely to be
               | tied to the rest of the operating system, such as SELinux
               | or PAM, are less likely to work. If there are
               | dependencies to things that is release dependent, it's
               | not worth the bother.
               | 
               | Maybe you can argue you don't want to "become a
               | packager", but someone has already done the work for you
               | and you don't need more than superficial knowledge about
               | the system to do it. In most distributions, source
               | packages aren't harder to install than binary packages.
        
             | avgcorrection wrote:
             | 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.
        
               | palata wrote:
               | Good points.
               | 
               | > It seems impossible to solve this by just everyone
               | adopting a manifesto that one GitHub guy wrote many years
               | ago
               | 
               | Well by "semver" I mostly mean "change the major number
               | to indicate a change of ABI", I don't mind so much about
               | the other numbers in this case. But that's a good
               | question: I don't know when it started being a thing. I
               | would guess much, much earlier than GitHub, though.
               | 
               | > human judgement about what is breaking and not
               | 
               | Hmmm... ABI compatibility for the public interface is not
               | really subjective, or is it?
               | 
               | > weird implicit social taboos about doing major releases
               | "too often"
               | 
               | Yes I don't get that one and I fight hard against it.
               | 
               | > But also doing static linking a bit more seems like it
               | would help a lot with the same problem.
               | 
               | Well I am not fundamentally against static linking; to me
               | it makes sense to do a mix, with the caveat that if you
               | link something statically, then _you are the maintainer
               | of that code_. Whereas if you link a system library
               | dynamically, you merely depend on it.
               | 
               | My problem is about moving to "static linking only" (or
               | "by default", but I don't even know if Rust allows
               | dynamic linking at all?).
        
           | nerpderp82 wrote:
           | 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 wrote:
             | 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.
        
               | soulofmischief wrote:
               | Same, I love Qubes' philosophy and UX, but GPU
               | passthrough support was a dealbreaker in the end and I
               | switched to a KVM system.
        
               | TimeBearingDown wrote:
               | I'm pretty sure GPU passthrough does work in Qubes HVMs,
               | although I haven't tried it myself. Here are three quick
               | and recent tutorials I found including one with a newer
               | VirtualGL approach that offloads work instead of passing
               | the entire card.
               | 
               | https://neowutran.ovh/qubes/articles/gaming_windows_hvm.h
               | tml
               | 
               | https://forum.qubes-os.org/t/nvidia-gpu-passthrough-into-
               | lin...
               | 
               | https://forum.qubes-os.org/t/seamless-gpu-passthrough-on-
               | qub...
               | 
               | Yes, the passthrough is probably a huge avenue for
               | attacks. Possibly VirtualGL too, I know less about that.
        
               | TimeBearingDown wrote:
               | One more, site won't let me edit.
               | 
               | https://neowutran.ovh/qubes/articles/gaming_windows_hvm.h
               | tml
        
               | Qwertious wrote:
               | That's the same as the first link in your previous
               | comment. Did you manage to edit it after all?
        
             | IshKebab wrote:
             | Exactly this. Windows apps aren't distributed as Docker
             | images. Guess why...
        
               | palata wrote:
               | Well nothing prevents you from dynamically linking only
               | glibc and statically linking everything else, _without
               | Docker at all_.
               | 
               | The fact that people distribute their app with a full
               | rootfs in a Docker containers says more about the fact
               | that they don't know how to link stuff properly, IMHO.
        
               | IshKebab wrote:
               | It's not about static vs dynamic linking at all. It's
               | about bundling dependencies or not.
               | 
               | And yes, you totally can do it. Most Linux software just
               | doesn't bother because - while you _can_ do it, in a lot
               | of languages (C, Python, etc.) it 's quite a pain to do.
               | Especially if you have lots of dependencies.
               | 
               | It's much easier to bundle dependencies in languages that
               | statically link by default (Go, Rust) because of course
               | statically linking implicitly bundles them.
        
               | palata wrote:
               | > Dynamic Library hell is why Docker exists.
               | 
               | > It's much easier to bundle dependencies in languages
               | that statically link by default
               | 
               | > It's not about static vs dynamic linking at all.
               | 
               | Sorry I'm confused :/. What did I say that you disagree
               | with?
        
         | jacquesm wrote:
         | 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.
        
         | arghwhat wrote:
         | 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 wrote:
           | 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.
        
             | jhallenworld wrote:
             | 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.
        
               | marwis wrote:
               | Yes but most processes are unique. The only bash process
               | I have running is my interactive shell.
        
             | arghwhat wrote:
             | 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.
        
               | marwis wrote:
               | > The case for the shared library having better caching
               | implies multiple processes that are distinct executables
               | 
               | But this is the most common case for
               | desktops/multipurpose systems.
               | 
               | On my desktop there are tens or hundreds distinct
               | processes sharing most of their code.
        
               | arghwhat wrote:
               | No it is not.
               | 
               | Depending on your CPU, you might have, say, 32KB of 8-way
               | associative instruction cache per core. Just _being_
               | shared does not make it fit in the cache.
               | 
               | A shared library would only be there across processes of
               | different executable images if its users _primarily_ ,
               | continuously execute the same paths in shared libs rather
               | than anything unique in their own executable image -
               | e.g., they'd more or less need to be stuck in the same
               | processing-intensive shared routine in the lib. There
               | would also have to be no other processing done in between
               | by other processes that would have trashed the cache.
               | 
               | On the other hand, the severe cache penalty of longer
               | code paths for each executable and the larger PLT call
               | overhead will universally lead to a loss in performance
               | for _all_ library usage.
               | 
               | The scenarios you may hit where different processes are
               | actually executing the same shared code paths to the
               | point of benefiting from shared cache utilization would
               | be cases where they share executable image as well. E.g.,
               | browser processes, threads, compilers. Electron too if
               | using system-packaged electron binaries.
        
               | marwis wrote:
               | > A shared library would only be there across processes
               | of different executable images if its users primarily,
               | continuously execute the same paths in shared libs rather
               | than anything unique in their own executable image
               | 
               | Yes, like libc/WinApi, Cairo/whatever graphics library of
               | your OS, Gtk/Qt etc
               | 
               | All of the apps on my desktop (I don't use electron)
               | share vast majority of their code (see above) and spend
               | most of their time drawing UI through shared libs or
               | doing their own business logic but that's part of their
               | code and not subject to shared lib overhead.
        
               | inkyoto wrote:
               | > Static linking gives you better instruction cache
               | utilization as you are executing local code linearly
               | rather than going through indirection with more
               | boilerplate.
               | 
               | No, it does not, it worsens it.
               | 
               | For example, <<strlen>>, if it comes from a dynamic
               | library, will be loaded into the physical memory once and
               | only once, and it will be mapped into each process's
               | address space as many times as there are processes. Since
               | <<strlen>> is a very frequently used function, there is a
               | very high chance that the page will remain resident in
               | memory for a very long time, and since the _physical_
               | page is resident in memory, there is also a very good
               | chance that the page will remain resident at least in the
               | L2 cache, but - depending on circumstances - in the L1
               | cache, too. A TLB flush might not even be necessary in
               | specific circumstances, which is a big performance win.
               | It is a 1:N scenario.
               | 
               | With the static linking, on the other hand, if there are
               | 10k processes in the system, there will be 10k distinct
               | pages containing <<strlen>> loaded into memory at 10k
               | random addresses. It is a M:N scenario. Since the
               | _physical_ memory pages are now distinct, the context
               | switching will nearly always require the TLB to be
               | flushed out which is costly or very costly, and more
               | frequent L1 /L2 cache invalidations due to <<strlen>> now
               | residing at 10k distinct _physical_ memory addresses.
               | 
               | P.S. I am aware that C compilers now inline <<strlen>> so
               | there is no actual function call, but let's pretend that
               | it is not inlined for the sake of the conversation.
        
         | javierhonduco wrote:
         | 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 wrote:
           | 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 wrote:
             | Had completely missed that line -- great point!
        
         | 1vuio0pswjnm7 wrote:
         | 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.)
        
       | peter_d_sherman wrote:
       | I've added links to the below quote:
       | 
       | >"oasis uses _smaller and simpler_ implementations of libraries
       | and tools whenever possible:
       | 
       | musl instead of glibc (https://www.musl-libc.org/)
       | 
       | sbase instead of coreutils
       | (https://git.suckless.org/sbase/file/README.html)
       | 
       | ubase instead of util-linux
       | (https://git.suckless.org/ubase/file/README.html)
       | 
       | pigz instead of gzip (https://zlib.net/pigz/)
       | 
       | mandoc instead of man-db (https://mandoc.bsd.lv/)
       | 
       | bearssl instead of openssl (https://bearssl.org/)
       | 
       | oksh instead of bash (https://github.com/ibara/oksh)
       | 
       | sdhcp instead of dhclient or dhcpcd
       | (https://core.suckless.org/sdhcp/)
       | 
       | vis instead of vim or emacs (https://github.com/martanne/vis)
       | 
       | byacc instead of bison (https://invisible-island.net/byacc/)
       | 
       | perp and sinit instead of sysvinit or system 44
       | (http://b0llix.net/perp/ https://github.com/wereHamster/perp
       | https://troubleshooters.com/linux/diy/suckless_init_on_plop....)
       | 
       | netsurf instead of chromium or firefox (https://www.netsurf-
       | browser.org/)
       | 
       | samurai instead of ninja
       | (https://github.com/michaelforney/samurai)
       | 
       | velox instead of Xorg (https://github.com/michaelforney/velox)
       | 
       | netbsd-curses instead of ncurses (https://github.com/sabotage-
       | linux/netbsd-curses)"
       | 
       | (Oh, and not to quote Dwayne "The Rock" Johnson's character
       | "Maui" from Disney's Moana or anything -- but _" You're
       | welcome!"_ <g> :-) <g>)
        
       | malux85 wrote:
       | Anyone have a link to the QEMU tarball in the README? It is
       | hosted on a private server and it looks like it's been HN hugged
        
       | lordwiz wrote:
       | Interesting, Like how its focused on making it lean by having
       | less bloated versions of the tools
        
       | schemescape wrote:
       | 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 wrote:
         | I have an old (2020) .qcow2 lying around that's about 360MB
        
           | xiconfjs wrote:
           | could you please upload it?
        
             | elfstead wrote:
             | https://elfstead.com/archive/oasis-qemu.tar.xz
        
       | notfed wrote:
       | > Fast builds that are 100% reproducible.
       | 
       | It's unclear to me what "100%" refers to here, but surely it does
       | not include the Linux kernel or drivers? (I've recently read
       | conversations about how difficult this would be.)
        
         | hn_go_brrrrr wrote:
         | Got a link? Sounds interesting.
        
           | notfed wrote:
           | Here's a link to a recent HN discussion:
           | 
           | https://news.ycombinator.com/item?id=38852616
           | 
           | TLDR: Linux kernel doesn't have a stable binary kernel
           | interface. And they don't want one.
           | 
           | Given this, the definition of "reproducible build" needs,
           | well, a refined definition, if it includes the Linux kernel.
           | 
           | [1] https://www.kernel.org/doc/Documentation/process/stable-
           | api-...
        
         | azornathogron wrote:
         | I'm no expert, but as an interested amateur I thought the Linux
         | kernel could already be built reproducibly?
         | 
         | There is some documentation at least... and I know several
         | Linux distributions have been working on reproducible builds
         | for a long time now - I'd be surprised if there hasn't been
         | good progress on this.
         | 
         | https://www.kernel.org/doc/html/latest/kbuild/reproducible-b...
        
           | dayjaby wrote:
           | In container context I've heard a definition of "100%
           | reproducible" that means even file timestamps are 100% the
           | same. Like your entire build is bit-by-bit precisely the same
           | if you didn't modify any source.
           | 
           | Not sure if that's what they mean here.
        
             | YoshiRulz wrote:
             | This is https://reproducible-builds.org/docs/source-date-
             | epoch/
        
         | YoshiRulz wrote:
         | I expect it refers to the proportion, weighted by filesize, of
         | programs that are byte-for-byte reproducible across machines.
         | (The assumption being that to take the same measurement in a
         | dynamically-linked context would result in a number less than
         | 100% due to machines having different copies of some libs.) In
         | other contexts, it might simply be a proportion of whole
         | packages, for example Arch Linux' core package set is 96.6%
         | reproducible[1] (=256/(256+9)).
         | 
         | The Linux kernel's lack of a stable ABI (specifically [2]; many
         | userspace APIs are stabilised) doesn't mean individual
         | revisions can't be built reproducibly.
         | 
         | [1]: https://reproducible.archlinux.org
         | 
         | [2]: https://en.wikipedia.org/wiki/Linux_kernel#In-kernel_ABI
        
       | speedgoose wrote:
       | BearSSL development's seems to have stopped and it's lacking
       | TLS1.3. Are there promising alternatives?
        
         | asmvolatile wrote:
         | wolfSSL. Open source, widely used, flexible licensing model,
         | TLS + DTLS 1.3 support, support for all modern ciphers and
         | protocol extensions, extremely tuneable for performance/size,
         | FIPS module, excellent customer support, the list goes on....
        
       | jollyllama wrote:
       | Anyway, here's wonder -Wall
        
         | notnmeyer wrote:
         | this is funnier than it has any right to be
        
       | sylware wrote:
       | 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.
        
         | stefan_ wrote:
         | 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 wrote:
           | 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.
        
         | AshamedCaptain wrote:
         | 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.
        
       | m463 wrote:
       | How big is it?
       | 
       | I could imagine there were unexpected efficiencies. Although
       | dynamic libraries should be able to share an address space, I
       | think with static libraries, the linked might strip out unused
       | routines.
       | 
       | also, it might be faster
        
       | alexnewman wrote:
       | Now I just need them to switch to GitHub actions for the ci/cd
        
       | ratrocket wrote:
       | 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
        
       | lproven wrote:
       | Previous discussion (Aug 2022):
       | 
       | https://news.ycombinator.com/item?id=32458744
        
       | transfire wrote:
       | Somehow this reminds me of Gentoo.
        
       ___________________________________________________________________
       (page generated 2024-01-27 23:01 UTC)