1
1
package sbtnativeimage
2
2
3
3
import java .io .File
4
- import java .nio .file .Files
5
- import java .nio .file .StandardCopyOption
4
+ import java .nio .file .{ Files , Path , Paths , StandardCopyOption }
6
5
import java .util .jar .Attributes
7
6
import java .util .jar .JarOutputStream
8
7
import java .util .jar .Manifest
@@ -16,7 +15,6 @@ import sbt.Keys._
16
15
import sbt ._
17
16
import sbt .plugins .JvmPlugin
18
17
import sbt .complete .DefaultParsers ._
19
- import java .nio .file .Paths
20
18
import scala .util .Try
21
19
22
20
object NativeImagePlugin extends AutoPlugin {
@@ -44,10 +42,27 @@ object NativeImagePlugin extends AutoPlugin {
44
42
taskKey[File ](
45
43
" Path to a coursier binary that is used to launch GraalVM native-image."
46
44
)
45
+ lazy val nativeImageInstalled : SettingKey [Boolean ] =
46
+ settingKey[Boolean ](" Whether GraalVM is manually installed or should be downloaded with coursier." )
47
+ lazy val nativeImageGraalHome : TaskKey [Path ] =
48
+ taskKey[Path ](" Path to GraalVM home directory." )
47
49
lazy val nativeImageCommand : TaskKey [Seq [String ]] =
48
50
taskKey[Seq [String ]](
49
51
" The command arguments to launch the GraalVM native-image binary."
50
52
)
53
+ lazy val nativeImageRunAgent : InputKey [Unit ] =
54
+ inputKey[Unit ](
55
+ " Run application, tracking all usages of dynamic features of an execution with `native-image-agent`."
56
+ )
57
+ lazy val nativeImageAgentOutputDir : SettingKey [File ] =
58
+ settingKey[File ](
59
+ " Directory where `native-image-agent` should put generated configurations."
60
+ )
61
+ lazy val nativeImageAgentMerge : SettingKey [Boolean ] =
62
+ settingKey[Boolean ](
63
+ " Whether `native-image-agent` should merge generated configurations." +
64
+ s " (See $assistedConfigurationOfNativeImageBuildsLink for details) "
65
+ )
51
66
lazy val nativeImage : TaskKey [File ] =
52
67
taskKey[File ](" Generate a native image for this project." )
53
68
lazy val nativeImageRun : InputKey [Unit ] =
@@ -62,6 +77,9 @@ object NativeImagePlugin extends AutoPlugin {
62
77
taskKey[Seq [String ]](
63
78
" Extra command-line arguments that should be forwarded to the native-image optimizer."
64
79
)
80
+
81
+ private lazy val assistedConfigurationOfNativeImageBuildsLink =
82
+ " https://www.graalvm.org/reference-manual/native-image/BuildConfiguration/#assisted-configuration-of-native-image-builds"
65
83
}
66
84
import autoImport ._
67
85
@@ -110,23 +128,30 @@ object NativeImagePlugin extends AutoPlugin {
110
128
out
111
129
}
112
130
},
113
- nativeImageCommand := Def .taskDyn {
114
- if (
131
+ nativeImageInstalled := Def .settingDyn {
132
+ val installed =
115
133
" true" .equalsIgnoreCase(System .getProperty(" native-image-installed" )) ||
116
- " true" .equalsIgnoreCase(System .getenv(" NATIVE_IMAGE_INSTALLED" ))
117
- ) {
118
- val binary =
119
- if (Properties .isWin) " native-image.cmd" else " native-image"
120
- val path =
121
- Paths .get(System .getenv(" JAVA_HOME" )).resolve(" bin" ).resolve(binary)
122
- Def .task(List [String ](path.toString()))
134
+ " true" .equalsIgnoreCase(System .getenv(" NATIVE_IMAGE_INSTALLED" )) ||
135
+ " true" .equalsIgnoreCase(System .getProperty(" graalvm-installed" )) ||
136
+ " true" .equalsIgnoreCase(System .getenv(" GRAALVM_INSTALLED" ))
137
+ Def .setting(installed)
138
+ }.value,
139
+ nativeImageGraalHome := Def .taskDyn {
140
+ if (nativeImageInstalled.value) {
141
+ val path = Paths .get {
142
+ List (" GRAAL_HOME" , " GRAALVM_HOME" , " JAVA_HOME" ).iterator
143
+ .map(key => Option (System .getenv(key)))
144
+ .collectFirst { case Some (value) => value }
145
+ .getOrElse(" " )
146
+ }
147
+ Def .task(path)
123
148
} else {
124
149
Def .task {
125
150
val coursier = nativeImageCoursier.value.absolutePath
126
151
val svm = nativeImageVersion.value
127
152
val jvm = nativeImageJvm.value
128
153
val index = nativeImageJvmIndex.value
129
- val javaHome = Paths .get(
154
+ Paths .get(
130
155
Process (
131
156
List (
132
157
coursier,
@@ -138,8 +163,21 @@ object NativeImagePlugin extends AutoPlugin {
138
163
)
139
164
).!! .trim
140
165
)
166
+ }
167
+ }
168
+ }.value,
169
+ nativeImageCommand := Def .taskDyn {
170
+ val graalHome = nativeImageGraalHome.value
171
+ if (nativeImageInstalled.value) {
172
+ val binary =
173
+ if (Properties .isWin) " native-image.cmd" else " native-image"
174
+ val path =
175
+ graalHome.resolve(" bin" ).resolve(binary)
176
+ Def .task(List [String ](path.toString()))
177
+ } else {
178
+ Def .task {
141
179
val cmd = if (Properties .isWin) " .cmd" else " "
142
- val ni = javaHome .resolve(" bin" ).resolve(s " native-image $cmd" )
180
+ val ni = graalHome .resolve(" bin" ).resolve(s " native-image $cmd" )
143
181
if (! Files .isExecutable(ni)) {
144
182
val gu = ni.resolveSibling(s " gu $cmd" )
145
183
Process (List (gu.toString, " install" , " native-image" )).!
@@ -155,6 +193,25 @@ object NativeImagePlugin extends AutoPlugin {
155
193
}
156
194
}
157
195
}.value,
196
+ nativeImageAgentOutputDir := target.value / " native-image-configs" ,
197
+ nativeImageAgentMerge := false ,
198
+ nativeImageRunAgent := {
199
+ val graalHome = nativeImageGraalHome.value.toFile
200
+ val agentConfig = if (nativeImageAgentMerge.value) " config-merge-dir" else " config-output-dir"
201
+ val agentOption = s " -agentlib:native-image-agent= $agentConfig= ${nativeImageAgentOutputDir.value}"
202
+ val tpr = thisProjectRef.value
203
+ val settings = Seq (
204
+ fork in (tpr, Compile , run) := true ,
205
+ javaHome in (tpr, Compile , run) := Some (graalHome),
206
+ javaOptions in (tpr, Compile , run) += agentOption
207
+ )
208
+ val state0 = state.value
209
+ val extracted = Project .extract(state0)
210
+ val newState = extracted.append(settings, state0)
211
+ val arguments = spaceDelimited(" <arg>" ).parsed
212
+ val input = if (arguments.isEmpty) " " else arguments.mkString(" " )
213
+ Project .extract(newState).runInputTask(run in (tpr, Compile ), input, newState)
214
+ },
158
215
nativeImageOutput :=
159
216
target.in(NativeImage ).value / name.in(NativeImage ).value,
160
217
nativeImageCopy := {
0 commit comments