7 ms·
Awesome, but there is kind of a deal-breaker here: AFAIK, there isn't an official and hassle-free way to generate a statically-compiled binary with SBCL the wa
by ducktective 3y ago
Awesome, but there is kind of a deal-breaker here:
AFAIK, there isn't an official and hassle-free way to generate a statically-compiled binary with SBCL the way Go and Rust can. Like you develop on a debian 12 system, then move the binary to your debian 11 server only to be confronted with the notorious 'incompatible glibc version error'. It's super annoying.
In ECL, I think it's possible to use musl and bundle libecl and mucl libc into the final binary, but I'm not sure.
The caveat is ECL output startup time is around 500ms (as opposed to the much more performant SBCL output)
- nathell 3y agoSure there is, as always: load all the code into the running SBCL, then call (SB-EXT:SAVE-LISP-AND-DIE :EXECUTABLE T :TOPLEVEL your-entry-point). The downside, as always, is that this kills the Lisp process, and the resulting binary weighs tens of megabytes even for a simple hello world. I guess one of these disqualifies it as not hassle-free.
- ducktective 3y agoNo, I mean the dumped image depends on system glibc (not portable)
- jjnoakes 3y agoDepending on glibc can be portable enough if you build against the oldest glibc version that you need. Running on newer systems works.
- ducktective 3y agoHow do you get the latest toolchain and compiler but an old glibc? The tools have their own dependency on libc
- jjnoakes 3y agoYou build them. Or if the latest compilers don't build against the older glibc (which is rare in my experience, but may be possible), then you just don't support the older glibc any more. But I've never had trouble building against older glibcs.
- vindarel 3y agoIndeed. This patch was working for a previous version of SBCL: https://www.timmons.dev/posts/static-executables-with-sbcl-v2.html https://www.timmons.dev/posts/static-executables-with-sbcl-v... I heard projects (like the Kandria game) build their releases on an old glibc (but latest SBCL and libraries), so it can be shipped to any more recent system.
- ducktective 3y agoCan you confirm the ECL part of my comment? I mean is it possible to do it with ECL?
- matheusmoreira 3y ago> only to be confronted with the notorious 'incompatible glibc version error'. It's super annoying. I started making my own freestanding Linux Lisp because of this exact issue. It's nowhere near as performant as something like SBCL but it's small and has zero dependencies. Once compiled it will literally run on any Linux of the same architecture. https://github.com/lone-lang/lone https://github.com/lone-lang/lone I'm taking a break from this project at the moment but eventually I'm gonna add a feature that lets me put a Lisp script into the ELF itself so I can just copy it with the scripts included and have a totally self-contained freestanding Lisp executable.
- regularfry 3y agoThis is one of the reasons that developing on your production OS is something of a best practice. Not specific to SBCL at all, but this general problem of dependencies not quite matching can bite you in a lot of ways. People forgot this lesson when macbooks got popular for development, then had to relearn it by upending the ecosystem into containers.
- Zambyte 3y agoIt's also a reason for distributing software under a Free license. If people who use your software want to try running against a different libc or different versions of other dependencies, why not let them? You can always say you only support binaries that you distribute.
- jackdaniel 3y agocurrently there is not build flag to statically link libc manually (it is planned though). Regarding startup time, it all comes to ASDF: $ time ecl --eval "(quit)" 0.052 secs $ time ecl --eval "(require 'asdf)" --eval "(quit)" ;;; Loading #P".../lib64/ecl-21.2.1/asdf.fas" 0.301 secs
- kazinator 3y ago> it is planned though This is a bad plan for target systems that use glibc, because static linking is not recommended and not supported.
- jackdaniel 3y agoit is planned to allow static linking against libc, not necessarily glibc (I've been thinking about musl). Dynamic linking is still a default, but different strokes for different folks I guess.
- deleted 3y ago[deleted]
- rjsw 3y agoThis is a Linux problem not a SBCL one. You could move your SBCL binary between different versions of a BSD variant.
- ducktective 3y agoHow come it's not a Go/Rust problem?
- rjsw 3y agoGo makes syscalls directly, it doesn't call through the system libc. This does cause support problems on at least NetBSD, don't know what happens on FreeBSD or OpenBSD. The NetBSD backwards compatibility mechanism is to not change the arguments to an existing syscall, if there is a need to change something then a new syscall will be created and aliased to the old name in the system include files. Old binaries use the old syscall, those compiled after the new one has been added will use that. Languages that don't parse the system .h files like Go need conditional code for NetBSD.
- matheusmoreira 3y agoThis is not a Linux problem. The Linux system call binary interface is documented as stable. It's user space libraries like glibc that break backwards compatibility. There's nothing Linux can do about that. I've written more about this here: https://www.matheusmoreira.com/articles/linux-system-calls https://www.matheusmoreira.com/articles/linux-system-calls
- kazinator 3y ago> It's user space libraries like glibc that break backwards compatibility. s/backward/forward/ The commlaint here is that the older glibc on Debian 11 doesn't run programs built against a newer glibc under Debian 12. glibc has very good backward compatibility, with careful symbol versioning and whatnot. Backward compatibility means that a newer glibc (like in Debian 12) will handle programs requesting the older glibc (e.g. from Debian 11).
- codemac 3y agoEven shops that shipped static binaries, they all still shipped containers at the end of the day to run in production. I find a lot of the static binary hand wringing basically: did you ever solve how to ship more than 1 file to production? Did you ever need to virtualize any resource on your compute? Then you're at a minimum using a chroot and containers. If you aren't shipping to production, if you're really just copying files around between your laptops and you want them to run - you have glibc.
- cmrdporcupine 3y agoThere's a big gap between what you're talking about: ship a dockerfile or snap or whatever to make your big ol' service distribution-portable vs what this article was about: writing CLI programs. The moment we end up in a world where a "small CLI program" requires docker.. I give up. Time to retire from software and go raise sheep or something instead.
- codemac 3y agoThus my last sentence: if you aren't shipping to production... you are really just copying files around, and you have a glibc. I think I just use linux enough that all the macos bugs I don't experience.
- cmrdporcupine 3y agoNo, it sounds like you just have a mostly "I write code that goes on servers" type job, and haven't been burned by the issue of older binaries, that won't work with new libcs. This is a real problem with Linux (not MacOS or other BSDs from what I understand) because it doesn't have a stable ABI (the ABI is basically glibc). It's a design choice, and a pain in the ass for people who want to distribute things as binaries. Which, well, it's not something I do, but, it has burned me using other people's things. Could docker/containerization solve this problem? Yes, in the same way that a shotgun would serve for eliminating mosquitoes...
- 3y ago
- lelanthran 3y ago> Like you develop on a debian 12 system, then move the binary to your debian 11 server only to be confronted with the notorious 'incompatible glibc version error'. It's super annoying. I get that with Go too. I now make all my release builds on the oldest version of Linux I have.
- yakubin 3y agoIt sounds like you’re using cgo.
- lelanthran 3y agoNot as far as I know :-/ I got the glibc errors when I moved a binary I compiled on the newest Linux Mint to my VPS running some ancient debian.
- Jach 3y agoKind of a deal breaker sure, but I don't think in that many cases. Is it really that hard to launch an older VM and make a build there? Or just decide you don't need to support anything older than your dev machine? Or just always run with source code? For my little scripts (which admittedly are much less organized than those in the article) they're mostly just on my own dev machine. Occasionally I build binaries and ship them over to another server without any tooling on it, but it's never very far out of date. Such scripts are also fairly long-lived; it's nice that some binary I made in 2021 (to replace a perl script that had been stable for ~10 years) continues to do its job.
- kazinator 3y agoYour deal-breaker applies to C programming on GNU/Linux. There is no official, hassle-free way to generate a statically-compiled binary with C for GNU/Linux. A C program compiled on Deb 12 might not work on 11, if it requests a new version of some function, or a new function. Go and Rust can, but they are silos. Glibc dropped support for static linking years ago. You can't deploy a new library to close a library security hole, for programs that have statically linked it. Rust and Go are doing a stupid thing.
- yakubin 3y ago> You can't deploy a new library to close a library security hole, for programs that have statically linked it. Of course you can. You just recompile affected programs. Just like you need to do in the case of header-only C/C++ libraries like much of widely-used Boost. And if the library is not strictly header-only, but still has significant code in headers, as is often the case in C++, if you only swap the dynamic library, the program is still broken, or much more likely: it becomes broken, even though it originally wasn’t.
- kazinator 3y agoPrograms on GNU/Linux linked against glibc can be proprietary.