summaryrefslogtreecommitdiff
path: root/docs/pages/6 - Cross Builds.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/pages/6 - Cross Builds.md')
-rw-r--r--docs/pages/6 - Cross Builds.md162
1 files changed, 162 insertions, 0 deletions
diff --git a/docs/pages/6 - Cross Builds.md b/docs/pages/6 - Cross Builds.md
new file mode 100644
index 00000000..f92678d5
--- /dev/null
+++ b/docs/pages/6 - Cross Builds.md
@@ -0,0 +1,162 @@
+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.Resolve` 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. \ No newline at end of file