Skip to content

Commit dcc8170

Browse files
committed
Adds support for //| mill-scala-library-version: 3.7.2-RC1 frontmatter.
1 parent 2ee59e4 commit dcc8170

File tree

3 files changed

+74
-14
lines changed

3 files changed

+74
-14
lines changed

runner/launcher/src/mill/launcher/CoursierClient.scala

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,32 +12,44 @@ import scala.concurrent.duration.Duration
1212
import mill.coursierutil.TestOverridesRepo
1313

1414
object CoursierClient {
15-
def resolveMillDaemon() = {
15+
/**
16+
* Resolves the classpath for the mill daemon.
17+
*
18+
* @param scalaLibraryVersion the version of the scala library to use. If not specified, the version from the
19+
* mill build is used.
20+
*/
21+
def resolveMillDaemon(scalaLibraryVersion: Option[String]): Array[String] = {
1622
val repositories = Await.result(Resolve().finalRepositories.future(), Duration.Inf)
1723
val coursierCache0 = FileCache[Task]()
1824
.withLogger(coursier.cache.loggers.RefreshLogger.create())
1925

20-
val artifactsResultOrError = {
21-
26+
val artifactsResult = {
2227
val resolve = Resolve()
2328
.withCache(coursierCache0)
24-
.withDependencies(Seq(Dependency(
25-
Module(Organization("com.lihaoyi"), ModuleName("mill-runner-daemon_3"), Map()),
26-
VersionConstraint(mill.client.BuildInfo.millVersion)
27-
)))
29+
.withDependencies(Seq(
30+
Dependency(
31+
Module(Organization("com.lihaoyi"), ModuleName("mill-runner-daemon_3"), attributes = Map.empty),
32+
VersionConstraint(mill.client.BuildInfo.millVersion)
33+
)
34+
) ++ scalaLibraryVersion.map { version =>
35+
Dependency(
36+
Module(Organization("org.scala-lang"), ModuleName("scala3-library_3"), attributes = Map.empty),
37+
VersionConstraint(version)
38+
)
39+
})
2840
.withRepositories(Seq(TestOverridesRepo) ++ repositories)
2941

3042
resolve.either() match {
3143
case Left(err) => sys.error(err.toString)
32-
case Right(v) =>
44+
case Right(resolution) =>
3345
Artifacts(coursierCache0)
34-
.withResolution(v)
46+
.withResolution(resolution)
3547
.eitherResult()
3648
.right.get
3749
}
3850
}
3951

40-
artifactsResultOrError.artifacts.map(_._2.toString).toArray
52+
artifactsResult.artifacts.iterator.map { case (_, file) => file.toString }.toArray
4153
}
4254

4355
def resolveJavaHome(id: String): java.io.File = {

runner/launcher/src/mill/launcher/MillProcessLauncher.java

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
import mill.constants.CodeGenConstants;
2020
import mill.constants.DaemonFiles;
2121
import mill.constants.EnvVars;
22+
import scala.None;
23+
import scala.None$;
24+
import scala.Option$;
2225

2326
public class MillProcessLauncher {
2427

@@ -120,11 +123,11 @@ static List<String> loadMillConfig(String key) throws Exception {
120123
Object conf = mill.launcher.ConfigReader.readYaml(
121124
buildFile, buildFile.getFileName().toString());
122125
if (!(conf instanceof Map)) return new String[] {};
123-
Map<String, Object> conf2 = (Map<String, Object>) conf;
126+
@SuppressWarnings("unchecked") Map<String, Object> conf2 = (Map<String, Object>) conf;
124127

125128
if (!conf2.containsKey(key)) return new String[] {};
126129
if (conf2.get(key) instanceof List) {
127-
List<String> list = (List<String>) conf2.get(key);
130+
@SuppressWarnings("unchecked") List<String> list = (List<String>) conf2.get(key);
128131
String[] arr = new String[list.size()];
129132
for (int i = 0; i < arr.length; i++) {
130133
arr[i] = mill.constants.Util.interpolateEnvVars(list.get(i), env);
@@ -152,7 +155,15 @@ static List<String> millOpts() throws Exception {
152155
}
153156

154157
static String millJvmVersion() throws Exception {
155-
List<String> res = loadMillConfig("mill-jvm-version");
158+
return loadMillConfigSingleValue("mill-jvm-version");
159+
}
160+
161+
static String millScalaLibraryVersion() throws Exception {
162+
return loadMillConfigSingleValue("mill-scala-library-version");
163+
}
164+
165+
static String loadMillConfigSingleValue(String key) throws Exception {
166+
List<String> res = loadMillConfig(key);
156167
if (res.isEmpty()) return null;
157168
else return res.get(0);
158169
}
@@ -228,10 +239,16 @@ static List<String> millLaunchJvmCommand() throws Exception {
228239
// extra opts
229240
vmOptions.addAll(millJvmOpts());
230241

242+
var maybeScalaLibraryVersion = millScalaLibraryVersion();
231243
vmOptions.add("-XX:+HeapDumpOnOutOfMemoryError");
232244
vmOptions.add("-cp");
245+
var classPathCacheKey =
246+
"mill:" + BuildInfo.millVersion +
247+
",scala-library-version:" + (maybeScalaLibraryVersion == null ? "default" : maybeScalaLibraryVersion);
233248
String[] runnerClasspath = cachedComputedValue0(
234-
"resolve-runner", BuildInfo.millVersion, () -> CoursierClient.resolveMillDaemon(), arr -> {
249+
"resolve-runner", classPathCacheKey,
250+
() -> CoursierClient.resolveMillDaemon(Option$.MODULE$.apply(maybeScalaLibraryVersion)),
251+
arr -> {
235252
for (String s : arr) {
236253
if (!Files.exists(Paths.get(s))) return false;
237254
}
@@ -246,6 +263,19 @@ static String[] cachedComputedValue(String name, String key, Supplier<String[]>
246263
return cachedComputedValue0(name, key, block, arr -> true);
247264
}
248265

266+
/**
267+
* Loads a value from the cache, or computes it if it's not in the cache, or re-computes it if it's
268+
* in the cache but invalid.
269+
* <p>
270+
* The cache is stored in the `out/mill-{name}` file and contains only a single key.
271+
*
272+
* @param name name of the cached value
273+
* @param key key of the value in the cache. If the cache exists but the key doesn't match, the value
274+
* will be re-computed.
275+
* @param block block to compute the value
276+
* @param validate function to validate the value. If the value is in cache but invalid, it will be
277+
* re-computed.
278+
*/
249279
static String[] cachedComputedValue0(
250280
String name, String key, Supplier<String[]> block, Function<String[], Boolean> validate) {
251281
try {

website/docs/modules/ROOT/pages/cli/build-header.adoc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ For example, a build header may look something like:
1515
//| mill-opts: ["--jobs=0.5C"]
1616
//| mill-jvm-version: temurin:11
1717
//| mill-jvm-opts: ["-XX:NonProfiledCodeHeapSize=250m", "-XX:ReservedCodeCacheSize=500m"]
18+
//| mill-scala-library-version: 3.7.2-RC1
1819
//| # newlines are allowed too
1920
//|
2021
//| repositories:
@@ -125,3 +126,20 @@ _build.mill_
125126

126127
Missing environment variables are converted to the empty string.
127128

129+
== mill-scala-library-version
130+
131+
Mill allows you to specify the exact scala-library version you want to use for your build
132+
via a `mill-scala-library-version` key in the build header:
133+
134+
_build.mill_
135+
136+
[source]
137+
----
138+
//| mill-scala-library-version: 3.7.2-RC1
139+
----
140+
141+
This allows you to use newer versions of the scala-library than the version used by Mill
142+
itself, as long as the version you use is backwards compatible.
143+
144+
If `mill-scala-library-version` is not provided, Mill uses the version of scala-library
145+
used by Mill itself.

0 commit comments

Comments
 (0)