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.
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.
Not everyone is using Linux with glibc linking issues.
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.
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.
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.
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).
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.
Yeah, but for non-embedded deployments i.e. 99% of Java code out there?
> Still, Python and Perl bundlers exist since around 2000 as well.
I don't know the Perl one, but the Python ones definitely aren't mainstream. They're finicky and relatively hard to use and definitely not distributed with the Python distribution, which would make them ubiquitous and well supported.
> 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.
Every language in the olden days had static compilation support :-))
That's why we had articles such as these: https://www.joelonsoftware.com/2004/01/28/please-sir-may-i-h... (which I agree with)
100% of commercial JDKs have support for AOT compilation, what you are getting nowadays on OpenJDK is the free beer version of it.
> I don't know the Perl one, but the Python ones definitely aren't mainstream.
They surely were mainstream on Windows back in .com days, specially via py2exe and ActiveState tooling.
> Every language in the olden days had static compilation support :-))
Many of which are still mainstream languages.
It was (is?): PHP, Javascript, Java, Python, Ruby, C# or nothing.
Especially the dynamic languages are extremely popular, primarily with smaller companies and startups.
Zope and AOL Server teached me that those dynamic languages are really only good for OS scripting tasks anyway, but that isn't the subject of this thread.
For many developers, maybe the majority, those languages are their objective reality. They haven't used anything else, they might not ever use anything else.
So things which extend the range of their tools are very much appreciated.
They're not going to shun their existing programming languages because other people don't like them and they're not going to switch to OCaml or to commercial Java compilers, either ;-)
[0] https://nts.strzibny.name/making-a-ruby-executable-with-ruby...
With internet speeds of today and immense storage sizes, the main attractiveness of dynamic linking vanished.
And given that shared libraries need to be installed and updated separately and they have to ship the entire code of the library (whereas a static binary can be link-time-optimized to get rid of unused code) it might not always be a win in terms of total bandwidth.
- Languages like Rust which have an ecosystem that evolves very quickly (and uses complex symbol mangling schemes that would break all the time) wouldn't fare very well with dynamic linking in the first place. What good is dynamic linking if you need a different version of your .so file for every binary?
- Dynamic linking is not quite as useful today a it was in the past. Code size is not usually very significant, either on cold storage or in RAM. Actually for RAM it's cache usage that matters most, and static linking can usually be more efficient here through LTO.
- Over the past ~2 decades a new generation of developer arrived and many of them (in my experience) barely use "low level" compile-to-machine-code languages. They often specialize in scripting languages or languages that require a framework. Some of these developers are now learning Go or Rust and for them the idea of shipping a single ELF binary that packages the entire app might be seen as a novelty or maybe even as an innovation.
Linux distributions need to be able to backport security fixes to shared libraries, test them and deliver updates to all users quickly.
With static linking it becomes practically impossible.
It's a little more complicated, but modern Node development is a huge step forward to the old days of sadly attempting to get the LINPACK header configuration correct in your C project.
Sure but most web apps are more than a single binary. There's generating static files, a database, background worker / cache, and more. Then there's wanting to be able to develop that project as a whole on Windows, macOS and various Linux distros as well as deploying it to a specific distro of Linux (most likely). Then there's the distribution of the binary across a network in a reasonable way.
Docker and its ecosystem of tools solves all of those problems once your app is containerized. And if you want to go 1 step further and run a distributed system with load balancers and friends, container orchestration tools let you solve this problem at a level above your application.
And the best part is you can do all of that in the same way with any tech stack.
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.
What’s old is new is old again!
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.
Except the single bundle trimmed off unused part from the standard runtime
Size was not really a goal for the first pass of the feature.
But I honestly don't mind up until about 100MB.
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.