Skip to content

Commit 7c9e136

Browse files
authored
Sort script sources to ensure deterministic generation of child module aliases in the build.mill/package.mill file (#4113)
* The `Seq` returned from `MillBuildRootModule#scriptSources` comes from the keys of a `Map`, meaning it is arbitrary non-deterministic orders * Causing the resultant child module aliases (generated in `build.mill` and `package.mill` files to reference sub-folder `package.mill` files) to occur in non-deterministic orders * Resulting in bytecode changes (e.g. varying the bit position of each reference the lazy val initialization bitmap) that causes lots of stuff to unnecessarily invalidate Tested manually, seems to remove the misbehavior reported in #4112. Managed to reproduce it in `integration/invalidation/codesig-subfolder` with some tweaks, so I left the repro in place to guard against regression This still leaves us open to unnecessary invalidations if someone adds a new `subfolder/package.mill` file in the middle of the list, but adding new `package.mill`s is pretty uncommon so we can probably fix that in a follow up
1 parent e46008d commit 7c9e136

File tree

10 files changed

+40
-2
lines changed

10 files changed

+40
-2
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package build.subfolder2
2+
import mill._
3+
4+
5+
def subFolder2Task = Task { println("running subFolder2Task") }
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package build.subfolder3
2+
import mill._
3+
4+
def subFolder2Task = Task { println("running subFolder3Task") }
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package build.subfolder4
2+
import mill._
3+
4+
def subFolder2Task = Task { println("running subFolder4Task") }
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package build.subfolder5
2+
import mill._
3+
4+
def subFolder2Task = Task { println("running subFolder3Task") }
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package build.subfolder6
2+
import mill._
3+
4+
def subFolder2Task = Task { println("running subFolder3Task") }
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package build.subfolder7
2+
import mill._
3+
4+
def subFolder2Task = Task { println("running subFolder3Task") }
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package build.subfolder8
2+
import mill._
3+
4+
def subFolder2Task = Task { println("running subFolder3Task") }
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package build.subfolder9
2+
import mill._
3+
4+
def subFolder2Task = Task { println("running subFolder3Task") }

integration/invalidation/codesig-subfolder/src/CodeSigSubfolderTests.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import utest._
77
// Basically a copy of CodeSigHelloTests, but split across two files
88
// (build.mill and subfolder/package.mill) and with some extra assertions
99
// to exercise invalidation behavior specific to multi-file-builds
10+
//
11+
// Add a bunch of dummy subfolders to try and ensure that codesig is computed
12+
// correctly even in the presence of non-trivial subfolder `package.mill` setups
1013
object CodeSigSubfolderTests extends UtestIntegrationTestSuite {
1114
val tests: Tests = Tests {
1215
test("simple") - integrationTest { tester =>
@@ -15,7 +18,7 @@ object CodeSigSubfolderTests extends UtestIntegrationTestSuite {
1518
val initial = eval("foo")
1619

1720
assert(initial.out.linesIterator.toSeq == Seq("running foo", "running helperFoo"))
18-
assert(initial.err.contains("compiling 2 Scala sources"))
21+
assert(initial.err.contains("compiling 10 Scala sources"))
1922

2023
val cached = eval("foo")
2124
assert(cached.out == "")

runner/src/mill/runner/MillBuildRootModule.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,10 @@ abstract class MillBuildRootModule()(implicit
4646
def scriptSources: Target[Seq[PathRef]] = Task.Sources {
4747
MillBuildRootModule.parseBuildFiles(rootModuleInfo)
4848
.seenScripts
49-
.keys.map(PathRef(_))
49+
.keys
5050
.toSeq
51+
.sorted // Ensure ordering is deterministic
52+
.map(PathRef(_))
5153
}
5254

5355
def parseBuildFiles: T[FileImportGraph] = Task {

0 commit comments

Comments
 (0)