I was inspired by the jane street post and implemented exactly this in my Scala unit testing library uTest (http://www.lihaoyi.com/post/GoldenLiteralTestinginuTest090.h...). Can confirm that auto updating golden test assertions does make working with a test suite much more joyful than struggling with each assertion by hand
With Mill build tool that I'm working on, you don't need to install Java at all! (https://mill-build.org/blog/16-zero-setup.html). Instead, it gets bootstrapped automatically when you launch the `./mill` script like any other third-party dependency. You can use any version you want just by editing the config file and it'll be downloaded and cached on demand. You can also configure different JVM versions to use in different Java modules without worrying about conflicts between them.
You don't need to globally install Apache-Commons, nor is there a "Apache Commons Version Manager" that you need to first install to then manage your different versions of Apache Commons. So why should the JVM need such a thing? Well with Mill, it doesn't
If you look at that thread, you'll see I've paid out quite a lot in bounties, somewhere around 50-60kUSD (the amount is not quite precise, because some bounties I completed myself without paying, and others I paid extra when the work turned out to be more than expected). In exchange, I did manage to get quite a lot of work done for that cost
You do get some trash, it does take significant work to review, and not everything is amenable to bounties. But for projects that already have interested users and potential collaborators, sometimes 500-1000USD in cash is enough motivation for someone to go from curious to engaged. And if I can pay someone 500-1000USD to save me a week of work (and associated context switching) it can definitely be worth the cost.
The bounties are certainly not a living wage for people, especially compared to my peers making 1mUSD/yr at some big tech FAANG. It's just a token of appreciation that somehow feels qualitatively different from the money that comes in your twice-monthly paycheck
That's basically what my MainArgs Scala library does: take either a method definition or class structure and use it's structure to parse your command line arguments. You get the final fields you want immediately without needing to imperatively walk to args array (and probably getting it wrong!)
Author here. Mill definitely works pretty well for monorepos. Within a single module Mill incrementally compiles the Java files, between modules Mill caches and parallelizes things much more aggressively, and when running tests Mill can take your PR's `git diff` and selectively execute only tests downstream of your changes.
This all comes built-in without any plugins or anything, and serves to help speed up dev and CI workflows even on pretty large codebases.
My experience with Bazel (7 years rolling it out and maintaining it in a large company) is that it provides huge value for larger teams/codebases, but at a huge cost in complexity. e.g. the three I rollouts I was closest to each took ~2 person-decades to happen; might be easier now than it was in 2016/2017, but Bazel hasn't really gotten simpler over the years
Mill is intended to be much easier than Bazel. Most people would not use Bazel for a 1-person project, or even a 5-person project, and it only starts pencilling out once you have 50-100 engineers on the team. Mill in contrast works great for small projects and medium projects as well.
One way I'd look at it is that Mill works great for 1-500 person projects, while Bazel works great for 100-5000 person projects. There's some overlap in the middle, but fundamentally they target different kinds of users who have very different constraints and requirements
Please try out Mill! We have a lot of Maven/Gradle/SBT refugees in the community who are quite happy with Mill, so perhaps if you give it a try you'll find a build tool you can be happy with as well
Mill is in many ways trying to be `uv` for the JVM. 3-6x faster than the existing tools, bundling everything necessary builtin without plugin-hell, superior IDE support and toolability than existing tools. If you want a `uv` for Java, you should try out Mill!
> I eschew frameworks in this custom build tool, because the build code should look conventional for whatever language it's written in.
That's really the case with Mill as well, at a deeper more-meaningful level. Mill builds are all built around objects, classes, methods, and overrides.
Maven is XML. Do you write large codebases in XML? Gradle is Groovy/Kotlin, but it's an odd Groovy/Kotlin dialect or DSL that looks totally unlike application codebases, and your IDE is unable to understand and navigate effectively.
Mill is Scala, sure, but what's important is that it is architected around objects, classes, methods, and overrides. Those are the core abstractions when working with Mill, which are the same core abstractions as any Java/Scala/Kotlin application. Thus IDEs are able to navigate Mill builds, profilers like JProfiler or Yourkit can work on Mill builds, and humans who learned Java 101 in college are immediately familiar with the structure and fundamental abstractions of Mill.
Author here. What most people don't realize is that "I hate programming my build." is a symptom of your existing build tools making programming your build dangerous and risky endeavor.
For example, in Maven you typically extend your build in Bash scripts + maven-exec-plugin, Ant script + maven-antrun-plugin, or custom Maven plugins entirely. None of these are "nice" programming environments, with proper IDE support, typechecking, introspectability, and so on. Writing lots of logic in Bash or Ant is risky, so you would be right to minimize writing code in it
Similarly, in Gradle you extend your build in Groovy/Kotlin, but it's a kind of "weird" Groovy/Kotlin unlike anything you'd write in application code. For example, your IDE support in Gradle-Kotlin is much worse than what you get in normal-Kotlin. Despite Gradle-Kotlin being the same language and same IDE, it's a much worse experience writing it, it's much easier to make mistakes, and so you are right to minimize the code you write in it.
In Mill, the build scripts are in Scala, but that's not the important part. The important part is you write normal code using classes, methods, and overrides. IDEs are very good at navigating classes, methods and overrides, and developers are very familiar with working with classes, methods, and overrides. And so build code in Mill feels as comfortable as your application code in Java/Scala/Kotlin: same quality of IDE experience, same typechecking, even can use the same Java third-party libraries (if you wish).
So it's understandable you hate programming your build. In Maven or Gradle or SBT, I'd hate programming my build as well. What Mill offers is that you can program your build where necessary without the hate that comes with doing so in other build tools!
Author here. The neat thing is, with Mill you don't need any of those plugins because it's all built in (except for the license plugin I believe), and is tested/documented together in the main codebase. So it generally all works pretty well together and you shouldn't have issues.
Mill generally is able to replace a lot of first-party/third-party extensions with builtin functionality: beyond the plugins above, it also subsumes autoformatting plugins, linting plugins, external tools like sdkman/jenv, and so on. Thus when using Mill you often don't even think about "what plugins I need", because the bulk of common use cases are provided out of the box, and you can instead focus on your actual project and application code
People like to rave about Monorepos, and they are great if set up correctly, but there's a lot of intricacies that often goes on behind the scenes to make a Monorepo successful that it's easy to overlook since usually some "other" team (devops teams, devtools team, etc.) is shouldering all that burden. Still worth it, but most be approached with caution
There are some companies out there using it in production. I know Netflix and Disney have some teams using it, and the Chisel project (and associated SciFive company) recently moved completely onto Mill from SBT. They all seem pretty happy
Build tools are generally an un-sexy field, and JVM build tools perhaps doubly so. But Mill demonstrates that with some thought put into the design and architecture, we can speed up JVM development workflows by 3-6x over traditional JVM tools like Maven or Gradle, and make it subjectively much easier to navigate in IDEs and extend with custom logic.
If you're passionate about developer experience and work on the JVM, I encourage you to give Mill a try!
A big problem with Bazel not mentioned here is the complexity. It's just really hard for many people to grasp, and adopting Bazel at the two places I worked was a ~10 person-year effort for the rollout with ongoing maintenance after. That's a lot of effort!
IMO Bazel has a lot of good ideas to it: hierarchical graph-based builds, pure hermetic build steps, and so on. Especially at the time, these were novel ideas. But in Bazel they are buried behind a sea of other concepts that may not be so critical: `query` vs `aquery` vs `cquery`, action-graph vs configured-action-graph vs target-graph, providers vs outputs, macro vs rule-impl, etc. Some of these are necessary for ultra-large-scale builds, some are compromises due to legacy, but for the vast majority of non-Google-scale companies there may be a better way.
I'm hoping the next generation of build tools can simplify things enough that you don't need a person-decade of engineering work to adopt it. My own OSS project Mill (https://mill-build.org/) is one attempt in that direction, by re-using ideas from functional and object-oriented programming that people are already familiar with to make build graphs easier to describe and work with. Maybe a new tool won't be able to support million-file monorepos with 10,000 active contributors, but I think for the vast majority of developers and teams that's not a problem at all.
My experience was that it was a surprisingly nice language with a surprisingly warty user experience: papercuts ranging from naming conventions and function call styles (`|> List.map` vs `.Select`), basic syntax (`foo.[0]` to lookup arrays), type system features (F# doesn't have covariance/contravariance even though C# does), IDE support (back then was only Visual Studio, whose support for F# was inferior to C#).
Ended up settling on Scala after that, as a language with its own Warts, but one that somehow managed to feel a more cohesive than F# did despite having largely the same featureset and positioning.
F# was my first functional language and one that changed how I look at programming, but at the same time I'm happy to not actually have to use it for serious programming!