[HN Gopher] Mill: A fast JVM build tool for Java and Scala
___________________________________________________________________
Mill: A fast JVM build tool for Java and Scala
Author : 0x54MUR41
Score : 152 points
Date : 2024-10-28 03:56 UTC (19 hours ago)
(HTM) web link (mill-build.org)
(TXT) w3m dump (mill-build.org)
| spuz wrote:
| A build tool that is not only fast but configured in a type safe
| way sounds great. I really like this quote from the "Why use
| scala" part of the documentation:
|
| > 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
| potamic wrote:
| What tends to be complex about build requirements that
| necessitates special purpose tools? Golang seems to be doing fine
| with just go build and go test. What else are people doing with
| gradle/maven that requires static typing, DAGs, plugins etc.?
| iamcalledrob wrote:
| I'm working on a project that encompasses both JVM (Gradle,
| Kotlin) and Golang.
|
| 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.
| threeseed wrote:
| > the community at large thinks this is normal
|
| Half are ignorant. Other half are like me and just stuck with
| no options.
|
| But the tooling ecosystem on the JVM truly is horrific.
| iamcalledrob wrote:
| I think there are a lot of "JVM Lifers" who are so deep in
| the ecosystem they are unaware how much better things can
| be.
|
| Anecdote: I wanted to publish a ~100LoC multiplatform
| Kotlin library -- just some bindings. I publish these sorts
| of things for Go with just a "git push".
|
| Steps were: 1. Spend a few hours trying to understand Maven
| Central/Sonotype, register and get "verified". They're in
| the middle of some kind of transition so everything is
| deprecated or unstable. 2. Figure out signing, because of
| course published packages must be signed. Now I have a
| secret to keep track of too, great. 3. Discover that there
| is no stable Gradle plugin for publishing to the "new"
| Maven Central, it's coming soon... Choose one of the
| handful of community plugins with a handful of stars on
| GitHub. 4. Spend a few hours troubleshooting a "Gradle
| build failed to end" error, which ended up being due to
| signing not finding a signing key. 3rd party plugin didn't
| handle errors properly, and a bug in Gradle meant that my
| secret wasn't picked up from local.properties. 4.
| Eventually discover that because Kotlin Multiplatform can't
| be cross-compiled, there is no way to actually publish a
| multiplatform library without spinning up a bunch of CI
| runners. And you can't just publish code -- JVM packages
| have to contain compiled artifacts. 5. Realise this now
| involves maintaining GitHub Actions and Gradle, which is an
| ongoing cost. 6. Give up.
|
| The harm that this kind of complexity must be causing to
| the ecosystem is immeasurable.
| iainmerrick wrote:
| I'd just like to add, NPM gets a lot of flak (mostly
| deservedly) but it too is still vastly easier than
| anything in the JVM ecosystem.
|
| Even with all the headaches around modules versus CJS,
| and JS versus TypeScript, NPM is a lot easier than
| Gradle. Notably, you have a choice of alternate tools (eg
| pnpm, yarn, bun) that interoperate pretty well.
|
| I guess my point is, Gradle and Maven are specifically
| and outstandingly bad.
| lihaoyi wrote:
| If you think gradle and maven are bad, you should try
| Mill! There is more to build tooling than gradle or
| maven, the field has evolved significantly since those
| tools launched 15-20 years ago, and Mill tries to do
| things better
| ackfoobar wrote:
| I must be missing something here. Don't the tools you
| mentioned do a lot less than Gradle? Gradle knows test
| depends on compile, which depends on code generation (say
| protobuf) - with caching and change detection. Compare
| that to chaining up the commands in the `scripts` section
| of `package.json`.
|
| EDIT: another comment making this point:
| https://news.ycombinator.com/item?id=41969847
| iainmerrick wrote:
| I could be convinced if those features of Gradle actually
| worked well, or even worked properly, like dependency
| management does in e.g. Bazel.
|
| In practice, Gradle really seems to fall down on the
| basic task of just being able to build stuff in the first
| place. It feels like you're constantly fighting version
| hell just to find a Gradle version and plugins that work
| together, let alone your actual code dependencies.
|
| And if you actually do need to do something slightly more
| complicated, like code generation, it's very difficult to
| work with and the docs are really bad.
| mike_hearn wrote:
| Although a lot of it is generic badness, Kotlin
| Multiplatform isn't the JVM ecosystem. You don't need CI
| runners to publish a JVM library. The reason it comes up
| with Multiplatform is because Kotlin defines
| "Multiplatform" to mean platforms like JavaScript, or
| their own LLVM based compiler toolchain that bypasses
| JVMs entirely.
| iamcalledrob wrote:
| Very true, although it definitely feels like part of the
| ecosystem since it uses the same project structure, build
| tooling etc.
| user1241320 wrote:
| One note from having worked with both that I don't see
| mentioned: Golang dependencies are sources you basically pull
| and compile with your own code. In JVM-land dependencies are
| precompliled packages (jars). This adds one little step.
| iamcalledrob wrote:
| ...or a big step, if cross-compiling is required (e.g.
| Kotlin Multiplatform)
|
| I'm surprised there is no source-only dependency solution
| for JVM -- it'd solve this issue. Pull down the source and
| build on the fly. Perhaps there is and I'm unaware?
| jitl wrote:
| Well since the builds tend to be monstrously complicated
| for some reason, and there's no standard build tool,
| maybe it's more impossible than possible to consider
| source based distribution. Or it would be like JavaScript
| where you still need a build and publish step to turn
| "developer Java / other languages" into "vanilla source
| distributable Java".
| pkolaczk wrote:
| I'm afraid Java/Scala/Kotlin compilers are too slow to
| make that convenient. Even currently building pure Java
| projects can take minutes when it's compiling just like
| 300k lines. What if it had to compile millions of lines
| from all the dependencies?
| kaba0 wrote:
| The actual compilation step is 100% not the bottleneck -
| it can go as fast as 10k-50k lines per second! (According
| to the Mill benchmark, but that's the Mill-independent
| part).
|
| Comparatively, Go does "only" 16k lines per second based
| on some HN comments.
| pkolaczk wrote:
| But you're likely comparing on different hardware though.
| Go compiling only 16k lines per second is hard to believe
| for me. Maybe they meant on single CPU core. Rustc
| compiles over 50k lines per second on my MBP in debug
| mode and Go must be definitely faster, as everyone knows
| rust is very slow to compile.
|
| But anyway, you may be right. I just ran mvn install for
| the second time with no source change on my current
| project. It took 57 seconds.
| kaba0 wrote:
| The java metric is also from a single core. But you are
| probably right that it should only be taken as a rough
| ballpark, but java is definitely in the same ballpark as
| go in compile speed.
| brabel wrote:
| What issue would it solve? The fact that you can build a
| jar in any OS and then just use that anywhere else is
| actually a huge benefit of using Java, as you don't force
| everyone to re-compile your library source code.
| cryptos wrote:
| You speak from my soul! I'm in the Java world for a really
| long time now and I'm wondering for years why the build tools
| need to be so complicated an annoying. I know Go, Node.js and
| bit of Rust and all have more pleasant easier to use build
| tools! The JVM (or GraalVM) as an ecosystem is just fine and
| probably one of the best, but build tools might be achille's
| heel. Maybe it would be a good idea for Oracle to invest into
| that area ...
| mike_hearn wrote:
| My experience of JS projects is that build tools are
| frequently ad-hoc. That is, there simply isn't a general
| build tool at all, but just a large pile of scripts calling
| under-documented libraries. Parallelization, caching and
| quite often even portability are just missing.
|
| To justify this statement consider this blog post I wrote a
| while ago about porting GitHub Desktop (an Electron app)
| from its prior build/deployment system to Conveyor [1].
| Conveyor is a tool for shipping desktop apps and is
| implemented as a single-purpose build system. The relevant
| part is this commit:
|
| https://github.com/hydraulic-software/github-
| desktop/commit/...
|
| The amount of code that can be deleted is huge! Some of it
| is in-process code that isn't needed with Conveyor (setting
| up Squirrel etc), but a lot is just shell scripts that
| happen to be written in JS. Replacing that with a real
| build system not only simplifies the codebase but means the
| build steps are fully parallelized, fully incremental,
| easier to debug, portable (the build can run on any
| platform), progress is reported in a uniform way and so on.
|
| So whilst the JS ecosystem's approach to build tools may be
| "simple" in some way, in the sense that there's no dominant
| build tool like Maven or Gradle, that simplicity does cost
| you in other ways.
|
| [1] https://hydraulic.dev/blog/8-packaging-electron-
| apps.html (Disclosure: Conveyor is a commercial product
| made by my company)
| dikei wrote:
| > 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.
|
| It's a bit Apple & Orange comparison: publishing a JVM only
| Kotlin library is quite easy, it's the multiplatform part
| that takes time.
| jitl wrote:
| Last time I published a JVM library I had to Open A Jira
| Ticket to request the rights to publish a package on the
| main package registry. Then I had to verify I owned the DNS
| name prefix for my package by fiddling the DNS records at
| my hosting provider. It took days just to get authorized!
| Not including the time needed to like, figure out how to
| make JARs happen.
|
| In go: `git push` to a public repo
|
| In js: `npm publish` after making an NPM account
| pkolaczk wrote:
| In rust: `cargo publish` after making an account on
| crates.io
| mdaniel wrote:
| Merely as a "for your consideration," GitLab ships with
| its own Maven repository (along with npm, docker, Nuget,
| and a bazillion others)[1] so you have total sovereignty
| over the publishing auth story. I can appreciate going
| with Central can be a DX win if you're distributing a
| library, since having folks add <repository> lines to
| their pom.xml or settings.xml is a hassle, but at least
| you get to decide which hassle you prefer :-D
|
| In fairness, GitHub also finally got on board the train,
| too: https://docs.github.com/en/actions/use-cases-and-
| examples/pu...
|
| 1: https://docs.gitlab.com/ee/user/packages/maven_reposit
| ory/
| vips7L wrote:
| Sometimes barrier to entry is good. For example, both npm
| and cargo struggle with package name squatting and
| malicious packages that are miss spellings of common
| packages.
| iamcalledrob wrote:
| This isn't an issue in the Go ecosystem, because the
| package name is the GitHub repo.
|
| I don't think a high barrier to entry is overall good, in
| fact I think it encourages larger more complex packages
| to justify the maintenance burden
| mdaniel wrote:
| Pedantically, that's only _one way_ to resolve a go
| package - and for sure the more obvious[1] - but the most
| famous one I know of is gopkg.in /yaml.whatever that uses
| a <meta> tag to redirect to its actual GH repo, which
| only the deepest golang ninja would know how to use:
| compare view-source:https://gopkg.in/yaml.v3 with view-
| source:https://gopkg.in/yaml.v3?go-get=1
|
| 1: err, modulo that go.mod stuff that secretly adds a
| version slug to an otherwise normal github URL -- I'm
| looking at you, Pulumi: https://github.com/pulumi/pulumi/
| blob/v3.137.0/sdk/go.mod#L1
| neeleshs wrote:
| Interesting. I spend nearly zero time with my maven setup and
| almost all the time is in coding. I am genuinely curious to
| know where that 30% time goes? Is it waiting for builds?
| philipwhiuk wrote:
| > I published my first Golang library in minutes, by
| comparison.
|
| For what platform(s)?
|
| Or did you really just push the source code?
| pkolaczk wrote:
| That's the trick. You publish the source code. And it's
| still faster to build all dependencies from source than
| maven / gradle manages to resolve and download the binary
| dependencies ;)
| brabel wrote:
| That's true, Maven is ridiculously slow to resolve
| dependencies while Gradle only really works with
| reasonable speed if you allow it to hog your system with
| a deamon.
|
| I myself wrote a dependency resolver that matches Maven
| in functionality, and even a large project that uses
| Spring Boot and its dozens of dependencies can be
| resolved in a couple of seconds. About 10x faster than
| Maven or something like that. If you look at Maven's
| source code you'll see why. It's the worst kind of Java
| Enterprise overengineering you can imagine, complete with
| its own dependency injection framework, everything is
| pluggable (for no reason, really, do you really need to
| replace HTTPS for your protocols?? In Plexus you can), to
| the point that all the de-coupling results in lots of
| things duplicating functionality everywhere. I am not
| sure but I would bet Maven parses your POM at least 10
| times to do anything due to the de-coupled nature of it.
| lihaoyi wrote:
| Maven is actually pretty behind in terms of JVM
| dependency resolution. Mill uses Coursier, same as my
| last company did, and when my last company switched from
| Maven to Coursier we saw a 2 order of magnitude speedup,
| with resolution commands that used to take 30min finish
| in a few seconds to give the exact same artifacts and
| versions.
|
| I actually have no idea why these other resolvers are so
| slow, or why Coursier is so fast, but this slowness is
| very much a "maven" or "gradle" thing rather than a "jvm"
| thing. And Mill using coursier does significantly better!
| pkolaczk wrote:
| I've been working on Java-based systems for about 20 years
| now, and I fully relate to that. Same experience.
|
| This is so annoying that I prefer to use Rust over Java even
| in areas where things like better performance or better type
| system don't matter. But being able to start a fresh project
| with one `cargo init` and a few `cargo add` invocations to
| add any dependencies... well, this is priceless.
| mdaniel wrote:
| Are you aware of Maven Archetypes[1]? I believe they were
| the "cookiecutter" before cookiecutter existed, although I
| am 10000000% on-board that their discovery story is total
| garbage :-(
|
| 1: https://maven.apache.org/archetype/index.html and
| https://maven.apache.org/archetype/maven-archetype-
| plugin/us...
| pkolaczk wrote:
| But I don't want to copy a full project with prepopulated
| list of dependencies chosen by someone else. I want to
| start small and add dependencies I need.
|
| It's like LEGO vs Playmobil. I want LEGO. ;)
| brabel wrote:
| Interesting that you ended up going all the way to Rust
| land instead of just using one of the multiple tools that
| have been created to help with this, like:
|
| * Spring Boot (it has a UI to create projects where you
| pick Java version, DB, build tool, some libs etc):
| https://spring.io/guides/gs/spring-boot
|
| * JHipster - the nuclear option, pick what you want a la
| carte: https://www.jhipster.tech/
|
| * JBang - a cute CLI for this: https://www.jbang.dev/
|
| * Maven Archetypes - the old fashioned way (existed before
| "create-app" kind of tools appeared):
| https://maven.apache.org/guides/introduction/introduction-
| to...
|
| And most IDEs also have "new project" wizzards.
| imtringued wrote:
| I'm in JVM land. I spend very little time dealing with the
| build system. It is actually insane how well it works.
|
| Also, why does it matter how long it takes to publish a
| library for the first time? It sounds like a non-issue to me.
| I have written dozens of libraries and published them to a
| local artifactory instance because it simply doesn't matter
| if your company specific code is accessible to the world or
| not.
| rykad wrote:
| To be blunt, nothing.
|
| 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...
| cryptos wrote:
| You have to keep in mind that Gradle Inc. earns money by
| providing consulting for complex builds. An easy build tool
| would destroy this business model ;-)
| mrudolph22 wrote:
| They transitioned to a product company 5+ years ago.
| https://gradle.com
|
| Gradle's complexity comes from at least two places:
|
| 1. The original vision of solving complex multi-
| technology/language Enterprise builds.
|
| 2. Poor early design decisions that they never recovered
| from.
| kaba0 wrote:
| To be blunt, if anything it might be you who live in a closed
| bubble.
|
| Builds that require ad-hoc functionality is the default. It's
| extremely rare that everything fits nicely into "cargo build"
| or other single language build tools' model. And while these
| often have escape hatches, at that point you have to write
| imperative code with no caching and parallelization that is
| literally the job of a build tool.
| rykad wrote:
| I've been doing jvm apps for almost 20yrs... What builds
| need to do and what people made the builds do are
| completely different things. I don't remember a single
| project I was involved in that could not had had a simpler
| build...
| elygre wrote:
| True. In our example we didn't _have to_ generate online
| help and pdf manuals from the same asciidoctor sources.
| But when we chose to, we really needed the customization
| that cradle offered.
| pkolaczk wrote:
| > It's extremely rare that everything fits nicely into
| "cargo build"
|
| 161538 crates do not agree with you ;)
| kaba0 wrote:
| Which are mostly small, isolated _library code_ , whose
| purpose is to be easily incorporated into larger
| programs. That's the 90% easy path of build tools.
|
| What about a large project built over 6 years by 50
| people, and that has to use some obscure technology to
| communicate with company A, and another one that has an
| idiotic build step?
| whartung wrote:
| The big thing is that many Java builds are not just blobs of
| binaries crammed together, but also have structure and
| metadata, sometimes generated on the fly.
|
| Not all Java builds are simply compiles. There are several
| projects that rely on processing steps during the Java build.
| EAR files are jars within jars.
|
| Then, of course, there's all of the dependencies.
|
| The modern Maven based repository based dependency manager is
| a blessing and a curse. Drag and dropping an artifact into
| your project that inevitably downloads the entirety of the
| internet. Now you may wish to cull your dependency tree, so
| that needs to be expressible as well.
|
| The primary benefit of Maven and the pom.xml file is that for
| a vast majority of applications it just work. Even better,
| its become a universal "project" format that many IDEs
| directly support. It well handles "dependency hell" in a
| cross tool way.
|
| I wish Maven were a bit faster, but, simply, it's as fast as
| it can be for what it does. A good Ant build just flies, but
| Ant "doesn't do anything". It's just a bag of steps that it
| follows (for good and ill), in contrast to Mavens declarative
| style (for good and ill).
|
| I have no experience with Gradle other than I've never run
| into enough problems with Maven to justify trying something
| else. On its surface, it doesn't really appeal to me. I was
| comfortable with Ant (I have no problem with XML), I'm mostly
| comfortable with Maven. I've not been unhappy enough with
| Maven to try and jump back to Ant w/Ivy.
| dikei wrote:
| In JVM world, the de factor equivalent to `go build` and `go
| test` are `mvn compile` and `mvn test`, which works 99% percent
| of the time.
|
| 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...
| dcminter wrote:
| Curmudgeon here: this was true for a relatively brief period
| of time. Nowadays I'd say that gradle has (inexplicably to
| me) taken the lead - and everyone adds custom crap to their
| gradle build making them far less predictable than maven
| builds used to be.
|
| I guess it's better than the nightmare over in the front-
| enders' world...
| switchbak wrote:
| I rarely see Maven files in non-trivial projects that are
| anything but a confusing mess of XML.
|
| Granted, the constrained abilities do tend to keep folks
| from writing one-off snowflake build customizations, which
| is nice. But it still leave a hell of a lot to be desired.
| It was however, leagues ahead of Ant, which wasn't a high
| bar.
| dcminter wrote:
| I saw a lot of that too - I just see more and worse with
| gradle.
|
| Maven gave us two things; good dependency management and
| convention driven builds (removing the horrible scripted
| build stuff in Ant).
|
| Gradle from my point of view took the second one away
| again and it feels like it was just because people didn't
| like XML and couldn't be bothered to learn how Maven's
| build lifecycle actually worked!
|
| Like I say, I'm a curmudgeon...
| pkolaczk wrote:
| My typical mvn session after a month of not touching maven:
| % mvn [ERROR] No goals have been specified for this
| build. Uh. % mvn build [ERROR]
| Unknown lifecycle phase "build". Uh, nope, that
| wasn't it.... % mvn compile BUILD
| SUCCESS Now trying to run the app... Error: app
| jar not found. Reading the README.md. Aha! So I need
| to install it! % mvn install
| 16:59:35,075 [INFO] Building <blahblahblah>
| [1/32] ... 16:59:38,483 [INFO]
| -------------------------------------------------------
| 16:59:38,483 [INFO] T E S T S 16:59:38,483 [INFO]
| -------------------------------------------------------
| ^C // me searching on google how to not run
| tests % mvn install -DskipTests=true //
| now good... Ok, let's run some tests. The
| FlakyTest broke again in CI. Let me run it locally:
| % mvn test FlakyTest 17:02:19,481 [ERROR] Unknown
| lifecycle phase "FlakyTest". Aaargh, ok,
| googling it again: % mvn test -Dtest=FlakyTest
| 17:03:16,102 [ERROR] Failed to execute goal
| org.apache.maven.plugins:maven-surefire-plugin:3.3.0:test
| (default-test) on project blah blah: No tests matching
| pattern "FlakyTest" were executed! (Set
| -Dsurefire.failIfNoSpecifiedTests=false to ignore this
| error.)
|
| The original idea behind maven is nice. But the defaults are
| so bad, that the whole experience of convention over
| configuration has been ruined.
|
| Cargo and go build systems took the original maven philosophy
| and implemented them right, with good UX.
|
| Gradle, SBT and friends took a step back to the times before
| maven, and went fully the Ant way, doubling down on
| "configuration over convention". Where "configuration" is
| actually "programming in a DSL on top of another language on
| top of Java".
| mdaniel wrote:
| I'm not trying to ignore your point, but FWIW the _next_
| line after the one you specified includes presumably what a
| normal person would want to see [ERROR] No
| goals have been specified for this build. You must specify
| a valid lifecycle phase or a goal in the format <plugin-
| prefix>:<goal> or <plugin-group-id>:<plugin-artifact-
| id>[:<plugin-version>]:<goal>. Available lifecycle phases
| are: pre-clean, clean, post-clean, validate, initialize,
| generate-sources, process-sources, generate-resources,
| process-resources, compile, process-classes, generate-test-
| sources, process-test-sources, generate-test-resources,
| process-test-resources, test-compile, process-test-classes,
| test, prepare-package, package, pre-integration-test,
| integration-test, post-integration-test, verify, install,
| deploy, pre-site, site, post-site, site-deploy. -> [Help 1]
|
| I am open to the fact that maybe catastrophically old
| versions of Maven did not include that help text, but
| certainly since 3.0 from 14 years ago
| https://github.com/apache/maven/blob/maven-3.0/maven-
| core/sr...
| Calzifer wrote:
| > [ERROR] No goals have been specified for this build.
|
| > [ERROR] Unknown lifecycle phase "build".
|
| And somehow missed that the error message also lists the
| valid lifecycle phases. (could have instead complained that
| it list all lifecycle phases which is a lot)
|
| > // me searching on google how to not run tests
|
| How do I know for other build tools how to skip tests?
| Skipping tests should not be necessary and is done to
| regularly. I would not consider a tool which immediately
| points out how to ignore those stupid tests as good UX.
| pkolaczk wrote:
| When I want to run tests, I tell it to run the tests.
| When I want to install, I tell it to install. I don't
| want it to run tests when I tell it to install. I don't
| want tools who know better what I want to do than me.
| mike_hearn wrote:
| Build tools sit in an unhappy corner of the design space where
| they provide features not found in the core of regular
| programming languages, and which are so generally useful that
| there's a temptation to make them very abstract, but then they
| often _lack_ some of the features that let regular programs
| scale well.
|
| 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.
| AtlasBarfed wrote:
| Build systems exist in two turning complete rabbit holes/
| slippery slides:
|
| Configuration and workflow execution.
| lihaoyi wrote:
| Author here!
|
| `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!
| kaba0 wrote:
| There are quite a few cases: the moment you touch another
| language, resources that require a compile-step (e.g. xml
| schemas to code dtos, protonbuf, all that kind of stuff),
| sometimes even the code itself requires generation.
| zem wrote:
| I recommend the "build systems a la carte" paper for a good
| overview of the various problems build systems address
| cyberax wrote:
| Try to build a Go project that uses Cgo and non-trivial C/C++
| libraries. Throw in cross-compilation for more fun. You'll end
| up with an external build system that invokes Go build as one
| of the steps.
|
| 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.
| iamcalledrob wrote:
| It's not clear to me how this is better than Gradle. And I hate
| Gradle.
|
| 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
| fabioz wrote:
| The first advantage the homepage lists is:
|
| > 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 ;)
| iainmerrick wrote:
| The goal should be more like 50x faster than Gradle. Gradle
| is ludicrously slow (at least in every single Gradle project
| I've had to work with).
| kaba0 wrote:
| First invocation may be. Subsequent builds are very fast,
| unless someone decided to write random bullshit into the
| build scripts that execute at config time, making the
| config process impure.
| iainmerrick wrote:
| I'm mostly thinking of Android projects. If I have time
| I'll try some speed tests with a new basic project. But I
| don't think I've even once done something in Android
| Studio and thought "huh, that was surprisingly fast".
| Maybe some of the hot reloading stuff is okay (when it
| actually works).
| ktosobcy wrote:
| AFAIR author made quite unfair comparison with simple compile
| vs full maven build (that executes a lot of additional stuff)
| switchbak wrote:
| For Scala (of which this is probably the main target) Maven
| builds are especially slow. I would not be surprised if
| that was his early focus.
| speed_spread wrote:
| Are we talking about Maven with its cache extension?
|
| https://github.com/apache/maven-build-cache-extension
|
| Because in my experience, this makes Maven very, very fast.
| kaba0 wrote:
| There is basically no DSL. You simply write what a build needs,
| e.g. you write a function `collectCFiles()` that collects every
| file with extension `.c`. You then issue a command like `gcc
| ${collectCFiles()}`. And pretty much that's it - you can use
| shell commands, or do _anything_ in scala (or java or
| whathaveyou). You simply have your functions return either a
| value (e.g. a checksum) or a location, which is the only mill-
| specific logic. So your compileC() function will simply invoke
| _your collectCFiles()_ function, and this invocation implicitly
| creates a dependency between these tasks. You have written
| literally the simplest way to describe your build logic. But in
| the background mill will cache your functions' inputs outputs
| and parallelize those that need re-run, which is what a build
| tool should do.
|
| The implementation may not be the theoretical best, but I think
| the idea is pretty much the perfect build system out there.
| lihaoyi wrote:
| Author here! The issue here is that builds, and many other
| "just configuration" scenarios, are fundamentally complex. So
| many projects that start off as "just XML" or "just YAML" end
| up implementing their own half-baked programming language
| interepreter inside of their XML/YAML/JSON/whatever.
|
| 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
| skybrian wrote:
| I agree that Bazel did pretty well with Starlark, but the
| reason that's sane is because it's _not_ Python, though the
| syntax is similar. It avoids getting into trouble with people
| using Python language features that would result in upgrade
| hell and annoy other programmers who aren't Python experts.
|
| (Though, debugging complicated Starlark code can still be
| difficult.)
|
| So why not use Starlark? :)
| mrudolph22 wrote:
| Just wanted to mention that there are much better config
| languages than Starlark by now: CUE, Pkl, etc.
| skybrian wrote:
| I was going to mention Cue, but I've only read about it,
| not used it, and couldn't actually say whether it's
| better.
| mrudolph22 wrote:
| I'm afraid that no current config language is an obvious
| fit for Mill. That's because Mill is fully reactive and
| doesn't distinguish between build configuration and
| execution by design.
| vamega wrote:
| Why do you call these other languages "better"? They're
| different, but I'm not sure why either of the one's you
| mentioned would be better for this use case.
| mrudolph22 wrote:
| Modern config languages offer strong validation and
| advanced IDE support, which is essential for a great user
| experience.
|
| https://pkl-lang.org/intellij/current/highlights.html
| lihaoyi wrote:
| Starlark is great, but so is Scala. People underestimate
| how big the ecosystem is even for a niche language like
| Scala:
|
| - Global publishing and distribution infrastructure
|
| - IDE support in multiple IDEs
|
| - A huge ecosystem of third party packages, both Scala and
| Java
|
| - An excellent Scala standard library and Java standard
| library
|
| - Good performance.
|
| - Tooling! Jprofiler is great. Others use Yourkit or JFR.
|
| - Mill leans havily on Scala's FP/OO hybrid style with
| types, while starlark provides none of that and is purely
| untyped procedural code
| ackfoobar wrote:
| > end up implementing their own half-baked programming
| language interpreter inside of their XML
|
| Greenspun's tenth rule.
| cryptos wrote:
| The comparision with Gradle is not up to date. There is stated
| that you would end up in an untyped mess of Groovy build files,
| but statically typed Kotlin files are the default for quite some
| time now in Gradle! https://mill-
| build.org/mill/0.12.1/comparisons/gradle.html
| lihaoyi wrote:
| Author here. Unfortunately this is because my own experience
| with Gradle is not up to date; I've only lived in the Gradle
| Groovy world! If anyone is interested in helping out, I have a
| 1500USD bounty on porting a gradle.kts build to Mill, so we can
| do a fair up-to-date comparison https://github.com/com-
| lihaoyi/mill/issues/3670
| mdaniel wrote:
| I believe you have influence over the syntax highlighting on
| GitHub of .mill files by informing it they're actually Scala,
| which would make reading those files much nicer IMHO:
| https://github.com/github-
| linguist/linguist/blob/v8.0.1/docs...
|
| Or, I believe you can submit a PR to linguist to make it
| globally registered: https://github.com/github-
| linguist/linguist/blob/v8.0.1/CONT...
| imtringued wrote:
| You can maintain your competitive advantage over gradle by
| not constantly breaking backwards compatiblity, by the way.
| brabel wrote:
| I never got why people thought Kotlin would help Gradle. It
| absolutely doesn't.
|
| 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.
| jiehong wrote:
| Why not compare it to bazel/pants/buck2 as well?
|
| Mill seems to have taken some inspiration from those as well.
| lihaoyi wrote:
| Author here. It does! I started working on Mill when I started
| learning Bazel, during my first months at Databricks. There's a
| lot of cross-pollination of ideas there, from my 7 years
| adopting and maintaining the Bazel build at Databricks, but I
| haven't had time to do a proper head-to-head comparison.
| Hopefully someone else can though!
| wocram wrote:
| What drove you away from Bazel?
|
| I would expect anyone considering migrating away from a
| "legacy" tool like maven would consider a "modern" tool like
| Bazel first.
| lihaoyi wrote:
| Bazel is a rats nest of complexity. In my experience it
| does what it does very well once set up, but setting it up
| is tremendously complicated, much of it IMO incidental
| complexity.
|
| Rolling out Bazel at my prior employer tool about one
| person decade of engineering time. I've talked to other
| companies that tried to roll it out and failed. Bazel is
| hard
|
| And Bazel is not really getting any easier! Like most
| projects, it is getting more complex over the years as
| features acrete. I think there is space for a tool like
| Mill for less sophisticated users who can't afford to spend
| a person-decade rolling out their build tool
| robert-brown wrote:
| There's a big difference between the complexity of
| setting up Bazel and the experience of using Bazel at a
| company where Bazel has been set up for you. As a user I
| love Bazel. When working with Java, I use the java_binary
| and java_library rules. When coding in Go, there's
| nothing new to learn regarding the build, just use
| go_binary and go_library instead. Everything is
| repeatable, builds and tests are cached, it's easy to
| query the build dependency tree, etc.
|
| A few startups are offering "Bazel build/test as a
| service." It's one way to eliminate the work involved in
| setting up Bazel for an organization.
| lihaoyi wrote:
| Author here! Hope you take a look at the project and find it
| cool. There's a lot of interesting stuff here. In particular, the
| Video linked on the landing page is a great intros from a Java
| developer point of view, and the following video is a great intro
| from a Build Tool Architect point of view:
|
| * 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
| philipwhiuk wrote:
| The current version is 0.12.1.
|
| What's required for v1.0?
| lihaoyi wrote:
| Traditionally I've labelled my OSS projects 1.0 when they've
| stabilized and the rate of change has greatly reduced. Right
| now Mill is not there yet, but maybe if at end-2025 we
| realize no breaking changes have been needed since end-2024,
| we can call it 1.0
| tenaf0 wrote:
| Just a tiny notice, the github page, nor the website seem
| to currently contain an "installation" link. The one found
| by google returns a 'page not found' for the current
| version.
| iainmerrick wrote:
| I'd be interested to read a comparison with Bazel (which you
| already mention as one of the influences).
|
| 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.
| jitl wrote:
| How possible is it to make your tool "zero-config" by default?
| I see a lot of comments in this thread and elsewhere on twitter
| asking for essentially `go build`, `go fmt`, `go test` for
| Java/JVM. I think the language has quite strong convention
| around directory layout and file naming already, so do you
| think it would be possible for mill or a mill wrapper to offer
| the same kind of standardized zero config workflow? I think a
| JVM tool that gets that right - takes it as far as possible to
| the golang model - would have a lot of happy users.
| hocuspocus wrote:
| Scala CLI has replaced the default runner since Scala 3.5, so
| you can effectively do `scala run`, `scala fmt`, and so on.
| On the Java side, I believe JBang provides a very similar
| developer experience.
|
| Fundamentally it's hard to reconcile both worlds though.
| Building non-trivial multi-module projects on the JVM is
| inherently complex especially when you throw in multiple
| build targets, multiple toolchains, multiple platforms...
|
| With simpler build tools (like in Go or Rust) you shift this
| complexity elsewhere, typically in a Makefile and/or a
| Docker/OCI based build pipeline, and these can get pretty
| complex too. Let alone distributed build tools like Bazel.
|
| - https://scala-cli.virtuslab.org
|
| - https://www.jbang.dev
| vvillena wrote:
| There's scala-cli, which has become the default Scala run
| command since Scala 3.5 but is also available separately. It
| has all those bells and whistles and allows scripts to grow
| organically. And no matter the name, it handles Java code
| too.
|
| With scala-cli, there's not even a need to download a Java
| runtime or a language distribution. You can let the runner do
| its thing, or pass options to choose the JVM and the language
| version to use, or even write those options into special
| headers in the code files. You can also write tests, format
| code... it's all built-in. And in cases the code outgrows the
| tool and there's a need to migrate to a different build tool,
| there's even a feature to export the build to Sbt or Mill.
| Axnyff wrote:
| Hi, it looks pretty interesting! There's a broken link in the
| homepage though, Mill vs sbt links to the gradle page
|
| Good luck for your project!
| wiradikusuma wrote:
| Does it support Quarkus (esp. native build)?
| hocuspocus wrote:
| There is no reason it would not:
| https://github.com/alexarchambault/mill-native-image
| layer8 wrote:
| I couldn't quickly find how dependency resolution and
| versioning works in Mill. Can you give any pointers?
|
| Also, what's with the "ivy" on https://mill-
| build.org/mill/0.12.1/comparisons/maven.html ? Any relation to
| Apache Ivy?
| lihaoyi wrote:
| Dependency resolution uses Coursier, which is one of the open
| source JVM dependency resolvers. SBT uses it too, and my last
| company used it with Bazel
|
| The "ivy" thing is legacy haha. Mill used to use Apache Ivy
| to resolve dependencies, years ago. Coursier was a
| better/faster replacement, but names have a tendency to stick
| around
| sireat wrote:
| Just a note that the author Li Haoyi is a fantastic contributor
| to Scala community.
|
| 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.
| k3vinw wrote:
| The thing that's great about maven is its declarative nature. You
| can declare goals and profiles for whatever you need the build
| system to do.
|
| 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?
| lihaoyi wrote:
| Yes, IDE support in Mill is key. Without IntelliJ or VSCode,
| Mill would not be nearly as pleasant to use as it is today.
|
| 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!
| msl09 wrote:
| Nice try, I'm still not going to write scala code.
| galdosdi wrote:
| Build times always were my biggest Scala complaint. Arguably
| code base specific, as I suspect it had a lot to do with all
| the macros and type level metaprogramming, but, if that kind of
| thing is possible and customary, an average working programmer
| who doesn't control the codebase they show up to is going to
| end up stuck dealing with it.
|
| It's a lot easier to build a language that works great, but
| only in the hands of a single skilled careful owner, than a
| language that stands up to the abuse of many careless temporary
| users, and still gets from point A to point B reliably.
|
| Like the difference between a sportscar and a rental company or
| police fleet sedan.
|
| Scala was a porsche, but most of us need camrys.
| whoodle wrote:
| Sorry to hijack this thread a bit, but I currently work at a
| Scala shop and have grown to like writing it. I worked at Clojure
| heavy place previously. This tool looks neat.
|
| Has anyone at the senior level recently moved on from Scala to
| other languages recently? Any issue finding jobs or learning the
| new role?
| pnathan wrote:
| I've used mill for some Scala projects in the past and I give it
| 5/5.
| carrotsalad wrote:
| Mill looks interesting, but, _from a Java development
| perspective_, it has the same fundamental challenge as Gradle
| (and most other build systems), which is that its config language
| _is something other than Java_. That means there's a significant
| cognitive burden to understand and manage something that one
| hopes to not have to think about very often.
|
| 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.
| beeboobaa3 wrote:
| My problem with gradle is that its configuration language is a
| programming language.
|
| Sounds amazing in practice. And it is. Until you need to fix a
| 3 year old build that has some insane wizardry going on.
| mdaniel wrote:
| > Until you need to fix a 3 year old build that has some
| insane wizardry going on.
|
| My experience with Gradle is that it's the "3 year old build"
| that is almost certainly a death knell more than the insane
| wizardry part. My experience: git clone
| .../ancient-codebase.git cd ancient-codebase
| ./gradlew # <-- oh, the wrapper, so it will download the
| version it wants, hazzah! for _ in $(seq 1 infinity);
| do echo gradle vomit you have to sift through; done
| echo 'BUILD FAILED' >&2 exit 1
|
| Contrast that with https://github.com/apache/maven-app-engine
| (just to pick on something sorted by earliest push date, some
| 10 years ago): $ git clone
| https://github.com/apache/maven-app-engine.git $ cd
| maven-app-engine $ mvn -B compile [INFO]
| -------------------------------------------------------------
| [ERROR] COMPILATION ERROR : [INFO]
| -------------------------------------------------------------
| [ERROR] error: Source option 6 is no longer supported. Use 8
| or later. [ERROR] error: Target option 6 is no longer
| supported. Use 8 or later. [INFO] 2 errors
| $ echo "Java gonna Java" $ git grep -n source.*6
| pom.xml:133: <source>1.6</source> $ sed
| -i.bak -e 's/1.6/1.8/g' pom.xml $ mvn -B compile
| [INFO] BUILD SUCCESS
| brabel wrote:
| I dislike Gradle as much as you probably do, but between
| Maven and Gradle, the one that "vomits" stuff on the
| command line is definitely Maven. Gradle errs by going too
| far to the other end: it just doesn't log anything at all,
| even the tasks that are actually being run (vs skipped...
| do you know how to get Gradle to show them?? It's `gradle
| --console=plain`, so obvious!! Why would anyone complain
| about that, right?!) or the print outs you add to the build
| to try to understand what the heck is going on.
| dkarl wrote:
| Having worked with Maven and Gradle, I'd say Gradle was worse
| in the average case, but better in the worst case. There are
| way more Gradle projects with unnecessary custom build code
| because Gradle makes it easy to do.
|
| On the other hand, when builds are specified in a limited-
| power build config language, like POM, then when someone
| needs to do something custom, they have to extend or modify
| the build tool itself, which in my experience causes way more
| pain than custom code in a build file. Custom logic in Maven
| means building and publishing an extension; it can't be local
| to the project. You may encounter projects that depend on
| extensions from long-lost open source projects, or long-lost
| internal projects. On one occasion, I was lucky to find a
| source jar for the extension in the Maven repository. It can
| be a nightmare.
|
| The same could happen with Gradle, since a build can depend
| on arbitrary libraries, but I never saw it in the wild.
| People depended on major open-source extensions and added
| their own custom code inside the build.
| cyberax wrote:
| > it can't be local to the project
|
| It certainly can be, in the same repository.
| dkarl wrote:
| When I used Maven, extensions had to be published to and
| pulled from a public repo. We couldn't even use the
| private repo that we used for the rest of our libraries,
| because the extension had to be loaded before Maven read
| the file where our private repo was configured.
|
| Whereas a Gradle build can read Groovy files straight
| from disk.
| cyberax wrote:
| > When I used Maven, extensions had to be published to
| and pulled from a public repo.
|
| You can just `mvn install` them locally into your local
| repository.
| lihaoyi wrote:
| You can, but why should you need to? Why can't the build
| tool take the plugin code directly off of disk, build it,
| and use it? This kind of orchestration of manual steps is
| what build tools are meant to be good at
| cyberax wrote:
| Sure. But adding ability to self-modify the build
| drastically increases the complexity of a build tool.
| Maven developers decided that they want to avoid that.
| mdaniel wrote:
| As the most extreme counterexample of your ...
| experience[1], someone made a _plugin_ that allowed
| writing pom files in languages other than XML:
| https://github.com/takari/polyglot-
| maven/tree/polyglot-0.7.2...
|
| With an especial nod to
| https://github.com/takari/polyglot-
| maven/tree/polyglot-0.7.2... given this submission
|
| 1: I believe that you encountered errors, programming is
| packed to the gills with them, but correlation is not
| causation in that just because it did not immediately
| work in your setup does not mean it's impossible or
| forbidden
| jackcviers3 wrote:
| It's intended as a replacement for _scala_ builds. Having a
| build definition in the native language that doesn't require a
| different syntax (like a declarative syntax such as maven xml
| or toml) makes task customization easier for the maintainer of
| a given project. Unfortunately, it also means that you have to
| know the language and read the documentation for the build
| system.
|
| 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.
|
| 1. https://bleep.build/docs/
|
| 2. https://scala-cli.virtuslab.org/
| carrotsalad wrote:
| > It's intended as a replacement for _scala_ builds. Having a
| build definition in the native language [...] makes task
| customization easier for the maintainer
|
| Totally agree! But the title of the post says "Mill: A fast
| JVM build tool for Java and Scala" :) - it certainly looks
| like better tool for the Scala community.
|
| For projects that are primarily building Java sources, it'd
| be nice to have a build system that uses Java code to
| describe the build. I don't think this exists at the moment.
| crznp wrote:
| One option is `bld`. They added IntelliJ support since I
| looked at it last, so that's nice.
|
| https://github.com/rife2/bld
| lihaoyi wrote:
| The intention has changed, Mill now explicity targets Java
| and Kotlin as well. It now has dedicated Java/Kotlin docsite
| sections and examples, and has grown integrations with
| Palantir-Format, Checkstyle, Errorprone, Jacoco, and all
| their Kotlin equivalents (ktfmt, ktlint, kover).
|
| Java and Scala (and Kotlin) are remarkably similar from a
| tooling perspective, so Mill tries to target both using the
| same shared infrastructure
| mike_hearn wrote:
| Not to defend Gradle too much, but Groovy is a superset of
| Java. So if you want, you can just use the regular Groovy
| dialect and then write Java in your build scripts, it should
| work.
|
| This is not entirely a solution though, because Gradle's APIs
| are fairly complicated and change regularly.
| kaba0 wrote:
| (Nitpick, but it's just a "superficial" superset. The biggest
| difference is probably doing "multi-methods", aka the
| _runtime_ type of an argument deciding which method
| implementation to call vs java's static overload resolution.)
| lihaoyi wrote:
| Even in Java, because the language is relatively verbose, many
| frameworks fall back to an "inner platform" of magic
| annotations which have the same problem: e.g. just because you
| know how Java works doesnt mean your mind hasn't unloaded all
| the SpringBoot annotation semantics! But despite that it is
| worth it, because conciseness does matter.
|
| 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
| mrudolph22 wrote:
| I gave Mill a try earlier this year. My hope was to escape the
| nightmare that is Gradle, which I've been using for many years.
| Mill sounds great in theory (except for the Scala DSL).
| Unfortunately, I couldn't get a basic Java build to work in half
| a day, even though I have (admittedly rusty) working knowledge of
| Scala. It was one obscure error after another. My conclusion was
| that Java support isn't ready. There was also very little
| documentation on how to build Java.
|
| 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.
| lihaoyi wrote:
| Depending on when you tried, it could be worth trying again:
| support for Java has improved greatly in the last few months,
| as have the documentation. Come by our discord channel if you
| get stuck and i can help unblock you
| mrudolph22 wrote:
| Thanks for the offer! I'll give Mill another shot the next
| time Gradle drives me crazy. :-)
| PaulHoule wrote:
| Speed wins for dev tools.
|
| 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?)
| thefaux wrote:
| The last time I checked, sbt was much faster than mill for
| incremental builds. Mill has a faster cold startup time, but sbt
| uses classloader tricks to reuse jitted classes so that it
| doesn't have to reload the scala standard library. When running
| tests continuously and rerunning on save, sbt was much faster
| than mill for equivalent projects. I haven't tested in three
| years or so though. But I would encourage people to make a simple
| project in sbt and mill and run `sbt ~test` and compare it to
| `mill -w test`. In the past, I found that after a few iterations,
| sbt could respond to changes in a few hundred milliseconds while
| mill would take multiple seconds to retest the same code. That
| difference really adds up when you are iterating on a problem.
|
| 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).
| weego wrote:
| sbt is one of the worst engineering mistakes I've ever
| witnessed. It was a constant source of esoteric ergonomics and
| frustration for no clear reason other than being the pet
| project of someone who _really loved_ implicits.
| lihaoyi wrote:
| The test thing is just a matter of defaults, in Mill subprocess
| testing is the default and in-process testing opt-in via
| .testLocal.
|
| I also believed that a lot of existing JVM tooling is bloated
| and slow, so we are in agreement! Mill tries to be different,
| so do give it a chance if you can. There is life beyond Maven,
| Gradle, and SBT
| TeaVMFan wrote:
| It's great to see continuing innovation in the Java space!
|
| 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.
|
| https://github.com/apache/maven-mvnd
| speed_spread wrote:
| I'm not sure I like the daemon approach. But the cache
| extension provided me fantastic gains:
| https://github.com/apache/maven-build-cache-extension
| lihaoyi wrote:
| Mill uses the same daemon design as Gradle and mvnd. You do
| hit edge cases occasionally, but overall it works great
| Raydat wrote:
| Big fan of mill! (Coming from maven, Gradle and SBT) - the 1:1
| mapping of build tasks to output files is the big one for me as
| it makes understanding other people's builds so much easier going
| through it step by step
___________________________________________________________________
(page generated 2024-10-28 23:01 UTC)