Scala Build Examples
Example Builds for Real Projects
Mill comes bundled with example builds for real-world open-source projects, demonstrating how Mill can be used to build code outside of tiny example codebases:
Acyclic
package build
import mill.*, scalalib.*, publish.*
import mill.api.BuildCtx
acyclic test suite assumes files are on disk at specific paths relative to os.pwd.
To avoid changing the test code, we instead copy the necessary files into the os.pwd
when preparing the resources for test suite execution
BuildCtx.withFilesystemCheckerDisabled {
os.copy.over(
BuildCtx.watch(mill.api.BuildCtx.workspaceRoot / "acyclic"),
os.pwd / "acyclic",
createFolders = true
)
}
object Deps {
def acyclic = mvn"com.lihaoyi:::acyclic:0.3.6"
def scalaCompiler(scalaVersion: String) = mvn"org.scala-lang:scala-compiler:$scalaVersion"
val utest = mvn"com.lihaoyi::utest:0.8.5"
}
val crosses =
Seq("2.11.12") ++
Range.inclusive(8, 17).map("2.12." + _) ++
Range.inclusive(0, 10).map("2.13." + _)
object acyclic extends Cross[AcyclicModule](crosses)
trait AcyclicModule extends CrossScalaModule, PublishModule {
def crossFullScalaVersion = true
def artifactName = "acyclic"
def publishVersion = "1.3.3.7"
def pomSettings = PomSettings(
description = artifactName(),
organization = "com.lihaoyi",
url = "https://github.com/com-lihaoyi/acyclic",
licenses = Seq(License.MIT),
versionControl = VersionControl.github(owner = "com-lihaoyi", repo = "acyclic"),
developers = Seq(Developer("lihaoyi", "Li Haoyi", "https://github.com/lihaoyi"))
)
def compileMvnDeps = Seq(Deps.scalaCompiler(crossScalaVersion))
object test extends ScalaTests, TestModule.Utest {
def sources = Task.Sources("src", "resources")
def mvnDeps = Seq(Deps.utest, Deps.scalaCompiler(crossScalaVersion))
}
}
Acyclic is an example of a very small project that is a Scala compiler
plugin. It is cross-built against all point versions of Scala from 2.11.12
to 2.13.10, and has a dependency on the org.scala-lang:scala-compiler
Project home: https://github.com/com-lihaoyi/acyclic
> ./mill resolve acyclic[_].compile
acyclic[2.11.12].compile
acyclic[2.12.10].compile
acyclic[2.12.11].compile
acyclic[2.12.12].compile
acyclic[2.12.13].compile
acyclic[2.12.14].compile
acyclic[2.12.15].compile
acyclic[2.12.16].compile
acyclic[2.12.8].compile
acyclic[2.12.9].compile
acyclic[2.13.0].compile
acyclic[2.13.1].compile
acyclic[2.13.2].compile
acyclic[2.13.3].compile
acyclic[2.13.4].compile
acyclic[2.13.5].compile
acyclic[2.13.6].compile
acyclic[2.13.7].compile
acyclic[2.13.8].compile
acyclic[2.13.9].compile
> ./mill acyclic[2.12.17].compile
compiling 6 Scala sources...
...
> ./mill acyclic[2.13.10].test.testLocal # acyclic tests need testLocal due to classloader assumptions
-------------------------------- Running Tests --------------------------------
...
Fansi
package build
import mill.*, scalalib.*, scalajslib.*, scalanativelib.*, publish.*
val dottyCommunityBuildVersion = sys.props.get("dottyVersion").toList
val scalaVersions = Seq("2.12.17", "2.13.16", "2.11.12", "3.1.3") ++ dottyCommunityBuildVersion
trait FansiModule extends PublishModule, CrossScalaModule, PlatformScalaModule {
def publishVersion = "1.3.3.7"
def pomSettings = PomSettings(
description = artifactName(),
organization = "com.lihaoyi",
url = "https://github.com/com-lihaoyi/Fansi",
licenses = Seq(License.MIT),
versionControl = VersionControl.github(owner = "com-lihaoyi", repo = "fansi"),
developers = Seq(Developer("lihaoyi", "Li Haoyi", "https://github.com/lihaoyi"))
)
def mvnDeps = Seq(mvn"com.lihaoyi::sourcecode::0.3.0")
trait FansiTests extends ScalaTests, TestModule.Utest {
def utestVersion = "0.8.5"
}
}
object fansi extends Module {
object jvm extends Cross[JvmFansiModule](scalaVersions)
trait JvmFansiModule extends FansiModule, ScalaModule {
object test extends FansiTests, ScalaTests
}
object js extends Cross[JsFansiModule](scalaVersions)
trait JsFansiModule extends FansiModule, ScalaJSModule {
def scalaJSVersion = "1.16.0"
object test extends FansiTests, ScalaJSTests
}
object native extends Cross[NativeFansiModule](scalaVersions)
trait NativeFansiModule extends FansiModule, ScalaNativeModule {
def scalaNativeVersion = "0.4.5"
object test extends FansiTests, ScalaNativeTests
}
}
Fansi is an example of a small library that is cross built against every minor version of Scala (including Scala 3.x) and every platform: JVM, JS, and Native. Both the library and the test suite are duplicated across all entries in the {version}x{platform} matrix, and you can select which one you want to compile, test, or publish
Project home: https://github.com/com-lihaoyi/fansi
> ./mill resolve __.compile
fansi.js[2.11.12].test.compile
fansi.js[2.12.17].compile
fansi.js[2.12.17].test.compile
fansi.js[2.13.16].compile
fansi.js[2.13.16].test.compile
fansi.js[3.1.3].compile
fansi.js[3.1.3].test.compile
fansi.jvm[2.11.12].compile
fansi.jvm[2.11.12].test.compile
fansi.jvm[2.12.17].compile
fansi.jvm[2.12.17].test.compile
fansi.jvm[2.13.16].compile
fansi.jvm[2.13.16].test.compile
fansi.jvm[3.1.3].compile
fansi.jvm[3.1.3].test.compile
fansi.native[2.11.12].compile
fansi.native[2.11.12].test.compile
fansi.native[2.12.17].compile
fansi.native[2.12.17].test.compile
fansi.native[2.13.16].compile
fansi.native[2.13.16].test.compile
fansi.native[3.1.3].compile
fansi.native[3.1.3].test.compile
> ./mill fansi.jvm[2.12.17].compile
compiling 1 Scala source...
...
> ./mill fansi.js[2.13.16].test
Starting process: node
-------------------------------- Running Tests --------------------------------
...
> ./mill fansi.native[3.1.3].publishLocal
Publishing Artifact(com.lihaoyi,fansi_native0.4_3,1.3.3.7) to ivy repo...
...
Real World Mill Builds
Ammonite
Ammonite is an ergonomic Scala REPL.
Scala-CLI
Scala-CLI is the primary CLI tool that
runs when you enter scala in the terminal. It is able to compile, test, run,
and package your Scala code in a variety of different ways
Coursier
Coursier is a fast JVM dependency resolver, used in many build tools down resolve and download third party dependencies