[HN Gopher] Mill: A better build tool for Java, Scala, and Kotlin
___________________________________________________________________
Mill: A better build tool for Java, Scala, and Kotlin
Author : lihaoyi
Score : 72 points
Date : 2025-07-16 15:45 UTC (7 hours ago)
(HTM) web link (mill-build.org)
(TXT) w3m dump (mill-build.org)
| ivolimmen wrote:
| It's nice that there are options but i'm sticking with maven. I
| hate programming my build; maven is just a configuration file.
| jpitz wrote:
| Which works fine.....until it doesn't. Many non-trivial builds
| require custom logic, and trying to do that in maven was
| painful the last time I tried it.
| throwaway7783 wrote:
| Out of curiosity, what is non-trivial in this context?
| spullara wrote:
| I have found that if it is hard to do in maven you probably
| shouldn't be doing it or there is a better way.
| ackfoobar wrote:
| Yeah. It's Greenspun's tenth rule.
|
| If you have any complexity, programming against a good
| abstraction (Gradle is not _good_ good, but decent) beats
| finding the magical incantation of configuration to get the
| tool to do what you want.
| lenkite wrote:
| That is why maven offers a plugin model for your custom logic
| that can be written in Java/Kotlin and a well defined
| lifecycle model where you can configure your plugin
| declaratively.
|
| You can also download custom CLI tools and invoke them as
| part of a well-defined build lifecycle.
| gf000 wrote:
| And then fail to do proper incremental builds, leaving you
| with no choice but a faulty build or clean installing on
| every occasion.
|
| At the very least, I would move to Gradle which does have
| proper knowledge of your build graph. But Mill is also a
| good choice and fills the same niche, with the added
| benefit that imperative-looking ordinary scala code will
| simply become a parallelizable, cacheable build graph.
| switchbak wrote:
| I think folks just get used to Maven-induced constraints
| (this applies to SBT, Bazel, others too). When you free
| yourself from that you realize: builds just aren't all that
| hard, it's often the tooling that becomes a real limitation.
|
| Of course, sometimes the limitations are good: preventing you
| from doing "the wrong thing", or encouraging cacheability,
| etc. But as with any abstraction layer - getting a model that
| fits across so many disparate use cases can be very
| challenging.
| henry700 wrote:
| I hate wrangling with configuration to make an amalgamation of
| plugins do what's expected in the expected order for my build;
| Gradle is just code and a DSL
| askonomm wrote:
| If I would've gotten a Euro for every time "is just a DSL"
| was a reason everything was hard to debug and prone to
| failure, I'd have many Euros by now.
| gf000 wrote:
| Well, good luck debugging a multi-module maven pom file,
| then. You can get terrible error messages from both, to be
| honest.
| imoverclocked wrote:
| It's two DSLs which are versioned and whose behaviors are
| different.
|
| Gradle groovy is extremely permissive (eg: you can access
| private class instance variables without even knowing that
| you are doing so)
|
| Kotlin lacks that permissive quality in exchange for much
| easier introspection.
|
| It's often trivial to move from one to the other but those
| edge cases can find you in a codebase of any complexity.
| chriswarbo wrote:
| > maven is just a configuration file
|
| Even better, Maven "POMs" are written in a common, standard
| format (XML); so we can transform and manipulate it using off-
| the-shelf tools, if we really want to. I've found this useful
| e.g. in pre-commit hooks (tidy the formatting,
| checking/linting, etc.); in Nix builds (e.g. removing the
| version number, so it doesn't affect the hash and avoids
| spurious rebuilds); etc. That was a nice bonus when I switched
| some projects from SBT to Maven (due to SBT being wildly
| unreproducible).
| pbh101 wrote:
| Anyone have a comparison to Bazel? They only compare to JVM-
| centric tools eg Maven, sbt, Gradle.
| frostirosti wrote:
| Bazel is just such a nightmare for me. It's amazing when
| someone understands it really well and can set things up. But
| for anything short of that, being on the hook to fix or debug
| things makes it a nightmare. That and trying to port anything
| over from sbt, like scalafix for instance, to bazel is a pain.
|
| Also too, bazel has this issue of googleability? like I feel
| like I can take any build issue I've run into in sbt and find
| the solution and an example by just searching, but with Bazel,
| anything outside of the happy path is a recipe for pain
| TheChaplain wrote:
| Reminded me of this: https://xkcd.com/927/
| dang wrote:
| Related. Others?
|
| _Mill as a direct style build tool_ -
| https://news.ycombinator.com/item?id=43943792 - May 2025 (9
| comments)
|
| _Why does Mill use Scala?_ -
| https://news.ycombinator.com/item?id=42997496 - Feb 2025 (75
| comments)
|
| _Mill: A fast JVM build tool for Java and Scala_ -
| https://news.ycombinator.com/item?id=41967734 - Oct 2024 (162
| comments)
|
| _What 's So Special About the Mill Scala Build Tool_ -
| https://news.ycombinator.com/item?id=38877882 - Jan 2024 (1
| comment)
|
| _Mill: A Build Tool Based on Pure Functional Programming_ -
| https://news.ycombinator.com/item?id=25925107 - Jan 2021 (1
| comment)
|
| _Mill: Better Scala Builds_ -
| https://news.ycombinator.com/item?id=16775545 - April 2018 (16
| comments)
| spullara wrote:
| this is a horrific build file:
| https://github.com/swaldman/c3p0/blob/0.11.x/build.mill
| billmcneale wrote:
| Yeah, hard to see how better this is than Gradle. If anything,
| it's worse by the mere fact this is Scala, but it's really so
| incredibly verbose to accomplish basic tasks such as upload to
| Sonatype.
| spullara wrote:
| making it easier to generate maven poms I thought was a
| reasonable idea 18 years ago but gradle and other tools all
| went down the "making the build Turing complete" path.
|
| https://github.com/spullara/graven/blob/master/pom.groovy
| imoverclocked wrote:
| You can write bad code in any language. Don't ask me how I know
| :)
| frant-hartm wrote:
| I wonder what people use/need apart from the usual stuff in Maven
| nowadays.
|
| In the last 5 years, I didn't need anything more than:
|
| - resource plugin - compiler plugin - jar plugin (jars, test
| jars, javadoc jars) - surefire/failsafe - shade plugin for
| repackaging to avoid classpath hell - assemble plugin - license
| plugin
|
| Most of the issues I had were with the shade/assemble/license
| plugins.
|
| I consider myself a Maven power-user and like the tool compared
| to others (Gradle is too ant-like, resulting in non-standard
| builds, sbt is just a torture tool).
|
| With time, I concluded that the simpler it is, the better.
| debarshri wrote:
| I think you can make it 10 years. It is super robust. It just
| works for java stuff.
| switchbak wrote:
| I've had the misfortune of having Maven forced on me for Scala
| projects, I just can't agree with you. The overhead of starting
| the compiler so often is a killer, and makes your builds much
| slower. Unless there's been some improvement of Zinc/Bloop/Etc
| with Maven since I've used it.
|
| I think I would prefer to use Mill than Maven (I haven't used
| Mill myself) ... going through the video tutorial, it's clear
| that it's also a very simple system without some of the ancient
| baggage of Maven (xml, too many plugins, etc).
| vips7L wrote:
| I've had sbt and scala forced upon me for Java projects and I
| feel the exact opposite of you!
|
| Sbt and Scalac are so slow they kill any productivity I could
| have.
| wellpast wrote:
| I agree 100%.
|
| I've been around for a while, I've used many different build
| systems for JVM based builds (Java, Hybrid Java/Clojure, Scala)
| and Maven is by far the simplest most solid.
|
| The basic reason is it's commitment to being declarative.
|
| I understand why programmers want imperative (we're
| programmers) but it's just the wrong choice for a build system.
|
| I've worked on many OSS projects. I've never pulled a Maven-
| based project that didn't immediately build and immediately
| load into my IDE. However for imperative based build systems
| (Gradle, Ant, now Mill) it's almost inevitable that you won't
| be able to get the build to work right away or pulled into your
| IDE in a sensible way (as IDEs cannot read imperative
| statemetns).
|
| I've created many many build with Maven with many many
| different demands (polygot codebase, weird deployment
| artifacts, weird testing runtime needs, etc etc) and Maven has
| never let me down. Yes, in some cases I've had to write my own
| plugin but it was _good_ that I had to do that; it forced me to
| ensure I really needed to -- the Maven plugin ecosystem is
| already great and covers 90+% of use cases of builds.
|
| I've met a lot of Maven naysayers and the disdain is almost
| always either some weird aversion to XML (such a trivial reason
| to choose a worser build system) and/or because the programmer
| never took the time to understand the rather simple Maven
| runtime semantics and architecture.
| ackfoobar wrote:
| > imperative based build systems (Gradle, Ant, now Mill)
|
| Build code in Mill is pretty declarative. You're using the
| word to mean "not 'pure, serialized data'".
|
| > IDEs cannot read imperative statemetns
|
| They can, however, run the code to dump the structure.
|
| It's easy for code to embed pure data; on the flip side it's
| hard to encode behaviour in serialized data. More often than
| custom Maven plugins I see people just drop down to using
| shell.
| mindcrime wrote:
| Ya know, I've directed a lot of criticism at Maven over the
| years... and most of it well-founded, I believe, even in
| hindsight. And yet, today, I find that of all the Java build
| tools, Maven is my preferred one. Part of that is me,
| normalizing the pain of Maven in some regards, and part of that
| is places where they have improved the tool. But however you
| break it down, it is indeed the case that for the most part
| Maven "just works"(tm). That is, at least for Java. I don't do
| a lot of Scala or Kotlin or anything, so no comment there. And
| for Groovy, I'm usually doing Grails projects which default to
| Gradle, so I tend to use Gradle in that context. But for plain
| Java projects, I honestly find Maven to be the path of least
| resistance.
| Tainnor wrote:
| My main problem with Maven is that it's dog slow and
| incremental compilation doesn't really work, especially on CI.
| For huge repos that's a real issue.
|
| In a sense I feel that part of the microservice craze is due to
| the fact that many of our build systems are not good enough to
| allow us to work with huge monoliths efficiently. Gradle is a
| bit better (definitely faster), but comes with additional
| complexity. Haven't tried Mill.
| Taranovski wrote:
| Maintainability: Mill's config and custom logic is written in
| concise type-checked JVM code - Inside - "why mill uses scala?"
| LOL))
| octopoc wrote:
| IMO there should be one build system for each language and it
| should be good at the basics, and if you need more then you
| should write your own (minimal-dependency) build script _in the
| same language as the code you 're building_, and in that system
| you do things like generate build files for the big, complicated
| thing you're trying to build.
|
| In Java terms, if you have a big complicated Java repo that
| requires lots of steps to build, you should have a separate Java
| project in there just for building the main repo. That separate
| Java project should be built and run with maven, and that
| separate project can do all kinds of fancy things, but ultimately
| it will be generating maven projects or calling maven with
| special command line parameters or something like that.
|
| I even put the logic for CI in my build project like this. It
| makes everything reproducible and debuggable. How cool is it to
| be able to put a breakpoint in your build script? How about
| stepping through your CI code? Things are way simpler this way.
|
| I eschew frameworks in this custom build tool, because the build
| code should look conventional for whatever language it's written
| in.
| zcw100 wrote:
| I don't know why I don't see anyone ever mention JeKa.
| https://jeka.dev/
|
| You don't have to learn a separate language or some weird config.
| seanw444 wrote:
| https://mill-build.org/mill/depth/parallelism.html#_mill_chr...
|
| This is kinda funny. Generating a profile that is meant to be
| visualized with a web browser's built-in profiler, not even an
| HTML file. I guess if it's already built and works well
| -\\_(tsu)_/-
| akazantsev wrote:
| That profiler is very powerful and used to analyze beasts like
| Android and Chromium. It's a pro, not a con.
|
| https://ui.perfetto.dev
| seanw444 wrote:
| I had no clue it was its own independent, comprehensive
| project. Very cool.
| switchbak wrote:
| Not a lot of love for Mill in these comments. I'm interested in
| what it has to offer.
|
| I find SBT just has a lot of unnecessary abstractions and
| complexity. It's so opaque that I'm sure I'm leaving a lot of
| performance on the table with hidden antipatterns. Mill seems to
| solve that by being 'boring' (in a good way). Being able to trace
| what's happening in my IDE would be lovely - and something I
| don't have in SBT or Maven either.
|
| Now that we also have fast running native CLI tooling, I think
| it's worth another look over SBT.
| vips7L wrote:
| A lot of people on the Java side have seen what being able to
| script your build turns into with Gradle. They've also don't
| want to learn Scala to do their build.
| pi_22by7 wrote:
| Honestly, I'm getting tired of the endless parade of "better"
| build tools. Maven works fine for most of what I do, even if it's
| occasionally painful. Gradle is... well, Gradle has its moments.
|
| That said, Mill's performance claims sound interesting. If it
| really can cut build times by 3-6x, that's really amazing. I've
| wasted too much time in my life waiting for builds, especially on
| larger projects.
|
| The Scala thing is a bit of a turn-off though. I get that you
| don't need to write Scala yourself, but now I'm dragging in the
| Scala ecosystem just to build my Java project? Feels heavy.
|
| The IDE integration sounds nice in theory - being able to
| actually navigate and understand your build in IntelliJ would be
| pretty sweet.
|
| Still not sure the switching costs are worth it unless you're
| really hitting Maven/Gradle pain points. But if I was starting a
| new project from scratch, might be worth a look.
| le-mark wrote:
| When has build time been an issue though? Running tests have
| taken the most time by far on every project I've ever worked
| on.
| HiPhish wrote:
| Is it bootstrappable? I mean really bootstrappable, not "the
| bootstrap script will download a binary from some server". This
| is where both Maven and Gradle fail (at least the last time I
| checked). Kotlin and Scala also have the problem that their
| compilers themselves are not bootstrappable either.
| smrtinsert wrote:
| Please anything beyond gradle. Didn't hate maven but didn't love
| it either. Happy to investigate alternatives
| elric wrote:
| Reading these comments I'm always amused by how different
| people/teams have radically different needs & preferences, and
| how other people seem to be dismissive of those. "I don't need
| anything more than maven", "maven is too slow", "if it's not
| bootstrappable I don't want it", "there should only be one
| ultimate build tool", "I hate programming my build", etc.
|
| These opinions are all valid, but only if they don't discount the
| validity of other strategies. There is no universal law of
| optimal build practices. There are cases where build performance
| is critical, and others where it's not. There are cases where
| configurability is important, and there are cases where it's not.
| Etc.
|
| Personally, I love having a programmable build in plain Java,
| which is why I enjoy bld [1] these days. I'm probably the only
| person you'll ever meet who actually enjoyed using ant, so you're
| welcome to take my opinion with as much salt as you need to
| digest that.
|
| [1] https://rife2.com/bld
| wiseowise wrote:
| > There are cases where build performance is critical, *and
| others where it's not.*
|
| I'm curious about those.
| Smar wrote:
| Often CI results are not put to use immediately, making build
| time irrelevant.
| wiseowise wrote:
| So you're okay with waiting a day to get "linter error,
| you've put this on a wrong line, dumbass"?
| kerblang wrote:
| Ant worked well because it was extremely _explicit_: You had to
| say what you wanted. This gave it a lot of flexibility. Unlike
| some other tools, you aren't running in front of a train trying
| to get it to stop and let you on. It doesn't go anywhere or do
| anything until you say so. The cost was pretty much zero
| defaults and a good bit of boilerplate.
|
| I think a lot of people expected this from Gradle because the
| idea of "build as programming" seemed like it would give that
| stop-the-train-let-me-on-already ability. I don't know that it
| really worked out that way. Maven is all about running devs
| over, but it's faster than Gradle, which tries to start a
| daemon just like SBT.
|
| Anyhow... this bld thing looks interesting, thanks...
| lucumo wrote:
| > These opinions are all valid, but only if they don't discount
| the validity of other strategies.
|
| I strongly agree with this as a general principle in nearly all
| technical discussions.
|
| But also, if the discussion starts with declaring something is
| better than everything else (as the title here), then there's
| really no salvaging it anymore.
| wiseowise wrote:
| I just want `uv`/`npm`/`crate` for JVM. Is that too much to ask?
|
| Can someone from Astral fix Java too, please?
| Tainnor wrote:
| JVM build tools have to do much more than just dependency
| management because of how the JVM works (e.g. packaging
| resources). It's not really comparable.
| xg15 wrote:
| Half expected this to be built in Rust...
___________________________________________________________________
(page generated 2025-07-16 23:01 UTC)