From 30c0051764ad4517b3ab609ba50c271c0f562f0d Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Tue, 29 Oct 2024 20:45:35 -0700 Subject: [PATCH] Add `Why Mill?` top-level section to readme (#3870) The goal is to be a single page to answer this frequently asked question, skimming over and summarizing the interesting bits from the other more-detailed pages in a way they are easily consumed in one read-through. For now it's mostly transcribed from my Japan Java User Group talk, and very copy-pasty with other parts of the repo. Not perfect, but it can evolve over time --- docs/modules/ROOT/images/index/gradle.svg | 19 + .../ROOT/images/index/iconscout-java.svg | 7 + .../ROOT/images/index/iconscout-kotlin.svg | 26 + .../ROOT/images/index/iconscout-scala.svg | 21 + docs/modules/ROOT/images/index/maven.png | Bin 0 -> 58060 bytes docs/modules/ROOT/images/index/sbt.png | Bin 0 -> 5465 bytes docs/modules/ROOT/nav.adoc | 169 +++--- docs/modules/ROOT/pages/index.adoc | 32 +- docs/modules/ROOT/pages/why-mill.adoc | 510 ++++++++++++++++++ docs/supplemental-ui/partials/nav-tree.hbs | 2 +- 10 files changed, 687 insertions(+), 99 deletions(-) create mode 100644 docs/modules/ROOT/images/index/gradle.svg create mode 100644 docs/modules/ROOT/images/index/iconscout-java.svg create mode 100644 docs/modules/ROOT/images/index/iconscout-kotlin.svg create mode 100644 docs/modules/ROOT/images/index/iconscout-scala.svg create mode 100644 docs/modules/ROOT/images/index/maven.png create mode 100644 docs/modules/ROOT/images/index/sbt.png create mode 100644 docs/modules/ROOT/pages/why-mill.adoc diff --git a/docs/modules/ROOT/images/index/gradle.svg b/docs/modules/ROOT/images/index/gradle.svg new file mode 100644 index 00000000000..8e7431e8230 --- /dev/null +++ b/docs/modules/ROOT/images/index/gradle.svg @@ -0,0 +1,19 @@ + + + diff --git a/docs/modules/ROOT/images/index/iconscout-java.svg b/docs/modules/ROOT/images/index/iconscout-java.svg new file mode 100644 index 00000000000..acf25c47343 --- /dev/null +++ b/docs/modules/ROOT/images/index/iconscout-java.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/docs/modules/ROOT/images/index/iconscout-kotlin.svg b/docs/modules/ROOT/images/index/iconscout-kotlin.svg new file mode 100644 index 00000000000..48ff1667158 --- /dev/null +++ b/docs/modules/ROOT/images/index/iconscout-kotlin.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/modules/ROOT/images/index/iconscout-scala.svg b/docs/modules/ROOT/images/index/iconscout-scala.svg new file mode 100644 index 00000000000..279070c5eec --- /dev/null +++ b/docs/modules/ROOT/images/index/iconscout-scala.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + diff --git a/docs/modules/ROOT/images/index/maven.png b/docs/modules/ROOT/images/index/maven.png new file mode 100644 index 0000000000000000000000000000000000000000..5b57ab516c93acba69d420f19083fc4149369bd4 GIT binary patch literal 58060 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
  • eq9J0IHpPtNa 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 literal 0 HcmV?d00001 diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index 3cbe43df906..648c969b58f 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -3,108 +3,99 @@ // but we intentionally skim over them and do not go into depth: the focus is // on end user goals and how to achieve them. -.xref:index.adoc[] - -.xref:javalib/intro.adoc[] -* xref:javalib/builtin-commands.adoc[] -* xref:javalib/module-config.adoc[] -* xref:javalib/dependencies.adoc[] -* xref:javalib/testing.adoc[] -* xref:javalib/linting.adoc[] -* xref:javalib/publishing.adoc[] -* xref:javalib/build-examples.adoc[] -* xref:javalib/web-examples.adoc[] -* xref:javalib/android-examples.adoc[] - -.xref:scalalib/intro.adoc[] -* xref:scalalib/builtin-commands.adoc[] -* xref:scalalib/module-config.adoc[] -* xref:scalalib/dependencies.adoc[] -* xref:scalalib/testing.adoc[] -* xref:scalalib/linting.adoc[] -* xref:scalalib/publishing.adoc[] -* xref:scalalib/build-examples.adoc[] -* xref:scalalib/web-examples.adoc[] - -.xref:kotlinlib/intro.adoc[] -* xref:kotlinlib/builtin-commands.adoc[] -* xref:kotlinlib/module-config.adoc[] -* xref:kotlinlib/dependencies.adoc[] -* xref:kotlinlib/testing.adoc[] -* xref:kotlinlib/linting.adoc[] -* xref:kotlinlib/publishing.adoc[] -// * xref:kotlinlib/build-examples.adoc[] -* xref:kotlinlib/web-examples.adoc[] -* xref:kotlinlib/android-examples.adoc[] - -.Build Tool Comparisons -* xref:comparisons/maven.adoc[] -* xref:comparisons/gradle.adoc[] -* xref:comparisons/sbt.adoc[] - -.The Mill CLI -* xref:cli/installation-ide.adoc[] -* xref:cli/flags.adoc[] -* xref:cli/alternate-installation.adoc[] - +* xref:why-mill.adoc[] +* xref:javalib/intro.adoc[] +** xref:javalib/builtin-commands.adoc[] +** xref:javalib/module-config.adoc[] +** xref:javalib/dependencies.adoc[] +** xref:javalib/testing.adoc[] +** xref:javalib/linting.adoc[] +** xref:javalib/publishing.adoc[] +** xref:javalib/build-examples.adoc[] +** xref:javalib/web-examples.adoc[] +** xref:javalib/android-examples.adoc[] +* xref:scalalib/intro.adoc[] +** xref:scalalib/builtin-commands.adoc[] +** xref:scalalib/module-config.adoc[] +** xref:scalalib/dependencies.adoc[] +** xref:scalalib/testing.adoc[] +** xref:scalalib/linting.adoc[] +** xref:scalalib/publishing.adoc[] +** xref:scalalib/build-examples.adoc[] +** xref:scalalib/web-examples.adoc[] +* xref:kotlinlib/intro.adoc[] +** xref:kotlinlib/builtin-commands.adoc[] +** xref:kotlinlib/module-config.adoc[] +** xref:kotlinlib/dependencies.adoc[] +** xref:kotlinlib/testing.adoc[] +** xref:kotlinlib/linting.adoc[] +** xref:kotlinlib/publishing.adoc[] +// ** xref:kotlinlib/build-examples.adoc[] +** xref:kotlinlib/web-examples.adoc[] +** xref:kotlinlib/android-examples.adoc[] +* Build Tool Comparisons +** xref:comparisons/maven.adoc[] +** xref:comparisons/gradle.adoc[] +** xref:comparisons/sbt.adoc[] +* The Mill CLI +** xref:cli/installation-ide.adoc[] +** xref:cli/flags.adoc[] +** xref:cli/alternate-installation.adoc[] // This section gives a tour of the various user-facing features of Mill: // library deps, out folder, queries, tasks, etc.. These are things that // every Mill user will likely encounter, and are touched upon in the various // language-specific sections, but here we go into a deeper language-agnostic // discussion of what these Mill features ar and how they work -.Mill Fundamentals -* xref:fundamentals/tasks.adoc[] -* xref:fundamentals/modules.adoc[] -* xref:fundamentals/out-dir.adoc[] -* xref:fundamentals/query-syntax.adoc[] -* xref:fundamentals/library-deps.adoc[] -* xref:fundamentals/cross-builds.adoc[] -* xref:fundamentals/bundled-libraries.adoc[] - +* Mill Fundamentals +** xref:fundamentals/tasks.adoc[] +** xref:fundamentals/modules.adoc[] +** xref:fundamentals/out-dir.adoc[] +** xref:fundamentals/query-syntax.adoc[] +** xref:fundamentals/library-deps.adoc[] +** xref:fundamentals/cross-builds.adoc[] +** xref:fundamentals/bundled-libraries.adoc[] // This section talks about Mill plugins. While it could theoretically fit in // either section above, it is probably an important enough topic it is worth // breaking out on its own -.Extending Mill -* xref:extending/import-ivy-plugins.adoc[] -* xref:extending/contrib-plugins.adoc[] +* Extending Mill +** xref:extending/import-ivy-plugins.adoc[] +** xref:extending/contrib-plugins.adoc[] // See also the list in Contrib_Plugins.adoc -** xref:contrib/artifactory.adoc[] -** xref:contrib/bintray.adoc[] -** xref:contrib/bloop.adoc[] -** xref:contrib/buildinfo.adoc[] -** xref:contrib/codeartifact.adoc[] -** xref:contrib/docker.adoc[] -** xref:contrib/flyway.adoc[] -** xref:contrib/gitlab.adoc[] -** xref:contrib/jmh.adoc[] -** xref:contrib/playlib.adoc[] -** xref:contrib/proguard.adoc[] -** xref:contrib/scalapblib.adoc[] -** xref:contrib/scoverage.adoc[] -** xref:contrib/sonatypecentral.adoc[] -** xref:contrib/testng.adoc[] -** xref:contrib/twirllib.adoc[] -** xref:contrib/versionfile.adoc[] -* xref:extending/thirdparty-plugins.adoc[] -* xref:extending/running-jvm-code.adoc[] -* xref:extending/writing-plugins.adoc[] -* xref:extending/meta-build.adoc[] -* xref:extending/new-language.adoc[] - +*** xref:contrib/artifactory.adoc[] +*** xref:contrib/bintray.adoc[] +*** xref:contrib/bloop.adoc[] +*** xref:contrib/buildinfo.adoc[] +*** xref:contrib/codeartifact.adoc[] +*** xref:contrib/docker.adoc[] +*** xref:contrib/flyway.adoc[] +*** xref:contrib/gitlab.adoc[] +*** xref:contrib/jmh.adoc[] +*** xref:contrib/playlib.adoc[] +*** xref:contrib/proguard.adoc[] +*** xref:contrib/scalapblib.adoc[] +*** xref:contrib/scoverage.adoc[] +*** xref:contrib/sonatypecentral.adoc[] +*** xref:contrib/testng.adoc[] +*** xref:contrib/twirllib.adoc[] +*** xref:contrib/versionfile.adoc[] +** xref:extending/thirdparty-plugins.adoc[] +** xref:extending/running-jvm-code.adoc[] +** xref:extending/writing-plugins.adoc[] +** xref:extending/meta-build.adoc[] +** xref:extending/new-language.adoc[] // This section focuses on diving into deeper, more advanced topics for Mill. // These are things that most Mill developers would not encounter day to day, // but people developing Mill plugins or working on particularly large or // sophisticated Mill builds will need to understand. -.Mill In Depth -* xref:depth/large-builds.adoc[] -* xref:depth/sandboxing.adoc[] -* xref:depth/evaluation-model.adoc[] -* xref:depth/design-principles.adoc[] -* xref:depth/why-scala.adoc[] - +* Mill In Depth +** xref:depth/large-builds.adoc[] +** xref:depth/sandboxing.adoc[] +** xref:depth/evaluation-model.adoc[] +** xref:depth/design-principles.adoc[] +** xref:depth/why-scala.adoc[] // Reference pages that a typical user would not typically read top-to-bottom, // but may need to look up once in a while, and thus should be written down // *somewhere*. -.Reference -* {mill-doc-url}/api/latest/mill/index.html[Mill Scaladoc] -* xref:reference/changelog.adoc[] +* Reference +** {mill-doc-url}/api/latest/mill/index.html[Mill Scaladoc] +** xref:reference/changelog.adoc[] diff --git a/docs/modules/ROOT/pages/index.adoc b/docs/modules/ROOT/pages/index.adoc index 5fd99199d09..26c6717cfc3 100644 --- a/docs/modules/ROOT/pages/index.adoc +++ b/docs/modules/ROOT/pages/index.adoc @@ -70,15 +70,23 @@ xref:extending/writing-plugins.adoc#_publishing[publish them] to Maven Central f To begin using Mill, check out the introductory documentation for each language: -* xref:javalib/intro.adoc[] -* xref:scalalib/intro.adoc[] -* xref:kotlinlib/intro.adoc[] -If you prefer a video introduction, see the following tech talk that was presented -at the Japan Java User Group Fall Conference Oct 2024: +[cols="1a,1a,1a"] +|=== +| xref:javalib/intro.adoc[image:index/iconscout-java.svg[java,32] Java with Mill] +| xref:scalalib/intro.adoc[image:index/iconscout-scala.svg[scala,20] Scala with Mill] +| xref:kotlinlib/intro.adoc[image:index/iconscout-kotlin.svg[kotlin,32] Kotlin with Mill] +|=== -* https://www.youtube.com/watch?v=Dry6wMRN6MI[Video: Better Java Builds with the Mill Build Tool] +For a quick introduction of why you may care about Mill, see the following page: + +* xref:why-mill.adoc[] + +Or if you prefer a video introduction: + +* https://www.youtube.com/watch?v=Dry6wMRN6MI[Video: Better Java Builds with the Mill Build Tool], + Japan Java User Group Fall Conference Oct 2024 Mill is used to build many real-world projects, such as the https://github.com/swaldman/c3p0[C3P0 JDBC Connection Pool], @@ -95,9 +103,15 @@ https://gradle.org/[Gradle], https://bazel.build/[Bazel], but tries to learn fro strengths of each tool and improve on their weaknesses. For comparisons with existing build tools, check out these pages: -* xref:comparisons/maven.adoc[Mill vs Maven] -* xref:comparisons/gradle.adoc[Mill vs Gradle] -* xref:comparisons/sbt.adoc[Mill vs SBT] + +[cols="1a,1a,1a"] +|=== +| xref:comparisons/maven.adoc[image:index/maven.png[maven,24] Mill vs Maven] +| xref:comparisons/gradle.adoc[image:index/gradle.svg[gradle,32] Mill vs Gradle] +| xref:comparisons/sbt.adoc[image:index/sbt.png[sbt,32] Mill vs SBT] +|=== + + If you want to contribute to Mill, or are interested in the fundamental ideas behind Mill rather than the user-facing benefits discussed above, check out the page on diff --git a/docs/modules/ROOT/pages/why-mill.adoc b/docs/modules/ROOT/pages/why-mill.adoc new file mode 100644 index 00000000000..c20f8ee6db9 --- /dev/null +++ b/docs/modules/ROOT/pages/why-mill.adoc @@ -0,0 +1,510 @@ += Why Mill? + +Mill is a fast build tool for Java, Scala, and Kotlin. Although the Java +compiler is very fast and the Java language is easy to learn, JVM build tools are +known to be slow and hard to use. Mill tries to offer a better alternative: 2-10x faster +than Maven or Gradle, better IDE support, and extensibility without needing plugins. +This results in time savings due to less time waiting for your build tool, as well as less +time struggling with your build tool, and more time to focus on the actual work you need to do. + +At a first glance, Mill looks like any other build tool. You have build files, you configure +dependencies, you can compile, run, or test your project: + +```scala +// build.mill +package build +import mill._, javalib._ + +object foo extends JavaModule { + def ivyDeps = Agg( + ivy"net.sourceforge.argparse4j:argparse4j:0.9.0", + ivy"org.thymeleaf:thymeleaf:3.1.1.RELEASE" + ) + + object test extends JavaTests with TestModule.Junit4 +} +``` +```bash +> /mill foo.compile +compiling 1 Java source... + +> /mill foo.run --text hello +

    hello

    + +> ./mill foo.test +Test foo.FooTest.testEscaping finished, ... +Test foo.FooTest.testSimple finished, ... +0 failed, 0 ignored, 2 total, ... +``` + +Beyond the basics, Mill provides 3 major advantages over other build tools. The comparison pages +for the respective build tool go into more detail (for xref:comparisons/maven.adoc[Maven], +xref:comparisons/gradle.adoc[Gradle], and xref:comparisons/sbt.adoc[SBT]), but at a high level +these advantages are: + +1. Performance + * *Mill offers a 2-10x speedup means less time waiting for your build tool*, meaning + less time waiting for your build and more time doing useful work + +2. Ease of Use + * *Mill offers better IDE support in IntelliJ and VSCode and rich visualization tools*, + to help understand your build and what it is doing + +3. Extensibility + * *Directly write code or use any Java library from Maven Central in your build*, + without being beholden to third party plugins that may not exist or be well maintained. + +We will discuss each one in turn: + +## Performance + +### Maven + +Overall across our benchmarks, Mill is 5-10x faster than Maven for clean compiles, +both parallel and sequential, and for many modules or for a single module: + +|=== +| Benchmark | Maven | Mill | Speedup +| xref:comparisons/maven.adoc#_sequential_clean_compile_all[Sequential Clean Compile All] | 2m 31.12s | 0m 22.19s | 6.8x +| xref:comparisons/maven.adoc#_parallel_clean_compile_all[Parallel Clean Compile All] | 1m 16.45s | 0m 09.95s | 7.7x +| xref:comparisons/maven.adoc#_clean_compile_single_module[Clean Compile Single Module] | 0m 19.62s | 0m 02.17s | 9.0x +| xref:comparisons/maven.adoc#_incremental_compile_single_module[Incremental Compile Single Module] | 0m 21.10s | 0m 00.54s | 39.1x +| xref:comparisons/maven.adoc#_no_op_compile_single_module[No-Op Compile Single Module] | 0m 17.34s | 0m 00.47s | 36.9x +|=== + +For the purposes of this page, we will focus on two benchmarks + +#### Parallel Clean Compile All + +|=== +| Benchmark | Maven | Mill | Speedup +| xref:comparisons/maven.adoc#_parallel_clean_compile_all[Parallel Clean Compile All] | 1m 16.45s | 0m 09.95s | 7.7x +|=== + + +```bash +> time ./mvnw -T 10 -DskipTests -Dcheckstyle.skip -Denforcer.skip=true clean install + +> ./mill clean; time ./mill __.compile +``` + + +This benchmark involves running `clean` to delete all generated files and re-compiling +everything in parallel. For Maven, parallelism is opt-in via `-T 10`, while for Mill it +is enabled by default. + +Mill sees a significant ~8x speedup over Maven for this benchmark. + +#### Incremental Compile Single-Module + +|=== +| Benchmark | Maven | Mill | Speedup +| xref:comparisons/maven.adoc#_incremental_compile_single_module[Incremental Compile Single Module] | 0m 21.10s | 0m 00.54s | 39.1x +|=== + +```bash +$ echo "" >> common/src/main/java/io/netty/util/AbstractConstant.java +$ time ./mvnw -pl common -DskipTests -Dcheckstyle.skip -Denforcer.skip=true install +Compiling 174 source files to /Users/lihaoyi/Github/netty/common/target/classes +Compiling 60 source files to /Users/lihaoyi/Github/netty/common/target/test-classes + + +$ echo "" >> common/src/main/java/io/netty/util/AbstractConstant.java +$ time ./mill common.test.compile +compiling 1 Java source to /Users/lihaoyi/Github/netty/out/common/compile.dest/classes ... +``` + +This benchmark involves making a single edit to a single already-compiled file in `common` - +adding a single newline to the end of the file - and re-compiling `common` and `common.test`. + +Mill sees a huge ~39x speedup for this benchmark, because Mill's incremental compiler (Zinc) +is able to detect that only one file in one module has changed, and the change is small enough +to not require other files to re-compile. In contrast, Maven re-compiles all files in both +modules, even though only one file was touched and the change was trivial. + + +### Gradle + +The comparison with Gradle is less stark, but still significant. Mill is 3-4x faster than Gradle +for clean compiles, both parallel and sequential, and for many modules or for a single module: + + +|=== +| Benchmark | Gradle | Mill | Speedup +| xref:comparisons/maven.adoc#_sequential_clean_compile_all[Sequential Clean Compile All] | 17.6s | 5.40s | 3.3x +| xref:comparisons/maven.adoc#_parallel_clean_compile_all[Parallel Clean Compile All] | 12.3s | 3.57s | 3.4x +| xref:comparisons/maven.adoc#_clean_compile_single_module[Clean Compile Single Module] | 4.41s | 1.20s | 3.7x +| xref:comparisons/maven.adoc#_incremental_compile_single_module[Incremental Compile Single Module] | 1.37s | 0.51s | 2.7x +| xref:comparisons/maven.adoc#_no_op_compile_single_module[No-Op Compile Single Module] | 0.94s | 0.46s | 2.0x +|=== + +Again, for the purposes of this page, we will focus on two benchmarks + +#### Parallel Clean Compile All + +|=== +| Benchmark | Gradle | Mill | Speedup +| xref:comparisons/maven.adoc#_parallel_clean_compile_all[Parallel Clean Compile All] | 12.3s | 3.57s | 3.4x +|=== + +```bash +$ ./gradlew clean; time ./gradlew classes testClasses --no-build-cache + +$ ./mill clean; time ./mill __.compile +``` + +Here we only run compilation for classes and test classes, without linting or testing or anything else. +Both Mill and Gradle are parallel by default, with 1 thread per core. For Gradle we disabled the global +build cache to ensure we can benchmark the actual compilation time. + +We measure Mill being ~3.4x faster than Gradle for this benchmark. + +#### Incremental Compile Single-Module + +|=== +| Benchmark | Gradle | Mill | Speedup +| xref:comparisons/maven.adoc#_incremental_compile_single_module[Incremental Compile Single Module] | 1.37s | 0.51s | 2.7x +|=== + +```bash +$ echo "" >> src/main/java/org/mockito/BDDMockito.java; time ./gradlew :classes + +$ echo "" >> src/main/java/org/mockito/BDDMockito.java; time ./mill compile +compiling 1 Java source to /Users/lihaoyi/Github/netty/out/common/compile.dest/classes ... +``` + + +Again, this benchmark involves making a single edit to a single already-compiled file in the +root module - adding a single newline to the end of the file - and re-compiling it along with +its tests. + +Both Gradle and Mill appear to do a good job limiting the compilation to only the changed +file, but Mill has less fixed overhead than Gradle does. + + +## Ease of Use + +The second area that Mill does well compared to tools like Maven or Gradle is in its ease +of use.This is not just in superficial things like the build file or command-line syntax, +but also in how Mill exposes how your build works and what your build is doing so you can +understand it and confidently make changes. We will consider three cases: the Mill Chrome +Profile, Mill Visualize, and Mill's IDE support + +### Chrome Profiles + +All Mill runs generate some debugging metadata files in `out/mill-*`. One of these +is `out/mill-chrome-profile.json`, which is a file following the Chrome Profiling format. +It can be loaded into any Chrome browser's built in `chrome://tracing` UI, to let you +interactively explore what Mill was doing during its last run. e.g. when performing a +clean compile on the Netty codebase, the profile ends up looking like this: + +image::comparisons/NettyCompileProfile.png[] + +The Chrome profile shows what task each Mill thread was executing throughout the run. +The Chrome profiling UI is interactive, so you can zoom in and out, or click on individual +tasks to show the exact duration and other metadata. + +But the real benefit of the Chrome profile isn't the low-level data it provides, but the +high-level view: in the profile above, it is clear that for the first ~700ms, Mill is able +to use all cores on 10 cores on my laptop to do useful work. But after that, utilization is +much more sparse: `common.compile`, `buffer.compile`, `transport.compile`, `codec.compile`, +appear to be "long polls" in the build. These 4 tasks wait for one another to run sequentially, +likely due to dependencies between them, and they take long enough that all the other tasks +depending on them get held up. For example, when `codec.compile` finishes above, we can see +a number of downstream tasks immediately start running. + +This understanding of your build's performance profile is not just an academic exercise, but +provides actionable information: + +* If I wanted to speed up the Netty clean compile timings, + speeding up `common.compile`, `buffer.compile`, `transport.compile`, or `codec.compile` would + make the most impact: perhaps some of these modules could be broken up into smaller sub-modules + that would compile in parallel! + +* On the other hand, time speeding up the various `codec-*.compile` tasks would help not at all: + these tasks are already running at a time where the CPUs are mostly idle, and speeding them up + would just result in more idle time while waiting for the the "long poll" tasks to complete + +Most build tools do provide some way of analyzing build performance, but none of them provide +it as easily as Mill does: any Mill run generates a profile automatically, and any computer +with Chrome on it is able to load and let you explore that profile. That is a powerful tool to +help engineers understand what the build is doing: any engineer who felt a build was slow +can trivially load it into their Chrome browser to analyze and figure out what. + +### Mill Visualize + +Apart from the Mill Chrome Profile, Mill also provides the `./mill visualize` command, which +is useful to show the logical dependency graph between tasks. For example, we can use +`./mill visualize __.compile` (double `__` means wildcard) to +show the dependency graph between the modules of the Netty build below: + +image::comparisons/NettyCompileGraph.svg[] + +In this graph, we can clearly see that `common.compile`, `buffer.compile`,`transport.compile`, +and `codec.compile` depend on each other in a linear fashion. This explains why they each must +wait for the prior task to complete before starting, and cannot run in parallel with one another. +Furthermore, we can again confirm that many of the `codec-*.compile` tasks depend on `codec.compile`, +which is in the profile why we saw them waiting for the upstream task to complete before starting. + +Although these are things we could have _guessed_ from looking at the Chrome Profile above, +`./mill visualize` gives you a separate angle from which to look at your build. Together these +tools can help give greater understanding of what your build is doing and why it is doing that: +something that can be hard to come by with build tools that are often considered confusing and +inscrutable. + +### IDE Support + +One area that Mill does better than Gradle is providing a seamless IDE experience. For example, +consider the snippet below where we are using Gradle to configure the javac compiler options. +Due to `.gradle` files being untyped Groovy, the autocomplete and code-assist experience working +with these files is hit-or-miss. In the example below, we can see that IntelliJ is able to identify +that `compileArgs` exists and has the type `List`: + +image::comparisons/IntellijMockitoGradleCompileOptions.png[] + +But if you try to jump to definition or find out anything else about it you hit a wall: + +image::comparisons/IntellijMockitoGradleCompileOptions2.png[] + +Often working with build configurations feels like hitting dead ends: if you don't have +`options.compilerArgs` memorized in your head, there is literally nothing you can do in your editor to +make progress to figure out what it is or what it is used for. That leaves you googling +for answers, which can be a frustrating experience that distracts you from the task at hand. + +The fundamental problem with tools like Gradle is that the code you write does not +actually perform the build: rather, you are just setting up some data structure that +is used to configure the _real_ build engine that runs later. Thus when you explore +the Gradle build in an IDE, the IDE can only explore the configuration logic (which +is usually un-interesting) and is unable to explore the actual build logic (which +is what you actually care about!) + +In comparison, Mill's `.mill` files are all statically typed, and as a result IntelliJ is easily able to +pull up the documentation for `def javacOptions`, even though it doesn't have any special support +for Mill built into the IDE: + +image::comparisons/IntellijMockitoMillJavacOptionsDocs.png[] + +Apart from static typing, the way Mill builds are structured also helps the IDE: Mill +code _actually performs your build_, rather than configuring some opaque build engine. +While that sounds academic, one concrete consequence is that IntelliJ is able to take +your `def javacOptions` override and +find the original definitions that were overridden, and show you where they are defined: + +image::comparisons/IntellijMockitoMillJavacOptionsParents.png[] + +image::comparisons/IntellijMockitoMillJavacOptionsDef.png[] + +Furthermore, because task dependencies in Mill are just normal method calls, IntelliJ is +able to _find usages_, showing you where the task is used. Below, we can see the method +call in the `def compile` task, which uses `javacOptions()` along with a number of other tasks: + +image::comparisons/IntellijMockitoMillCompile.png[] + +From there, if you are curious about any of the other tasks used alongside `javacOptions`, it's +easy for you to pull up _their_ documentation, jump to _their_ +definition, or find _their_ usages. For example we can pull up the docs of +`compileClasspath()` below: + +image::comparisons/IntellijMockitoMillCompileClasspath.png[] + +Or we can use _find usages_ on `def compile` to see where it is used, both in this build +and upstream in the Mill libraries: + +image::comparisons/IntellijMockitoMillCompileUsages.png[] + +Unlike most other build tools, Mill builds are extremely easy to explore interactively in your +IDE. If you do not know what something does, it's documentation, definition, or usages is always +one click away in IntelliJ or VSCode. That's not to say Mill builds aren't complex - as +we saw above, compilation has to deal with upstream outputs, classpaths, flags, reporters, and so on - +but at least in Mill your IDE can help you explore, understand and manage the complexity in a way +that no other build tool supports. + +## Extensibility + +Mill allows you to directly write code to configure your build, and even download libraries +from Maven Central. + +Most build tools need plugins to do anything: if you want to Foo you need a +Foo plugin, if you want to Bar you need a Bar plugin, for any possible Foo or Bar. These could +be simple tasks - zipping up files, pre-rendering web templates, preparing static assets for +deployment - but even tasks that would be trivial to implement in a few lines of code need you +to google for third-party plugins, dig through their Github to see which one is best maintained, +and hope for the best when you include it in your build. + +Mill is different. Although it does have plugins for more advanced integrations, for most +simple things you can directly write code to achieve what you want, using the bundled +filesystem, subprocess, and dependency-management libraries. And even if you need third-party +libraries from Maven Central, you can directly import the "Foo" library and use it programmatically, +without having to find a "Foo build plugin" wrapper. + +### Simple Custom Tasks + +The following Mill build is a minimal Java module `foo`. It contains no custom configuration, and +so inherits all the defaults from `mill.javalib.JavaModule`: default source folder layout, default +assembly configuration, default compiler flags, and so on. + +```scala +package build +import mill._, javalib._ + +object foo extends JavaModule { +} +``` +```bash +> mill compile +Compiling 1 Java source... +``` + +If you want to add a custom task, this is as simple as defining a method e.g. +`def lineCount = Task`. The body of which performs the action we want, and +can depend on other tasks such as `allSourceFiles()` below: + +```scala +package build +import mill._, javalib._ + +object foo extends JavaModule { + /** Total number of lines in module source files */ + def lineCount = Task { + allSourceFiles().map(f => os.read.lines(f.path).size).sum + } +} +``` + +Once we define a new task, we can immediately begin using it in our build. +`lineCount` is not used by any existing `JavaModule` tasks, but we can still +show its value via the Mill command line to force it to evaluate: + +```bash +> mill show foo.lineCount +17 +``` + + +### Overriding Tasks + +To wire up `lineCount` into our main `JavaModule` `compile`/`test`/`run` tasks, +one way is to take the line count value and write it to a file in `def resources`. +This file can then be read at runtime as a JVM resource. We do that below +by overriding `def resources` and making it depend on `lineCount`, in addition +to its existing value `super.resources()`: + +```scala +package build +import mill._, javalib._ + +object foo extends JavaModule { + /** Total number of lines in module source files */ + def lineCount = Task { + allSourceFiles().map(f => os.read.lines(f.path).size).sum + } + + /** Generate resources using lineCount of sources */ + override def resources = Task { + os.write(Task.dest / "line-count.txt", "" + lineCount()) + super.resources() ++ Seq(PathRef(Task.dest)) + } +} +``` + + +Because `override def resources` overrides the existing `resources` method used +in the rest of `JavaModule`, the downstream tasks automatically now use the new +override instead, as that is how overrides work. That means if you call `mill foo.run`, +it will automatically pick up the new `line-count.txt` file and make it available to +the application code to use e.g. below, where we just print it out: + +```bash +> mill foo.run +Line Count: 17 +``` + +Most developers do not need to embed the line-count of their codebase in a resource +file to look up at runtime, but nevertheless this example shows how easy it is to write +code to perform ad-hoc tasks without needing to pull in and configure some third-party +plugin. Next, we'll look at a more realistic example, which includes usage of third-party +libraries in the build. + +### Using Libraries from Maven Central in Tasks + +Earlier on we discussed possibly pre-rendering HTML pages in the build so they can be +served at runtime. The use case for this are obvious: if a page never changes, rendering +it on every request is wasteful, and even rendering it once and then caching it can impact +your application startup time. Thus, you may want to move some HTML rendering to build-time, +but with traditional build tools such a move is sufficiently inconvenient and complicated +that people do not do it. + +With Mill, pre-rendering HTML at build time is really easy, even if you need a third-party +library. Mill does not ship with a bundled HTML templating engine, but you can use the +`import $ivy` syntax to include one such as Thymeleaf, which would immediately make the +Thymeleaf classes available for you to import and use in your build as below: + + +```scala +package build +import mill._, javalib._ +import $ivy.`org.thymeleaf:thymeleaf:3.1.1.RELEASE` +import org.thymeleaf.TemplateEngine +import org.thymeleaf.context.Context +object foo extends JavaModule { + def htmlSnippet = Task { + val context = new Context() + context.setVariable("heading", "hello") + new TemplateEngine().process( + "

    ", + context + ) + } + def resources = Task.Sources{ + os.write(Task.dest / "snippet.txt", htmlSnippet()) + super.resources() ++ Seq(PathRef(Task.dest)) + } +} +``` + +Once we have run `import $ivy`, we can `import org.thymeleaf.TemplateEngine`, +`import org.thymeleaf.context.Context`, and replace our `def lineCount` with a `def htmlSnippet` +task that instead of counting lines uses Thymeleaf to render some HTML. Again, it is inspectable +from the Mill command line via `show`, and we wire it up into `def resources` so it can be +inspected and used (in this case just printed out) at runtime by the application: + +```bash +> mill show foo.htmlSnippet +"

    hello

    " + +> mill foo.compile +compiling 1 Java source... +... + +> mill foo.run +generated snippet.txt resource:

    hello

    +``` + +Rendering HTML using the Thymelead templating engine is not rocket science, but what is +interesting here is what we did _not_ need to do: + +* We did not need to find a Thymeleaf-Mill plugin in order to include Thymeleaf in our + build + +* We did not need to learn a special API or framework for authoring build plugins ourselves + to write a plugin to include Thymeleaf in our build + +Instead, we could simply import Thymeleaf directly from Maven Central and use it just +like we would use it in any Java application, complete with full IDE support for +autocomplete and code navigation, with the same experience you probably are already +used to for your application code. This makes it an order of magnitude easier for +non-experts to configure their build to do exactly what they need, rather than be +limited by what some unmaintained third-party plugin might support. And although +the configuration is done in the Scala language, the syntax should be relatively +familiar ("Java without Semicolons" it is sometimes called) and the JVM libraries +and tools (e.g. IntelliJ, VSCode) are the exact same libraries and tools you are +already used to. + +## Conclusion + +To wrap up, Mill does all the same things that other build tools like Maven or Gradle do, +but aims to do them better: faster, easier to user, and easier to extend. All together, +this means both time saved waiting for your build tool to run in day-to-day work, as well +as time saved when you inevitably need to evolve or adjust your build system to accommodate +changing requirements. With Mill, you can therefore spend less time waiting for or fighting +with your build tool, and more time on the actual work you are trying to accomplish. \ No newline at end of file diff --git a/docs/supplemental-ui/partials/nav-tree.hbs b/docs/supplemental-ui/partials/nav-tree.hbs index 5522e4c3e8a..5faae549e5c 100644 --- a/docs/supplemental-ui/partials/nav-tree.hbs +++ b/docs/supplemental-ui/partials/nav-tree.hbs @@ -12,7 +12,7 @@ show all of them all the time