@@ -49,15 +49,31 @@ object JlinkPlugin extends AutoPlugin {
49
49
jlinkModules := (jlinkModules ?? Nil ).value,
50
50
jlinkModules ++= {
51
51
val log = streams.value.log
52
- val run = runJavaTool(javaHome.in(jlinkBuildImage).value, log) _
52
+ val javaHome0 = javaHome.in(jlinkBuildImage).value.getOrElse(defaultJavaHome)
53
+ val run = runJavaTool(javaHome0, log) _
53
54
val paths = fullClasspath.in(jlinkBuildImage).value.map(_.data.getPath)
54
55
val shouldIgnore = jlinkIgnoreMissingDependency.value
55
56
57
+ // We can find the java toolchain version by parsing the `release` file. This
58
+ // only works for Java 9+, but so does this whole plugin.
59
+ // Alternatives:
60
+ // - Parsing `java -version` output - the format is not standardized, so there
61
+ // are a lot of weird incompatibilities.
62
+ // - Parsing `java -XshowSettings:properties` output - the format is nicer,
63
+ // but the command itself is subject to change without notice.
64
+ val releaseFile = javaHome0 / " release"
65
+ val javaVersion = IO
66
+ .readLines(releaseFile)
67
+ .collectFirst {
68
+ case javaVersionPattern(feature) => feature
69
+ }
70
+ .getOrElse(sys.error(" JAVA_VERSION not found in ${releaseFile.getAbsolutePath}" ))
71
+
56
72
// Jdeps has a few convenient options (like --print-module-deps), but those
57
73
// are not flexible enough - we need to parse the full output.
58
- val output = runForOutput(run(" jdeps" , " -R" +: paths), log)
74
+ val jdepsOutput = runForOutput(run(" jdeps" , " --multi-release " +: javaVersion +: " -R" +: paths), log)
59
75
60
- val deps = output .linesIterator
76
+ val deps = jdepsOutput .linesIterator
61
77
// There are headers in some of the lines - ignore those.
62
78
.flatMap(PackageDependency .parse(_).iterator)
63
79
.toSeq
@@ -109,7 +125,8 @@ object JlinkPlugin extends AutoPlugin {
109
125
},
110
126
jlinkBuildImage := {
111
127
val log = streams.value.log
112
- val run = runJavaTool(javaHome.in(jlinkBuildImage).value, log) _
128
+ val javaHome0 = javaHome.in(jlinkBuildImage).value.getOrElse(defaultJavaHome)
129
+ val run = runJavaTool(javaHome0, log) _
113
130
val outDir = target.in(jlinkBuildImage).value
114
131
115
132
IO .delete(outDir)
@@ -130,15 +147,22 @@ object JlinkPlugin extends AutoPlugin {
130
147
mappings in Universal ++= mappings.in(jlinkBuildImage).value
131
148
)
132
149
150
+ // Extracts java version from a release file line (`JAVA_VERSION` property):
151
+ // - if the feature version is 1, yield the minor version number (e.g. 1.9.0 -> 9);
152
+ // - otherwise yield the major version number (e.g. 11.0.3 -> 11).
153
+ private [jlink] val javaVersionPattern = """ JAVA_VERSION="(?:1\.)?(\d+).*?"""" .r
154
+
133
155
// TODO: deduplicate with UniversalPlugin and DebianPlugin
134
156
/** Finds all files in a directory. */
135
157
private def findFiles (dir : File ): Seq [(File , String )] =
136
158
((PathFinder (dir) ** AllPassFilter ) --- dir)
137
159
.pair(file => IO .relativize(dir, file))
138
160
139
- private def runJavaTool (jvm : Option [File ], log : Logger )(exeName : String , args : Seq [String ]): ProcessBuilder = {
140
- val jh = jvm.getOrElse(file(sys.props.getOrElse(" java.home" , sys.error(" no java.home" ))))
141
- val exe = (jh / " bin" / exeName).getAbsolutePath
161
+ private lazy val defaultJavaHome : File =
162
+ file(sys.props.getOrElse(" java.home" , sys.error(" no java.home" )))
163
+
164
+ private def runJavaTool (jvm : File , log : Logger )(exeName : String , args : Seq [String ]): ProcessBuilder = {
165
+ val exe = (jvm / " bin" / exeName).getAbsolutePath
142
166
143
167
log.info(" Running: " + (exe +: args).mkString(" " ))
144
168
0 commit comments