[HN Gopher] Oasis - a small, statically-linked Linux system
___________________________________________________________________
Oasis - a small, statically-linked Linux system
Author : smartmic
Score : 355 points
Date : 2024-01-26 14:11 UTC (8 hours 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?
| 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.
| 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..._
| 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.
| 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.
| 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?
| 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.
| 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!
| 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
| skywal_l wrote:
| glibc is LGPL. Static linking your application implies some
| obligation on your part. Musl being MIT is less restrictive.
| Zambyte wrote:
| > Musl being MIT is less restrictive.
|
| It depends who you're speaking for
| bigstrat2003 wrote:
| No it doesn't. The MIT license is objectively less
| restrictive than the LGPL. Whether it's a good or bad thing
| to be less restrictive is a matter of opinion, but whether
| or not it is less restrictive is a matter of fact.
| Zambyte wrote:
| Lots of software licensed as MIT is distributed under a
| proprietary sublicense, which is as restrictive as it
| gets. That isn't the case with GPL licenses.
|
| It is a matter of fact that it's a matter of perspective.
| 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.
| 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.
| 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.
| 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
| 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.
| 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.
| 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.
| 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.
| 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.
| 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.
| 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.
| 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.
| 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
| 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.
| 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.
| IshKebab wrote:
| Exactly this. Windows apps aren't distributed as Docker
| images. Guess why...
| 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.
| 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!
| 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.
| 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.
| 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
___________________________________________________________________
(page generated 2024-01-26 23:00 UTC)