| ▲ | bschwindHN 3 days ago |
| Rust with Clap solved this forever ago. Also - don't write CLI programs in languages that don't compile to native binaries. I don't want to have to drag around your runtime just to execute a command line tool. |
|
| ▲ | MathMonkeyMan 3 days ago | parent | next [-] |
| Almost every command line tool has runtime dependencies that must be installed on your system. $ ldd /usr/bin/rg
linux-vdso.so.1 (0x00007fff45dd7000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x000070764e7b1000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x000070764e6ca000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x000070764de00000)
/lib64/ld-linux-x86-64.so.2 (0x000070764e7e6000)
The worst is compiling a C program with a compiler that uses a more recent libc than is installed on the installation host. |
| |
| ▲ | craftkiller 3 days ago | parent | next [-] | | Don't let your dreams be dreams $ wget 'https://github.com/BurntSushi/ripgrep/releases/download/14.1.1/ripgrep-14.1.1-x86_64-unknown-linux-musl.tar.gz'
$ tar -xvf 'ripgrep-14.1.1-x86_64-unknown-linux-musl.tar.gz'
$ ldd ripgrep-14.1.1-x86_64-unknown-linux-musl/rg
ldd (0x7f1dcb927000)
$ file ripgrep-14.1.1-x86_64-unknown-linux-musl/rg
ripgrep-14.1.1-x86_64-unknown-linux-musl/rg: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), static-pie linked, stripped
| | |
| ▲ | 3836293648 3 days ago | parent [-] | | Which only works on linux. No other OS allows static binaries, you always need to link to libc for syscalls. | | |
| ▲ | craftkiller 3 days ago | parent | next [-] | | Also works on FreeBSD. FreeBSD maintains ABI compatibility within each major version (so 14.0 is compatible with 14.1, 14.2, and 14.3 but not 15.0): You also can install compatibility packages that make binaries compiled for older major versions run on newer major versions. $ pkg install git rust
$ git clone https://github.com/BurntSushi/ripgrep.git
$ cd ripgrep
$ RUSTFLAGS='-C target-feature=+crt-static' cargo build --release
$ ldd target/release/rg
ldd: target/release/rg: not a dynamic ELF executable
$ file target/release/rg
target/release/rg: ELF 64-bit LSB executable, x86-64, version 1 (FreeBSD), statically linked, for FreeBSD 14.3, FreeBSD-style, with debug_info, not stripped
| |
| ▲ | exe34 3 days ago | parent | prev [-] | | try cosmopolitan! | | |
| ▲ | 3836293648 2 days ago | parent [-] | | Cosmopolitan isn't statically linked, it's just a hack that works on all systems, dynamically linking on windows and macos (I think with a statically linked custom dynamic linker?) |
|
|
| |
| ▲ | Sharlin 3 days ago | parent | prev | next [-] | | Sure, but Rust specifically uses static linking for everything but the very basics (ie. libc) in order to avoid the DLL hell. | |
| ▲ | bschwindHN 3 days ago | parent | prev | next [-] | | Yes but I've never had a native tool fail on a missing libc. I've had several Python tools and JS tools fail on missing the right version of their interpreter. Even on the right interpreter version Python tools frequently shit the bed because they're so fragile. | | |
| ▲ | mjevans 3 days ago | parent [-] | | I have. During system upgrades, usually along unsupported paths. If you're ever living dangerously, bring along busybox-static. It might not be the best, but you'll thank yourself later. |
| |
| ▲ | sestep 3 days ago | parent | prev | next [-] | | I statically link all my Linux CLI tools against musl for this reason. Or use Nix. | |
| ▲ | 3 days ago | parent | prev | next [-] | | [deleted] | |
| ▲ | dboon 3 days ago | parent | prev | next [-] | | That’s the first rule anyone writing portable binaries learns. Compile against an old libc, and stuff tends to just work. | | |
| ▲ | delta_p_delta_x 3 days ago | parent [-] | | > Compile against an old libc This clause is abstracting away a ton of work. If you want to compile the latest LLVM and get 'portable C++26', you need to bootstrap everything, including CMake from that old-hat libc on some ancient distro like CentOS 6 or Ubuntu 12.04. I've said it before, I'll say it again: the Linux kernel may maintain ABI compatibility, but the fact that GNU libc breaks it anyway makes it a moot point. It is a pain to target older Linux with a newer distro, which is by far the most common development use case. | | |
| ▲ | dboon 3 days ago | parent [-] | | Definitely, and I know this sounds like ignoring the problem, but in my experience the best solution is to just not use the bleeding edge. Write your code such that you can load it onto (for example) the oldest supported Ubuntu and compile cleanly and you’ll have virtually zero problems. Again, I know that if your goal is to truly ship something written in e.g. C++26 portably then it’s a huge pain. But as someone who writes plain C and very much enjoys it, I think it’s better to skip this class of problem. | | |
| ▲ | delta_p_delta_x 3 days ago | parent [-] | | > I think it’s better to skip this class of problem. I'll keep my templates, smart pointers, concepts, RAII, and now reflection, thanks. C and its macros are good for compile times but nothing much else. Programming in C feels like banging rocks together. | | |
| ▲ | dboon 2 days ago | parent [-] | | Agree to disagree, then! Templates, smart pointers, and RAII have cost me far, far more than they’ve paid me back. You should write whatever feels good to you. | | |
| ▲ | delta_p_delta_x 2 days ago | parent [-] | | Happy to. If I may, I have an analogy: C feels a little like survival mode in Minecraft; you have a set of very simple abstractions, a relatively simple language, with which one can build the world (and in many cases, we have). C++ feels like a complex city builder, with lots of tools, designs, and paradigms available, but also allows one to screw up in bigger ways. |
|
|
|
|
| |
| ▲ | 1718627440 3 days ago | parent | prev [-] | | > The worst is compiling a C program with a compiler that uses a more recent libc than is installed on the installation host. This is only a problem, when the program USES a symbol that was only introduced in the newer libc. In other words, when the program made a choice to deliberately need that newer symbol. |
|
|
| ▲ | majorbugger 3 days ago | parent | prev | next [-] |
| I will keep writing my CLI programs in the languages I want, thanks. Have it crossed your mind that these programs might be for yourself or for internal consumption? When you know runtime will be installed anyway? |
| |
| ▲ | dcminter 3 days ago | parent | next [-] | | You do you, obviously, but "now let npm work its wicked way" is an offputting step for some of us when narrowing down which tool to use. My most comfortable tool is Java, but I'm not going to persuade most of the HN crowd to install a JVM unless the software I'm offering is unbearably compelling. Internal to work? Yeah, Java's going to be an easy sell. I don't think OP necessarily meant it as a political statement. | | |
| ▲ | goku12 3 days ago | parent | next [-] | | There should be some way to define the CLI argument format and its constraints in some sort of DSL that can be compiled into the target language before the final compilation of the application. This way, it can be language agnostic (though I don't know why you would need this) without the need for another runtime. The same interface specification should be able to represent a customizable help/usage message with sane defaults, generate dynamic tab completions code for multiple shells, generate code for good quality customizable error messages in case of CLI argument errors and generate a neatly formatted man page with provisions for additional content, etc. In fact, I think something like this already exists. I just can't recollect the project. | | | |
| ▲ | vvillena 3 days ago | parent | prev | next [-] | | This is not an issue with Java and the other JVM languages, it's simple to use GraalVM and package a static binary. | |
| ▲ | lazide 3 days ago | parent | prev [-] | | most java CLIs (well, non shitty ones), and most distributed java programs in general, package their own jvms in a hermetic environment. it’s just saner. |
| |
| ▲ | bschwindHN 3 days ago | parent | prev [-] | | That's fine, I'll be avoiding using them :) | | |
| ▲ | perching_aix 3 days ago | parent [-] | | You'll avoid using his personal tooling he doesn't share, and his internal tooling he shares where you don't work? Are you stuck in write-only mode or something? How does this make any sense to you? |
|
|
|
| ▲ | rs186 3 days ago | parent | prev | next [-] |
| Apparently that ship has sailed. Claude Code and Gemini CLI requires
Node.js installation, and Gemini README reads as if npm is a tool that everybody knows and has already installed. https://www.anthropic.com/claude-code https://github.com/google-gemini/gemini-cli |
| |
| ▲ | dboon 3 days ago | parent | next [-] | | Opencode is a great model agnostic alternative which does not require a separate runtime | | |
| ▲ | yunohn 3 days ago | parent [-] | | Opencode uses TS and Golang, it definitely needs a runtime for the TS part. CPU usage hovers around 100% for me on an MBP M3 Max. | | |
| ▲ | dboon 2 days ago | parent [-] | | I meant that it’s bundled with the binary such that you don’t need to make sure some random version of eg Node is available |
|
| |
| ▲ | Sharlin 3 days ago | parent | prev [-] | | That's terrible, but at the very least there's the tiny justification that those are web API clients rather than standalone/local tools. |
|
|
| ▲ | jampekka 3 days ago | parent | prev | next [-] |
| > Also - don't write CLI programs in languages that don't compile to native binaries. I don't want to have to drag around your runtime just to execute a command line tool. And don't write programs with languages that depend on CMake and random tarballs to build and/or shared libraries to run. I usually have a lot less issues with dragging a runtime than fighting with builds. |
|
| ▲ | perching_aix 3 days ago | parent | prev | next [-] |
| Like shell scripts? Cause I mean, I agree, I think this world would be a better place if starting tomorrow shell scripts were no longer a thing. Just probably not what you meant. |
| |
| ▲ | ycombobreaker 3 days ago | parent | next [-] | | Shell scripts are a byproduct of the shell existing. Generations of programmers have cut their teeth in CLI environments. Anything that made shell scripts "no longer a thing" would necessarily destroy the interactive environment, and sounds like a ladder-pull to the curiosity of future generations. | |
| ▲ | bschwindHN 3 days ago | parent | prev [-] | | > I think this world would be a better place if starting tomorrow shell scripts were no longer a thing. Pretty much agreed - once any sort of complicated logic enters a shell script it's probably better off written in C/Rust/Go or something akin to that. |
|
|
| ▲ | ndsipa_pomu 3 days ago | parent | prev | next [-] |
| > don't write CLI programs in languages that don't compile to native binaries. I don't want to have to drag around your runtime just to execute a command line tool. Well that's confused me. I write a lot of scripts in BASH specifically to make it easy to move them to different architectures etc. and not require a custom runtime. Interpreted scripts also have the advantage that they're human readable/editable. |
|
| ▲ | dcminter 3 days ago | parent | prev | next [-] |
| The declarative form of clap is not quite as well documented as the programmatic approach (but it's not too bad to figure out usually). One of the things I love about clap is that you can configure it to automatically spit out --help info, and you can even get it to generate shell autocompletions for you! I think there are some other libraries that are challenging it now (fewer dependencies or something?) but clap sets the standard to beat. |
|
| ▲ | LtWorf 3 days ago | parent | prev | next [-] |
| > Also - don't write CLI programs in languages that don't compile to native binaries. I don't want to have to drag around your runtime just to execute a command line tool. Go programs compile to native executables, they're still rather slow to start, especially if you just want to do --help |
|
| ▲ | geon 3 days ago | parent | prev [-] |
| This seems like a really weird stance. Who are you to dictate what language people should use? Why CLIs in particular? |
| |
| ▲ | bschwindHN 2 days ago | parent [-] | | I'm just making an opinionated suggestion for the case when you're shipping a tool to end users and you don't want the tool to suck. Attaching a python or nodejs runtime to your tool is a quick way to make it suck for end users. It's laziness on the dev's part who didn't bother learning a better tool for the job. |
|