import $ivy

Importing Java Libraries

The following example shows how to import the library org.apache.commons:commons-text:1.12.0 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.

build.mill (download, browse)
package build
import mill._, javalib._
import $ivy.`org.apache.commons:commons-text:1.12.0`
import org.apache.commons.text.StringEscapeUtils

object foo extends JavaModule {
  def scalaVersion = "2.13.8"

  def htmlSnippet = Task {
    "<div><h1>" +
      StringEscapeUtils.escapeHtml4("hello") +
    "</h1><p>" +
      StringEscapeUtils.escapeHtml4("world") +
    "</p></div>"
  }
  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 JVM 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.apache.commons:commons-text:1.12.0 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:

build.mill (download, browse)
import mill._, scalalib._
import $ivy.`com.lihaoyi::scalatags:0.12.0`, scalatags.Text.all._

object foo 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 foo.compile
compiling 1 Scala 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>