Skip to content

Commit

Permalink
Add support for multi-release Jar files
Browse files Browse the repository at this point in the history
If the user configures javacOptions to include Seq("--release", "17"),
for example, then multi-release Jar files will be opened and processed
accordingly.
  • Loading branch information
Flowdalic committed Sep 7, 2023
1 parent c75e29c commit 0932c20
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 7 deletions.
20 changes: 15 additions & 5 deletions scalalib/src/mill/scalalib/Assembly.scala
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ object Assembly {

def loadShadedClasspath(
inputPaths: Agg[os.Path],
assemblyRules: Seq[Assembly.Rule]
assemblyRules: Seq[Assembly.Rule],
runtimeVersion: Option[Runtime.Version]
): (Generator[(String, UnopenedInputStream)], ResourceCloser) = {
val shadeRules = assemblyRules.collect {
case Rule.Relocate(from, to) => ShadePattern.Rename(List(from -> to)).inAll
Expand All @@ -148,13 +149,20 @@ object Assembly {
}

val pathsWithResources = inputPaths.filter(os.exists).map { path =>
if (os.isFile(path)) path -> Some(new JarFile(path.toIO))
if (os.isFile(path)) path -> {
val file = path.toIO
val jarFile = runtimeVersion match {
case Some(version) => new JarFile(file, true, java.util.zip.ZipFile.OPEN_READ, version)
case None => new JarFile(file)
}
Some(jarFile)
}
else path -> None
}

val generators = Generator.from(pathsWithResources).flatMap {
case (path, Some(jarFile)) =>
Generator.from(jarFile.entries().asScala.filterNot(_.isDirectory))
Generator.from(jarFile.versionedStream().iterator().asScala.filterNot(_.isDirectory))
.flatMap(entry => shader(entry.getName, () => jarFile.getInputStream(entry)))
case (path, None) =>
os.walk
Expand Down Expand Up @@ -193,7 +201,8 @@ object Assembly {
manifest: mill.api.JarManifest = mill.api.JarManifest.MillDefault,
prependShellScript: String = "",
base: Option[os.Path] = None,
assemblyRules: Seq[Assembly.Rule] = Assembly.defaultRules
assemblyRules: Seq[Assembly.Rule] = Assembly.defaultRules,
runtimeVersion: Option[Runtime.Version]
)(implicit ctx: Ctx.Dest with Ctx.Log): PathRef = {
val tmp = ctx.dest / "out-tmp.jar"

Expand All @@ -213,7 +222,8 @@ object Assembly {
manifest.build.write(manifestOut)
manifestOut.close()

val (mappings, resourceCleaner) = Assembly.loadShadedClasspath(inputPaths, assemblyRules)
val (mappings, resourceCleaner) =
Assembly.loadShadedClasspath(inputPaths, assemblyRules, runtimeVersion)
try {
Assembly.groupAssemblyEntries(mappings, assemblyRules).foreach {
case (mapping, entry) =>
Expand Down
17 changes: 15 additions & 2 deletions scalalib/src/mill/scalalib/JavaModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,17 @@ trait JavaModule
*/
def javacOptions: T[Seq[String]] = T { Seq.empty[String] }

private def extractRuntimeVersion(javacOptions: Seq[String]): Option[Runtime.Version] = {
val releaseOptIndex = javacOptions.indexOf("--release")
val releaseOptValueIndex = releaseOptIndex + 1
if (releaseOptIndex >= 0 && javacOptions.length >= releaseOptValueIndex) {
val runtimeVersionString = javacOptions(releaseOptValueIndex)
val runtimeVersion = Runtime.Version.parse(runtimeVersionString)
println(s"Extracted javac --release version $runtimeVersion")
Some(runtimeVersion)
} else None
}

/** The direct dependencies of this module */
def moduleDeps: Seq[JavaModule] = Seq.empty

Expand Down Expand Up @@ -447,7 +458,8 @@ trait JavaModule
Assembly.createAssembly(
upstreamAssemblyClasspath().map(_.path),
manifest(),
assemblyRules = assemblyRules
assemblyRules = assemblyRules,
runtimeVersion = extractRuntimeVersion(javacOptions())
)
}

Expand All @@ -461,7 +473,8 @@ trait JavaModule
manifest(),
prependShellScript(),
Some(upstreamAssembly().path),
assemblyRules
assemblyRules,
runtimeVersion = extractRuntimeVersion(javacOptions())
)
}

Expand Down

0 comments on commit 0932c20

Please sign in to comment.