Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
1b91e3e
WIP: I don't think this approach will work
arturaz Aug 29, 2025
50d1428
WIP: this compiles but doesn't work
arturaz Aug 29, 2025
1f02621
WIP: yeah, I'm stuck
arturaz Aug 29, 2025
b77f709
WIP: force to always use semantic db
arturaz Sep 11, 2025
c59e092
Merge remote-tracking branch 'upstream/main' into fix/semanticdb-gene…
arturaz Sep 11, 2025
1ac358d
WIP: force to always use semantic db
arturaz Sep 11, 2025
31e0309
WIP: works?
arturaz Sep 11, 2025
8ed1ef3
[autofix.ci] apply automated fixes
autofix-ci[bot] Sep 11, 2025
f60ae90
Fix `BuildCtx.withFilesystemCheckerDisabled`
arturaz Sep 11, 2025
559b18f
Merge branch 'fix/semanticdb-generation-on-compile' of https://github…
arturaz Sep 11, 2025
017c331
Merge remote-tracking branch 'upstream/main' into fix/semanticdb-gene…
arturaz Oct 3, 2025
f7e6b00
Binary compatibility and code review fixes.
arturaz Oct 3, 2025
317f5fc
[autofix.ci] apply automated fixes
autofix-ci[bot] Oct 3, 2025
93777e2
Docs.
arturaz Oct 3, 2025
73a724e
Undeprecate public JVM worker API
arturaz Oct 3, 2025
9d66aa2
docs
arturaz Oct 3, 2025
ee7f50e
test fixes
arturaz Oct 3, 2025
e24a0b2
test fixes
arturaz Oct 3, 2025
de7fa17
[autofix.ci] apply automated fixes
autofix-ci[bot] Oct 3, 2025
08e2819
Refactor to dynamically construct a different task graph based on a b…
arturaz Oct 17, 2025
f4043b0
Merge remote-tracking branch 'refs/remotes/origin/fix/semanticdb-gene…
arturaz Oct 17, 2025
e8becf3
Fix semantic db compilation for `KotlinModule`
arturaz Oct 26, 2025
16ff91d
Fix semantic db compilation for `MillBuildRootModule`
arturaz Oct 26, 2025
8e9c7e3
Merge remote-tracking branch 'upstream/main' into fix/semanticdb-gene…
arturaz Oct 26, 2025
e6445cb
Fix `HelloJavaTests`
arturaz Oct 26, 2025
16c0ca6
[autofix.ci] apply automated fixes
autofix-ci[bot] Oct 26, 2025
5d66ac4
Fix `KotlinModule` compilation
arturaz Oct 26, 2025
4ea7fc3
[autofix.ci] apply automated fixes
autofix-ci[bot] Oct 26, 2025
ababf65
Fix `KotlinModule` compilation: zinc was receiving kotlin files
arturaz Oct 26, 2025
d55ac0f
[autofix.ci] apply automated fixes
autofix-ci[bot] Oct 26, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ object PlayModuleTests extends TestSuite with PlayTestSuite {
val (crossScalaVersion, crossPlayVersion) = (crossValue, crossValue2)
override def playVersion = crossPlayVersion
override def scalaVersion = crossScalaVersion

object test extends PlayTests
override def mvnDeps = Task { super.mvnDeps() ++ Seq(ws()) }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ object PlaySingleApiModuleTests extends TestSuite with PlayTestSuite {
object playsingleapi extends TestRootModule with PlayApiModule {
override val moduleDir = os.temp() // workaround problem in `SingleModule`
override def playVersion = Task { testPlay28 }
override def scalaVersion = Task { "2.13.12" }
override def scalaVersion = Task { "2.13.17" }
object test extends PlayTests

lazy val millDiscover = Discover[this.type]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ trait SemanticDbJavaModuleApi {
private[mill] def bspCompiledClassesAndSemanticDbFiles: TaskApi[UnresolvedPathApi[?]]
}
object SemanticDbJavaModuleApi {
val buildTimeJavaSemanticDbVersion = BuildInfo.semanticDbJavaVersion
val buildTimeSemanticDbVersion = BuildInfo.semanticDBVersion
val buildTimeJavaSemanticDbVersion: String = BuildInfo.semanticDbJavaVersion
val buildTimeSemanticDbVersion: String = BuildInfo.semanticDBVersion

private[mill] val contextSemanticDbVersion: InheritableThreadLocal[Option[String]] =
new InheritableThreadLocal[Option[String]] {
protected override def initialValue(): Option[String] = None.asInstanceOf[Option[String]]
protected override def initialValue(): Option[String] = None
}

private[mill] val contextJavaSemanticDbVersion: InheritableThreadLocal[Option[String]] =
new InheritableThreadLocal[Option[String]] {
protected override def initialValue(): Option[String] = None.asInstanceOf[Option[String]]
protected override def initialValue(): Option[String] = None
}

private[mill] def resetContext(): Unit = {
Expand Down
16 changes: 15 additions & 1 deletion core/api/src/mill/api/BuildCtx.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package mill.api
import collection.mutable
import mill.api.Watchable
import mill.constants.EnvVars
import mill.constants.{EnvVars, OutFiles, OutFolderMode}

import scala.util.DynamicVariable

/**
Expand Down Expand Up @@ -50,6 +51,7 @@ object BuildCtx {
}
}

/** As [[watchValue]] but watches a file path. */
def watch(p: os.Path): os.Path = {
val watchable = Watchable.Path(p.toNIO, false, PathRef(p).sig)
watchedValues.append(watchable)
Expand All @@ -59,4 +61,16 @@ object BuildCtx {
def watch0(w: Watchable): Unit = watchedValues.append(w)

def evalWatch0(w: Watchable): Unit = evalWatchedValues.append(w)

/**
* Folder in the filesystem where Mill's BSP sessions that require semanticdb store an indicator file (name =
* process PID, contents are irrelevant) to communicate to main Mill daemon and other BSP sessions that there is at
* least one Mill session that will need the semanticdb.
*
* The reasoning is that if at least one of Mill's clients requests semanticdb, then there is no point in running
* regular `compile` without semanticdb, as eventually we will have to rerun it with semanticdb, and thus we should
* compile with semanticdb upfront to avoid paying the price of compling twice (without semanticdb and then with it).
*/
private[mill] def bspSemanticDbSessionsFolder: os.Path =
workspaceRoot / os.SubPath(OutFiles.outFor(OutFolderMode.BSP)) / "semanticdb-sessions"
}
6 changes: 6 additions & 0 deletions core/constants/src/mill/constants/EnvVars.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ public class EnvVars {
*/
public static final String MILL_OUTPUT_DIR = "MILL_OUTPUT_DIR";

/**
* Output directory where Mill workers' state and Mill tasks output should be
* written to for the Mill instances running in BSP mode.
*/
public static final String MILL_BSP_OUTPUT_DIR = "MILL_BSP_OUTPUT_DIR";

/**
* If set to "1", Mill will re-use the regular @{Link OutFiles#out} folder instead of
* using a separate one for BSP output.
Expand Down
20 changes: 16 additions & 4 deletions core/constants/src/mill/constants/OutFiles.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ public class OutFiles {
*/
private static final String envOutOrNull = System.getenv(EnvVars.MILL_OUTPUT_DIR);

/**
* Allows us to override the `out/mill-bsp-out` folder from the environment via the
* {@link EnvVars#MILL_BSP_OUTPUT_DIR} variable.
*/
private static final String envBspOutOrNull = System.getenv(EnvVars.MILL_BSP_OUTPUT_DIR);

/** @see EnvVars#MILL_NO_SEPARATE_BSP_OUTPUT_DIR */
public static final boolean mergeBspOut =
"1".equals(System.getenv(EnvVars.MILL_NO_SEPARATE_BSP_OUTPUT_DIR));
Expand All @@ -28,24 +34,30 @@ public class OutFiles {
*/
public static final String out = envOutOrNull == null ? defaultOut : envOutOrNull;

/**
* Default hard-coded value for the Mill `out/` folder path when Mill is running in BSP mode. Unless you know
* what you are doing, you should favor using {@link #outFor} instead.
*/
public static final String defaultBspOut = "out/mill-bsp-out";

/**
* Path of the Mill `out/` folder when Mill is running in BSP mode. Unless you know
* what you are doing, you should favor using {@link #outFor} instead.
*/
public static final String bspOut = "out/mill-bsp-out";
public static final String bspOut = envBspOutOrNull == null ? defaultBspOut : envBspOutOrNull;

/**
* Path of the Mill {@link #out} folder.
*
* @param outMode If {@link #envOutOrNull} is set, this parameter is ignored.
*/
public static String outFor(OutFolderMode outMode) {
if (envOutOrNull != null) return envOutOrNull;
switch (outMode) {
case REGULAR:
return out;
return envOutOrNull != null ? envOutOrNull : out;
case BSP:
return mergeBspOut ? out : bspOut;
if (envBspOutOrNull != null) return envBspOutOrNull;
return mergeBspOut ? outFor(OutFolderMode.REGULAR) : bspOut;
default:
throw new IllegalArgumentException("Unknown out folder mode: " + outMode);
}
Expand Down
2 changes: 1 addition & 1 deletion core/exec/src/mill/exec/GroupExecution.scala
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ object GroupExecution {
if (path.startsWith(workspace) && !validReadDests.exists(path.startsWith(_))) {
sys.error(
s"Reading from ${path.relativeTo(workspace)} not allowed during execution of `$terminal`.\n" +
"You can only read files referenced by `Task.Source` or `Task.Sources`, or within a `Task.Input"
"You can only read files referenced by `Task.Source` or `Task.Sources`, or within a `Task.Input`"
)
}
}
Expand Down
2 changes: 2 additions & 0 deletions example/scalalib/spark/1-hello-spark/build.mill
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import mill.*, scalalib.*

object foo extends ScalaModule {
def scalaVersion = "2.12.20"
def semanticDbVersion = "4.9.0" // last version to support this Scala

def mvnDeps = Seq(
mvn"org.apache.spark::spark-core:3.5.4",
mvn"org.apache.spark::spark-sql:3.5.4"
Expand Down
2 changes: 2 additions & 0 deletions example/scalalib/spark/3-semi-realistic/build.mill
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import mill.*, scalalib.*

object `package` extends ScalaModule {
def scalaVersion = "2.12.20"
def semanticDbVersion = "4.9.0" // last version to support this Scala

def mvnDeps = Seq(
mvn"org.apache.spark::spark-core:3.5.6",
mvn"org.apache.spark::spark-sql:3.5.6"
Expand Down
3 changes: 2 additions & 1 deletion integration/bsp-util/src/BspServerTestUtil.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import org.eclipse.lsp4j.jsonrpc.services.JsonRequest
import java.io.ByteArrayOutputStream
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.{CompletableFuture, ExecutorService, Executors, ThreadFactory}
import scala.annotation.unused
import scala.jdk.CollectionConverters.*
import scala.reflect.ClassTag

Expand Down Expand Up @@ -226,7 +227,7 @@ object BspServerTestUtil {
workspacePath: os.Path,
coursierCache: os.Path = os.Path(CacheDefaults.location),
javaHome: os.Path = os.Path(sys.props("java.home")),
javaVersion: String = sys.props("java.version")
@unused javaVersion: String = sys.props("java.version")
): Seq[(String, String)] =
Seq(
workspacePath.toURI.toASCIIString.stripSuffix("/") -> "file:///workspace",
Expand Down
11 changes: 11 additions & 0 deletions integration/feature/scoverage/resources/build.mill
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,27 @@ object Deps {
object core extends Cross[CoreCross]("2.13.11")
trait CoreCross extends CrossScalaModule with ScoverageModule {
override def scoverageVersion = "2.0.11"
override def semanticDbVersion = "4.9.9" // last version to support this Scala

// customized scoverage data
override lazy val scoverage: ScoverageData = new ScoverageData {
override def semanticDbVersion = "4.9.9" // last version to support this Scala
}

object test extends ScoverageTests with TestModule.ScalaTest {
override def semanticDbVersion = "4.9.9" // last version to support this Scala
override def mvnDeps = Seq(Deps.scalaTest, Deps.millMain)
}
}

object extra extends ScalaModule with ScoverageModule {
override def scoverageVersion = "2.0.11"
override def scalaVersion = "2.13.11"
override def semanticDbVersion = "4.9.9" // last version to support this Scala

// customized scoverage data
override lazy val scoverage: ScoverageData = new ScoverageData {
// some customizations
override def semanticDbVersion = "4.9.9" // last version to support this Scala
}
}
5 changes: 3 additions & 2 deletions integration/feature/scoverage/src/ScoverageTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ object ScoverageTests extends UtestIntegrationTestSuite {
test("test") - retry(3) {
integrationTest { tester =>
import tester._
assert(eval("__.compile").isSuccess)
assert(eval("core[2.13.11].scoverage.xmlReport").isSuccess)

prepEval("__.compile").runWithClues(r => assert(r.isSuccess))
prepEval("core[2.13.11].scoverage.xmlReport").runWithClues(r => assert(r.isSuccess))
}
}
}
Expand Down
34 changes: 21 additions & 13 deletions integration/ide/bsp-server/resources/snapshots/logging
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
[1-buildInitialize] Entered buildInitialize
[1-buildInitialize] Got client semanticdbVersion: * Enabling SemanticDB support.
[1-buildInitialize] buildInitialize took * msec
[bsp-init-mill-build/build.mill-59] [info] compiling * Scala sources to * ...
[bsp-init-mill-build/build.mill-59] [info] done compiling
[bsp-init-build.mill-59] [info] compiling * Scala sources to * ...
[bsp-init-build.mill-59] [info] done compiling
[bsp-init-098] [info] compiling * Scala source to * ...
[bsp-init-098] [info] done compiling
[bsp-init-mill-build/build.mill-70] [info] compiling * Scala sources to * ...
[bsp-init-mill-build/build.mill-70] [info] done compiling
[bsp-init-build.mill-70] [info] compiling * Scala sources to * ...
[bsp-init-build.mill-70] [info] done compiling
[bsp-init-109] [info] compiling * Scala source to * ...
[bsp-init-109] [info] done compiling
[bsp-init] SNAPSHOT
[2-workspaceBuildTargets] Entered workspaceBuildTargets
[2-workspaceBuildTargets] Evaluating * tasks
Expand All @@ -29,16 +29,24 @@
[3-loggingTest] loggingTest took * msec
[4-compile] Entered buildTargetCompile
[4-compile] Evaluating 1 task
[4-compile] Done
[4-compile-60] errored.exception.compile task failed
[4-compile] 1 tasks failed
[4-compile] errored.exception.compile java.lang.RuntimeException: nope
[4-compile] scala.sys.package$.error(package.scala:27)
[4-compile] build_.package_.build_$package_$errored$exception$$$_$compile$$anonfun$1$$anonfun$1(build.mill:75)
[4-compile] mill.api.Task$Named.evaluate(Task.scala:389)
[4-compile] mill.api.Task$Named.evaluate$(Task.scala:374)
[4-compile] mill.api.Task$Computed.evaluate(Task.scala:400)
[4-compile] Failed
[4-compile] buildTargetCompile took * msec
[5-compile] Entered buildTargetCompile
[5-compile] Evaluating 1 task
[5-compile-55] [info] compiling * Scala source to * ...
[5-compile-55] [error] *:2:3: not found: value nope
[5-compile-55] [error] nope
[5-compile-55] [error] ^
[5-compile-55] [error] one error found
[5-compile-55] errored.compilation-error.semanticDbDataDetailed task failed
[5-compile-59] [info] compiling * Scala source to * ...
[5-compile-59] [error] *:2:3: not found: value nope
[5-compile-59] [error] nope
[5-compile-59] [error] ^
[5-compile-59] [error] one error found
[5-compile-59] errored.compilation-error.compile task failed
[5-compile] Done
[5-compile] buildTargetCompile took * msec
[6-compile] Entered buildTargetCompile
Expand Down
2 changes: 2 additions & 0 deletions libs/androidlib/src/mill/androidlib/AndroidModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,7 @@ trait AndroidModule extends JavaModule { outer =>
.internalWorker()
.compileJava(
ZincCompileJava(
compileTo = Task.dest,
upstreamCompileOutput = upstreamCompileOutput(),
sources = androidLibsRClasses().map(_.path),
compileClasspath = Seq.empty,
Expand Down Expand Up @@ -734,6 +735,7 @@ trait AndroidModule extends JavaModule { outer =>
.internalWorker()
.compileJava(
ZincCompileJava(
compileTo = Task.dest,
upstreamCompileOutput = upstreamCompileOutput(),
sources = sources.map(_.path),
compileClasspath = androidTransitiveLibRClasspath().map(_.path),
Expand Down
Loading