Rendered at 16:55:13 GMT+0000 (Coordinated Universal Time) with Cloudflare Workers.
chabska 13 hours ago [-]
Zig, Go, and Python developers do this thing, where they announce that "We have removed the radiator fluid from the fuel tank", and all their supporters cheer about how this is good for the language, how performance will surely improve significantly, and I'm over here wondering why did they put the radiator fluid in the fuel tank in the first place.
MomsAVoxell 9 hours ago [-]
Individual developer convenience takes priority early in projects like this, in lieu of actually thinking about the consequences of the design. It was convenient to have package management in the compiler, it meant the developers didn’t have to think about things outside their own scope - but as the language and its tooling gets wider adoption these personally-beneficial features become liabilities to adoption.
It happens in many projects .. devs will just ‘do something convenient so they dont have to do the work to do it properly’ and then that just becomes the convention, because nobody else wants to do hard work to do things properly, either.
chabska 3 hours ago [-]
I can accept this for a hobby project language that unexpectedly blew up in popularity. Go is not that language. Zig's developer also had grandiose plans for his project language, based on his writings, so I had expected more care put into its design.
uecker 7 hours ago [-]
Fair, but with all the new C-alternative languages I also see a lot of Chesterton's Fences being teared down. In part, this is also perfectly fine for experimentation, but sometimes it leaves me wondering as well.
MomsAVoxell 7 hours ago [-]
Software is a social activity, therefore it follows social mechanics, organically. As time goes by, all these fences will need to be maintained or removed.
uecker 6 hours ago [-]
It is exactly because software is a social activity that one should try to understand the purpose of a design before changing it.
NonHyloMorph 3 hours ago [-]
Well then go ahead and dig for that understanding :) From hearing interviews with some of the zig developers it's imho pretty clear, how deeply involved they are with their work.
portly 11 hours ago [-]
Sounds like you've never built something. Even with small products you have to keep correcting yourself as it's hard to foresee how each component interacts.
Now try building a self-hosted C replacement lol
chabska 3 hours ago [-]
Programming language development have been happening for 60 years. We have tonnes of prior art, we have a rich history of experimentations. If you're a language developer that doesn't study the history, and keep making the same mistakes that other people know to avoid, I don't respect your product.
Rust language mistakes are understandable, because they do a lot of novel stuff so they encounter situations that no one have seen before. For the three languages that I mentioned, their mistakes are fairly well-known errors with obvious consequences. How hard was it to foresee that lacking generic in Go is a mistake, when the language was created well after Java had generics?
Twey 47 minutes ago [-]
Ironically Rust (hence the name) was originally billed as the language that did nothing novel at all, but just productized a bunch of concepts that were already well understood in the PL field :)
I think that a programming language — much less a programming language _ecosystem_ — is such a large space of decisions that statistically you're inevitably going to let a few of them slip. And even (as in Rust's case, initially) if you don't aim to do anything new, the combination of the interactions between features and the ways people want to use your language culturally can land you places you never anticipated when doing the initial language design. I don't think anybody in the early years of Rust could have anticipated how async would look today, for example, and IIRC Graydon Hoare still doesn't like where it ended up.
Then, there's the old software adage that the right decision for one level of adoption doesn't necessarily translate to another level. Because it's so hard to predict the impact of early decisions, early versions of programming languages are basically prototypes: your aim is to get out enough of the core differentiators of the language that people can start playing with it and _imagining_ what it will be like to work with the final thing. Part of that involves making the barrier to entry as small as possible (e.g. bundling a full build system into the precompiled compiler executable) but it also implies that you don't want to spend more time than necessary on things that work the same as other languages. If you can see the ‘obvious omission’ in the language then that means you can already imagine how it will work when that thing is implemented! As an implementor you can always flesh it out as you approach 1.0, or, if the right thing to do is so obvious and you have an enthusiastic open-source community, you can just wait for the community to build it for you.
Go's generics case is a bit different, I think. I don't claim to be an expert here (I haven't followed Go development much) but as far as I understand it the omission of generics from Go was a deliberate ideological choice: they hoped to get by with the absolute minimum of generic functionality, and the experiment was how little they could get away with and still have it adopted. (Unfortunately, I think the experiments Go was trying to run were stymied by Google and Kubernetes throwing their weight behind it, which led to a pattern of adoption that had little to do with the language design itself: we may never know what would have become of it if it had been left to stand on its own.)
portly 3 hours ago [-]
Not being sarcastic but genuine because I do not know: are there any previous languages that have a build system like Zig?
I found really cool that you have a bunch of options to configure compilation of source code itself. Not just the compiler optimization but you can automate all kinds of things: https://ziglang.org/learn/build-system/#build-system
pjmlp 10 hours ago [-]
Creating a C compiler is basically the assignment on plenty of CS degrees around the globe.
Plenty people do it every year, naturally nothing to compare to GCC/clang.
xydone 9 hours ago [-]
C compiler != C replacement
pjmlp 8 hours ago [-]
C23 is a replacement for C17,...
lifthrasiir 9 hours ago [-]
Creating a part of C compiler, most frequently a working optimization pass, is a regular assignment. The entirety of C compiler is too large to give it as a student assignment.
pjmlp 8 hours ago [-]
Depends which ISO C version, C89 is quite doable, and clever students might dust off a copy of "A Retargetable C Compiler:
Design and Implementation" or "Compiler Design in C" as starting point.
lifthrasiir 5 hours ago [-]
Clever students can do anything without steering anyway ;-) Typical, I mean median, students would rather struggle to learn C.
pjmlp 5 hours ago [-]
Back on my day, high school students would learn C on introduction to programming classes, while 10 year olds were able to write Z80 or 6502 Assembly and some of them would go on to create the games industry we have today.
I guess education system went downhill since then, which I guess it is kind of true, given the poliferation of header only libraries, as if C was a scripting language.
rootlocus 10 hours ago [-]
This is exactly how I feel about performance. Unrelated to any programming language, including my own optimizations. The higher the speedup the more we cheer, however most optimizations aren't clever techniques. They're just someone using a profiler to find "huh, radiator fluid shouldn't go in the fuel tank".
Most performance bottlenecks aren't inherent limitations of the hardware or the problem. There's some minimum amount of effort required to get the result, but that's never the reason why the application doesn't perform well. It's always the cruft we add on top.
rmunn 11 hours ago [-]
Which part of Zig development (I'm not asking about Go or Python right now) do you consider to be radiator fluid in the fuel tank, in this analogy of yours?
simonask 10 hours ago [-]
I think it's pretty obvious they are referring to package management functionality as the radiator fluid in this analogy, and the compiler is the fuel tank.
chabska 3 hours ago [-]
You don't think having a package management system in the compiler is weird?
goranmoomin 13 hours ago [-]
So this is the change that forced Zig to remove @cImport (and into the build system), right?
I know that it’s purely a UX concern, and that the changes (to decouple the build system and the compiler) are pretty critical for the maintainers, but it’s still a bit sad that development sanity comes first than the UX. (It’s the right call, just that it’s sad.) @cImport was a big killing feature imho to the language…
csande17 11 hours ago [-]
Not really? This change is about the code for downloading and extracting third-party packages. The @cImport change was part of an effort to (eventually) make Zig's dependency on LLVM/libclang optional, so that it could (eventually) be put into a third-party package, but it doesn't seem directly related.
beepbooptheory 5 hours ago [-]
Yes. @cImport was removed last major version (0.16.0) so I dont think it has much to do with what tfa is talking about.
nesarkvechnep 21 hours ago [-]
Development of Zig feels so wholesome.
SwellJoe 20 hours ago [-]
The thing about Zig in these times is that it proves that software development as a craft is not dead or replaced by LLMs.
Even though I use LLMs every day, and have to admit they're remarkably good at many classes of problem, I don't want a programming language built by an LLM. Every line of code in a programming language, every decision, every trade off, matters. A vibe-designed/vibe-coded programming language would be a disaster. I don't know how else to put it, and I've never seen any model produce code that would convince me otherwise (even Fable, which is, in fact, a notable improvement over the prior best models). The models don't want anything. They don't have meaningful opinions. They don't know what comfortable vs. uncomfortable feels like in a language (or in a GUI or CLI interface at sufficient levels of complexity).
You can't get a language like Zig out of an LLM without simply copying Zig, and even then it would be a copy that is worse. (I mean, I'm assuming "copy with an LLM" means, "have an LLM write the spec and another build the language to the spec", not literally `cp` the source tree.)
Quothling 9 hours ago [-]
> The thing about Zig in these times is that it proves that software development as a craft is not dead or replaced by LLMs.
We've heavily adopted LLM's, to the point where I'll often not touch any code and have a better and more maintainable codebase than if it had been written by any of our developers (myself included). I'm not sure it would be possible if our philosophy wasn't explicity, no abstractions and defensive programming, but when every function is it's own thing with runtime assertions and ways of dealing with corrupt states as soon as they happen. Well... the LLM can do that when you can.
That being said. I think it's not new that you can write computer software without computer science, until you can't. Where I see the challenge with LLM's and software development as a business is that a lot of software developers work(ed) that can be automated because they don't actually require computer science as such. Having setup company wide "apps" for Microsoft's cowork, I think any sort of semi-expert level office job is going to be in danger. I'm not a huge fan, and I was never hyped on AI but it's ridilous what you can do in the enterprise office space (and how easy it is) when you're married with Microsoft.
jamiejquinn 5 hours ago [-]
This is an interesting approach. When you say no abstractions though, what do you actually mean? I would count functions as abstractions but do you mean classes/structs representing an object? Effectively no new types?
ashikns 12 hours ago [-]
> They don't know what comfortable vs. uncomfortable feels like in a language
This is mostly about human preferences right. If software is just taken as the end product, does it matter what "feels" good and doesn't?
boomlinde 8 hours ago [-]
Writing the compiler and standard library in Zig is probably the greatest dog fooding opportunity for the Zig maintainers. In doing so they get to feel the weight of every change they make to the language, for as long as they don't simply hand that task over to a chatbot.
It's also an open source project, so the end product is as much the codebase as it is the binary releases.
I've interacted enough with largely computer generated codebases to see that ergonomics problems easily grow and accumulate when LLMs remove the burden of dealing with those problems from the developer. I've always considered my laziness an asset. Now I would qualify that by saying that laziness is an asset for as long as it compels you to keep things simple and easily understandable so that the cost of making changes (whether that's measured in human gray hairs or tokens) doesn't grow with every change.
RossBencina 11 hours ago [-]
I agree that it depends on whether you want humans to interact/interpret the software at all, but I'd push back on "mostly human preferences." Do you think that how something feels is mostly a matter of human preference? Intuition and aesthetic sensibility are distinct from preference, and both play a role in research mathematics and scientific discovery as well as in art. There is also (human) cognitive affordance which I think is important for human code review. That said, I'm sure there is a language and coding style that optimises for both human and machine processing that is much better than what we have today.
ChrisGreenHeur 20 hours ago [-]
Sure a human would write the language spec and the llm implement it
SwellJoe 18 hours ago [-]
I think this makes two incorrect assumptions:
1. That a human, even a brilliant human with a lot of experience, can sit down and one-shot a language spec for a new language that is actually good.
2. That an agent can produce code that is good enough for a programming language that intends to last for decades without exhaustive human review.
We might advance to the point where 2 is true, we're not there yet. We'll never make a better human that can one-shot a good programming language. It takes iteration, with a human in the loop. Zig has taken ten years to get to this point, and is still occasionally experiencing major refactors.
If you want to argue an LLM could potentially accelerate development by some amount, I would agree with you. How much it could accelerate it is debatable. And, I understand why the Zig folks have decided not to accelerate in that way. There is a cost to it. You lose the junior programmer pipeline, as your "good first bug" list gets chewed up by people using LLMs. You still have to exhaustively review the code for a critical path like a compiler and AI code is hard to review; it doesn't have a point to it. The model doesn't want anything, so it's not always clear where it's going. Code without clear intention, like prose without clear intention, is hard to read and hard to review. It's verbose and often makes weird assumptions.
If I, for some reason, needed to implement a tiny DSL for something, I would 100% do it with an LLM. If I, for some reason, were tasked with building the best programming language to replace C, I would not hand it to an LLM (though I would get help from an LLM, because I don't know how to build a programming language beyond the tiniest toy interpreter or compiler, I'd need to read and understand every line of code, and use it daily, for it to turn out good).
hansvm 18 hours ago [-]
For complicated problems, you can't just write the language spec. You need to iteratively develop it, which itself requires some intermediate state/language describing what you know so far. That intermediate state being the end programming language in consideration isn't mandatory per se, but iteratively refining, replacing, and reworking solutions using code as a drafting board is very common in the industry. That's doubly true for languages, where the social pressures in how it "feels" or is actually used are paramount. If you move away from iterative coding drafts, you still need some sort of interactive product to work on to actually develop the spec.
Plus, current-gen agents/LLMs can't implement a non-trivial language spec without significant hand-holding.
linguae 14 hours ago [-]
I’ve been thinking about this over the past few days. There was an exciting keynote at PLDI 2026 by MIT professor Saman Amarasinghe where he talked about the intersection between compilers and machine learning, including LLMs. One of the works discussed during the keynote was the use of Claude Code by his colleague Martin Rinard to implement a compiler known as a credible compiler that outputs both compiled code and a proof that the output code correctly matches the input.
Such a spec would never survive contact with reality. Maybe a human could stumble their way through iterating on it with the help of an LLM, but with current models you’re going to end up with nothing but a steaming pile of garbage. Not Zig.
edoceo 21 hours ago [-]
It's kinda fun to build with too. Making a bootloader, doing some UEFI things. Much easier (for me) than when trying with C. But also, new&shiny and learning is fun - increases my bias.
vitaminCPP 20 hours ago [-]
I've read somewhere that the longer-term goal is to move the build system into a WebAssembly VM. If so, this is incredible.
jswny 20 hours ago [-]
What’s the advantage of that for building?
pdpi 13 hours ago [-]
Zig build scripts are arbitrary zig programs, so sandboxing those scripts is a Good Thing. Wasm might be overkill, but using something off-the-shelf that's specifically designed for sandboxing untrusted code is definitely the right approach.
Panzerschrek 11 hours ago [-]
I see no benefits in sandboxing such things as build systems. Sooner or later one eventually needs to execute some external code, like a shell script or cmake. And these external programs can do whatever they want. So, caring about sandboxing within a build system executable is just creating a security theater.
csande17 10 hours ago [-]
As I understand it, Zig is trying to bring in almost all the stuff that would usually be done by external tools. Zig has its own solution for finding system libraries (instead of pkg-config), it integrates its own C/C++ compiler, and you can do code generation with comptime (or, worst-case, a Zig program that can also be compiled to WebAssembly) instead of an external script. So I think there's a good chance that you'll be able to build most Zig projects entirely inside the sandbox someday.
There's still the obvious problem that if the build system emits malicious code, you'll probably run that code anyway. Personally I think this kind of sandboxing is more useful for enforcing build reproducibility rather than, like, protecting you from viruses in the build.zig file.
simonask 11 hours ago [-]
I think "build systems" is a too broad category in that argument.
Language-specific build facilities, like Cargo's build.rs and Zig's build scripts, typically have a limited scope - generating a bit of source code, discovering some linker flags, stuff like that. These scripts need to be run by LSP servers when opening the project in an editor to get basic features working, so that's a fairly risky thing.
They are also currently doing things like invoking CMake and other build systems, but you could definitely conceive of a world where that was a separate step in the build process, and that world seems pretty attractive to me.
A common pattern in Rust projects is to have a `*-sys` crate representing the C FFI bindings, and they typically also do something like invoke CMake or similar to actually build the C/C++ library underneath. But if you have a larger project that already integrates multiple build systems, this is really quite inconvenient in most cases.
Panzerschrek 10 hours ago [-]
Your proposal still contains a security hole, since it still allows executing cmake or something similar. Adding sandboxing in some parts/steps of a build system has no benefits, as soon as the system as whole has loopholes allowing bypassing such sandboxing. It's like adding more locks to the front door, when the backdoor has no locks at all.
simonask 10 hours ago [-]
Security is not, and in fact can never be, all-or-nothing. An imperfect solution is better than no solution. Developers have the reasonable expectation that opening a project in VS Code does not upload their home directory to a remote server. Performing a full build of a project is a different operation with different associated expectations.
himata4113 19 hours ago [-]
sandboxing, which feels a weird way to achieve that. Although the reason for it to begin with is because builds systems can typically access raw memory and disable artificial restrictions.
I think this is a bad move since the real fix to these attacks is a sandboxed environment rather than a single tool implementing sandboxing.
insanitybit 19 hours ago [-]
These are not mutually exclusive, and one makes the other better. "Whole process" sandboxing has always been far worse than native sandboxing because when the devs writing the software design the software to be sandboxed they can achieve far more fine grained permissions. Similarly, "whole environment" sandboxes are the absolute worst - they're the least fine grained possible.
The benefit of "whole environment" is that if you stuff everything into that environment then anything in it is confined, but it's all confined with everything stuffed in and is sort of maximally capable. You can rarely do things are significant as, say, system call filtering, because all software in the environment must continue to work and none of it was designed with that in mind.
Native sandboxing like this will likely make auditing much easier as well. If a dependency requires something like "give me the ability to execute code on the OS", now it has to ask for it and now it gets additional scrutiny.
Native sandboxing is and always will be the infinitely superior method when it's actually used. Whole process/ Environment is only what we use because of how rare native sandboxing is.
cornstalks 19 hours ago [-]
How would you do it, then? Sandboxing a project's build.zig via Wasm (and the various dependencies's build.zig files) seems like a great improvement to me and is how I would personally try to sandbox the build process.
afdbcreid 19 hours ago [-]
I don't know what build.zig commonly does, but in Rust build.rs often does things like compiling C/C++ libraries, so you can't sandbox it with WASM (contrary to proc macros, which most of the times can be compiled to WASM and there were/are efforts for that). How does Zig fare with that?
insanitybit 18 hours ago [-]
Even if they end up with a "this dependency can execute arbitrary code" it'll be a huge win because that will be an explicit grant to that dependency. You'll be able to know "which of my dependencies execute arbitrary code?" and encourage most of them not to. In rust, you can know this but it's going to be "basically all of my dependencies can do it" because somewhere they'll use a build script/ proc macro.
I don't know Zig's plan, but once you have the ability to broker privileges like this you have the ability to audit the privileges being brokered and things change forever.
audunw 15 hours ago [-]
I assume the compiler(s) do not run in WASM. Just the build script. The build script just orchestrates the compilers. So you can run any compiler that the build script is given access to, so compiling C/C++ or potentially any other language shouldn’t be an issue.
In theory, you could run the whole compiler (including C) in WASM as well but I don’t think that’s the goal? You kinda need to trust the compiler itself.
afdbcreid 7 hours ago [-]
If the build script can execute arbitrary processes, the entire security is lost.
himata4113 19 hours ago [-]
Use containerized development systems: bwrap (my favorite), devcontainers.json, isolated server, anything really. You can't protect yourself against malicious vscode extensions with a zig build system sandbox.
hansvm 18 hours ago [-]
It makes more sense when you view sandboxing as enabling project correctness in the presence of skilled, fallible maintainers rather than preventing explicit attacks. Solutions for the former do a lot to thwart attacks from the latter, but attack prevention (especially with the form of "just another sandbox") is unlikely to help with the former.
skybrian 16 hours ago [-]
Not a lot if you're going to run the code anyway.
But when looking at open source code you don't trust yet, you might want to build code, without running it, so your development tools will work.
reinitctxoffset 15 hours ago [-]
I just got so fed up with Starlark trying to do a nontrivial RBE prelude that's fairly different than Meta's.
I added WASM/WASI bindings and wrote the prelude in Haskell.
Both the bindings and the prelude took less time than I already wasted on multiple attempts in Starlark that all collapsed into string goop.
It's nice to be able to bound the execution environment in a build tool but still use a serious programming language.
Given Zig has excellent support for targeting WASM, seems you'd get the same advantages.
hoppp 18 hours ago [-]
Good for zig. I am very tempted to switch from go to zig but also enjoying things from the sidelines.
allthetime 11 hours ago [-]
You can (and perhaps should) use both, depending on your use cases.
malkia 20 hours ago [-]
Everytime I see a language creating their own package system, all I can think of it how much we've missed here.
The only exception is C/C++, where there is none established that well, for good or bad.
These choices may create later super-convoluted processes when you have to mix more than one language together.
Packaging systems makes thing easy, but complicate further the line if another language needs to be used.
afdbcreid 19 hours ago [-]
What do you think we've missed? Do you want one build systems for all languages? There are such systems (e.g. Bazel) and they're often used for multi-languages projects, but I think reality has proven that build systems with language-specific knowledge are much easier to navigate.
__float 16 hours ago [-]
I'm not sure how outlandish we're allowed to get here, but IMO we have a fundamental mismatch between application <> operating system <> CPU in terms of dependencies and trust.
Fixing this is beyond any one tool, of course :)
Panzerschrek 11 hours ago [-]
I think it's actually good that C++ has no standardized packaging system. This forces one to think carefully before introducing a dependency, since often such dependency have hidden costs, like security vulnerabilities. Since many critical systems are written in C++, it's too much risk to depend on dozens of easily-accessible third-party packages without properly auditing each of them.
simonask 10 hours ago [-]
I'm sorry, I have to address this take every time someone brings it up. The lack of a modern, ubiquitous, cross-platform packaging system is an absolutely terrible thing for C++.
I've worked on many large projects in C++, and every single one of them contains a bespoke, buggy, undermaintained JSON parser, URL parser, configuration file parser, async framework, and so on. It used to be the case that almost every large C++ project started out by defining its own friggin' string type.
Dependency anxiety is a variant of NIH syndrome, and it leads to much, much worse quality software in the average case. Most companies are not in the business of writing a bug-free async framework, and yet here we are. The cost of vetting your dependencies is much, much lower than writing and maintaining all these things from scratch.
jstimpfle 5 hours ago [-]
If you use a JSON parser, URL parser, configuration file parser, async framework, and so on, maybe you have other problems. Not that I don't know these project or don't have to work on them, but I don't think it matters what JSON library or URL parser library or async framework you're using.
The actual problem is the complexity coming from the choice to use these things at all (and thinking they should play any important role in the system at all, instead of being entirely replaceable), which means to do anything useful you have to go through a lot of abstraction, which makes everything tedious and buggy and hard to fix.
Panzerschrek 10 hours ago [-]
I didn't say one should not use thirdparty dependencies at all. They are sometimes useful. But they should be chosen carefully and ideally reviewed. And any updates should be done manually in order to prevent security chain attacks.
Having a standardized package manager allows lowering the bar and bypassing careful thinking. It has also a cumulative effect - if one adds each dependency in its project one by one with proper audits, transitive dependencies may not be managed so carefully. And then we have cargo-style cancer with trivial projects having hundreds of dependent packages.
rcxdude 8 hours ago [-]
The C++ style tends to create much larger omnibus libraries. If you're concerned about the liability and bloat extra dependencies create, you should be thinking of a) the number of people you are trusting in your supply chain, and b) the total amount of code you are importing. Neither of these correlate directly with the number of different packages that appear in your package manager, and in fact cargo-style splitting can allow you much more fine-grained control over what code appears in your application.
Probably the one security sin of most language package managers is allowing anyone to upload to the central repository without review. This is good for accessibility but bad for security. There are tools like cargo-crev, though, which can help you enforce some level of vetting if you wish.
simonask 10 hours ago [-]
I don't think masochism is a reliable or sound security strategy.
uecker 10 hours ago [-]
On the other hand, systems like cargo a clearly a supply chain disaster.
I also think that languages should not have their own specific packaging system. This should be done on a distribution level, which provides curated lists of software. This system works well in the Linux world. The problem is the support for the commercial platforms.
The whole trend to think of programming languages as closed frameworks is bad. It is replacing a better system with one which is fundamentally much worse, instead of trying to fix the problems with the existing systems (which is hard because it needs collaboration and harmonization, instead of going into your own little bubble and pretending to do something superior).
simonask 47 minutes ago [-]
> On the other hand, systems like cargo a clearly a supply chain disaster.
I don't think that has been shown to be true. There's a lot of FUD, though. Tools like `cargo vet` and `cargo audit` seem to be pretty good.
> I also think that languages should not have their own specific packaging system. This should be done on a distribution level, which provides curated lists of software. This system works well in the Linux world. The problem is the support for the commercial platforms.
I mean, it works until it doesn't. There are really significant drawbacks to this as well, including the knack some distributors have for thinking they know better than the original developer.
pjmlp 10 hours ago [-]
Conan and vcpkg are getting there.
It is as standard as in many languages where package management came after years of using the language.
small_model 17 hours ago [-]
C should have fixed its various issues and added a package manager (or blessed one), Zig is filling that gap.
malkia 11 hours ago [-]
No it's not. Not everybody uses Zig. Rust/Python/And others have also tried "fixing" it.
forrestthewoods 19 hours ago [-]
The world has yet to standardize on a good crossplatform polyglot build system.
The only real such build systems are Buck and Bazel. But they have way too much baggage from their overlords.
It’s a shame.
arikrahman 19 hours ago [-]
Zig is pretty good for my use case. It may not be fully pollyglot at a technical level, but I can use it for my embedded C use case, for Jank to export the .cpp to other platforms, and thereby Clojure.
himata4113 19 hours ago [-]
build systems using llvm as the backend are getting there, but zig is making their own compiler too.
forrestthewoods 13 hours ago [-]
compilers and build systems are and should be different.
A good polyglot build system should support llvm and zig and python and literally any toolchain under the sun.
It happens in many projects .. devs will just ‘do something convenient so they dont have to do the work to do it properly’ and then that just becomes the convention, because nobody else wants to do hard work to do things properly, either.
Rust language mistakes are understandable, because they do a lot of novel stuff so they encounter situations that no one have seen before. For the three languages that I mentioned, their mistakes are fairly well-known errors with obvious consequences. How hard was it to foresee that lacking generic in Go is a mistake, when the language was created well after Java had generics?
I think that a programming language — much less a programming language _ecosystem_ — is such a large space of decisions that statistically you're inevitably going to let a few of them slip. And even (as in Rust's case, initially) if you don't aim to do anything new, the combination of the interactions between features and the ways people want to use your language culturally can land you places you never anticipated when doing the initial language design. I don't think anybody in the early years of Rust could have anticipated how async would look today, for example, and IIRC Graydon Hoare still doesn't like where it ended up.
Then, there's the old software adage that the right decision for one level of adoption doesn't necessarily translate to another level. Because it's so hard to predict the impact of early decisions, early versions of programming languages are basically prototypes: your aim is to get out enough of the core differentiators of the language that people can start playing with it and _imagining_ what it will be like to work with the final thing. Part of that involves making the barrier to entry as small as possible (e.g. bundling a full build system into the precompiled compiler executable) but it also implies that you don't want to spend more time than necessary on things that work the same as other languages. If you can see the ‘obvious omission’ in the language then that means you can already imagine how it will work when that thing is implemented! As an implementor you can always flesh it out as you approach 1.0, or, if the right thing to do is so obvious and you have an enthusiastic open-source community, you can just wait for the community to build it for you.
Go's generics case is a bit different, I think. I don't claim to be an expert here (I haven't followed Go development much) but as far as I understand it the omission of generics from Go was a deliberate ideological choice: they hoped to get by with the absolute minimum of generic functionality, and the experiment was how little they could get away with and still have it adopted. (Unfortunately, I think the experiments Go was trying to run were stymied by Google and Kubernetes throwing their weight behind it, which led to a pattern of adoption that had little to do with the language design itself: we may never know what would have become of it if it had been left to stand on its own.)
I found really cool that you have a bunch of options to configure compilation of source code itself. Not just the compiler optimization but you can automate all kinds of things: https://ziglang.org/learn/build-system/#build-system
Plenty people do it every year, naturally nothing to compare to GCC/clang.
I guess education system went downhill since then, which I guess it is kind of true, given the poliferation of header only libraries, as if C was a scripting language.
Most performance bottlenecks aren't inherent limitations of the hardware or the problem. There's some minimum amount of effort required to get the result, but that's never the reason why the application doesn't perform well. It's always the cruft we add on top.
I know that it’s purely a UX concern, and that the changes (to decouple the build system and the compiler) are pretty critical for the maintainers, but it’s still a bit sad that development sanity comes first than the UX. (It’s the right call, just that it’s sad.) @cImport was a big killing feature imho to the language…
Even though I use LLMs every day, and have to admit they're remarkably good at many classes of problem, I don't want a programming language built by an LLM. Every line of code in a programming language, every decision, every trade off, matters. A vibe-designed/vibe-coded programming language would be a disaster. I don't know how else to put it, and I've never seen any model produce code that would convince me otherwise (even Fable, which is, in fact, a notable improvement over the prior best models). The models don't want anything. They don't have meaningful opinions. They don't know what comfortable vs. uncomfortable feels like in a language (or in a GUI or CLI interface at sufficient levels of complexity).
You can't get a language like Zig out of an LLM without simply copying Zig, and even then it would be a copy that is worse. (I mean, I'm assuming "copy with an LLM" means, "have an LLM write the spec and another build the language to the spec", not literally `cp` the source tree.)
We've heavily adopted LLM's, to the point where I'll often not touch any code and have a better and more maintainable codebase than if it had been written by any of our developers (myself included). I'm not sure it would be possible if our philosophy wasn't explicity, no abstractions and defensive programming, but when every function is it's own thing with runtime assertions and ways of dealing with corrupt states as soon as they happen. Well... the LLM can do that when you can.
That being said. I think it's not new that you can write computer software without computer science, until you can't. Where I see the challenge with LLM's and software development as a business is that a lot of software developers work(ed) that can be automated because they don't actually require computer science as such. Having setup company wide "apps" for Microsoft's cowork, I think any sort of semi-expert level office job is going to be in danger. I'm not a huge fan, and I was never hyped on AI but it's ridilous what you can do in the enterprise office space (and how easy it is) when you're married with Microsoft.
This is mostly about human preferences right. If software is just taken as the end product, does it matter what "feels" good and doesn't?
It's also an open source project, so the end product is as much the codebase as it is the binary releases.
I've interacted enough with largely computer generated codebases to see that ergonomics problems easily grow and accumulate when LLMs remove the burden of dealing with those problems from the developer. I've always considered my laziness an asset. Now I would qualify that by saying that laziness is an asset for as long as it compels you to keep things simple and easily understandable so that the cost of making changes (whether that's measured in human gray hairs or tokens) doesn't grow with every change.
1. That a human, even a brilliant human with a lot of experience, can sit down and one-shot a language spec for a new language that is actually good.
2. That an agent can produce code that is good enough for a programming language that intends to last for decades without exhaustive human review.
We might advance to the point where 2 is true, we're not there yet. We'll never make a better human that can one-shot a good programming language. It takes iteration, with a human in the loop. Zig has taken ten years to get to this point, and is still occasionally experiencing major refactors.
If you want to argue an LLM could potentially accelerate development by some amount, I would agree with you. How much it could accelerate it is debatable. And, I understand why the Zig folks have decided not to accelerate in that way. There is a cost to it. You lose the junior programmer pipeline, as your "good first bug" list gets chewed up by people using LLMs. You still have to exhaustively review the code for a critical path like a compiler and AI code is hard to review; it doesn't have a point to it. The model doesn't want anything, so it's not always clear where it's going. Code without clear intention, like prose without clear intention, is hard to read and hard to review. It's verbose and often makes weird assumptions.
If I, for some reason, needed to implement a tiny DSL for something, I would 100% do it with an LLM. If I, for some reason, were tasked with building the best programming language to replace C, I would not hand it to an LLM (though I would get help from an LLM, because I don't know how to build a programming language beyond the tiniest toy interpreter or compiler, I'd need to read and understand every line of code, and use it daily, for it to turn out good).
Plus, current-gen agents/LLMs can't implement a non-trivial language spec without significant hand-holding.
https://youtu.be/Fc3cW0nqAQ0
There's still the obvious problem that if the build system emits malicious code, you'll probably run that code anyway. Personally I think this kind of sandboxing is more useful for enforcing build reproducibility rather than, like, protecting you from viruses in the build.zig file.
Language-specific build facilities, like Cargo's build.rs and Zig's build scripts, typically have a limited scope - generating a bit of source code, discovering some linker flags, stuff like that. These scripts need to be run by LSP servers when opening the project in an editor to get basic features working, so that's a fairly risky thing.
They are also currently doing things like invoking CMake and other build systems, but you could definitely conceive of a world where that was a separate step in the build process, and that world seems pretty attractive to me.
A common pattern in Rust projects is to have a `*-sys` crate representing the C FFI bindings, and they typically also do something like invoke CMake or similar to actually build the C/C++ library underneath. But if you have a larger project that already integrates multiple build systems, this is really quite inconvenient in most cases.
I think this is a bad move since the real fix to these attacks is a sandboxed environment rather than a single tool implementing sandboxing.
The benefit of "whole environment" is that if you stuff everything into that environment then anything in it is confined, but it's all confined with everything stuffed in and is sort of maximally capable. You can rarely do things are significant as, say, system call filtering, because all software in the environment must continue to work and none of it was designed with that in mind.
Native sandboxing like this will likely make auditing much easier as well. If a dependency requires something like "give me the ability to execute code on the OS", now it has to ask for it and now it gets additional scrutiny.
Native sandboxing is and always will be the infinitely superior method when it's actually used. Whole process/ Environment is only what we use because of how rare native sandboxing is.
I don't know Zig's plan, but once you have the ability to broker privileges like this you have the ability to audit the privileges being brokered and things change forever.
In theory, you could run the whole compiler (including C) in WASM as well but I don’t think that’s the goal? You kinda need to trust the compiler itself.
But when looking at open source code you don't trust yet, you might want to build code, without running it, so your development tools will work.
I added WASM/WASI bindings and wrote the prelude in Haskell.
Both the bindings and the prelude took less time than I already wasted on multiple attempts in Starlark that all collapsed into string goop.
It's nice to be able to bound the execution environment in a build tool but still use a serious programming language.
Given Zig has excellent support for targeting WASM, seems you'd get the same advantages.
The only exception is C/C++, where there is none established that well, for good or bad.
These choices may create later super-convoluted processes when you have to mix more than one language together.
Packaging systems makes thing easy, but complicate further the line if another language needs to be used.
Fixing this is beyond any one tool, of course :)
I've worked on many large projects in C++, and every single one of them contains a bespoke, buggy, undermaintained JSON parser, URL parser, configuration file parser, async framework, and so on. It used to be the case that almost every large C++ project started out by defining its own friggin' string type.
Dependency anxiety is a variant of NIH syndrome, and it leads to much, much worse quality software in the average case. Most companies are not in the business of writing a bug-free async framework, and yet here we are. The cost of vetting your dependencies is much, much lower than writing and maintaining all these things from scratch.
The actual problem is the complexity coming from the choice to use these things at all (and thinking they should play any important role in the system at all, instead of being entirely replaceable), which means to do anything useful you have to go through a lot of abstraction, which makes everything tedious and buggy and hard to fix.
Having a standardized package manager allows lowering the bar and bypassing careful thinking. It has also a cumulative effect - if one adds each dependency in its project one by one with proper audits, transitive dependencies may not be managed so carefully. And then we have cargo-style cancer with trivial projects having hundreds of dependent packages.
Probably the one security sin of most language package managers is allowing anyone to upload to the central repository without review. This is good for accessibility but bad for security. There are tools like cargo-crev, though, which can help you enforce some level of vetting if you wish.
I also think that languages should not have their own specific packaging system. This should be done on a distribution level, which provides curated lists of software. This system works well in the Linux world. The problem is the support for the commercial platforms.
The whole trend to think of programming languages as closed frameworks is bad. It is replacing a better system with one which is fundamentally much worse, instead of trying to fix the problems with the existing systems (which is hard because it needs collaboration and harmonization, instead of going into your own little bubble and pretending to do something superior).
I don't think that has been shown to be true. There's a lot of FUD, though. Tools like `cargo vet` and `cargo audit` seem to be pretty good.
> I also think that languages should not have their own specific packaging system. This should be done on a distribution level, which provides curated lists of software. This system works well in the Linux world. The problem is the support for the commercial platforms.
I mean, it works until it doesn't. There are really significant drawbacks to this as well, including the knack some distributors have for thinking they know better than the original developer.
It is as standard as in many languages where package management came after years of using the language.
The only real such build systems are Buck and Bazel. But they have way too much baggage from their overlords.
It’s a shame.
A good polyglot build system should support llvm and zig and python and literally any toolchain under the sun.