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
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.
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
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.)
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.
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.
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.
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.
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).
Mill's early goal was to be a saner sbt, incidentally also fixing the parts of sbt that are/were unreasonably slow due to questionable design decisions.
Maven has never been relevant to the Scala ecosystem given most of the community has pretty much moved straight from ant to sbt. Only a few Spark related projects stubbornly use Maven, which is a major pain given the lack of cross-building abilities. Slow dependency resolution and inefficient use of Zinc merely add insult to injury.
Yeah... that's my experience with Scala all around - it's abysmally slow, especially if you use any sort of "metaprograming"... (one of the reasons I stay clear of the language)
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