Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support module.sc files in subfolders #3213

Merged
merged 73 commits into from
Aug 8, 2024
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
e93dfea
.
lihaoyi Jun 13, 2024
9297f37
wip
lihaoyi Jun 16, 2024
3f9425c
compiles
lihaoyi Jun 16, 2024
e0a71c4
compiles
lihaoyi Jun 16, 2024
edac3e9
things compile with multiple root modules
lihaoyi Jun 17, 2024
d5af69e
compile passes kinda
lihaoyi Jun 17, 2024
327e88c
combined sub-folder build.sc resolution works
lihaoyi Jun 17, 2024
338196c
CLI handling of nested rootmodules works
lihaoyi Jun 17, 2024
d9096e3
merge
lihaoyi Jun 17, 2024
c2fd1ed
add test for commands
lihaoyi Jun 18, 2024
8229ed4
wip try to derive segments from nested build.sc
lihaoyi Jun 18, 2024
be77e65
pass Segments to all root modules (now RootModule.Base) and properly …
lihaoyi Jun 18, 2024
db85faf
relativize packages
lihaoyi Jun 18, 2024
56e9af6
add doubly nested build.sc to example
lihaoyi Jun 18, 2024
11b3f51
fix compile errors
lihaoyi Jun 25, 2024
a637e58
merge
lihaoyi Jun 25, 2024
5f8d58d
mill.integration.local.ForeignBuildsTest.checkProjectPaths passes
lihaoyi Jun 25, 2024
41b8bd1
almost all of ForeignBuildsTest passes, one remaining
lihaoyi Jun 25, 2024
279e5ab
all of ForeignBuildsTest passes
lihaoyi Jun 25, 2024
2f07454
avoid walking mill-build folder
lihaoyi Jun 25, 2024
aa336e9
fix
lihaoyi Jun 26, 2024
48e023a
re-enable relative up imports
lihaoyi Jun 26, 2024
2e16b48
fix failure tests
lihaoyi Jun 26, 2024
113f019
.
lihaoyi Jun 26, 2024
c065dfe
.
lihaoyi Jun 27, 2024
2301413
.
lihaoyi Jun 28, 2024
3d2358c
fix
lihaoyi Jun 28, 2024
6046085
.
lihaoyi Jun 28, 2024
7715603
.
lihaoyi Jun 28, 2024
f23bf98
.
lihaoyi Jun 28, 2024
e6f573b
.
lihaoyi Jun 28, 2024
f36f315
.
lihaoyi Jun 28, 2024
eb31770
rename millbuild package to build
lihaoyi Jun 30, 2024
5bca32e
improve package object discovery
lihaoyi Jun 30, 2024
dd0dbcd
remove hardcoded filters from module.sc discovery logic
lihaoyi Jun 30, 2024
e03be05
import nested package objects into scope for enclosing package objects
lihaoyi Jun 30, 2024
be5a5a3
.
lihaoyi Jul 1, 2024
67b1ed4
.
lihaoyi Jul 1, 2024
4810e15
.
lihaoyi Jul 1, 2024
69e254b
.
lihaoyi Jul 1, 2024
de50a36
skip folders without module.sc files
lihaoyi Jul 2, 2024
0e2c0e5
.
lihaoyi Jul 2, 2024
3019b15
update foreign modules tests
lihaoyi Jul 2, 2024
3d9b969
wip
lihaoyi Jul 2, 2024
72650a9
.
lihaoyi Jul 2, 2024
a060b93
.
lihaoyi Jul 2, 2024
a97d988
wip trying to do multi main module resolution
lihaoyi Jul 6, 2024
85806a1
augment resolution logic with nested module.sc files
lihaoyi Jul 6, 2024
34a452a
.
lihaoyi Jul 6, 2024
0cf3f9e
.
lihaoyi Jul 6, 2024
90cc28d
no mainmodule methods in module.sc
lihaoyi Jul 6, 2024
aff816f
reformat
lihaoyi Jul 6, 2024
ab7b9a5
.
lihaoyi Jul 6, 2024
451e409
.
lihaoyi Jul 6, 2024
4f6fc22
.
lihaoyi Jul 7, 2024
5805f98
.
lihaoyi Jul 7, 2024
e6f5aae
introduce BaseModuleTree
lihaoyi Jul 7, 2024
db64a64
pre-computed BaseModuleTree
lihaoyi Jul 7, 2024
61b7656
consolidate rootModule into BaseModuleTree
lihaoyi Jul 7, 2024
3e85f94
.
lihaoyi Jul 7, 2024
b80b9bc
.
lihaoyi Jul 18, 2024
9e7a6b4
.
lihaoyi Jul 18, 2024
f67ba73
.
lihaoyi Jul 18, 2024
949cc97
.
lihaoyi Jul 18, 2024
9789515
.
lihaoyi Jul 18, 2024
ab2a09b
.
lihaoyi Jul 18, 2024
c3f14d6
.
lihaoyi Aug 5, 2024
38e1fa5
.
lihaoyi Aug 5, 2024
6f43b70
.
lihaoyi Aug 5, 2024
422164e
.
lihaoyi Aug 6, 2024
b59e986
cleanup
lihaoyi Aug 6, 2024
d34c2d0
Merge branch 'main' into multi-build-file
lihaoyi Aug 6, 2024
4ebb2f2
.
lihaoyi Aug 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions bsp/worker/src/mill/bsp/worker/State.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import mill.eval.Evaluator
private class State(evaluators: Seq[Evaluator], debug: String => Unit) {
lazy val bspModulesById: Map[BuildTargetIdentifier, (BspModule, Evaluator)] = {
val modules: Seq[(Module, Seq[Module], Evaluator)] = evaluators
.map(ev => (ev.rootModule, JavaModuleUtils.transitiveModules(ev.rootModule), ev))
.flatMap(ev => ev.rootModules.map(rm => (rm, JavaModuleUtils.transitiveModules(rm), ev)))

val map = modules
.flatMap { case (rootModule, otherModules, eval) =>
Expand All @@ -28,7 +28,7 @@ private class State(evaluators: Seq[Evaluator], debug: String => Unit) {
map
}

lazy val rootModules: Seq[mill.define.BaseModule] = evaluators.map(_.rootModule)
lazy val rootModules: Seq[mill.define.BaseModule] = evaluators.flatMap(_.rootModules)

lazy val bspIdByModule: Map[BspModule, BuildTargetIdentifier] =
bspModulesById.view.mapValues(_._1).map(_.swap).toMap
Expand Down
6 changes: 5 additions & 1 deletion build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,11 @@ trait MillStableScalaModule extends MillPublishScalaModule with Mima {
),
ProblemFilter.exclude[ReversedMissingMethodProblem](
"mill.scalalib.JavaModule.mill$scalalib$JavaModule$$super$runMain"
)
),

// Not sure why mima is picking up this stuff which is private[mill]
ProblemFilter.exclude[Problem]("mill.resolve.*.resolve0"),
ProblemFilter.exclude[Problem]("mill.resolve.*.resolveRootModule"),
)
def mimaPreviousVersions: T[Seq[String]] = Settings.mimaBaseVersions

Expand Down
13 changes: 13 additions & 0 deletions ci/mill-bootstrap.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
diff --git a/build.sc b/build.sc
index 526ebaa9cf..616be491f9 100644
--- a/build.sc
+++ b/build.sc
@@ -1968,7 +1968,7 @@ def uploadToGithub(authKey: String) = T.command {

private def resolveTasks[T](taskNames: String*): Seq[NamedTask[T]] = {
mill.resolve.Resolve.Tasks.resolve(
- build,
+ build.`package`,
taskNames,
SelectMode.Separated
).map(x => x.asInstanceOf[Seq[mill.define.NamedTask[T]]]).getOrElse(???)
2 changes: 1 addition & 1 deletion contrib/bloop/src/mill/contrib/bloop/BloopImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ class BloopImpl(evs: () => Seq[Evaluator], wd: os.Path) extends ExternalModule {
val evals = evs()
evals.flatMap { eval =>
if (eval != null)
JavaModuleUtils.transitiveModules(eval.rootModule, accept)
eval.rootModules.flatMap(JavaModuleUtils.transitiveModules(_, accept))
.collect { case jm: JavaModule => jm }
else
Seq.empty
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,15 @@ trait ScoverageReport extends Module {
dataTargets: String
): Task[PathRef] = {
val sourcesTasks: Seq[Task[Seq[PathRef]]] = Resolve.Tasks.resolve(
evaluator.rootModule,
evaluator.rootModules,
Seq(sources),
SelectMode.Separated
) match {
case Left(err) => throw new Exception(err)
case Right(tasks) => tasks.asInstanceOf[Seq[Task[Seq[PathRef]]]]
}
val dataTasks: Seq[Task[PathRef]] = Resolve.Tasks.resolve(
evaluator.rootModule,
evaluator.rootModules,
Seq(dataTargets),
SelectMode.Separated
) match {
Expand Down
5 changes: 5 additions & 0 deletions example/misc/8-multi-build-file/bar/qux/module.sc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import mill._, scalalib._

object module extends build.MyModule {
def ivyDeps = Agg(ivy"com.lihaoyi::scalatags:0.8.2")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package bar.qux
import scalatags.Text.all._
object BarQux {
def printText(text: String): Unit = {
val value = p("world")
println("BarQux.value: " + value)
}
def main(args: Array[String]) = printText(args(0))
}
21 changes: 21 additions & 0 deletions example/misc/8-multi-build-file/build.sc
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import mill._, scalalib._

trait MyModule extends ScalaModule {
def scalaVersion = "2.13.11"
}

// Example Docs


/** Usage

> ./mill resolve __

> ./mill bar.qux.module.compile

> ./mill foo.compile

> ./mill foo.run --foo-text hello --bar-qux-text world
Foo.value: hello
BarQux.value: <p>world</p>
*/
6 changes: 6 additions & 0 deletions example/misc/8-multi-build-file/foo/module.sc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import mill._, scalalib._

object build extends RootModule with MyModule {
def moduleDeps = Seq(bar.qux.module)
def ivyDeps = Agg(ivy"com.lihaoyi::mainargs:0.4.0")
}
14 changes: 14 additions & 0 deletions example/misc/8-multi-build-file/foo/src/Foo.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package foo
import mainargs.{main, ParserForMethods, arg}
object Foo {
val value = "hello"

@main
def main(@arg(name = "foo-text") fooText: String,
@arg(name = "bar-qux-text") barQuxText: String): Unit = {
println("Foo.value: " + Foo.value)
bar.qux.BarQux.printText(barQuxText)
}

def main(args: Array[String]): Unit = ParserForMethods(this).runOrExit(args)
}
13 changes: 6 additions & 7 deletions example/src/mill/integration/ExampleTestSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -72,18 +72,17 @@ object ExampleTestSuite extends IntegrationTestSuite {
}

test("exampleUsage") {

val parsed = upickle.default.read[Seq[(String, String)]](sys.env("MILL_EXAMPLE_PARSED"))
val usageComment = parsed.collect { case ("example", txt) => txt }.mkString("\n\n")
val commandBlocks = ("\n" + usageComment.trim).split("\n> ").filter(_.nonEmpty)

retryOnTimeout(3) {
try {
for (commandBlock <- commandBlocks) processCommandBlock(workspaceRoot, commandBlock)
if (integrationTestMode != "fork") evalStdout("shutdown")
} finally {
try os.remove.all(workspaceRoot / "out")
catch { case e: Throwable => /*do nothing*/ }
}
try os.remove.all(workspaceRoot / "out")
catch { case e: Throwable => /*do nothing*/ }

for (commandBlock <- commandBlocks) processCommandBlock(workspaceRoot, commandBlock)
if (integrationTestMode != "fork") evalStdout("shutdown")
}
}
}
Expand Down
8 changes: 5 additions & 3 deletions idea/src/mill/idea/GenIdeaImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ case class GenIdeaImpl(
)(implicit ctx: Ctx) {
import GenIdeaImpl._

val workDir: os.Path = evaluators.head.rootModule.millSourcePath
val workDir: os.Path = evaluators.head.rootModules.head.millSourcePath
val ideaDir: os.Path = workDir / ".idea"

val ideaConfigVersion = 4
Expand Down Expand Up @@ -67,7 +67,9 @@ case class GenIdeaImpl(
fetchMillModules: Boolean = true
): Seq[(os.SubPath, scala.xml.Node)] = {

val rootModules = evaluators.zipWithIndex.map { case (ev, idx) => (ev.rootModule, ev, idx) }
val rootModules = evaluators.zipWithIndex.map { case (ev, idx) =>
(ev.rootModules.head, ev, idx)
}
val transitive: Seq[(BaseModule, Seq[Module], Evaluator, Int)] = rootModules
.map { case (rootModule, ev, idx) =>
(rootModule, JavaModuleUtils.transitiveModules(rootModule), ev, idx)
Expand Down Expand Up @@ -118,7 +120,7 @@ case class GenIdeaImpl(
}

// is head the right one?
val buildDepsPaths = Classpath.allJars(evaluators.head.rootModule.getClass.getClassLoader)
val buildDepsPaths = Classpath.allJars(evaluators.head.rootModules.head.getClass.getClassLoader)
.map(url => os.Path(java.nio.file.Paths.get(url.toURI)))

def resolveTasks: Map[Evaluator, Seq[Task[ResolvedModule]]] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ object CompileErrorTests extends IntegrationTestSuite {
assert(res.err.contains("""println(doesntExist)"""))
assert(res.err.contains("""qux.sc:3:34: type mismatch;"""))
assert(res.err.contains(
"""build.sc:8:5: value noSuchMethod is not a member of object build.this.foo"""
"""build.sc:8:5: value noSuchMethod is not a member of object"""
))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ object CrossCollisionsTests extends IntegrationTestSuite {
test("detect-collision") {
val res = evalStdout("resolve", "foo._")
assert(!res.isSuccess)
assert(res.err.contains("Cross module "))
assert(
res.err.contains(
"Cross module millbuild.build#foo contains colliding cross values: List(List(a, b), List(c)) and List(List(a), List(b, c))"
" contains colliding cross values: List(List(a, b), List(c)) and List(List(a), List(b, c))"
)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ object MultipleTopLevelModulesTests extends IntegrationTestSuite {
val res = evalStdout("resolve", "_")
assert(!res.isSuccess)
assert(res.err.contains(
"Only one RootModule can be defined in a build, not 2: millbuild.build$bar$,millbuild.build$foo$"
"Only one RootModule can be defined in a build, not 2:"
))
}
}
Expand Down
11 changes: 4 additions & 7 deletions integration/feature/bsp-modules/repo/build.sc
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import mill._
import mill.api.{PathRef}
import mill.scalalib._
import $file.proj1.{build => proj1}
import $file.proj2.{build => proj2}
import $file.proj3.{build => proj3}

trait HelloBspModule extends ScalaModule {
def scalaVersion = sys.props.getOrElse("TEST_SCALA_2_13_VERSION", ???)
Expand All @@ -12,17 +9,17 @@ trait HelloBspModule extends ScalaModule {

object HelloBsp extends HelloBspModule {
// Explicitly depends on proj1
def moduleDeps: Seq[JavaModule] = Seq(proj1.proj1)
def moduleDeps: Seq[JavaModule] = Seq(build.proj1.module)
// Explicitly depends on proj2
def compileModuleDeps: Seq[JavaModule] = Seq(proj2.proj2)
def compileModuleDeps: Seq[JavaModule] = Seq(build.proj2.module)
// Implicitly depends on proj3 via a target
override def unmanagedClasspath: T[Agg[PathRef]] = T {
Agg(proj3.proj3.jar())
Agg(build.proj3.module.jar())
}
}

def validate() = T.command {
val transitiveModules = mill.scalalib.internal.JavaModuleUtils.transitiveModules(build)
val transitiveModules = mill.scalalib.internal.JavaModuleUtils.transitiveModules(build.`package`)
val file = T.dest / "transitive-modules.json"
val moduleNames = transitiveModules.map(m =>
mill.scalalib.internal.ModuleUtils.moduleDisplayName(m)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import mill._
import mill.scalalib._

object proj1 extends ScalaModule {
object module extends ScalaModule {
def scalaVersion = sys.props.getOrElse("TEST_SCALA_2_13_VERSION", ???)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import mill._
import mill.scalalib._

object proj2 extends ScalaModule {
object module extends ScalaModule {
def scalaVersion = sys.props.getOrElse("TEST_SCALA_2_13_VERSION", ???)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import mill._
import mill.scalalib._

object proj3 extends ScalaModule {
object module extends ScalaModule {
def scalaVersion = sys.props.getOrElse("TEST_SCALA_2_13_VERSION", ???)
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ object BspModulesTests extends IntegrationTestSuite {
"", // the root module has no segments at all
"HelloBsp",
"HelloBsp.test",
"foreign-modules.proj1.build.proj1",
"foreign-modules.proj2.build.proj2"
"proj1.module",
"proj2.module"
// "foreign-modules.proj3.proj3" // still not detected
).sorted
assert(readModules == expectedModules)
Expand Down
2 changes: 1 addition & 1 deletion integration/feature/foreign/repo/conflict/build.sc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import $file.inner.{build => innerBuild}
import build.conflict.inner
import mill._

// In this build, we have a local module targeting
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import $file.inner.build

import mill._

trait PathAware extends mill.Module {
Expand Down
Loading