<html><head><meta charset="utf-8" /><link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css" /><link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" type="text/css" /><link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/styles/github-gist.min.css" rel="stylesheet" type="text/css" /><title>Cross Builds</title><style>@media (min-width: 60em) {.WideStyles-header{
bottom: 0px;
display: flex;
flex-direction: column;
justify-content: center;
position: fixed;
top: 0px;
width: 25%;
}
.WideStyles-tableOfContentsItem{
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
vertical-align: middle;
width: 100%;
}
.WideStyles-tableOfContents{
display: flex;
flex-direction: column;
flex-grow: 1;
flex-shrink: 1;
min-height: 0px;
width: 100%;
}
.WideStyles-content{
box-sizing: border-box;
margin-left: 25%;
padding: 48px;
}
.WideStyles-footer{
bottom: 0px;
height: 50px;
position: fixed;
width: 25%;
}
.WideStyles-marginLeftZero{
margin-left: 0px;
}
}</style><style>@media (max-width: 60em) {.NarrowStyles-header{
margin-bottom: 10px;
}
.NarrowStyles-content{
padding: 16px;
}
.NarrowStyles-headerContent{
align-items: center;
display: flex;
flex-direction: row;
width: 100%;
}
.NarrowStyles-flexFont{
font-size: 4vw;
}
.NarrowStyles-disappear{
display: none;
}
.NarrowStyles-floatLeft{
float: left;
margin-left: 30px;
}
}</style><style>.Styles-hoverBox{
align-items: center;
display: flex;
flex-direction: row;
justify-content: space-between;
}
.Styles-hoverBox:hover .Styles-hoverLink{
opacity: 0.5;
}
.Styles-hoverLink{
opacity: 0.1;
}
.Styles-hoverLink:hover{
opacity: 1.0;
}
.Styles-headerStyle{
background-color: rgb(61, 79, 93);
box-sizing: border-box;
display: flex;
}
.Styles-headerLinkBox{
display: flex;
flex: 1;
flex-direction: column;
}
.Styles-headerLink{
align-items: center;
display: flex;
flex: 1;
justify-content: center;
padding: 10px 10px;
}
.Styles-footerStyle{
color: rgb(158, 167, 174);
display: flex;
justify-content: center;
}
.Styles-subtleLink{
text-decoration: none;
}
</style><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/highlight.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/languages/scala.min.js"></script><script>hljs.initHighlightingOnLoad();</script><meta name="viewport" content="initial-scale = 1.0,maximum-scale = 1.0" /></head><body style="margin: 0px;background-color: #f8f8f8;"><div class=" WideStyles-header NarrowStyles-header Styles-headerStyle"><div class=" NarrowStyles-headerContent"><h1 style="text-align: center;padding: 30px 30px;margin: 0px;"><a style="color: #f8f8f8;font-weight: bold;" href=".." class=" Styles-subtleLink NarrowStyles-flexFont"><img src="../logo-white.svg" style="height: 30px;margin-top: -5px;" /> Mill</a></h1><div class=" Styles-headerLinkBox"><div class=" WideStyles-tableOfContents" style="color: #f8f8f8;"><div style="padding-left: 40px;" class=" NarrowStyles-disappear"><b>Pages</b></div><div style="overflow-y: auto;flex-shrink: 1;min-height: 0px;"><ul style="overflow: hidden;text-align: start;margin-top: 10px;white-space: nowrap;text-overflow: ellipsis;margin-right: 10px;"><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="../index.html">Intro to Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="configuring-mill.html">Configuring Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="common-project-layouts.html">Common Project Layouts</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="tasks.html">Tasks</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="modules.html">Modules</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="cross-builds.html">Cross Builds</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="extending-mill.html">Extending Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="mill-internals.html">Mill Internals</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="contrib-modules.html">Contrib Modules</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="thirdparty-modules.html">Thirdparty Modules</a></li></ul></div></div></div></div><hr class=" NarrowStyles-disappear" style="background-color: #f8f8f8;width: 80%;" /><div class=" WideStyles-tableOfContents NarrowStyles-disappear" style="color: #f8f8f8;"><div style="padding-left: 40px;" class=" NarrowStyles-disappear"><b>Table of Contents</b></div><div style="overflow-y: auto;flex-shrink: 1;min-height: 0px;"><ul style="overflow: hidden;text-align: start;margin-top: 10px;white-space: nowrap;text-overflow: ellipsis;margin-right: 10px;"><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#defining-cross-modules">Defining Cross Modules</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#using-cross-modules-from-outside">Using Cross Modules from Outside</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#using-cross-modules-from-other-cross-modules">Using Cross Modules from other Cross Modules</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#cross-resolvers">Cross Resolvers</a></li></ul></div></div></div><div class=" WideStyles-content NarrowStyles-content" style="max-width: 900px;"><h1>Cross Builds</h1><div style="margin-bottom: 10px;"><div style="display: flex;flex-direction: row;justify-content: space-between;"><a href="modules.html"><i class="fa fa-arrow-left" aria-hidden="true"></i> Modules</a><a href="extending-mill.html">Extending Mill <i class="fa fa-arrow-right" aria-hidden="true"></i></a></div></div><p>Mill handles cross-building of all sorts via the <code>Cross[T]</code> module.</p><h2 id="defining-cross-modules" class="Styles-hoverBox">Defining Cross Modules<a href="#defining-cross-modules" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
<p>You can use this as follows:</p>
<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="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() }
}
</code></pre>
<p>This defines three copies of <code>FooModule</code>: <code>"210"</code>, <code>"211"</code> and <code>"212"</code>, each of which has their own <code>suffix</code> target. You can then run them via</p>
<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="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
</code></pre>
<p>The modules each also have a <code>millSourcePath</code> of</p>
<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="text">foo/2.10
foo/2.11
foo/2.12
</code></pre>
<p>And the <code>suffix</code> targets will have the corresponding output paths for their metadata and files:</p>
<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="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
</code></pre>
<p>You can also have a cross-build with multiple inputs:</p>
<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="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 }
}
</code></pre>
<p>Here, we define our cross-values programmatically using a <code>for</code>-loop that spits out tuples instead of individual values. Our <code>FooModule</code> template class then takes two parameters instead of one. This creates the following modules each with their own <code>suffix</code> target:</p>
<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="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
</code></pre><h2 id="using-cross-modules-from-outside" class="Styles-hoverBox">Using Cross Modules from Outside<a href="#using-cross-modules-from-outside" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
<p>You can refer to targets defined in cross-modules as follows:</p>
<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="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 }
</code></pre>
<p>Here, <code>foo("2.10")</code> references the <code>"2.10"</code> instance of <code>FooModule</code>. You can refer to whatever versions of the cross-module you want, even using multiple versions of the cross-module in the same target:</p>
<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="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 }
</code></pre><h2 id="using-cross-modules-from-other-cross-modules" class="Styles-hoverBox">Using Cross Modules from other Cross Modules<a href="#using-cross-modules-from-other-cross-modules" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
<p>Targets in cross-modules can depend on one another the same way that external targets:</p>
<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="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() }
}
</code></pre>
<p>Here, you can run:</p>
<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="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
</code></pre><h2 id="cross-resolvers" class="Styles-hoverBox">Cross Resolvers<a href="#cross-resolvers" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
<p>You can define an implicit <code>mill.define.Cross.Resolver</code> within your cross-modules, which would let you use a shorthand <code>foo()</code> syntax when referring to other cross-modules with an identical set of cross values:</p>
<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="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() }
}
</code></pre>
<p>While the example <code>resolver</code> simply looks up the target <code>Cross</code> value for the cross-module instance with the same <code>crossVersion</code>, you can make the resolver arbitrarily complex. E.g. the <code>resolver</code> for <code>mill.scalalib.CrossSbtModule</code> looks for a cross-module instance whose <code>scalaVersion</code> is binary compatible (e.g. 2.10.5 is compatible with 2.10.3) with the current cross-module.</p><hr /><p><b>About the Author:</b><i> Haoyi is a software engineer, an early contributor to <a href="http://www.scala-js.org/">Scala.js</a>, and the author of many open-source Scala tools such as Mill, the <a href="http://lihaoyi.com/Ammonite">Ammonite REPL</a> and <a href="https://github.com/lihaoyi/fastparse">FastParse</a>. </i></p><p><i>If you've enjoy using Mill, or enjoyed using Haoyi's other open source libraries, please chip in (or get your Company to chip in!) via <a href="https://www.patreon.com/lihaoyi">Patreon</a> so he can continue his open-source work</i></p><hr /><div style="display: flex;flex-direction: row;justify-content: space-between;"><a href="modules.html"><i class="fa fa-arrow-left" aria-hidden="true"></i> Modules</a><a href="extending-mill.html">Extending Mill <i class="fa fa-arrow-right" aria-hidden="true"></i></a></div></div></body></html>