Multi-Language Builds
This example demonstrates a simple multi-langauge project,
running a spring boot webserver
serving a react client
and interacting with a python binary
through the web-server api.
package build
import mill._, javascriptlib._, pythonlib._, javalib._
object client extends ReactScriptsModule
object `sentiment-analysis` extends PythonModule {
def mainScript = Task.Source { moduleDir / "src" / "foo.py" }
def pythonDeps = Seq("textblob==0.19.0")
object test extends PythonTests with pythonlib.TestModule.Unittest
}
object server extends JavaModule {
def mvnDeps = Seq(
mvn"org.springframework.boot:spring-boot-starter-web:2.5.6",
mvn"org.springframework.boot:spring-boot-starter-actuator:2.5.6"
)
/** Bundle client & sentiment-analysis as resource */
def resources = Task {
os.copy(client.bundle().path, Task.dest / "static")
os.makeDir.all(Task.dest / "analysis")
os.copy(`sentiment-analysis`.bundle().path, Task.dest / "analysis" / "analysis.pex")
super.resources() ++ Seq(PathRef(Task.dest))
}
object test extends JavaTests with javalib.TestModule.Junit5 {
def mvnDeps = super.mvnDeps() ++ Seq(
mvn"org.springframework.boot:spring-boot-starter-test:2.5.6"
)
}
}
Mill as a build tool is not inherently limited to working with JVM languages like Java/Scala/Kotlin, and you can set up toolchains for other languages as well. This example makes use of Mill’s experimental Python Toolchain and Typescript Toolchain together with it’s builtin Java Toolchain to build a multi-language project containing all three languages. This provides several benefits over having separate build tools for each language:
-
Mill can provide caching and automatic invalidation across languages, e.g. changing the Typescript
client
code automatically makes the Javaserver
re-build -
Mill can parallelize different language toolchains, e.g. building the Typescript
client
, Pythonsentiment-analysis
module, and Javaserver
code in parallel on multiple cores
If you wish to learn how additional language toolchains can be added to Mill, you can see
the pages on Example: Python Support and
Example: Typescript Support for walk-throughs on how language traits such
as PythonModule
can be defined by users.
> ./mill client.test
PASS src/test/App.test.tsx
...Text Analysis Tool
...renders the app with initial UI...
...displays sentiment result...
...
Test Suites:...1 passed, 1 total
Tests:...2 passed, 2 total
...
> ./mill sentiment-analysis.test
...
test_negative_sentiment... ok
test_neutral_sentiment... ok
test_positive_sentiment... ok
...
Ran 3 tests...
...
OK
...
> ./mill server.test
...com.example.ServerTest#shouldReturnStaticPage() finished...
...com.example.ServerTest#shouldReturnPositiveAnalysis() finished...
...com.example.ServerTest#shouldReturnNegativeAnalysis() finished...
> ./mill server.runBackground
> curl http://localhost:8086
...<title>Sentiment Analysis Tool</title>...
> curl -X POST http://localhost:8086/api/analysis -H "Content-Type: text/plain" --data "This is awesome!" # Make request to the analysis api
Positive sentiment (polarity: 1.0)
> ./mill clean server.runBackground