diff --git a/dist/package.mill b/dist/package.mill
index 0ee1ca34cebc..0bdbcb133e18 100644
--- a/dist/package.mill
+++ b/dist/package.mill
@@ -9,6 +9,9 @@ import mill.util.Jvm
import millbuild.*
import mill.api.BuildCtx
import scala.util.Using
+import scala.util.Properties
+import java.nio.file.Files
+import java.nio.file.attribute.PosixFilePermission
trait DistModule extends Module {
// All modules that we want to aggregate as part of this `dev` assembly.
@@ -19,9 +22,49 @@ trait DistModule extends Module {
def executableRaw: T[PathRef]
+ def localRepo: T[PathRef] = Task {
+ val dest = Task.dest
+ val repos = Task.traverse(allPublishModules)(m => m.publishLocalTestRepo)().map(_.path)
+ for (repo <- repos; elem <- os.list(repo))
+ os.copy.into(elem, dest, mergeFolders = true)
+ PathRef(dest)
+ }
+
def executable = Task {
- Task.traverse(allPublishModules)(m => m.publishLocal(doc = false))()
- executableRaw()
+ val rawExecutable = executableRaw()
+ if (Properties.isWin) {
+ val launcher = Task.dest / "mill.bat"
+ val launcherContent =
+ s"""@echo off
+ |set "NEW_COURSIER_REPOSITORIES=${localRepo().path.toNIO.toUri.toASCIIString}|ivy2Local|central"
+ |if defined COURSIER_REPOSITORIES (
+ | set "NEW_COURSIER_REPOSITORIES=%NEW_COURSIER_REPOSITORIES%|%COURSIER_REPOSITORIES%"
+ |) else (
+ | set "NEW_COURSIER_REPOSITORIES=%NEW_COURSIER_REPOSITORIES%|ivy2Local|central"
+ |)
+ |set "COURSIER_REPOSITORIES=%NEW_COURSIER_REPOSITORIES%"
+ |set NEW_COURSIER_REPOSITORIES=
+ |"${rawExecutable.path.toString.replace("\"", "\\\"")}" %*
+ |if errorlevel 1 exit /b %errorlevel%
+ |""".stripMargin
+ os.write(launcher, launcherContent)
+ PathRef(launcher)
+ } else {
+ val launcher = Task.dest / "mill"
+ val launcherContent =
+ s"""#!/usr/bin/env bash
+ |set -e
+ |export COURSIER_REPOSITORIES="${localRepo().path.toNIO.toUri.toASCIIString}|$${COURSIER_REPOSITORIES:-ivy2Local|central}"
+ |exec '${rawExecutable.path.toString.replace("'", "\\'")}' "$$@"
+ |""".stripMargin
+ os.write(launcher, launcherContent)
+ val perms = Files.getPosixFilePermissions(launcher.toNIO)
+ perms.add(PosixFilePermission.OWNER_EXECUTE)
+ perms.add(PosixFilePermission.GROUP_EXECUTE)
+ perms.add(PosixFilePermission.OTHERS_EXECUTE)
+ Files.setPosixFilePermissions(launcher.toNIO, perms)
+ PathRef(launcher)
+ }
}
def localBinName: String
@@ -32,12 +75,15 @@ trait DistModule extends Module {
* Build and install Mill locally.
*
* @param binFile The location where the Mill binary should be installed
- * @param ivyRepo The local Ivy repository where Mill modules should be published to
*/
- def installLocal(binFile: String = localBinName, ivyRepo: String = null) =
+ def installLocal(binFile: String = localBinName) = {
+ val binFile0 = os.Path(binFile, BuildCtx.workspaceRoot)
+ val task = installIvyLocalTask(binFile0)
Task.Command {
- PathRef(installLocalTask(Task.Anon(binFile), ivyRepo)())
+ task()
+ PathRef(binFile0)
}
+ }
val batExt = if (scala.util.Properties.isWin) ".bat" else ""
@@ -53,16 +99,28 @@ trait DistModule extends Module {
PathRef(path)
}
- def installLocalTask(binFile: Task[String], ivyRepo: String = null): Task[os.Path] = Task.Anon {
- val targetFile = os.Path(binFile(), BuildCtx.workspaceRoot)
- if (os.exists(targetFile))
- Task.log.info(s"Overwriting existing local Mill binary at ${targetFile}")
- os.copy.over(executable().path, targetFile, createFolders = true)
- Task.log.info(
- s"Published ${build.dist.allPublishModules.size} modules and installed ${targetFile}"
- )
- targetFile
- }
+ def installLocalTask(binFile: Task[String]): Task[os.Path] =
+ Task.Anon {
+ val targetFile = os.Path(binFile(), BuildCtx.workspaceRoot)
+ if (os.exists(targetFile))
+ Task.log.info(s"Overwriting existing local Mill binary at ${targetFile}")
+ os.copy.over(executable().path, targetFile, createFolders = true)
+ Task.log.info(
+ s"Published ${build.dist.allPublishModules.size} modules under Mill sources local repo ${localRepo().path} and installed ${targetFile}"
+ )
+ targetFile
+ }
+
+ def installIvyLocalTask(targetFile: os.Path): Task[Unit] =
+ Task.Anon {
+ if (os.exists(targetFile))
+ Task.log.info(s"Overwriting existing local Mill binary at ${targetFile}")
+ Task.traverse(allPublishModules)(m => m.publishLocal(doc = false))()
+ os.copy.over(executableRaw().path, targetFile, createFolders = true)
+ Task.log.info(
+ s"Published ${build.dist.allPublishModules.size} modules under ~/.ivy2/local and installed ${targetFile}"
+ )
+ }
def artifactName: T[String]
def artifact = Task { Artifact(Settings.pomOrg, artifactName(), build.millVersion()) }
diff --git a/integration/ide/bsp-server/resources/snapshots/build-targets-jvm-test-environments.json b/integration/ide/bsp-server/resources/snapshots/build-targets-jvm-test-environments.json
index 555076f46b88..c14bf2eee68f 100644
--- a/integration/ide/bsp-server/resources/snapshots/build-targets-jvm-test-environments.json
+++ b/integration/ide/bsp-server/resources/snapshots/build-targets-jvm-test-environments.json
@@ -18,7 +18,7 @@
"file:///workspace/app/test/compile-resources",
"file:///workspace/app/test/resources",
"file:///workspace/out/mill-bsp-out/app/test/compile.dest/classes",
- "file:///user-home/.ivy2/local/com.lihaoyi/mill-libs-javalib-testrunner-entrypoint/SNAPSHOT/jars/mill-libs-javalib-testrunner-entrypoint.jar",
+ "file:///mill-workspace/out/dist/localRepo.dest/com/lihaoyi/mill-libs-javalib-testrunner-entrypoint/SNAPSHOT/mill-libs-javalib-testrunner-entrypoint-SNAPSHOT.jar",
"file:///coursier-cache/https/repo1.maven.org/maven2/org/scala-sbt/test-interface/1.0/test-interface-1.0.jar"
],
"jvmOptions": [],
@@ -52,7 +52,7 @@
"file:///workspace/hello-java/test/compile-resources",
"file:///workspace/hello-java/test/resources",
"file:///workspace/out/mill-bsp-out/hello-java/test/compile.dest/classes",
- "file:///user-home/.ivy2/local/com.lihaoyi/mill-libs-javalib-testrunner-entrypoint/SNAPSHOT/jars/mill-libs-javalib-testrunner-entrypoint.jar",
+ "file:///mill-workspace/out/dist/localRepo.dest/com/lihaoyi/mill-libs-javalib-testrunner-entrypoint/SNAPSHOT/mill-libs-javalib-testrunner-entrypoint-SNAPSHOT.jar",
"file:///coursier-cache/https/repo1.maven.org/maven2/org/scala-sbt/test-interface/1.0/test-interface-1.0.jar"
],
"jvmOptions": [],
@@ -87,7 +87,7 @@
"file:///workspace/hello-scala/test/compile-resources",
"file:///workspace/hello-scala/test/resources",
"file:///workspace/out/mill-bsp-out/hello-scala/test/compile.dest/classes",
- "file:///user-home/.ivy2/local/com.lihaoyi/mill-libs-javalib-testrunner-entrypoint/SNAPSHOT/jars/mill-libs-javalib-testrunner-entrypoint.jar",
+ "file:///mill-workspace/out/dist/localRepo.dest/com/lihaoyi/mill-libs-javalib-testrunner-entrypoint/SNAPSHOT/mill-libs-javalib-testrunner-entrypoint-SNAPSHOT.jar",
"file:///coursier-cache/https/repo1.maven.org/maven2/org/scala-sbt/test-interface/1.0/test-interface-1.0.jar"
],
"jvmOptions": [],
diff --git a/integration/ide/build-classpath-contents/src/BuildClasspathContentsTests.scala b/integration/ide/build-classpath-contents/src/BuildClasspathContentsTests.scala
index 37c1f30ec4c3..fad8eaa2ccec 100644
--- a/integration/ide/build-classpath-contents/src/BuildClasspathContentsTests.scala
+++ b/integration/ide/build-classpath-contents/src/BuildClasspathContentsTests.scala
@@ -18,37 +18,38 @@ object BuildClasspathContentsTests extends UtestIntegrationTestSuite {
.filter(_.startsWith(BuildCtx.workspaceRoot))
.map(_.subRelativeTo(BuildCtx.workspaceRoot))
.filter(!_.startsWith("out/integration"))
+ .filter(!_.startsWith("out/dist/localRepo.dest"))
.map(_.toString)
.sorted
if (sys.env("MILL_INTEGRATION_IS_PACKAGED_LAUNCHER") == "true") {
assertGoldenLiteral(
millPublishedJars,
List(
- "mill-core-api-daemon_3.jar",
- "mill-core-api_3.jar",
- "mill-core-constants.jar",
- "mill-libs-androidlib-databinding_3.jar",
- "mill-libs-androidlib_3.jar",
- "mill-libs-daemon-client.jar",
- "mill-libs-daemon-server_3.jar",
- "mill-libs-javalib-api_3.jar",
- "mill-libs-javalib-testrunner-entrypoint.jar",
- "mill-libs-javalib-testrunner_3.jar",
- "mill-libs-javalib_3.jar",
- "mill-libs-javascriptlib_3.jar",
- "mill-libs-kotlinlib-api_3.jar",
- "mill-libs-kotlinlib-ksp2-api_3.jar",
- "mill-libs-kotlinlib_3.jar",
- "mill-libs-pythonlib_3.jar",
- "mill-libs-rpc_3.jar",
- "mill-libs-scalajslib-api_3.jar",
- "mill-libs-scalajslib_3.jar",
- "mill-libs-scalalib_3.jar",
- "mill-libs-scalanativelib-api_3.jar",
- "mill-libs-scalanativelib_3.jar",
- "mill-libs-script_3.jar",
- "mill-libs-util_3.jar",
- "mill-libs_3.jar",
+ "mill-core-api-daemon_3-SNAPSHOT.jar",
+ "mill-core-api_3-SNAPSHOT.jar",
+ "mill-core-constants-SNAPSHOT.jar",
+ "mill-libs-androidlib-databinding_3-SNAPSHOT.jar",
+ "mill-libs-androidlib_3-SNAPSHOT.jar",
+ "mill-libs-daemon-client-SNAPSHOT.jar",
+ "mill-libs-daemon-server_3-SNAPSHOT.jar",
+ "mill-libs-javalib-api_3-SNAPSHOT.jar",
+ "mill-libs-javalib-testrunner-entrypoint-SNAPSHOT.jar",
+ "mill-libs-javalib-testrunner_3-SNAPSHOT.jar",
+ "mill-libs-javalib_3-SNAPSHOT.jar",
+ "mill-libs-javascriptlib_3-SNAPSHOT.jar",
+ "mill-libs-kotlinlib-api_3-SNAPSHOT.jar",
+ "mill-libs-kotlinlib-ksp2-api_3-SNAPSHOT.jar",
+ "mill-libs-kotlinlib_3-SNAPSHOT.jar",
+ "mill-libs-pythonlib_3-SNAPSHOT.jar",
+ "mill-libs-rpc_3-SNAPSHOT.jar",
+ "mill-libs-scalajslib-api_3-SNAPSHOT.jar",
+ "mill-libs-scalajslib_3-SNAPSHOT.jar",
+ "mill-libs-scalalib_3-SNAPSHOT.jar",
+ "mill-libs-scalanativelib-api_3-SNAPSHOT.jar",
+ "mill-libs-scalanativelib_3-SNAPSHOT.jar",
+ "mill-libs-script_3-SNAPSHOT.jar",
+ "mill-libs-util_3-SNAPSHOT.jar",
+ "mill-libs_3-SNAPSHOT.jar",
"mill-moduledefs_3-0.11.10.jar"
)
)
diff --git a/integration/ide/gen-idea/resources/extended/idea/mill_modules/mill-build.iml b/integration/ide/gen-idea/resources/extended/idea/mill_modules/mill-build.iml
index b1cea1775c1b..dcaf14ec659e 100644
--- a/integration/ide/gen-idea/resources/extended/idea/mill_modules/mill-build.iml
+++ b/integration/ide/gen-idea/resources/extended/idea/mill_modules/mill-build.iml
@@ -53,38 +53,38 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/integration/ide/gen-idea/resources/extended/idea/mill_modules/mill-build.mill-build.iml b/integration/ide/gen-idea/resources/extended/idea/mill_modules/mill-build.mill-build.iml
index bcdc6b4da6de..4cf3a039ce1f 100644
--- a/integration/ide/gen-idea/resources/extended/idea/mill_modules/mill-build.mill-build.iml
+++ b/integration/ide/gen-idea/resources/extended/idea/mill_modules/mill-build.mill-build.iml
@@ -54,41 +54,41 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
diff --git a/integration/ide/gen-idea/resources/hello-idea/idea/mill_modules/mill-build.iml b/integration/ide/gen-idea/resources/hello-idea/idea/mill_modules/mill-build.iml
index fdf6a0bdf623..6b6c2c2d8efb 100644
--- a/integration/ide/gen-idea/resources/hello-idea/idea/mill_modules/mill-build.iml
+++ b/integration/ide/gen-idea/resources/hello-idea/idea/mill_modules/mill-build.iml
@@ -50,38 +50,38 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/integration/package.mill b/integration/package.mill
index 016fb9f01bf1..83047da8a0e9 100644
--- a/integration/package.mill
+++ b/integration/package.mill
@@ -168,7 +168,10 @@ object `package` extends mill.Module {
def testMill: T[PathRef] = {
val name = if (scala.util.Properties.isWin) "mill.bat" else "mill"
Task {
- PathRef(build.dist.installLocalTask(binFile = Task.Anon((Task.dest / name).toString()))())
+ val executable = build.dist.executable().path
+ val dest = Task.dest / name
+ os.copy.over(executable, dest)
+ PathRef(dest)
}
}