scalabuild-toolsmill

Mill: How can I build cross build for RootModule?


I have Mill project and currently built for Scala 3.

I'm preparing for cross build for Scala 2.13.

Currently I have this build.sc:

import mill._, scalalib._
import publish._

// qw is my project name
object qw extends Cross[QwModule]("2.13.11", "3.3.0") {
  def defaultCrossSegments = Seq("3.3.0")
}
trait QwModule
    extends Cross.Module[String]
    with RootModule
    with ScalaModule
    with PublishModule
    with Cross.Module[String] {
  def scalaVersion = crossValue
  // ...
}

However this doesn't compile:

% mill 'qw[3.3.0].compile'                                                                                    [39/1074]
[build.sc] [43/52] compile                                                                                             
[info] compiling 1 Scala source to /home/windymelt/src/github.com/windymelt/qw.scala/out/mill-build/compile.dest/classe
s ...                                                                                                                  
[info] done compiling                                                                                                  
[build.sc] [52/52] methodCodeHashSignatures              
Exception in thread "MillServerActionRunner" java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length
 0                                                                                                                     
        at scala.collection.immutable.ArraySeq$ofRef.apply(ArraySeq.scala:331)
        at scala.collection.IndexedSeqOps.head(IndexedSeq.scala:94)
        at scala.collection.IndexedSeqOps.head$(IndexedSeq.scala:94)
        at scala.collection.immutable.ArraySeq.head(ArraySeq.scala:35)
        at mill.resolve.Resolve$.mill$resolve$Resolve$$instantiateTarget(Resolve.scala:92)                            
        at mill.resolve.Resolve$Tasks$.$anonfun$handleResolved$3(Resolve.scala:46)
        at scala.util.Either.flatMap(Either.scala:352)
        at mill.resolve.Resolve$Tasks$.$anonfun$handleResolved$2(Resolve.scala:46)
        at scala.collection.immutable.List.map(List.scala:246)
        at scala.collection.immutable.List.map(List.scala:79)
        at mill.resolve.Resolve$Tasks$.handleResolved(Resolve.scala:42)
        at mill.resolve.Resolve.$anonfun$resolveNonEmptyAndHandle$3(Resolve.scala:241)
        at scala.util.Either.flatMap(Either.scala:352)
        at mill.resolve.Resolve.resolveNonEmptyAndHandle(Resolve.scala:241)
        at mill.resolve.Resolve.resolveNonEmptyAndHandle$(Resolve.scala:223)
        at mill.resolve.Resolve$Tasks$.resolveNonEmptyAndHandle(Resolve.scala:34)
        at mill.resolve.Resolve.$anonfun$resolve0$4(Resolve.scala:207)
        at scala.util.Either.map(Either.scala:382)
        at mill.resolve.Resolve.$anonfun$resolve0$3(Resolve.scala:206)
        at scala.collection.immutable.List.map(List.scala:246)
        at scala.collection.immutable.List.map(List.scala:79)
        at mill.resolve.Resolve.$anonfun$resolve0$2(Resolve.scala:205)
...

How can I build RootModule with cross scala versioning?


Solution

  • A RootModule always needs to be a singleton top-level module.

    The quick fix to your specific problem is to remove the extends RootModule from your QwModule trait, and your Mill command should work as expected.

    Some more explanation

    Without an explicit RootModule, Mill uses a built-in root module, and all modules you define in your build.sc become sub modules of it. Hence, you need to specify their full segmented names or use some patterns when running them from the Mill CLI.

    So, to compile a top-level Scala module qw, your Mill command is mill qw.compile. Whereas if you make the qw module a RootModule, your Mill command to compile it is mill compile.

    Adding a RootModule to a Cross.Module module violates both requirements:

    1. It is no longer a top-level module, as Cross.Module instances are sub-modules of their holding Cross module.

    2. It is not a singleton anymore, as you have many of them (in your case: two), one for each crossValue.

    And some other musing

    I wonder how you managed to get this error (java.lang.ArrayIndexOutOfBoundsException). Instead, you should see at least one compile error, as your posted build.sc doesn't compile and RootModule is an abstract class, so it can't be mixed-in with the with keyword.