* https://www.youtube.com/watch?v=UsXgCeU-ovI
While Mill is focusing on JVM for now, it is very extensible and I have a strawman demo of adding a Javascript toolchain in ~100 lines of code https://mill-build.org/mill/0.12.1/extending/new-language.ht...
For those of you who want to learn more about the design principles and architecture of Mill, and what makes it unique, you should check out the page on Design Principles which has links to videos and blog posts where I elaborate on what exactly makes Mill so different from Maven, Gradle, SBT, Bazel, and so on:
* Mill Design Principles https://mill-build.org/mill/0.12.1/depth/design-principles.h...
I've mentioned this in a few places, but the comparisons with other build tools are best-effort. I have no doubt they can be made more accurate, and welcome feedback so I can go back and refine them. Please take them with a grain of salt
I'm also trying to get the community involved, so it's not just me writing code and running the show. To that end, I have set up a bounty program, so pay out significant sums of money (500-2000USD a piece) for people who make non-trivial contributions. It's already paid out about 10kUSD and has another 20kUSD on the table, so if anyone wants to get involved and make a little cash, feel free to take a shot at one of the bounties! https://github.com/orgs/com-lihaoyi/discussions/6
Also, what’s with the “ivy” on https://mill-build.org/mill/0.12.1/comparisons/maven.html ? Any relation to Apache Ivy?
Good luck for your project!
For somebody looking to escape from Gradle, Bazel seems like one of the most promising alternatives, as it’s built on sane and sound fundamentals. Although in practice it has plenty of rough edges and annoyances, so maybe there are areas where Mill can do better.
What's required for v1.0?
He has written multiple useful libraries. Out of many JSON libraries, his one was the most intuitive and practial.
His book is excellent too. I bought it when it came out. It is worthy of a plug: https://www.handsonscala.com/
I miss working on Scala projects. Sadly I rarely see new ones these days.
Does IntelliJ plugin finally work on Scala 3? About 2 years ago it was half broken.
> Most developers using a build tool are not build tool experts, and have no desire to become build tool experts. They will forever be cargo-culting examples they find online, copy-pasting from other parts of the codebase, or blindly fumbling their customizations. It is in this context that Mill’s static typing really shines: what such "perpetual beginners" need most is help understanding/navigating the build logic, and help checking their proposed changes for dumb mistakes. And there will be dumb mistakes, because most people are not and will never be build-tool experts or enthusiasts
In my opinion, using a GPL as the build language of a polyglot build tool is a dead end, both for technical/usability reasons and because the ensuing language wars can't be won. I'm looking forward to the day when a build tool embraces a modern config language such as CUE or Pkl.
I find that the pain I experience with Gradle isn't usually about how to do something clever or customized etc, but instead it's when I haven't thought about Gradle syntax in the last 3 months since everything has been silently working, but now I need to figure out some small thing, and that means I need to go re-learn basic Gradle stuff - whether it's groovy, Kotlin, or some aspect of the build DSL - since my mind has unloaded everything about Gradle in the meantime.
Simplifying the semantic complexity of a general purpose build system will always help, but the most useful thing for me would be if the configuration for a Java build were to natively use the Java language directly.
If you want something declarative, there's also bleep[1] in the scala ecosystem. And for single module builds there's scala-cli[2]. It's also possible to use gradle and maven for scala projects, but for an java-only shop I wouldn't be using mill or bleep because there's no need to introduce a new language just to manage the build. For scala/java/kotlin hybrid projects though, gradle or mill or sbt would be my recommended tool because of how tightly they are coupled with the cross-platform build matrix nature of scala library and build system plugin ecosystems. For larger builds, it's mill or bazel because there s a performance cliff in sbt and gradle, and bleep is too new to have all the standard plugins ported. We use mill at writer.
Mill using Scala syntax is like that, but with the added advantage that even if you forget how Scala works, your IDE does not. You can really lean on Intellij or VScode to help you understand and navigate around a Mill build in a way that is beyond what is possible for most build tools: You can autocomplete things, peek at docs, navigate the build graph and module tree, etc. and learn what you need to learn without needing to reach for Google/ChatGPT. I use this ability heavily, and I hope others will enjoy these benefits as well
Sounds amazing in practice. And it is. Until you need to fix a 3 year old build that has some insane wizardry going on.
This is not entirely a solution though, because Gradle's APIs are fairly complicated and change regularly.
The main appeal that I can see from mill over maven is the power of dynamic programming over static xml files. Maybe good lsp/ide support will make managing a build system like this bearable?
Mill and Maven both let you declare goals for what you want to do. One does it in XML and one does it in typechecked code. While XML does work, doing things in code with typechecking and full IDE support turns out to be pretty nice as well!
Groovy was never the problem (Groovy has types, always had, you could use them if you wanted).
Think about it: what do you do with a build tool? You write a little recipe, then you run it. Does that remind something? Yes, it reminds scripts, like bash scripts you run all the time in your terminal. And why are scripts almost universally written without types... and no typed alternative, of which there are many, has caught on? Because if you're just going to modify a script and immediately run it, while keeping it short enough so you can know what it does without reading a book, how does adding types help you? Quite to the contrary, scripts (including build scripts) should be small, and having types all over the place make it far more verbose than it should be, likely pushing it out of your comfortable local memory in your brain, at which point you need something akin to a "real" programming language and a compiled program, not a script. Larger programs benefit from types because you don't just run the program, make changes, and run them again, like you do with scripts. You write them, test them, compile them, package them and finally you distribute them to your users who hopefully only need to configure them, not modify their internals. If your build is that complex, that's exactly what you should be doing instead of trying to shoehorn types into your scripts and expecting them to look like real programs.
Also, the Kotlin DSL just doesn't assist in the most problematic aspect of Gradle: its total lack of discoverability. Try doing something on your Kotlin Gradle file using a plugin you're not familiar with (which is all of them for most of us). It's completely impossible unless you know the DSL of the plugin, just like it was the case with Groovy... Once you know the DSL, it's fairly easy, but even in Groovy you will get auto-completion once you've got to the DSL "entry point", no need for Kotlin. I've been saying this since before they introduced the Kotlin DSL, and now i feel completely vindicated. I've never met anyone who told me "Gradle is so much easier now with Kotlin". But it did mess up plugins I wrote in Kotlin as now Gradle has a dependency on a very particular version of the Kotlin compiler, and God help you if your plugin was written with a different version in mind.
`go build` and `go test` do work, at limited scale and complexity. In Scala there's Scala-CLI which is excellent. If they work for you, you probably aren't the target market for these build tools. Once you start layering on bash scripts, layering on make, layering on Python scripts, layering on manual steps written down in a readme.md somewhere, that's the time when you should consider a proper build tool. And if that has never happened to you in your career, count your blessings :)
Why not just write some boring, pure code to handle the build? Why not write my build system in vanilla LYAH Haskell? It turns out that builds do have some specific requirements that most programs do not need to care about: caching, parallelization, introspection, and so on. Check out the following blog/talk for more details:
* Blog Post: Build Tools as Pure Functional Programs https://www.lihaoyi.com/post/BuildToolsasPureFunctionalProgr...
* Video: Mill: a Build Tool based on Pure Functional Programming https://www.youtube.com/watch?v=j6uThGxx-18&list=PLBqWQH1Miw...
Thus "naively" building your project "directly with code" ends up not working, so you do need some additional support. While most build tools end up constructing a complete bespoke programming environment from scratch, Mill tries to leverage the Scala language and JVM as much as possible, so you can re-use all your expertise and tooling (e.g. IntelliJ, VSCode, Maven Central, etc.) almost verbatim while getting all the necessary build-tool stuff (parallelism, caching, introspection) for free. Check out those two links if you want to learn more!
The issue is that most people in jvm land are on a closed bubble and haven't seen anything else. This is true for build systems as is for non OO design for example. Most simply don't know better and the rest of us are simply stuck.
Ant and then Maven started simple enough but people always find a way to justify adding more stuff. Gradle already started complex enough and they keep adding more stuff...
Other build tools and plugins just compete/fill in for:
* improved build speed / test speed: using background daemon to reduce strtup speed, intelligent caching / task reordering to avoid redoing, etc..
* extra functionalities like code generation, publishing or deployments. As code generation is really big in JVM world, and there are many ways to deploy an application: jar + libs in a zip file, uber jars, container image, etc...
Go projects normally just tend to be self-contained server-like software that doesn't need a lot of external libraries. But once you step away from that, you're on your own.
I guess my problem with Gradle is that app building should be way simpler than it is. Apps are not something niche anymore, but the tooling is still similar to the embedded software for microcontrollers.
My hot take: JVM build tools, especially Gradle, are a soup of unnecessary complexity, and people working in that ecosystem have Stockholm Syndrome.
In Golang, I spend about 99% of my time dealing with code.
In JVM land, I'm spending 30% just dealing with the build system. It's actually insane, and the community at large thinks this is normal. The amount of time it takes to publish a multi-platform Kotlin library for the first time can be measured in days. I published my first Golang library in minutes, by comparison.
The key feature that justifies their existence is parallel and incremental execution of DAGs of world-mutating tasks. This is an awkward fit with most programming languages, hence the prevalence of DSLs. But people don't want their build system to become a general purpose programming language, because they don't want to think about build systems at all and because programmers don't buy programming languages anymore, so, this causes a big design tension between generality (people want to use build systems to automate many things) and deliberately limiting the expressive power to try and constrain the design space and thus tooling investment required.
Java is in an awkward place because the JDK was born in the 90s on UNIX, by people who thought make is a sufficiently good solution. You still see remnants of this belief in the official Java tutorials, in JEPs, and in the fact that OpenJDK itself is compiled using an autotools based build system! (fortunately it's one of the nice make based build systems out there).
The problem with make is twofold:
1. It assumes a CLI that's both powerful and standardized provided by the host OS. Windows violates this assumption but Java is meant to be portable to Windows.
2. "Plugins" are CLI tools or scripts and so make implicitly assumes that subprocess creation is cheap. But process creation on Windows is expensive, and starting up JVM programs is also expensive due to the JIT compiling.
Therefore make just doesn't work well in the JVM ecosystem. At the same time, the Java project wasn't providing any competing solution, so the wider open source community was left to fill in the gaps. These days language developers provide build tooling out of the box as part of the base toolset along with the compiler, but Java still doesn't.
So - you ask, what are people doing with Gradle/Maven that requires all those features. The answer is: everything! Gradle builds frequently orchestrate dozens of different tools as part of a build pipeline, build documentation websites, do upload and deployment, download and manage dependencies, run security scanners and license compliance checkers, analyze dependency graphs, modify compiler behaviors, and so on.
Additionally Gradle isn't specific to Java, or even JVM apps. It can also be used to compile C/C++ programs, run native code compilers like Kotlin/Native, and it abstracts the underlying platform so Gradle builds aren't tied to UNIX.
That's why it's so complicated.
At first glance, Mill looks like it has many of the pitfalls of Gradle: - Plugins: Creates the temptation to rely on plugins for everything, and suddenly you're in plugin dependency hell with no idea how anything actually works. - Build scripts written in a DSL on top of a new language: Now I have to learn Scala and your DSL. I don't want to do either! - Build scripts written in a language that can be used for code too: Versioning hell when the compiler for the build system needs to be a different version to the compiler for the actual project code. See: Gradle and Kotlin
Examples:
* Github Actions Config Expressions https://docs.github.com/en/actions/writing-workflows/choosin...
* CloudFormation Functions https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGui...
* Helm Chart Templates https://helm.sh/docs/chart_best_practices/templates/
There is a reason why Bazel went with Python/Starlark, why Pulumi and CDK and friends are getting popular. Fundamentally, many of these use cases look surprisingly like programming languages: maybe not immediately, but certainly after you've dug in a bit. And having a properly designed purpose-build programming language (e.g. StarLark) or a flexible general purpose language (e.g. Typescript, Kotlin, Scala) does turn out to be the least-bad option
The implementation may not be the theoretical best, but I think the idea is pretty much the perfect build system out there.
> Mill can build the same Java codebase 5-10x faster than Maven, or 2-4x faster than Gradle
Speed per se can be a good selling point (having to wait for slow builds is really annoying).
I can't really comment on anything else though as I just stumbled upon it here in HN ;)
I had worked out that math for “like pip but actually works” but few people were conscious that pip didn’t quite work reliably for large and complex projects — I didn’t think it was possible to sell it.
Uv won hearts and minds because it was uncompromisingly fast: people did not really care that it had a correct resolving algorithim or that is was really reliable because it is not written in Python and thus can’t trash it’s own dependencies (maybe a solvable problem in that the build tool can have its own virtualenv but isn’t it nice to for your package manager to be a binary that can’t get dependencies screwed up no matter how hard the users try?)
One tool I've been using to speed up maven is mvnd, the maven daemon. It's a drop in replacement for mvn with impressive speedups.
That said, I have come to believe that the jvm is a bad platform for a build tool. Everything that touches the jvm becomes bloated and slow, particularly for startup. I no longer write scala because of my frustration with the bloat (and scala adds its own bloat on top of the jvm).
Mill seems to have taken some inspiration from those as well.
Has anyone at the senior level recently moved on from Scala to other languages recently? Any issue finding jobs or learning the new role?