7 ms·
This is such a good feature. Go has been great for shipping single purpose binaries (like the CLI for https://fly.io https://fly.io), but I really enjoy writing
by mrkurt 6y ago
This is such a good feature. Go has been great for shipping single purpose binaries (like the CLI for https://fly.io https://fly.io), but I really enjoy writing TypeScript more than Go.
- echelon 6y agoA lot of languages are doing single static binary deploys now. Rust, Nim, Go. It's a really nice pattern. Static binaries are so much easier that the gross PHP / Ruby / Python pattern that has to ship directories full of files that (usually) have to be put in the correct place. It's also easier than shipping a runtime like a JVM. With a single binary, containers get even slimmer.
- qeternity 6y ago> With a single binary, containers get even slimmer. Not really. I agree on the other benefits of binaries but our containers usually only have the final layer change (the source code). This means that all the lower layers, python base image, requirements, etc are cached. So we can ship 100 times and add maybe 100mb of new container overhead. Binaries will ship 100% every time.
- loosescrews 6y agoDo they? As far as I know, Go is the only mainstream language that supports static binaries with normal non-trivial programs. Rust for example depends on dynamically linked libc if you use the standard library. While you technically can statically link libc, it is unsafe with glibc.
- mrkurt 6y agoRust and Deno qualify as a "single executable" for what I need, but you're basically correct. It's not quite as dependency free as a Go binary.
- pjmlp 6y agoAda, FreePascal, C and C++ do perfectly fine. Not everyone is using Linux with glibc linking issues.
- loosescrews 6y agoUsing C and C++ without libc excludes the use of nearly all common libraries.
- lucacasonato 6y agoWe currently do dynamically link to glibc. But we could in theory support musl, which would remove our dependance on the glibc dynamic link.
- lock-free 6y agoThat's why you statically link musl C
- kibwen 6y agoI think the belief that Go does no dynamic linking whatsoever is outdated; I seem to recall that they recanted this approach on Mac and Windows since these platforms only offer a stable system interface via dynamically-linked libraries, and trying to re-implement all of it ended up being a lot of work only to end up with broken code after system updates. On Linux I think Go still tries to link mostly statically, but if you use parts of the stdlib (e.g. `net`) you'll still end up dynamically linking to libc unless you instruct it otherwise. If anyone more knowledgeable could speak up I'd welcome it.
- sim_card_map 6y agoThis is correct.
- loosescrews 6y agoGo supports dynamic linking and most Go binaries will be dynamically linked. On Linux, this is mostly due to optional features which can be easily disabled. The optional features are all related to supporting rare and unusual system configurations and do not affect normal operation. Note that cross compilation with Linux as the target does not support dynamic linking, so all Go Linux binaries compiled on a non-Linux OS will be statically linked. Regardless of how we scope it, Go is still the only mainstream language capable of producing statically linked Linux binaries without libc while still allowing full use of the standard library.
- pjmlp 6y agoC with musl does just fine.
- hetman 6y agoRust has supported statically linking to MSVC and musl for a while now but also added static glibc support on Linux very recently: https://github.com/rust-lang/rust/pull/77386 https://github.com/rust-lang/rust/pull/77386
- loosescrews 6y agoIs it possible to compile with statically linked musl with the pre-built Rust toolchain on a standard glibc based distribution?
- SomaticPirate 6y agoYes, but there are claims it is slower https://www.reddit.com/r/rust/comments/a6pna3/comment/ebzpzld https://www.reddit.com/r/rust/comments/a6pna3/comment/ebzpzl...
- saagarjha 6y agomusl is generally not optimized for performance.
- mkj 6y agoYes, it works well. The main caveat I've found is you need the rustls feature of packages rather than openssl. Though perhaps that was more related to cross compiling for Arm.
- tryptophan 6y agoYeah, its especially horrible in python for webdev. How are you supposed to deploy django/flask projects when NOT using docker or some PassS? I haven't figured out anything better than a git pull script to update things. I can't imagine there is nothing better in 2020.
- dglass 6y agoPrior to docker some common patterns were to rsync the files up to each server, or compress the files to .tar or .zip on a build server, rsync it to the servers and then uncompress into your desired directory.
- marcopolo 6y agoYou may be interested in Nix. It can track all the dependencies of your project. So you d an copy them to a server, or Tarball them, or just run them with Nix on the server. It also has a nice property that you only ship what is necessary, since it keeps track of all dependencies.
- ric2b 6y agoPip freeze?
- Hokusai 6y ago> A lot of languages are doing single static binary deploys now As a developer for more than 30 years, I find that statement quite interesting. When I was a kid I was very happy to find a way to compile Basic to an executable like I was doing in Pascal and C++. For me is the standard way of thinking about applications. Is it a common experience to actually have to ship many files for one application? I thought that it was just common for the web as it fits how HTML evolved not for anything else.
- dljsjr 6y agoIn the case of the above listed languages, it's not just that the application is compiled to a single executable, it's that they're statically linked/truly self-contained. The only thing they dynamically link against is the OS's standard library. So there's no "DLL hell" either.
- pjmlp 6y agoSame here, the static linking hype feels real strange, given that was the only option we used to have back in the day, and having access to dynamic linking on 16 bit platforms felt like liberating.
- oblio 6y agoPHP, JavaScript, Python, Ruby, even Java and C# didn't (don't?) have a mainstream way to create a single binary with unused code and unused dependencies removed. Dynamic linking was cool because you could use system dependencies which people don't want to use because you can't rely on them, especially for cross platform apps and also for efficiency, RAM (which people stopped caring about) and, disk space (this boat sailed a loong time ago) and compilation (we have 10000x as powerful computers now).
- pjmlp 6y agoJava has had static linking support since around 2000, for embedded deployments. C#, yes it has been mostly dynamic. PHP, JavaScript, Python, Ruby, don't count, they are scripting languages, bundled with an interpreter. Still, Python and Perl bundlers exist since around 2000 as well. Compiled languages like Basic, Pascal, Modula-2, Ada, Eiffel, Modula-3, C, C++, Haskell, OCaml, SML, .... all started in days where static linking was the main option.
- axaxs 6y agoPython has had packagers for many years...cxfreeze, pyinstaller, and others. I hear Nuitka works well. Just pointing out the fact, not disputing your statement. I also wish it was more of a first class citizen.
- stevetodd 6y ago> It's also easier than shipping a runtime like a JVM. jlink has shipped since JDK 9 and can package all dependencies and the JRE into a single file. Hello world clocks in at about 22 MB.
- momokoko 6y agoIt’s funny you say that because when PHP / Python / Ruby were all the rage, most people considered needing to compile everything into a single binary gross. What’s old is new is old again!
- Cthulhu_ 6y agoIt's a circular argument and a false dichotomy tbh, they both have their place. Ex: I maintain an 'old' PHP / JS application while building a new Go / TS one. With the old one, I change a file, it gets automatically ssh'd to my dev server, and my changes work instantly. I'm sure that if the PHP and JS had to be comp/transpiled, it would take a minute or so (it's just under 100K LOC, some files 13K LOC). For the new application, I get the same fast feedback because Go does incremental compiles and create-react-app with TS also does incremental compiles with live reload (without requiring a full page reload). For production builds, the old is pulled through tools like ioncube and uglify, the new one churns out an optimized binary and webpack-flavored .js files. I mean if you zoom out enough there's no noticeable difference.
- zeroc8 6y agoBecause compilers - apart from Pascal dialects - were quite slow. With Go, you aren't wasting time waiting for the compiler. So it feels like a script language, but gives you that extra security of a compiler.
- aabbcc1241 6y agoThe single binary still have to embed the runtime somehow. So the container size would be similar? Except the single bundle trimmed off unused part from the standard runtime
- Siilwyn 6y agoDefinitely, I do wonder how it compares in binary size. Especially the 'baseline' size of a hello world.
- andyfleming 6y agoThe files are big now. ~30 MB. Size was not really a goal for the first pass of the feature.
- javajosh 6y agoThe link shows its 48MB for a trivial program (I assume its trivial - its called "cat")
- mrkurt 6y agoSeems like it's big, our Go CLI clocks in about 30MB on Linux. Deno with hello world is like 32MB. But I honestly don't mind up until about 100MB.
- lucacasonato 6y agoCurrently binary size is a bit larger than the `deno` cli. We are currently working on reducing size for these `deno compile` binaries though. From preliminary testing we think we can reduce size by around 60% - maybe even more.
- bartlomieju 6y agoCurrently it's 30-45Mb depending on the OS. We're working on providing a "lite" version of the runtime, that doesn't include tools like formatter or linter. Preliminary works show that we should be able to trim executables down to about 20Mb.