summaryrefslogblamecommitdiff
path: root/docs/pages/1 - Intro to Mill.md
blob: bfbb3d9aa996882747cf648db4d40ca53086e457 (plain) (tree)
1
2
3
4
5
6
7
8
9
                                                                           


                                                                            
 



                                                                                     
 





                                                                               
 

               







                                                                                                   









                                                                                   



                                                                               
                                                                                                                                      
   
 

                        




                                                                          

                                                                               
 

                  


                                                             
           





















                                               



                                                          






                                                                             
                                                                    
 
                                                                
 
                                                                                       
 
                                                                     
 

                                                                                      
                                                                                                          
 
                                                                                                           

   
                                                                                
                                                                            


                                                                     




                                                                              





















                                                                               
 
                   

        
           























































                                                                              
           















































                                                        
                        








                                                                                



                                                                             
                     


                                                                         
       










                                                           
           

       





































                                                                               







                                                                                   
                                                                                   

   
           

       
                       








                               
                                                                          



                                                                          
                                                                        



                                   









                                

   
        
 




                             



                                                                              
                                                    
 


                                                                                

       
                       







                                                                                   

                                                                               

       
                       



                                                          
                                   







                                                                                        


                                                                              
                   
 
                                                                                 




                                                                             
                 

       
         





























                                                                                               
                                                                             



                                                                             
                                                                                   
 
                      
 


                                                                         
 











































                                                                              
                                
                                                                 






                                                                   



                                                          









                                                                                         
                                                       







                                                                             
                                                                                                                     
                                                                               
[Mill](https://github.com/lihaoyi/mill) is your shiny new Scala build tool!
[Scared of SBT](http://www.lihaoyi.com/post/SowhatswrongwithSBT.html)?
Melancholy over Maven? Grumbling about Gradle? Baffled by Bazel? Give Mill a
try!

Mill aims for simplicity by re-using concepts you are already
[familiar with](http://www.lihaoyi.com/post/BuildToolsasPureFunctionalPrograms.html),
borrowing ideas from modern tools like [Bazel](https://bazel.build/), to let you
build your projects in a way that's simple, fast, and predictable.

Mill has built in support for the [Scala](https://www.scala-lang.org/)
programming language, and can serve as a replacement for
[SBT](http://www.scala-sbt.org/), but can also be
[extended](http://www.lihaoyi.com/mill/page/extending-mill.html) to support any
other language or platform via modules (written in Java or Scala) or through
external subprocesses.

## Installation

### OS X

Installation via [homebrew](https://github.com/Homebrew/homebrew-core/blob/master/Formula/mill.rb):

```sh
brew install mill
```

### Arch Linux

Arch Linux has an [AUR package for mill](https://aur.archlinux.org/packages/mill/):

```bash
pacaur -S mill
```

### Manual

To get started, download Mill and install it into your system via the following
`curl`/`chmod` command:

```bash
sudo curl -L -o /usr/local/bin/mill https://github.com/lihaoyi/mill/releases/download/0.1.7/0.1.7 && sudo chmod +x /usr/local/bin/mill
```

### Development Releases

In case you want to try out the latest features and improvements that are 
currently in master, unstable versions of Mill are
[available](https://github.com/lihaoyi/mill/releases) as binaries named 
`#.#.#-n-hash` linked to the latest tag.

Come by our [Gitter Channel](https://gitter.im/lihaoyi/mill) if you want to ask
questions or say hi!

## Getting Started

The simplest Mill build for a Scala project looks as follows:

```scala
// build.sc
import mill._
import mill.scalalib._

object foo extends ScalaModule {
  def scalaVersion = "2.12.4"
}
```

This would build a project laid out as follows:

```
build.sc
foo/
    src/
        Main.scala
    resources/
        ...
out/
    foo/
        ... 
```

You can download an example project with this layout here:

- [Example 1](example-1.zip)

The source code for this module would live in the `foo/src/` folder, matching
the name you assigned to the module. Output for this module (compiled files,
resolved dependency lists, ...) would live in `out/foo/`.

This can be run from the Bash shell via:

```bash
$ mill foo.compile                 # compile sources into classfiles

$ mill foo.run                     # run the main method, if any

$ mill foo.launcher                # prepares a foo/launcher/dest/run you can run later

$ mill foo.jar                     # bundle the classfiles into a jar

$ mill foo.assembly                # bundle classfiles and all dependencies into a jar
 
$ mill -i foo.console              # start a Scala console within your project (in interactive mode: "-i")
 
$ mill -i foo.repl                 # start an Ammonite REPL within your project (in interactive mode: "-i")
```

You can run `mill resolve __` to see a full list of the different tasks that are
available, `mill resolve foo._` to see the tasks within `foo`, `mill inspect
foo.compile` to see what an individual task depends on, or `mill show
foo.scalaVersion` to inspect the output of any task.

The most common **tasks** that Mill can run are cached **targets**, such as
`compile`, and un-cached **commands** such as `foo.run`. Targets do not
re-evaluate unless one of their inputs changes, where-as commands re-run every
time.

## Output

Mill puts all it's output in the top-level `out/` folder. The above commands
would end up in:

```text
out/
    foo/
        compile/
        run/
        jar/
        assembly/
```

Within the output folder for each task, there's a `meta.json` file containing
the metadata returned by that task, and a `dest/` folder containing any files
that the task generates. For example, `out/foo/compile/dest/` contains the
compiled classfiles, while `out/foo/assembly/dest/` contains the self-contained
assembly with the project's classfiles jar-ed up with all it's dependencies.

Given a task `foo.bar`, all it's output and results can be found be within it's
respective `out/foo/bar/` folder.

## Multiple Modules

```scala
// build.sc
import mill._
import mill.scalalib._
object foo extends ScalaModule {
  def scalaVersion = "2.12.4"
}
object bar extends ScalaModule {
  def moduleDeps = Seq(foo)
  def scalaVersion = "2.12.4"
}
```

You can define multiple modules the same way you define a single module, using
`def moduleDeps` to define the relationship between them. The above build
expects the following project layout:

```
build.sc
foo/
    src/
        Main.scala
    resources/
        ...
bar/
    src/
        Main2.scala
    resources/
        ...
out/
    foo/
        ... 
    bar/
        ... 
```

And can be built/run using:

```bash
$ mill foo.compile        
$ mill bar.compile        

$ mill foo.run            
$ mill bar.run            

$ mill foo.jar            
$ mill bar.jar            

$ mill foo.assembly        
$ mill bar.assembly        
```

Mill's evaluator will ensure that the modules are compiled in the right order,
and re-compiled as necessary when source code in each module changes.

Modules can also be nested:

```scala
// build.sc
import mill._
import mill.scalalib._
object foo extends ScalaModule {
  def scalaVersion = "2.12.4"
  object bar extends ScalaModule {
    def moduleDeps = Seq(foo)
    def scalaVersion = "2.12.4"
  }
}
```

Which would result in a similarly nested project layout:

```
build.sc
foo/
    src/
        Main.scala
    resources/
        ...
    bar/
        src/
            Main2.scala
        resources/
            ...
out/
    foo/
        ...
        bar/
            ...
```

Where the nested modules can be run via:

```bash
$ mill foo.compile        
$ mill foo.bar.compile        

$ mill foo.run            
$ mill foo.bar.run            

$ mill foo.jar            
$ mill foo.bar.jar            

$ mill foo.assembly        
$ mill foo.bar.assembly        
```

## Watch and Re-evaluate

You can use the `--watch` flag to make Mill watch a task's inputs, re-evaluating
the task as necessary when the inputs change:

```bash
$ mill --watch foo.compile 
$ mill --watch foo.run 
```

Mill's `--watch` flag watches both the files you are building using Mill, as
well as Mill's own `build.sc` file and anything it imports, so any changes to
your `build.sc` will automatically get picked up.

## Command-line Tools

Mill comes built in with a small number of useful command-line utilities:

### all

```bash
mill all foo.{compile,run}
mill all "foo.{compile,run}"
mill all foo.compile foo.run
mill all _.compile # run compile for every top-level module
mill all __.compile  # run compile for every module
```

`all` runs multiple tasks in a single command

### resolve

```bash
$ mill resolve _
main
moduledefs
core
scalaworker
scalalib
scalajslib
integration
testRepos
...

$ mill resolve _.compile

main.compile
moduledefs.compile
core.compile
scalaworker.compile
scalalib.compile
scalajslib.compile
integration.compile

$ mill resolve core._

core.test
core.compile
core.publishVersion
core.runClasspath
core.testArgs
core.sources
...
```

`resolve` lists the tasks that match a particular query, without running them.
This is useful for "dry running" an `mill all` command to see what would be run
before you run them, or to explore what modules or tasks are available from the
command line using `resolve _`, `resolve foo._`, etc.

```bash
mill resolve foo.{compile,run}
mill resolve "foo.{compile,run}"
mill resolve foo.compile foo.run
mill resolve _.compile          # list the compile tasks for every top-level module
mill resolve __.compile         # list the compile tasks for every module
mill resolve _                  # list every top level module or task
mill resolve foo._              # list every task directly within the foo module
mill resolve __                 # list every module or task recursively
mill resolve foo.__             # list every task recursively within the foo module
```

### inspect

```bash
$ mill inspect core.run

core.run(ScalaModule.scala:211)
Inputs:
    core.mainClass
    core.runClasspath
    core.forkArgs
    core.forkEnv
```

`inspect` is a more verbose version of [resolve](#resolve). In addition to
printing out the name of one-or-more tasks, it also display's it's source
location and a list of input tasks. This is very useful for debugging and
interactively exploring the structure of your build from the command line.

`inspect` also works with the same `_`/`__` wildcard/query syntaxes that
[all](#all)/[resolve](#resolve) do:


```bash
mill inspect foo.compile
mill inspect foo.{compile,run}
mill inspect "foo.{compile,run}"
mill inspect foo.compile foo.run
mill inspect _.compile
mill inspect __.compile
mill inspect _
mill inspect foo._
mill inspect __
mill inspect foo._
```

### show

```bash
$ mill show core.scalaVersion
"2.12.4"
```

By default, Mill does not print out the metadata from evaluating a task. Most
people would not be interested in e.g. viewing the metadata related to
incremental compilation: they just want to compile their code! However, if you
want to inspect the build to debug problems, you can make Mill show you the
metadata output for a task using the `show` command:

All tasks return values that can be `show`n, not just configuration values. e.g.
`compile` returns that path to the `classes` and `analysisFile` that are
produced by the compilation:

```bash
$ mill show foo.compile
{
    "analysisFile": "/Users/lihaoyi/Dropbox/Github/test/out/foo/compile/dest/zinc",
    "classes": {
        "path": "/Users/lihaoyi/Dropbox/Github/test/out/foo/compile/dest/classes"
    }
}
```

`show` is generally useful as a debugging tool, to see what is going on in your
build:

```bash
$ mill show foo.sources
[
    {"path": "/Users/lihaoyi/Dropbox/Github/test/foo/src"}
]

$ mill show foo.compileDepClasspath
[
    {"path": ".../org/scala-lang/scala-compiler/2.12.4/scala-compiler-2.12.4.jar"},
    {"path": ".../org/scala-lang/scala-library/2.12.4/scala-library-2.12.4.jar"},
    {"path": ".../org/scala-lang/scala-reflect/2.12.4/scala-reflect-2.12.4.jar"},
    {"path": ".../org/scala-lang/modules/scala-xml_2.12/1.0.6/scala-xml_2.12-1.0.6.jar"}
]
```

`show` is also useful for interacting with Mill from external tools, since the
JSON it outputs is structured and easily parsed & manipulated.

## IntelliJ Support

Mill supports IntelliJ by default. Use `mill mill.scalalib.GenIdeaModule/idea` to
generate an IntelliJ project config for your build.

This also configures IntelliJ to allow easy navigate & code-completion within
your build file itself.

## The Build Repl

```bash
$ mill -i
Loading...
@ foo
res1: foo.type = ammonite.predef.build#foo:2
Commands:
    .runLocal(args: String*)()
    .run(args: String*)()
    .runMainLocal(mainClass: String, args: String*)()
    .runMain(mainClass: String, args: String*)()
    .console()()
Targets:
    .allSources()
    .artifactId()
    .artifactName()
...

@ foo.compile
res3: mill.package.T[mill.scalalib.CompilationResult] = mill.scalalib.ScalaModule#compile:152
Inputs:
    foo.scalaVersion
    foo.allSources
    foo.compileDepClasspath
...
    
@ foo.compile()
res2: mill.scalalib.CompilationResult = CompilationResult(
  root/'Users/'lihaoyi/'Dropbox/'Github/'test/'out/'foo/'compile/'dest/'zinc,
  PathRef(root/'Users/'lihaoyi/'Dropbox/'Github/'test/'out/'foo/'compile/'dest/'classes, false)
)
```

You can run `mill -i` to open a build REPL; this is a Scala console with your
`build.sc` loaded, which lets you run tasks interactively. The task-running
syntax is slightly different from the command-line, but more in-line with how
you would depend on tasks from within your build file.

You can use this REPL to interactively explore your build to see what is available.

## Deploying your code

The two most common things to do once your code is complete is to make an
assembly (e.g. for deployment/installation) or publishing (e.g. to Maven
Central). Mill comes with both capabilities built in.

Mill comes built-in with the ability to make assemblies. Given a simple Mill
build:

```scala
// build.sc
import mill._, scalalib._

object foo extends ScalaModule{
  def scalaVersion = "2.12.4"
}
```

You can make a self-contained assembly via:

```bash
$ mill foo.assembly

$ ls -lh out/foo/assembly/dest/out.jar
-rw-r--r--  1 lihaoyi  staff   5.0M Feb 17 11:14 out/foo/assembly/dest/out.jar
```

You can then move the `out.jar` file anywhere you would like, and run it
standalone using `java`:

```bash
$ java -cp out/foo/assembly/dest/out.jar foo.Example
Hello World!
```

To publish to Maven Central, you need to make `foo` extend Mill's
`PublishModule` trait:

```scala
// build.sc
import mill._, scalalib._, publish._

object foo extends PublishModule{
  def scalaVersion = "2.12.4"
  def publishVersion = "0.0.1"

  def pomSettings = PomSettings(
    description = "Hello",
    organization = "com.lihaoyi",
    url = "https://github.com/lihaoyi/example",
    licenses = Seq(License.MIT),
    versionControl = VersionControl.github("lihaoyi", "example"),
    developers = Seq(
      Developer("lihaoyi", "Li Haoyi","https://github.com/lihaoyi")
    )
  )
}
```

You can download an example project with this layout here:

- [Example 2](example-2.zip)

Which you can then publish using the `mill foo.publish` command, which takes
your sonatype credentials (e.g. `lihaoyi:foobarbaz`) and GPG password as inputs:

```bash
$ mill foo.publish
Missing arguments: (--sonatypeCreds: String, --gpgPassphrase: String, --release: Boolean)

Arguments provided did not match expected signature:

publish
  --sonatypeCreds  String (format: "username:password")
  --gpgPassphrase  String
  --release        Boolean
```

You also need to specify `release` as `true` or `false`, depending on whether
you just want to stage your module on `oss.sonatype.org` or you want Mill to
complete the release process to Maven Central.

If you are publishing multiple artifacts, you can also use `mill mill.scalalib.PublishModule/publishAll` as described
[here](http://www.lihaoyi.com/mill/page/common-project-layouts.html#publishing)