Import Libraries and Plugins
This page illustrates usage of import $ivy
.
import $ivy
lets you import JVM dependencies into your build.mill
, so
you can use arbitrary third-party libraries at build-time. This makes
lets you perform computations at build-time rather than run-time,
speeding up your application start up. Unlike most other build tools that
require purpose-built plugins to extend them, Mill’s import $ivy
can be used to pull
in any JVM library on Maven Central to use in your custom tasks, with
Third-Party Plugins only necessary for
more sophisticated integrations.
Importing Java Libraries
The following example shows how to import the library org.thymeleaf:thymeleaf:3.1.1.RELEASE
into your build, so you can use it at build-time to safely generate escaped HTML snippets
in your resource path for your application to use.
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")
context.setVariable("paragraph", "world")
new TemplateEngine().process(
"""<div><h1 th:text="${heading}"></h1><p th:text="${paragraph}"></p></div>""",
context
)
}
def resources = Task.Sources {
os.write(Task.dest / "snippet.txt", htmlSnippet())
super.resources() ++ Seq(PathRef(Task.dest))
}
}
This is a toy example: we generate a resource snippet.txt
containing
<div><h1>hello</h1><p>world</p></div>
that the application can read at runtime.
However, it demonstrates how you can easily move logic from application code at runtime
to build logic at build time, while using the same set of Java libraries and packages
you are already familiar with. This makes it easy to pre-compute things at build time
to reduce runtime latency or application startup times.
> mill foo.compile
compiling 1 Java source...
...
> mill foo.run
generated snippet.txt resource: <div><h1>hello</h1><p>world</p></div>
> mill show foo.assembly
".../out/foo/assembly.dest/out.jar"
> ./out/foo/assembly.dest/out.jar # mac/linux
generated snippet.txt resource: <div><h1>hello</h1><p>world</p></div>
Importing Scala Libraries
import $ivy
can also be used with Scala libraries. The following example
replaces org.thymeleaf:thymeleaf:3.1.1.RELEASE
above with com.lihaoyi::scalatags:0.12.0
,
a HTML generation library that does the string concatenation/construction internally
and also escapes the input strings on your behalf:
import mill._, scalalib._
import $ivy.`com.lihaoyi::scalatags:0.12.0`, scalatags.Text.all._
object bar extends ScalaModule {
def scalaVersion = "2.13.8"
def ivyDeps = Agg(ivy"com.lihaoyi::os-lib:0.10.7")
def htmlSnippet = Task { div(h1("hello"), p("world")).toString }
def resources = Task.Sources {
os.write(Task.dest / "snippet.txt", htmlSnippet())
super.resources() ++ Seq(PathRef(Task.dest))
}
}
In this case, we move the Scalatags rendering logic to build time, so the application
code gets a pre-rendered string it can directly print without further work.
Note that using import $ivy
on Scala libraries requires a double colon ::
between
the organization name and artifact name.
> mill bar.compile
compiling 1 Scala source...
...
> mill bar.run
generated snippet.txt resource: <div><h1>hello</h1><p>world</p></div>
> mill show bar.assembly
".../out/bar/assembly.dest/out.jar"
> ./out/bar/assembly.dest/out.jar # mac/linux
generated snippet.txt resource: <div><h1>hello</h1><p>world</p></div>
Importing Plugins
Mill plugins are ordinary JVM libraries jars and are loaded as any other external dependency with
the import $ivy
mechanism.
There exist a large number of Mill plugins, Many of them are available on GitHub and via Maven Central. We also have a list of plugins, which is most likely not complete, but it might be a good start if you are looking for plugins: Third-Party Plugins.
Some plugin contributions are also hosted in Mill’s own git tree as Contrib Plugins.
Mill plugins are typically bound to a specific version range of Mill. This is called the binary platform. To ease the use of the correct versions and avoid runtime issues (caused by binary incompatible plugins, which are hard to debug) you can apply one of the following techniques:
Use the specific Mill Binary Platform notation
// for classic Scala dependencies
import $ivy.`<group>::<plugin>::<version>` (1)
// for dependencies specific to the exact Scala version
import $ivy.`<group>:::<plugin>::<version>` (2)
1 | This is equivalent to
|
2 | This is equivalent to
|
Use special placeholders in your import $ivy
$MILL_VERSION
-
to substitute the currently used Mill version. This is typical required for Mill contrib modules, which are developed in the Mill repository and highly bound to the current Mill version.
Example: Usemill-contrib-bloop
plugin matching the current Mill versionimport $ivy.`com.lihaoyi:mill-contrib-bloop:$MILL_VERSION`
There is the even more convenient option to leave the version completely empty. Mill will substitute it with its current version. But don’t forget to provide the trailing colon!
Example: Usemill-contrib-bloop
plugin matching the current Mill versionimport $ivy.`com.lihaoyi:mill-contrib-bloop:`
$MILL_BIN_PLATFORM
-
to substitute the currently used Mill binary platform.
Example: Usingmill-vcs-version
plugin matching the current Mill Binary Platformimport $ivy.`de.tototec::de.tobiasroeser.mill.vcs.version_mill$MILL_BIN_PLATFORM:0.1.2`
If you want to publish re-usable libraries that other people can use in their builds, simply publish your code as a library to maven central. |