summaryrefslogblamecommitdiff
path: root/docs/pages/6 - Cross Builds.md
blob: 98540faee42179c1cb0685f43baa45a90813655b (plain) (tree)
1
2
3
4
5
6
7
8
9








                                                                   


                                                      






                                                                               





                             

   
                                                





















                                                                           
                       





                                                        

                                                                        








                                                                               






                                







                                                                

                                                      

 
                                              







                                                                            

                                                      

 
                                                                              








                                                                             

                                                      


                                                                

                                                                





                  





                             




                  
                                                                   



                                                                                
                               
                          
                                                                         
                                                                              



                                                                

                                                            


                                                                

                                                            




                                                                             
                                                                           
                                                                           
                                                                      
Mill handles cross-building of all sorts via the `Cross[T]` module.


## Defining Cross Modules

You can use this as follows:

```scala
object foo extends mill.Cross[FooModule]("2.10", "2.11", "2.12")
class FooModule(crossVersion: String) extends Module {
  def suffix = T { crossVersion }
  def bigSuffix = T { suffix().toUpperCase() }
}
```

This defines three copies of `FooModule`: `"210"`, `"211"` and `"212"`, each of
which has their own `suffix` target. You can then run them via

```bash
mill show foo[2.10].suffix
mill show foo[2.10].bigSuffix
mill show foo[2.11].suffix
mill show foo[2.11].bigSuffix
mill show foo[2.12].suffix
mill show foo[2.12].bigSuffix
```

The modules each also have a `millSourcePath` of

```text
foo/2.10
foo/2.11
foo/2.12
```

And the `suffix` targets will have the corresponding output paths for their
metadata and files:

```text
foo/2.10/suffix
foo/2.10/bigSuffix
foo/2.11/suffix
foo/2.11/bigSuffix
foo/2.12/suffix
foo/2.12/bigSuffix
```

You can also have a cross-build with multiple inputs:

```scala
val crossMatrix = for {
  crossVersion <- Seq("210", "211", "212")
  platform <- Seq("jvm", "js", "native")
  if !(platform == "native" && crossVersion != "212")
} yield (crossVersion, platform)

object foo extends mill.Cross[FooModule](crossMatrix:_*)
class FooModule(crossVersion: String, platform: String) extends Module {
  def suffix = T { crossVersion + "_" + platform }
}
```

Here, we define our cross-values programmatically using a `for`-loop that spits
out tuples instead of individual values. Our `FooModule` template class then
takes two parameters instead of one. This creates the following modules each
with their own `suffix` target:

```bash
mill show foo[210,jvm].suffix
mill show foo[211,jvm].suffix
mill show foo[212,jvm].suffix
mill show foo[210,js].suffix
mill show foo[211,js].suffix
mill show foo[212,js].suffix
mill show foo[212,native].suffix
```

## Using Cross Modules from Outside

You can refer to targets defined in cross-modules as follows:

```scala
object foo extends mill.Cross[FooModule]("2.10", "2.11", "2.12")
class FooModule(crossVersion: String) extends Module {
  def suffix = T { crossVersion }
}

def bar = T { "hello " + foo("2.10").suffix } 
```

Here, `foo("2.10")` references the `"2.10"` instance of `FooModule`. You can
refer to whatever versions of the cross-module you want, even using multiple
versions of the cross-module in the same target:

```scala
object foo extends mill.Cross[FooModule]("2.10", "2.11", "2.12")
class FooModule(crossVersion: String) extends Module {
  def suffix = T { crossVersion }
}

def bar = T { "hello " + foo("2.10").suffix + " world " + foo("2.12").suffix }
```

## Using Cross Modules from other Cross Modules

Targets in cross-modules can depend on one another the same way that external
targets:

```scala
object foo extends mill.Cross[FooModule]("2.10", "2.11", "2.12")
class FooModule(crossVersion: String) extends Module {
  def suffix = T { crossVersion }
}

object bar extends mill.Cross[BarModule]("2.10", "2.11", "2.12")
class BarModule(crossVersion: String) extends Module {
  def bigSuffix = T { foo(crossVersion).suffix().toUpperCase() }
}
```

Here, you can run:

```bash
mill show foo[2.10].suffix
mill show foo[2.11].suffix
mill show foo[2.12].suffix
mill show bar[2.10].bigSuffix
mill show bar[2.11].bigSuffix
mill show bar[2.12].bigSuffix
```


## Cross Resolvers

You can define an implicit `mill.define.Cross.Resolver` within your
cross-modules, which would let you use a shorthand `foo()` syntax when referring
to other cross-modules with an identical set of cross values:

```scala
trait MyModule extends Module {
  def crossVersion: String
  implicit object resolver extends mill.define.Cross.Resolver[MyModule] {
    def resolve[V <: MyModule](c: Cross[V]): V = c.itemMap(List(crossVersion))
  }
}

object foo extends mill.Cross[FooModule]("2.10", "2.11", "2.12")
class FooModule(val crossVersion: String) extends MyModule {
  def suffix = T { crossVersion }
}

object bar extends mill.Cross[BarModule]("2.10", "2.11", "2.12")
class BarModule(val crossVersion: String) extends MyModule {
  def longSuffix = T { "_" + foo().suffix() }
}
```

While the example `resolver` simply looks up the target `Cross` value for the
cross-module instance with the same `crossVersion`, you can make the resolver
arbitrarily complex. E.g. the `resolver` for `mill.scalalib.CrossSbtModule`
looks for a cross-module instance whose `scalaVersion` is binary compatible
(e.g. 2.10.5 is compatible with 2.10.3) with the current cross-module.