From 1637685f09c4b13acc23611844648eb96e669ebb Mon Sep 17 00:00:00 2001 From: albertpchen Date: Wed, 9 Oct 2024 22:09:48 +0100 Subject: [PATCH 01/10] make ZincWorkerModule java home configurable, add resolveJavaHome to CoursierModule --- build.mill | 1 + main/package.mill | 2 +- main/util/src/mill/util/CoursierSupport.scala | 30 ++++++++++++++++ .../src/mill/scalalib/CoursierModule.scala | 9 +++++ scalalib/src/mill/scalalib/JavaModule.scala | 10 ++++-- scalalib/src/mill/scalalib/ScalaModule.scala | 2 +- .../src/mill/scalalib/ZincWorkerModule.scala | 10 ++++-- .../src/mill/scalalib/HelloJavaTests.scala | 34 ++++++++++++++++++- .../mill/scalalib/worker/ZincWorkerImpl.scala | 8 +++-- 9 files changed, 95 insertions(+), 11 deletions(-) diff --git a/build.mill b/build.mill index 9c2c741026a..a7f949c09fd 100644 --- a/build.mill +++ b/build.mill @@ -123,6 +123,7 @@ object Deps { val coursier = ivy"io.get-coursier::coursier:2.1.14" val coursierInterface = ivy"io.get-coursier:interface:1.0.19" + val coursierJvm = ivy"io.get-coursier::coursier-jvm:2.1.13" val cask = ivy"com.lihaoyi::cask:0.9.4" val castor = ivy"com.lihaoyi::castor:0.3.0" diff --git a/main/package.mill b/main/package.mill index 083d84bce05..b0ff0386445 100644 --- a/main/package.mill +++ b/main/package.mill @@ -100,7 +100,7 @@ object `package` extends RootModule with build.MillStableScalaModule with BuildI object util extends build.MillStableScalaModule { def moduleDeps = Seq(api, client) - def ivyDeps = Agg(build.Deps.coursier, build.Deps.jline) + def ivyDeps = Agg(build.Deps.coursier, build.Deps.coursierJvm, build.Deps.jline) } object define extends build.MillStableScalaModule { diff --git a/main/util/src/mill/util/CoursierSupport.scala b/main/util/src/mill/util/CoursierSupport.scala index ba09b7bfb0b..41af6ee2e47 100644 --- a/main/util/src/mill/util/CoursierSupport.scala +++ b/main/util/src/mill/util/CoursierSupport.scala @@ -5,6 +5,7 @@ import coursier.error.FetchError.DownloadingArtifacts import coursier.error.ResolutionError.CantDownloadModule import coursier.params.ResolutionParams import coursier.parse.RepositoryParser +import coursier.jvm.{JvmCache, JvmIndex, JavaHome} import coursier.util.Task import coursier.{Artifacts, Classifier, Dependency, Repository, Resolution, Resolve, Type} import mill.api.Loose.Agg @@ -12,6 +13,8 @@ import mill.api.{Ctx, PathRef, Result} import scala.collection.mutable import scala.util.chaining.scalaUtilChainingOps +import coursier.cache.ArchiveCache +import scala.util.control.NonFatal trait CoursierSupport { import CoursierSupport._ @@ -164,6 +167,33 @@ trait CoursierSupport { (deps0, res.getOrThrow) } + /** + * Resolve java home using Coursier. + * + * The id string has format "$DISTRIBUTION:$VERSION". e.g. graalvm-community:23.0.0 + */ + def resolveJavaHome( + id: String, + ctx: Option[mill.api.Ctx.Log] = None, + coursierCacheCustomizer: Option[FileCache[Task] => FileCache[Task]] = None + ): Result[os.Path] = { + val coursierCache0 = coursierCache(ctx, coursierCacheCustomizer) + val jvmCache = JvmCache() + .withArchiveCache( + ArchiveCache().withCache(coursierCache0) + ) + .withIndex(JvmIndex.load()) + val javaHome = JavaHome() + .withCache(jvmCache) + try { + val file = javaHome.get(id).unsafeRun()(coursierCache0.ec) + Result.Success(os.Path(file)) + } catch { + case NonFatal(error) => + Result.Exception(error, new Result.OuterStack((new Exception).getStackTrace)) + } + } + def resolveDependenciesMetadataSafe( repositories: Seq[Repository], deps: IterableOnce[Dependency], diff --git a/scalalib/src/mill/scalalib/CoursierModule.scala b/scalalib/src/mill/scalalib/CoursierModule.scala index a952acb62eb..cbb27c44db0 100644 --- a/scalalib/src/mill/scalalib/CoursierModule.scala +++ b/scalalib/src/mill/scalalib/CoursierModule.scala @@ -32,6 +32,15 @@ trait CoursierModule extends mill.Module { Lib.depToDependencyJava(_: Dep) } + def resolveJavaHome(id: String): Task[PathRef] = Task.Anon { + val path = mill.util.Jvm.resolveJavaHome( + id=id, + coursierCacheCustomizer = coursierCacheCustomizer(), + ctx = Some(implicitly[mill.api.Ctx.Log]) + ).getOrThrow + PathRef(path, quick = true) + } + def defaultResolver: Task[CoursierModule.Resolver] = Task.Anon { new CoursierModule.Resolver( repositories = repositoriesTask(), diff --git a/scalalib/src/mill/scalalib/JavaModule.scala b/scalalib/src/mill/scalalib/JavaModule.scala index e7da0fb7760..2a8ce4c4492 100644 --- a/scalalib/src/mill/scalalib/JavaModule.scala +++ b/scalalib/src/mill/scalalib/JavaModule.scala @@ -1071,14 +1071,18 @@ trait JavaModule ) @internal - def bspJvmBuildTarget: JvmBuildTarget = + def bspJvmBuildTarget: Task[JvmBuildTarget] = Task.Anon { JvmBuildTarget( - javaHome = Option(System.getProperty("java.home")).map(p => BspUri(os.Path(p))), + javaHome = zincWorker() + .javaHome() + .map(p => BspUri(p.path)) + .orElse(Option(System.getProperty("java.home")).map(p => BspUri(os.Path(p)))), javaVersion = Option(System.getProperty("java.version")) ) + } @internal override def bspBuildTargetData: Task[Option[(String, AnyRef)]] = Task.Anon { - Some((JvmBuildTarget.dataKind, bspJvmBuildTarget)) + Some((JvmBuildTarget.dataKind, bspJvmBuildTarget())) } } diff --git a/scalalib/src/mill/scalalib/ScalaModule.scala b/scalalib/src/mill/scalalib/ScalaModule.scala index c91ef4add7b..7da35a4c560 100644 --- a/scalalib/src/mill/scalalib/ScalaModule.scala +++ b/scalalib/src/mill/scalalib/ScalaModule.scala @@ -592,7 +592,7 @@ trait ScalaModule extends JavaModule with TestModule.ScalaModuleBase { outer => scalaBinaryVersion = ZincWorkerUtil.scalaBinaryVersion(scalaVersion()), platform = ScalaPlatform.JVM, jars = scalaCompilerClasspath().map(_.path.toNIO.toUri.toString).iterator.toSeq, - jvmBuildTarget = Some(bspJvmBuildTarget) + jvmBuildTarget = Some(bspJvmBuildTarget()) ) )) } diff --git a/scalalib/src/mill/scalalib/ZincWorkerModule.scala b/scalalib/src/mill/scalalib/ZincWorkerModule.scala index eb2ebb6f6b1..be1c3831b3e 100644 --- a/scalalib/src/mill/scalalib/ZincWorkerModule.scala +++ b/scalalib/src/mill/scalalib/ZincWorkerModule.scala @@ -44,6 +44,10 @@ trait ZincWorkerModule extends mill.Module with OfflineSupportModule { self: Cou def zincLogDebug: T[Boolean] = Task.Input(T.ctx().log.debugEnabled) + def javaHome: T[Option[PathRef]] = Task { + None + } + def worker: Worker[ZincWorkerApi] = Task.Worker { val jobs = T.ctx() match { case j: Ctx.Jobs => j.jobs @@ -66,7 +70,8 @@ trait ZincWorkerModule extends mill.Module with OfflineSupportModule { self: Cou classOf[(Agg[PathRef], String) => PathRef], // compilerJarNameGrep classOf[KeyedLockedCache[_]], // compilerCache classOf[Boolean], // compileToJar - classOf[Boolean] // zincLogDebug + classOf[Boolean], // zincLogDebug + classOf[Option[PathRef]], // javaHome ) .newInstance( Left(( @@ -83,7 +88,8 @@ trait ZincWorkerModule extends mill.Module with OfflineSupportModule { self: Cou ZincWorkerUtil.grepJar(_, "scala-compiler", _, sources = false), new FixSizedCache(jobs), java.lang.Boolean.FALSE, - java.lang.Boolean.valueOf(zincLogDebug()) + java.lang.Boolean.valueOf(zincLogDebug()), + javaHome() ) instance.asInstanceOf[ZincWorkerApi] } diff --git a/scalalib/test/src/mill/scalalib/HelloJavaTests.scala b/scalalib/test/src/mill/scalalib/HelloJavaTests.scala index 7c8a0461087..7f08e34e1ae 100644 --- a/scalalib/test/src/mill/scalalib/HelloJavaTests.scala +++ b/scalalib/test/src/mill/scalalib/HelloJavaTests.scala @@ -5,7 +5,7 @@ import mill.api.Result import mill.testkit.UnitTester import mill.testkit.TestBaseModule import utest._ -import utest.framework.TestPath +import mill.define.ModuleRef object HelloJavaTests extends TestSuite { @@ -25,6 +25,21 @@ object HelloJavaTests extends TestSuite { } } } + + object HelloJavaJavaHomeOverride extends TestBaseModule { + object ZincWorkerOverride extends ZincWorkerModule with CoursierModule { + override def javaHome: T[Option[PathRef]] = Task { + Some(resolveJavaHome("graalvm-community:23.0.0")()) + } + } + + object core extends JavaModule { + override def zincWorker: ModuleRef[ZincWorkerModule] = ModuleRef(ZincWorkerOverride) + override def docJarUseArgsFile = false + object test extends JavaTests with TestModule.Junit4 + } + } + val resourcePath = os.Path(sys.env("MILL_TEST_RESOURCE_DIR")) / "hello-java" def testEval() = UnitTester(HelloJava, resourcePath) @@ -47,6 +62,23 @@ object HelloJavaTests extends TestSuite { !os.walk(result3.value.classes.path).exists(_.last == "Core.class") ) } + + test("javaHome") { + val eval = UnitTester(HelloJavaJavaHomeOverride, resourcePath) + + val Right(result) = eval.apply(HelloJavaJavaHomeOverride.core.compile) + + val coreClassFile = os.walk(result.value.classes.path).find(_.last == "Core.class") + + assert( + coreClassFile.isDefined, + + // The first eight bytes are magic numbers followed by two bytes for major version and two bytes for minor version + // We are overriding to java 23 which corresponds to class file version 67 + os.read.bytes(coreClassFile.get, 4, 4).toSeq == Seq[Byte](0, 0, 0, 67), + ) + } + test("semanticDbData") { val expectedFile1 = os.rel / "META-INF/semanticdb/core/src/Core.java.semanticdb" diff --git a/scalalib/worker/src/mill/scalalib/worker/ZincWorkerImpl.scala b/scalalib/worker/src/mill/scalalib/worker/ZincWorkerImpl.scala index f8bb3ccdea5..a652304621f 100644 --- a/scalalib/worker/src/mill/scalalib/worker/ZincWorkerImpl.scala +++ b/scalalib/worker/src/mill/scalalib/worker/ZincWorkerImpl.scala @@ -62,7 +62,8 @@ class ZincWorkerImpl( compilerJarNameGrep: (Agg[PathRef], String) => PathRef, compilerCache: KeyedLockedCache[Compilers], compileToJar: Boolean, - zincLogDebug: Boolean + zincLogDebug: Boolean, + javaHome: Option[PathRef] ) extends ZincWorkerApi with AutoCloseable { private val zincLogLevel = if (zincLogDebug) sbt.util.Level.Debug else sbt.util.Level.Info private[this] val ic = new sbt.internal.inc.IncrementalCompilerImpl() @@ -113,12 +114,13 @@ class ZincWorkerImpl( } private def getLocalOrCreateJavaTools(javacRuntimeOptions: Seq[String]): JavaTools = { + val javaHome = this.javaHome.map(_.path.toNIO) val (javaCompiler, javaDoc) = // Local java compilers don't accept -J flags so when we put this together if we detect // any javacOptions starting with -J we ensure we have a non-local Java compiler which // can handle them. - if (javacRuntimeOptions.exists(filterJavacRuntimeOptions)) { - (javac.JavaCompiler.fork(None), javac.Javadoc.fork(None)) + if (javacRuntimeOptions.exists(filterJavacRuntimeOptions) || javaHome.isDefined) { + (javac.JavaCompiler.fork(javaHome), javac.Javadoc.fork(javaHome)) } else { val compiler = javac.JavaCompiler.local.getOrElse(javac.JavaCompiler.fork(None)) From 415897b0659ecbbd82b717e86807a2937684358f Mon Sep 17 00:00:00 2001 From: albertpchen Date: Thu, 10 Oct 2024 17:31:23 +0100 Subject: [PATCH 02/10] update test and run tasks to use custom java home, update mockito example to use custom java home --- example/thirdparty/mockito/build.mill | 10 +++++++ main/util/src/mill/util/Jvm.scala | 29 ++++++++++++------- scalalib/src/mill/scalalib/RunModule.scala | 11 ++++--- scalalib/src/mill/scalalib/TestModule.scala | 3 +- .../src/mill/scalalib/TestModuleUtil.scala | 6 ++-- .../src/mill/scalalib/ZincWorkerModule.scala | 6 ++++ 6 files changed, 48 insertions(+), 17 deletions(-) diff --git a/example/thirdparty/mockito/build.mill b/example/thirdparty/mockito/build.mill index ad0fbf5e3b1..44b802452f1 100644 --- a/example/thirdparty/mockito/build.mill +++ b/example/thirdparty/mockito/build.mill @@ -1,4 +1,5 @@ package build +import mill.define.{Discover, ExternalModule, ModuleRef} import mill._, javalib._ object libraries{ @@ -36,7 +37,16 @@ object libraries{ val groovy = ivy"org.codehaus.groovy:groovy:3.0.22" } +object ZincWorkerModule11 extends ExternalModule with ZincWorkerModule with CoursierModule { + lazy val millDiscover = Discover[this.type] + override def javaHome = Task { + Some(resolveJavaHome("temurin:1.11.0.24")()) + } +} + trait MockitoModule extends MavenModule{ + override def zincWorker = ModuleRef(ZincWorkerModule11) + def javacOptions = Seq("-encoding", "UTF-8") def testModuleDeps: Seq[JavaModule] = Nil def testIvyDeps: T[Agg[Dep]] = Agg.empty[Dep] def testRuntimeIvyDeps: T[Agg[Dep]] = Agg.empty[Dep] diff --git a/main/util/src/mill/util/Jvm.scala b/main/util/src/mill/util/Jvm.scala index aaff3514375..1ff17df6620 100644 --- a/main/util/src/mill/util/Jvm.scala +++ b/main/util/src/mill/util/Jvm.scala @@ -25,11 +25,12 @@ object Jvm extends CoursierSupport { mainArgs: Seq[String] = Seq.empty, workingDir: os.Path = null, streamOut: Boolean = true, - check: Boolean = true + check: Boolean = true, + javaHome: Option[os.Path] = None )(implicit ctx: Ctx): CommandResult = { val commandArgs = - Vector(javaExe) ++ + Vector(javaExe(javaHome)) ++ jvmArgs ++ Vector("-cp", classPath.iterator.mkString(java.io.File.pathSeparator), mainClass) ++ mainArgs @@ -65,9 +66,10 @@ object Jvm extends CoursierSupport { /** * Resolves a tool to a path under the currently used JDK (if known). */ - def jdkTool(toolName: String): String = { - sys.props - .get("java.home") + def jdkTool(toolName: String, javaHome: Option[os.Path]): String = { + javaHome + .map(_.toString()) + .orElse(sys.props.get("java.home")) .map(h => if (isWin) new File(h, s"bin\\${toolName}.exe") else new File(h, s"bin/${toolName}") @@ -77,7 +79,11 @@ object Jvm extends CoursierSupport { } - def javaExe: String = jdkTool("java") + def jdkTool(toolName: String): String = jdkTool(toolName, None) + + def javaExe(javaHome: Option[os.Path]): String = jdkTool("java", javaHome) + + def javaExe: String = javaExe(None) def defaultBackgroundOutputs(outputDir: os.Path): Option[(ProcessOutput, ProcessOutput)] = Some((outputDir / "stdout.log", outputDir / "stderr.log")) @@ -107,7 +113,8 @@ object Jvm extends CoursierSupport { workingDir: os.Path = null, background: Boolean = false, useCpPassingJar: Boolean = false, - runBackgroundLogToConsole: Boolean = false + runBackgroundLogToConsole: Boolean = false, + javaHome: Option[os.Path] = None )(implicit ctx: Ctx): Unit = { runSubprocessWithBackgroundOutputs( mainClass, @@ -119,7 +126,8 @@ object Jvm extends CoursierSupport { if (!background) None else if (runBackgroundLogToConsole) Some((os.Inherit, os.Inherit)) else Jvm.defaultBackgroundOutputs(ctx.dest), - useCpPassingJar + useCpPassingJar, + javaHome ) } @@ -169,7 +177,8 @@ object Jvm extends CoursierSupport { mainArgs: Seq[String] = Seq.empty, workingDir: os.Path = null, backgroundOutputs: Option[Tuple2[ProcessOutput, ProcessOutput]] = None, - useCpPassingJar: Boolean = false + useCpPassingJar: Boolean = false, + javaHome: Option[os.Path] = None )(implicit ctx: Ctx): Unit = { val cp = @@ -193,7 +202,7 @@ object Jvm extends CoursierSupport { Seq(mainClass) } else Seq.empty val args = - Vector(javaExe) ++ + Vector(javaExe(javaHome)) ++ jvmArgs ++ cpArgument ++ mainClassArgument ++ diff --git a/scalalib/src/mill/scalalib/RunModule.scala b/scalalib/src/mill/scalalib/RunModule.scala index b8212f5a2d4..c6e3940c422 100644 --- a/scalalib/src/mill/scalalib/RunModule.scala +++ b/scalalib/src/mill/scalalib/RunModule.scala @@ -135,7 +135,8 @@ trait RunModule extends WithZincWorker { runClasspath().map(_.path), forkArgs(), forkEnv(), - runUseArgsFile() + runUseArgsFile(), + zincWorker().javaHome().map(_.path) ) } @@ -194,7 +195,7 @@ trait RunModule extends WithZincWorker { Seq(procId.toString, procTombstone.toString, token, finalMainClass) ++ args, workingDir = forkWorkingDir, backgroundOutputs, - useCpPassingJar = runUseArgsFile + useCpPassingJar = runUseArgsFile, )(ctx) ) catch { @@ -257,7 +258,8 @@ object RunModule { runClasspath: Seq[os.Path], forkArgs0: Seq[String], forkEnv0: Map[String, String], - useCpPassingJar0: Boolean + useCpPassingJar0: Boolean, + javaHome: Option[os.Path] ) extends Runner { def run( @@ -283,7 +285,8 @@ object RunModule { case Some(b) => b case None => useCpPassingJar0 }, - runBackgroundLogToConsole = runBackgroundLogToConsole + runBackgroundLogToConsole = runBackgroundLogToConsole, + javaHome ) } } diff --git a/scalalib/src/mill/scalalib/TestModule.scala b/scalalib/src/mill/scalalib/TestModule.scala index 8b6d1d4185d..f1fd922bd6f 100644 --- a/scalalib/src/mill/scalalib/TestModule.scala +++ b/scalalib/src/mill/scalalib/TestModule.scala @@ -200,7 +200,8 @@ trait TestModule forkEnv(), testSandboxWorkingDir(), forkWorkingDir(), - testReportXml() + testReportXml(), + zincWorker().javaHome().map(_.path) ) } diff --git a/scalalib/src/mill/scalalib/TestModuleUtil.scala b/scalalib/src/mill/scalalib/TestModuleUtil.scala index b7a29bcbdcc..a65624122e1 100644 --- a/scalalib/src/mill/scalalib/TestModuleUtil.scala +++ b/scalalib/src/mill/scalalib/TestModuleUtil.scala @@ -28,7 +28,8 @@ private[scalalib] object TestModuleUtil { forkEnv: Map[String, String], testSandboxWorkingDir: Boolean, forkWorkingDir: os.Path, - testReportXml: Option[String] + testReportXml: Option[String], + javaHome: Option[os.Path] )(implicit ctx: mill.api.Ctx) = { val (jvmArgs, props: Map[String, String]) = loadArgsAndProps(useArgsFile, forkArgs) @@ -72,7 +73,8 @@ private[scalalib] object TestModuleUtil { envArgs = forkEnv ++ resourceEnv, mainArgs = Seq(testRunnerClasspathArg, argsFile.toString), workingDir = if (testSandboxWorkingDir) sandbox else forkWorkingDir, - useCpPassingJar = useArgsFile + useCpPassingJar = useArgsFile, + javaHome = javaHome ) if (!os.exists(outputPath)) Left(s"Test reporting Failed: ${outputPath} does not exist") diff --git a/scalalib/src/mill/scalalib/ZincWorkerModule.scala b/scalalib/src/mill/scalalib/ZincWorkerModule.scala index be1c3831b3e..dc102525ab2 100644 --- a/scalalib/src/mill/scalalib/ZincWorkerModule.scala +++ b/scalalib/src/mill/scalalib/ZincWorkerModule.scala @@ -44,6 +44,12 @@ trait ZincWorkerModule extends mill.Module with OfflineSupportModule { self: Cou def zincLogDebug: T[Boolean] = Task.Input(T.ctx().log.debugEnabled) + /** + * Optional custom Java Home for the ZincWorker to use + * + * If this value is None, then the ZincWorker uses the same Java used to run + * the current mill instance. + */ def javaHome: T[Option[PathRef]] = Task { None } From e13dc6c498d7753bcbd3effe9d58d30a2dc3dfb0 Mon Sep 17 00:00:00 2001 From: albertpchen Date: Thu, 10 Oct 2024 18:34:22 +0100 Subject: [PATCH 03/10] add ZincWorker cross module based on couriser JVM Index --- example/thirdparty/mockito/build.mill | 9 +------ main/util/src/mill/util/CoursierSupport.scala | 8 +++++++ .../src/mill/scalalib/ZincWorkerModule.scala | 24 +++++++++++++++++++ .../src/mill/scalalib/HelloJavaTests.scala | 3 ++- 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/example/thirdparty/mockito/build.mill b/example/thirdparty/mockito/build.mill index 44b802452f1..6409c13e4ce 100644 --- a/example/thirdparty/mockito/build.mill +++ b/example/thirdparty/mockito/build.mill @@ -37,15 +37,8 @@ object libraries{ val groovy = ivy"org.codehaus.groovy:groovy:3.0.22" } -object ZincWorkerModule11 extends ExternalModule with ZincWorkerModule with CoursierModule { - lazy val millDiscover = Discover[this.type] - override def javaHome = Task { - Some(resolveJavaHome("temurin:1.11.0.24")()) - } -} - trait MockitoModule extends MavenModule{ - override def zincWorker = ModuleRef(ZincWorkerModule11) + override def zincWorker = ModuleRef(ZincWorkerModule.ForJvm("temurin:1.11.0.24")) def javacOptions = Seq("-encoding", "UTF-8") def testModuleDeps: Seq[JavaModule] = Nil def testIvyDeps: T[Agg[Dep]] = Agg.empty[Dep] diff --git a/main/util/src/mill/util/CoursierSupport.scala b/main/util/src/mill/util/CoursierSupport.scala index 41af6ee2e47..d609ee82743 100644 --- a/main/util/src/mill/util/CoursierSupport.scala +++ b/main/util/src/mill/util/CoursierSupport.scala @@ -167,6 +167,14 @@ trait CoursierSupport { (deps0, res.getOrThrow) } + def jvmIndex( + ctx: Option[mill.api.Ctx.Log] = None, + coursierCacheCustomizer: Option[FileCache[Task] => FileCache[Task]] = None + ): Result[JvmIndex] = { + val coursierCache0 = coursierCache(ctx, coursierCacheCustomizer) + JvmIndex.load().unsafeRun()(coursierCache0.ec) + } + /** * Resolve java home using Coursier. * diff --git a/scalalib/src/mill/scalalib/ZincWorkerModule.scala b/scalalib/src/mill/scalalib/ZincWorkerModule.scala index dc102525ab2..e3912e0ffdc 100644 --- a/scalalib/src/mill/scalalib/ZincWorkerModule.scala +++ b/scalalib/src/mill/scalalib/ZincWorkerModule.scala @@ -8,6 +8,7 @@ import mill.define.{ExternalModule, Discover} import mill.scalalib.Lib.resolveDependencies import mill.scalalib.api.ZincWorkerUtil.{isBinaryBridgeAvailable, isDotty, isDottyOrScala3} import mill.scalalib.api.{ZincWorkerApi, ZincWorkerUtil, Versions} +import mill.util.Jvm import mill.util.Util.millProjectModule /** @@ -15,6 +16,29 @@ import mill.util.Util.millProjectModule */ object ZincWorkerModule extends ExternalModule with ZincWorkerModule with CoursierModule { lazy val millDiscover = Discover[this.type] + + trait ZincWorkerModuleForJvm extends ZincWorkerModule with CoursierModule with Cross.Module[String] { + override def javaHome: T[Option[PathRef]] = Task { + Some(resolveJavaHome(crossValue)()) + } + } + + private val jvmIds = (new Interp).watchValue { + Jvm + .jvmIndex() + .asSuccess + // JvmIndex.available() returns a Map[String, Map[String, String]] + // The first key is the distribution, the second key is the version, + // and the inner-most value is the URL + .map(_.value.available().getOrElse(Map.empty)) + .getOrElse(Map.empty) + .flatMap { case (distribution, versions) => + versions.map(version => s"$distribution:${version._1}") + } + .toSeq + } + + object ForJvm extends Cross[ZincWorkerModuleForJvm](jvmIds) } /** diff --git a/scalalib/test/src/mill/scalalib/HelloJavaTests.scala b/scalalib/test/src/mill/scalalib/HelloJavaTests.scala index 7f08e34e1ae..c4c5c635771 100644 --- a/scalalib/test/src/mill/scalalib/HelloJavaTests.scala +++ b/scalalib/test/src/mill/scalalib/HelloJavaTests.scala @@ -34,7 +34,8 @@ object HelloJavaTests extends TestSuite { } object core extends JavaModule { - override def zincWorker: ModuleRef[ZincWorkerModule] = ModuleRef(ZincWorkerOverride) + override def zincWorker: ModuleRef[ZincWorkerModule] = + ModuleRef(ZincWorkerModule.ForJvm("graalvm-community:23.0.0")) override def docJarUseArgsFile = false object test extends JavaTests with TestModule.Junit4 } From 2dc3000a9378d11c232419759672f169d1842fdc Mon Sep 17 00:00:00 2001 From: albertpchen Date: Thu, 10 Oct 2024 19:11:51 +0100 Subject: [PATCH 04/10] update Jmh tasks to use javaHome, update commons-io to use custom javaHome --- contrib/jmh/src/mill/contrib/jmh/JmhModule.scala | 6 +++--- example/thirdparty/commons-io/build.mill | 5 ++++- example/thirdparty/mockito/build.mill | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/contrib/jmh/src/mill/contrib/jmh/JmhModule.scala b/contrib/jmh/src/mill/contrib/jmh/JmhModule.scala index 27f71e6b81d..01d8f436dad 100644 --- a/contrib/jmh/src/mill/contrib/jmh/JmhModule.scala +++ b/contrib/jmh/src/mill/contrib/jmh/JmhModule.scala @@ -43,7 +43,8 @@ trait JmhModule extends JavaModule { classPath = (runClasspath() ++ generatorDeps()).map(_.path) ++ Seq(compileGeneratedSources().path, resources), mainArgs = args, - workingDir = T.ctx().dest + workingDir = T.ctx().dest, + javaHome = zincWorker().javaHome().map(_.path) ) } @@ -72,7 +73,6 @@ trait JmhModule extends JavaModule { def generateBenchmarkSources = Task { val dest = T.ctx().dest - val javacOpts = javacOptions().toSeq val sourcesDir = dest / "jmh_sources" val resourcesDir = dest / "jmh_resources" @@ -90,7 +90,7 @@ trait JmhModule extends JavaModule { resourcesDir.toString, "default" ), - jvmArgs = javacOpts + javaHome = zincWorker().javaHome().map(_.path) ) (sourcesDir, resourcesDir) diff --git a/example/thirdparty/commons-io/build.mill b/example/thirdparty/commons-io/build.mill index 66d635da957..5497d46a72a 100644 --- a/example/thirdparty/commons-io/build.mill +++ b/example/thirdparty/commons-io/build.mill @@ -1,9 +1,12 @@ package build import mill._, javalib._, publish._ +import mill.define.ModuleRef import $ivy.`com.lihaoyi::mill-contrib-jmh:$MILL_VERSION` import contrib.jmh.JmhModule object `package` extends RootModule with PublishModule with MavenModule { + override def zincWorker = ModuleRef(ZincWorkerModule.ForJvm("temurin:1.11.0.24")) + def javacOptions = Seq("-encoding", "UTF-8") def publishVersion = "2.17.0-SNAPSHOT" def pomSettings = PomSettings( @@ -69,4 +72,4 @@ PathUtilsContentEqualsBenchmark.testCurrent_fileContentEquals_Blackhole ss PathUtilsContentEqualsBenchmark.testProposal_contentEquals ss 5 ... PathUtilsContentEqualsBenchmark.testProposal_contentEquals_Blackhole ss 5 ... -*/ \ No newline at end of file +*/ diff --git a/example/thirdparty/mockito/build.mill b/example/thirdparty/mockito/build.mill index 6409c13e4ce..2e6383b6514 100644 --- a/example/thirdparty/mockito/build.mill +++ b/example/thirdparty/mockito/build.mill @@ -1,6 +1,6 @@ package build -import mill.define.{Discover, ExternalModule, ModuleRef} import mill._, javalib._ +import mill.define.ModuleRef object libraries{ From ca4f84619ae36f5e260e14b2c71611e53eddc4ae Mon Sep 17 00:00:00 2001 From: albertpchen Date: Thu, 10 Oct 2024 20:24:51 +0100 Subject: [PATCH 05/10] reformatting and bincompat --- main/util/src/mill/util/CoursierSupport.scala | 10 ++++---- main/util/src/mill/util/Jvm.scala | 23 +++++++++++++++++++ .../src/mill/scalalib/CoursierModule.scala | 2 +- scalalib/src/mill/scalalib/RunModule.scala | 2 +- .../src/mill/scalalib/ZincWorkerModule.scala | 5 ++-- .../src/mill/scalalib/HelloJavaTests.scala | 2 +- 6 files changed, 34 insertions(+), 10 deletions(-) diff --git a/main/util/src/mill/util/CoursierSupport.scala b/main/util/src/mill/util/CoursierSupport.scala index d609ee82743..6049f341aff 100644 --- a/main/util/src/mill/util/CoursierSupport.scala +++ b/main/util/src/mill/util/CoursierSupport.scala @@ -168,8 +168,8 @@ trait CoursierSupport { } def jvmIndex( - ctx: Option[mill.api.Ctx.Log] = None, - coursierCacheCustomizer: Option[FileCache[Task] => FileCache[Task]] = None + ctx: Option[mill.api.Ctx.Log] = None, + coursierCacheCustomizer: Option[FileCache[Task] => FileCache[Task]] = None ): Result[JvmIndex] = { val coursierCache0 = coursierCache(ctx, coursierCacheCustomizer) JvmIndex.load().unsafeRun()(coursierCache0.ec) @@ -181,9 +181,9 @@ trait CoursierSupport { * The id string has format "$DISTRIBUTION:$VERSION". e.g. graalvm-community:23.0.0 */ def resolveJavaHome( - id: String, - ctx: Option[mill.api.Ctx.Log] = None, - coursierCacheCustomizer: Option[FileCache[Task] => FileCache[Task]] = None + id: String, + ctx: Option[mill.api.Ctx.Log] = None, + coursierCacheCustomizer: Option[FileCache[Task] => FileCache[Task]] = None ): Result[os.Path] = { val coursierCache0 = coursierCache(ctx, coursierCacheCustomizer) val jvmCache = JvmCache() diff --git a/main/util/src/mill/util/Jvm.scala b/main/util/src/mill/util/Jvm.scala index 1ff17df6620..5767a9b7709 100644 --- a/main/util/src/mill/util/Jvm.scala +++ b/main/util/src/mill/util/Jvm.scala @@ -216,6 +216,29 @@ object Jvm extends CoursierSupport { runSubprocess(args, envArgs, workingDir) } + // bincompat shim + def runSubprocessWithBackgroundOutputs( + mainClass: String, + classPath: Agg[os.Path], + jvmArgs: Seq[String], + envArgs: Map[String, String], + mainArgs: Seq[String], + workingDir: os.Path, + backgroundOutputs: Option[Tuple2[ProcessOutput, ProcessOutput]], + useCpPassingJar: Boolean + )(implicit ctx: Ctx): Unit = + runSubprocessWithBackgroundOutputs( + mainClass, + classPath, + jvmArgs, + envArgs, + mainArgs, + workingDir, + backgroundOutputs, + useCpPassingJar, + None + )(ctx) + /** * Runs a generic subprocess and waits for it to terminate. */ diff --git a/scalalib/src/mill/scalalib/CoursierModule.scala b/scalalib/src/mill/scalalib/CoursierModule.scala index cbb27c44db0..5c8b0516a05 100644 --- a/scalalib/src/mill/scalalib/CoursierModule.scala +++ b/scalalib/src/mill/scalalib/CoursierModule.scala @@ -34,7 +34,7 @@ trait CoursierModule extends mill.Module { def resolveJavaHome(id: String): Task[PathRef] = Task.Anon { val path = mill.util.Jvm.resolveJavaHome( - id=id, + id = id, coursierCacheCustomizer = coursierCacheCustomizer(), ctx = Some(implicitly[mill.api.Ctx.Log]) ).getOrThrow diff --git a/scalalib/src/mill/scalalib/RunModule.scala b/scalalib/src/mill/scalalib/RunModule.scala index c6e3940c422..f9a24b2b1fa 100644 --- a/scalalib/src/mill/scalalib/RunModule.scala +++ b/scalalib/src/mill/scalalib/RunModule.scala @@ -195,7 +195,7 @@ trait RunModule extends WithZincWorker { Seq(procId.toString, procTombstone.toString, token, finalMainClass) ++ args, workingDir = forkWorkingDir, backgroundOutputs, - useCpPassingJar = runUseArgsFile, + useCpPassingJar = runUseArgsFile )(ctx) ) catch { diff --git a/scalalib/src/mill/scalalib/ZincWorkerModule.scala b/scalalib/src/mill/scalalib/ZincWorkerModule.scala index e3912e0ffdc..9b72242db73 100644 --- a/scalalib/src/mill/scalalib/ZincWorkerModule.scala +++ b/scalalib/src/mill/scalalib/ZincWorkerModule.scala @@ -17,7 +17,8 @@ import mill.util.Util.millProjectModule object ZincWorkerModule extends ExternalModule with ZincWorkerModule with CoursierModule { lazy val millDiscover = Discover[this.type] - trait ZincWorkerModuleForJvm extends ZincWorkerModule with CoursierModule with Cross.Module[String] { + trait ZincWorkerModuleForJvm extends ZincWorkerModule with CoursierModule + with Cross.Module[String] { override def javaHome: T[Option[PathRef]] = Task { Some(resolveJavaHome(crossValue)()) } @@ -101,7 +102,7 @@ trait ZincWorkerModule extends mill.Module with OfflineSupportModule { self: Cou classOf[KeyedLockedCache[_]], // compilerCache classOf[Boolean], // compileToJar classOf[Boolean], // zincLogDebug - classOf[Option[PathRef]], // javaHome + classOf[Option[PathRef]] // javaHome ) .newInstance( Left(( diff --git a/scalalib/test/src/mill/scalalib/HelloJavaTests.scala b/scalalib/test/src/mill/scalalib/HelloJavaTests.scala index c4c5c635771..5e7a1a53358 100644 --- a/scalalib/test/src/mill/scalalib/HelloJavaTests.scala +++ b/scalalib/test/src/mill/scalalib/HelloJavaTests.scala @@ -76,7 +76,7 @@ object HelloJavaTests extends TestSuite { // The first eight bytes are magic numbers followed by two bytes for major version and two bytes for minor version // We are overriding to java 23 which corresponds to class file version 67 - os.read.bytes(coreClassFile.get, 4, 4).toSeq == Seq[Byte](0, 0, 0, 67), + os.read.bytes(coreClassFile.get, 4, 4).toSeq == Seq[Byte](0, 0, 0, 67) ) } From 4a08b372eeb435a8fe78c0cbb11e3248e943729a Mon Sep 17 00:00:00 2001 From: albertpchen Date: Sun, 13 Oct 2024 00:19:32 +0100 Subject: [PATCH 06/10] exclude argonaut-shapeless from couriser-jvm dep --- main/package.mill | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/main/package.mill b/main/package.mill index b0ff0386445..33efe562796 100644 --- a/main/package.mill +++ b/main/package.mill @@ -100,7 +100,15 @@ object `package` extends RootModule with build.MillStableScalaModule with BuildI object util extends build.MillStableScalaModule { def moduleDeps = Seq(api, client) - def ivyDeps = Agg(build.Deps.coursier, build.Deps.coursierJvm, build.Deps.jline) + def ivyDeps = Agg( + build.Deps.coursier, + build.Deps.coursierJvm.exclude( + "com.github.alexarchambault" -> "argonaut-shapeless_6.3", + "com.chuusai" -> "shapeless", + "io.argonaut" -> "argonaut", + ), + build.Deps.jline + ) } object define extends build.MillStableScalaModule { From c0cf2a807c36d582c7f099a699e640e66d1226dc Mon Sep 17 00:00:00 2001 From: albertpchen Date: Sun, 13 Oct 2024 01:29:02 +0100 Subject: [PATCH 07/10] fix exclude --- main/package.mill | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/main/package.mill b/main/package.mill index 33efe562796..71e47b85aa5 100644 --- a/main/package.mill +++ b/main/package.mill @@ -103,9 +103,7 @@ object `package` extends RootModule with build.MillStableScalaModule with BuildI def ivyDeps = Agg( build.Deps.coursier, build.Deps.coursierJvm.exclude( - "com.github.alexarchambault" -> "argonaut-shapeless_6.3", - "com.chuusai" -> "shapeless", - "io.argonaut" -> "argonaut", + "com.github.alexarchambault" -> "argonaut-shapeless_6.3_2.13", ), build.Deps.jline ) From 6803682e0dd9f064d73dad9d3009d6fd21f0a217 Mon Sep 17 00:00:00 2001 From: albertpchen Date: Sun, 13 Oct 2024 09:54:29 +0100 Subject: [PATCH 08/10] add comment about shapeless exclusion --- main/package.mill | 3 +++ 1 file changed, 3 insertions(+) diff --git a/main/package.mill b/main/package.mill index 71e47b85aa5..f2535efba3e 100644 --- a/main/package.mill +++ b/main/package.mill @@ -103,6 +103,9 @@ object `package` extends RootModule with build.MillStableScalaModule with BuildI def ivyDeps = Agg( build.Deps.coursier, build.Deps.coursierJvm.exclude( + // coursier-jvm has an unused dependency on argonaut-shapeless and + // shapeless causes issues with the assembly task when the locale + // is not set properly https://github.com/sbt/sbt-assembly/issues/496 "com.github.alexarchambault" -> "argonaut-shapeless_6.3_2.13", ), build.Deps.jline From 29c805b291a5adb0139bc322fe5c75f2f2a05e4e Mon Sep 17 00:00:00 2001 From: albertpchen Date: Sun, 13 Oct 2024 11:01:53 +0100 Subject: [PATCH 09/10] make ForJvm an abstract class instead of a cross module --- example/thirdparty/commons-io/build.mill | 4 +- example/thirdparty/mockito/build.mill | 4 +- .../src/mill/scalalib/ZincWorkerModule.scala | 23 +------- .../src/mill/scalalib/HelloJavaTests.scala | 53 +++++++++++++------ 4 files changed, 45 insertions(+), 39 deletions(-) diff --git a/example/thirdparty/commons-io/build.mill b/example/thirdparty/commons-io/build.mill index 5497d46a72a..1d44f8a7d30 100644 --- a/example/thirdparty/commons-io/build.mill +++ b/example/thirdparty/commons-io/build.mill @@ -4,8 +4,10 @@ import mill.define.ModuleRef import $ivy.`com.lihaoyi::mill-contrib-jmh:$MILL_VERSION` import contrib.jmh.JmhModule +object ZincWorkerJava11 extends ZincWorkerModule.ForJvm("temurin:1.11.0.24") + object `package` extends RootModule with PublishModule with MavenModule { - override def zincWorker = ModuleRef(ZincWorkerModule.ForJvm("temurin:1.11.0.24")) + override def zincWorker = ModuleRef(ZincWorkerJava11) def javacOptions = Seq("-encoding", "UTF-8") def publishVersion = "2.17.0-SNAPSHOT" diff --git a/example/thirdparty/mockito/build.mill b/example/thirdparty/mockito/build.mill index 2e6383b6514..ea1ec445fb4 100644 --- a/example/thirdparty/mockito/build.mill +++ b/example/thirdparty/mockito/build.mill @@ -37,8 +37,10 @@ object libraries{ val groovy = ivy"org.codehaus.groovy:groovy:3.0.22" } +object ZincWorkerJava11 extends ZincWorkerModule.ForJvm("temurin:1.11.0.24") + trait MockitoModule extends MavenModule{ - override def zincWorker = ModuleRef(ZincWorkerModule.ForJvm("temurin:1.11.0.24")) + override def zincWorker = ModuleRef(ZincWorkerJava11) def javacOptions = Seq("-encoding", "UTF-8") def testModuleDeps: Seq[JavaModule] = Nil def testIvyDeps: T[Agg[Dep]] = Agg.empty[Dep] diff --git a/scalalib/src/mill/scalalib/ZincWorkerModule.scala b/scalalib/src/mill/scalalib/ZincWorkerModule.scala index 9b72242db73..c6619d70ef1 100644 --- a/scalalib/src/mill/scalalib/ZincWorkerModule.scala +++ b/scalalib/src/mill/scalalib/ZincWorkerModule.scala @@ -8,7 +8,6 @@ import mill.define.{ExternalModule, Discover} import mill.scalalib.Lib.resolveDependencies import mill.scalalib.api.ZincWorkerUtil.{isBinaryBridgeAvailable, isDotty, isDottyOrScala3} import mill.scalalib.api.{ZincWorkerApi, ZincWorkerUtil, Versions} -import mill.util.Jvm import mill.util.Util.millProjectModule /** @@ -17,29 +16,11 @@ import mill.util.Util.millProjectModule object ZincWorkerModule extends ExternalModule with ZincWorkerModule with CoursierModule { lazy val millDiscover = Discover[this.type] - trait ZincWorkerModuleForJvm extends ZincWorkerModule with CoursierModule - with Cross.Module[String] { + abstract class ForJvm(jvmId: String) extends ZincWorkerModule with CoursierModule { override def javaHome: T[Option[PathRef]] = Task { - Some(resolveJavaHome(crossValue)()) + Some(resolveJavaHome(jvmId)()) } } - - private val jvmIds = (new Interp).watchValue { - Jvm - .jvmIndex() - .asSuccess - // JvmIndex.available() returns a Map[String, Map[String, String]] - // The first key is the distribution, the second key is the version, - // and the inner-most value is the URL - .map(_.value.available().getOrElse(Map.empty)) - .getOrElse(Map.empty) - .flatMap { case (distribution, versions) => - versions.map(version => s"$distribution:${version._1}") - } - .toSeq - } - - object ForJvm extends Cross[ZincWorkerModuleForJvm](jvmIds) } /** diff --git a/scalalib/test/src/mill/scalalib/HelloJavaTests.scala b/scalalib/test/src/mill/scalalib/HelloJavaTests.scala index 5e7a1a53358..4f4be930107 100644 --- a/scalalib/test/src/mill/scalalib/HelloJavaTests.scala +++ b/scalalib/test/src/mill/scalalib/HelloJavaTests.scala @@ -26,16 +26,20 @@ object HelloJavaTests extends TestSuite { } } - object HelloJavaJavaHomeOverride extends TestBaseModule { - object ZincWorkerOverride extends ZincWorkerModule with CoursierModule { - override def javaHome: T[Option[PathRef]] = Task { - Some(resolveJavaHome("graalvm-community:23.0.0")()) - } + object HelloJavaJavaHome23Override extends TestBaseModule { + object ZincWorkerJava23 extends ZincWorkerModule.ForJvm("graalvm-community:23.0.0") + + object core extends JavaModule { + override def zincWorker: ModuleRef[ZincWorkerModule] = ModuleRef(ZincWorkerJava23) + override def docJarUseArgsFile = false + object test extends JavaTests with TestModule.Junit4 } + } + object HelloJavaJavaHome11Override extends TestBaseModule { + object ZincWorkerJava11 extends ZincWorkerModule.ForJvm("temurin:1.11.0.24") object core extends JavaModule { - override def zincWorker: ModuleRef[ZincWorkerModule] = - ModuleRef(ZincWorkerModule.ForJvm("graalvm-community:23.0.0")) + override def zincWorker: ModuleRef[ZincWorkerModule] = ModuleRef(ZincWorkerJava11) override def docJarUseArgsFile = false object test extends JavaTests with TestModule.Junit4 } @@ -65,19 +69,36 @@ object HelloJavaTests extends TestSuite { } test("javaHome") { - val eval = UnitTester(HelloJavaJavaHomeOverride, resourcePath) + test("23") { + val eval = UnitTester(HelloJavaJavaHome23Override, resourcePath) - val Right(result) = eval.apply(HelloJavaJavaHomeOverride.core.compile) + val Right(result) = eval.apply(HelloJavaJavaHome23Override.core.compile) - val coreClassFile = os.walk(result.value.classes.path).find(_.last == "Core.class") + val coreClassFile = os.walk(result.value.classes.path).find(_.last == "Core.class") - assert( - coreClassFile.isDefined, + assert( + coreClassFile.isDefined, - // The first eight bytes are magic numbers followed by two bytes for major version and two bytes for minor version - // We are overriding to java 23 which corresponds to class file version 67 - os.read.bytes(coreClassFile.get, 4, 4).toSeq == Seq[Byte](0, 0, 0, 67) - ) + // The first eight bytes are magic numbers followed by two bytes for major version and two bytes for minor version + // We are overriding to java 23 which corresponds to class file version 67 + os.read.bytes(coreClassFile.get, 4, 4).toSeq == Seq[Byte](0, 0, 0, 67) + ) + } + test("11") { + val eval = UnitTester(HelloJavaJavaHome11Override, resourcePath) + + val Right(result) = eval.apply(HelloJavaJavaHome11Override.core.compile) + + val coreClassFile = os.walk(result.value.classes.path).find(_.last == "Core.class") + + assert( + coreClassFile.isDefined, + + // The first eight bytes are magic numbers followed by two bytes for major version and two bytes for minor version + // We are overriding to java 11 which corresponds to class file version 55 + os.read.bytes(coreClassFile.get, 4, 4).toSeq == Seq[Byte](0, 0, 0, 55) + ) + } } test("semanticDbData") { From 6f1127287a6a08268c56da65613884505ff7d6ae Mon Sep 17 00:00:00 2001 From: albertpchen Date: Mon, 14 Oct 2024 10:06:06 +0100 Subject: [PATCH 10/10] test java home for "run" and "test" tasks --- .../resources/hello-java/core/src/Core.java | 13 ++- .../hello-java/core/test/src/MyCoreTests.java | 21 ++++- .../src/mill/scalalib/HelloJavaTests.scala | 90 ++++++++++++++----- 3 files changed, 101 insertions(+), 23 deletions(-) diff --git a/scalalib/test/resources/hello-java/core/src/Core.java b/scalalib/test/resources/hello-java/core/src/Core.java index 3ecb1f61032..313d7711eee 100644 --- a/scalalib/test/resources/hello-java/core/src/Core.java +++ b/scalalib/test/resources/hello-java/core/src/Core.java @@ -1,7 +1,18 @@ package hello; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.Path; + public class Core{ public static String msg(){ return "Hello World"; } -} \ No newline at end of file + + public static void main(String[] args) throws IOException { + Path path = Paths.get(args[0]); + String version = System.getProperty("java.version"); + Files.write(path, version.getBytes()); + } +} diff --git a/scalalib/test/resources/hello-java/core/test/src/MyCoreTests.java b/scalalib/test/resources/hello-java/core/test/src/MyCoreTests.java index 38bebaebe46..e11c78c8fd1 100644 --- a/scalalib/test/resources/hello-java/core/test/src/MyCoreTests.java +++ b/scalalib/test/resources/hello-java/core/test/src/MyCoreTests.java @@ -1,6 +1,7 @@ package hello; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; import org.junit.Test; public class MyCoreTests { @@ -12,4 +13,22 @@ public void msgTest() { public void lengthTest() { assertEquals(Core.msg().length(), 11); } -} \ No newline at end of file + + @Test + public void java11Test() { + String version = System.getProperty("java.version"); + int dot = version.indexOf("."); + assertNotEquals(dot, -1); + System.out.println(version); + assertEquals(version.substring(0, dot), "11"); + } + + @Test + public void java17Test() { + String version = System.getProperty("java.version"); + int dot = version.indexOf("."); + assertNotEquals(dot, -1); + System.out.println(version); + assertEquals(version.substring(0, dot), "17"); + } +} diff --git a/scalalib/test/src/mill/scalalib/HelloJavaTests.scala b/scalalib/test/src/mill/scalalib/HelloJavaTests.scala index 4f4be930107..549a9d08a3d 100644 --- a/scalalib/test/src/mill/scalalib/HelloJavaTests.scala +++ b/scalalib/test/src/mill/scalalib/HelloJavaTests.scala @@ -26,20 +26,20 @@ object HelloJavaTests extends TestSuite { } } - object HelloJavaJavaHome23Override extends TestBaseModule { - object ZincWorkerJava23 extends ZincWorkerModule.ForJvm("graalvm-community:23.0.0") - + object HelloJavaJavaHome11Override extends TestBaseModule { + object ZincWorkerJava11 extends ZincWorkerModule.ForJvm("temurin:1.11.0.24") object core extends JavaModule { - override def zincWorker: ModuleRef[ZincWorkerModule] = ModuleRef(ZincWorkerJava23) + override def zincWorker: ModuleRef[ZincWorkerModule] = ModuleRef(ZincWorkerJava11) override def docJarUseArgsFile = false object test extends JavaTests with TestModule.Junit4 } } - object HelloJavaJavaHome11Override extends TestBaseModule { - object ZincWorkerJava11 extends ZincWorkerModule.ForJvm("temurin:1.11.0.24") + object HelloJavaJavaHome17Override extends TestBaseModule { + object ZincWorkerJava17 extends ZincWorkerModule.ForJvm("temurin:1.17.0.9") + object core extends JavaModule { - override def zincWorker: ModuleRef[ZincWorkerModule] = ModuleRef(ZincWorkerJava11) + override def zincWorker: ModuleRef[ZincWorkerModule] = ModuleRef(ZincWorkerJava17) override def docJarUseArgsFile = false object test extends JavaTests with TestModule.Junit4 } @@ -69,10 +69,10 @@ object HelloJavaTests extends TestSuite { } test("javaHome") { - test("23") { - val eval = UnitTester(HelloJavaJavaHome23Override, resourcePath) + test("compile11") { + val eval = UnitTester(HelloJavaJavaHome11Override, resourcePath) - val Right(result) = eval.apply(HelloJavaJavaHome23Override.core.compile) + val Right(result) = eval.apply(HelloJavaJavaHome11Override.core.compile) val coreClassFile = os.walk(result.value.classes.path).find(_.last == "Core.class") @@ -80,14 +80,14 @@ object HelloJavaTests extends TestSuite { coreClassFile.isDefined, // The first eight bytes are magic numbers followed by two bytes for major version and two bytes for minor version - // We are overriding to java 23 which corresponds to class file version 67 - os.read.bytes(coreClassFile.get, 4, 4).toSeq == Seq[Byte](0, 0, 0, 67) + // We are overriding to java 11 which corresponds to class file version 55 + os.read.bytes(coreClassFile.get, 4, 4).toSeq == Seq[Byte](0, 0, 0, 55) ) } - test("11") { - val eval = UnitTester(HelloJavaJavaHome11Override, resourcePath) + test("compile17") { + val eval = UnitTester(HelloJavaJavaHome17Override, resourcePath) - val Right(result) = eval.apply(HelloJavaJavaHome11Override.core.compile) + val Right(result) = eval.apply(HelloJavaJavaHome17Override.core.compile) val coreClassFile = os.walk(result.value.classes.path).find(_.last == "Core.class") @@ -95,8 +95,54 @@ object HelloJavaTests extends TestSuite { coreClassFile.isDefined, // The first eight bytes are magic numbers followed by two bytes for major version and two bytes for minor version - // We are overriding to java 11 which corresponds to class file version 55 - os.read.bytes(coreClassFile.get, 4, 4).toSeq == Seq[Byte](0, 0, 0, 55) + // We are overriding to java 17 which corresponds to class file version 67 + os.read.bytes(coreClassFile.get, 4, 4).toSeq == Seq[Byte](0, 0, 0, 61) + ) + } + test("run11") { + val eval = UnitTester(HelloJavaJavaHome11Override, resourcePath) + + val path = eval.evaluator.workspace / "java.version" + val Right(_) = eval.apply(HelloJavaJavaHome11Override.core.run(Task.Anon(Args(path)))) + + assert( + os.read(path).startsWith("11.") + ) + } + test("run17") { + val eval = UnitTester(HelloJavaJavaHome17Override, resourcePath) + + val path = eval.evaluator.workspace / "java.version" + val Right(_) = eval.apply(HelloJavaJavaHome17Override.core.run(Task.Anon(Args(path)))) + + assert( + os.read(path).startsWith("17.") + ) + } + test("test11") { + val eval = UnitTester(HelloJavaJavaHome11Override, resourcePath) + + val Left(Result.Failure(ref1, Some(v1))) = + eval.apply(HelloJavaJavaHome11Override.core.test.test()) + + assert( + v1._2(0).fullyQualifiedName == "hello.MyCoreTests.java11Test", + v1._2(0).status == "Success", + v1._2(1).fullyQualifiedName == "hello.MyCoreTests.java17Test", + v1._2(1).status == "Failure" + ) + } + test("test17") { + val eval = UnitTester(HelloJavaJavaHome17Override, resourcePath) + + val Left(Result.Failure(ref1, Some(v1))) = + eval.apply(HelloJavaJavaHome17Override.core.test.test()) + + assert( + v1._2(0).fullyQualifiedName == "hello.MyCoreTests.java11Test", + v1._2(0).status == "Failure", + v1._2(1).fullyQualifiedName == "hello.MyCoreTests.java17Test", + v1._2(1).status == "Success" ) } } @@ -206,10 +252,12 @@ object HelloJavaTests extends TestSuite { val Left(Result.Failure(ref1, Some(v1))) = eval.apply(HelloJava.core.test.test()) assert( - v1._2(0).fullyQualifiedName == "hello.MyCoreTests.lengthTest", - v1._2(0).status == "Success", - v1._2(1).fullyQualifiedName == "hello.MyCoreTests.msgTest", - v1._2(1).status == "Failure" + v1._2(0).fullyQualifiedName == "hello.MyCoreTests.java11Test", + v1._2(1).fullyQualifiedName == "hello.MyCoreTests.java17Test", + v1._2(2).fullyQualifiedName == "hello.MyCoreTests.lengthTest", + v1._2(2).status == "Success", + v1._2(3).fullyQualifiedName == "hello.MyCoreTests.msgTest", + v1._2(3).status == "Failure" ) val Right(result2) = eval.apply(HelloJava.app.test.test())