Compare commits
4 commits
develop
...
dfox/refle
Author | SHA1 | Date | |
---|---|---|---|
|
c2db9f6076 | ||
|
a5f4803777 | ||
|
1a7ea17eb4 | ||
|
3f6aae13a8 |
5 changed files with 220 additions and 8 deletions
|
@ -76,6 +76,17 @@ public class GradleGraalPlugin implements Plugin<Project> {
|
|||
task.dependsOn(downloadGraal);
|
||||
});
|
||||
|
||||
TaskProvider<ReflectionConfigTask> reflectionConfig = project.getTasks().register(
|
||||
"reflectionConfig",
|
||||
ReflectionConfigTask.class,
|
||||
task -> {
|
||||
task.add("java.util.ArrayList");
|
||||
task.add("java.util.Optional");
|
||||
task.setFile(project.getLayout().getBuildDirectory()
|
||||
.dir("graal")
|
||||
.map(d -> d.file("reflectconfig.json")));
|
||||
});
|
||||
|
||||
TaskProvider<Jar> jar = project.getTasks().withType(Jar.class).named("jar");
|
||||
project.getTasks().register(
|
||||
"nativeImage",
|
||||
|
@ -87,8 +98,12 @@ public class GradleGraalPlugin implements Plugin<Project> {
|
|||
task.setJarFile(jar.map(j -> j.getOutputs().getFiles().getSingleFile()));
|
||||
task.setClasspath(project.getConfigurations().named("runtimeClasspath"));
|
||||
task.setCacheDir(cacheDir);
|
||||
task.option(reflectionConfig.get().getOutputJsonFile()
|
||||
.map(file -> "-H:ReflectionConfigurationFiles=" + file));
|
||||
|
||||
task.dependsOn(extractGraal);
|
||||
task.dependsOn(jar);
|
||||
task.dependsOn(reflectionConfig);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* (c) Copyright 2018 Palantir Technologies Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.palantir.gradle.graal;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.provider.ListProperty;
|
||||
import org.gradle.api.provider.Provider;
|
||||
|
||||
/**
|
||||
* See substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java in
|
||||
* https://github.com/oracle/graal/.
|
||||
*/
|
||||
public final class NativeImageOptions implements Serializable {
|
||||
private static final long serialVersionUID = 9307652985066589L;
|
||||
|
||||
// using Object to represent String | Provider<String>
|
||||
private final ListProperty<Object> list;
|
||||
|
||||
public NativeImageOptions(Project project) {
|
||||
list = project.getObjects().listProperty(Object.class);
|
||||
}
|
||||
|
||||
public List<String> get() {
|
||||
return getProvider().get();
|
||||
}
|
||||
|
||||
public void set(String option) {
|
||||
list.add(option);
|
||||
}
|
||||
|
||||
public void set(Provider<String> option) {
|
||||
list.add(option);
|
||||
}
|
||||
|
||||
// TODO(dfox): make the incremental behaviour here understand when a file has changed or not
|
||||
|
||||
public Provider<List<String>> getProvider() {
|
||||
return list.map(providers -> providers.stream().flatMap(object -> {
|
||||
|
||||
if (object instanceof Provider) {
|
||||
Provider provider = (Provider) object;
|
||||
return provider.isPresent() ? Stream.of((String) provider.get()) : Stream.empty();
|
||||
}
|
||||
|
||||
if (object instanceof String) {
|
||||
return Stream.of((String) object);
|
||||
}
|
||||
|
||||
throw new IllegalStateException("list elements must be either String or Provider<String>, was: " + object);
|
||||
}).collect(toList()));
|
||||
}
|
||||
}
|
|
@ -49,6 +49,8 @@ public class NativeImageTask extends DefaultTask {
|
|||
private final RegularFileProperty jarFile = newInputFile();
|
||||
private final RegularFileProperty outputFile = newOutputFile();
|
||||
private final Property<Path> cacheDir = getProject().getObjects().property(Path.class);
|
||||
private final NativeImageOptions options = new NativeImageOptions(getProject());
|
||||
|
||||
|
||||
public NativeImageTask() {
|
||||
setGroup(GradleGraalPlugin.TASK_GROUP);
|
||||
|
@ -58,6 +60,9 @@ public class NativeImageTask extends DefaultTask {
|
|||
.dir("graal")
|
||||
.map(d -> d.file(outputName.get())));
|
||||
|
||||
options.set(outputName.map(string -> "-H:Name=" + string));
|
||||
options.set(maybeCreateOutputDirectory(outputFile).map(string -> "-H:Path=" + string));
|
||||
|
||||
doLast(t -> {
|
||||
getLogger().warn("native-image available at {} ({}MB)",
|
||||
getProject().relativePath(outputFile.get().getAsFile()),
|
||||
|
@ -70,10 +75,7 @@ public class NativeImageTask extends DefaultTask {
|
|||
List<String> args = new ArrayList<>();
|
||||
args.add("-cp");
|
||||
args.add(generateClasspathArgument());
|
||||
args.add("-H:Path=" + maybeCreateOutputDirectory().getAbsolutePath());
|
||||
if (outputName.isPresent()) {
|
||||
args.add("-H:Name=" + outputName.get());
|
||||
}
|
||||
args.addAll(options.get());
|
||||
args.add(mainClass.get());
|
||||
|
||||
getProject().exec(spec -> {
|
||||
|
@ -82,10 +84,17 @@ public class NativeImageTask extends DefaultTask {
|
|||
});
|
||||
}
|
||||
|
||||
private File maybeCreateOutputDirectory() throws IOException {
|
||||
File directory = getOutputFile().get().getAsFile().getParentFile();
|
||||
Files.createDirectories(directory.toPath());
|
||||
return directory;
|
||||
private static Provider<String> maybeCreateOutputDirectory(Provider<RegularFile> output) {
|
||||
return output.map(o -> {
|
||||
try {
|
||||
File directory = o.getAsFile().getParentFile();
|
||||
Files.createDirectories(directory.toPath());
|
||||
String absolutePath = directory.getAbsolutePath();
|
||||
return absolutePath;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private String getExecutable() {
|
||||
|
@ -164,6 +173,19 @@ public class NativeImageTask extends DefaultTask {
|
|||
jarFile.set(getProject().getLayout().file(provider));
|
||||
}
|
||||
|
||||
@Input
|
||||
public final Provider<List<String>> getOptions() {
|
||||
return options.getProvider();
|
||||
}
|
||||
|
||||
public final void option(String string) {
|
||||
this.options.set(string);
|
||||
}
|
||||
|
||||
public final void option(Provider<String> string) {
|
||||
this.options.set(string);
|
||||
}
|
||||
|
||||
@OutputFile
|
||||
public final Provider<RegularFile> getOutputFile() {
|
||||
return outputFile;
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* (c) Copyright 2018 Palantir Technologies Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.palantir.gradle.graal;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import groovy.json.JsonOutput;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.gradle.api.DefaultTask;
|
||||
import org.gradle.api.file.RegularFile;
|
||||
import org.gradle.api.file.RegularFileProperty;
|
||||
import org.gradle.api.provider.ListProperty;
|
||||
import org.gradle.api.provider.Provider;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.OutputFile;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
|
||||
// TODO(dfox): make this read files containing class names
|
||||
public class ReflectionConfigTask extends DefaultTask {
|
||||
|
||||
private final RegularFileProperty file = newOutputFile();
|
||||
private final ListProperty<String> classes = getProject().getObjects().listProperty(String.class);
|
||||
|
||||
public ReflectionConfigTask() {
|
||||
setGroup(GradleGraalPlugin.TASK_GROUP);
|
||||
setDescription("Generates a reflectconfig.json file based on supplied class names");
|
||||
|
||||
onlyIf(t -> classes.isPresent() && !classes.get().isEmpty());
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
public final void generateFile() throws IOException {
|
||||
List<Map<String, Object>> json = classes.get().stream()
|
||||
.map(clazz -> {
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("name", clazz);
|
||||
map.put("allDeclaredConstructors", true);
|
||||
map.put("allPublicConstructors", true);
|
||||
map.put("allDeclaredMethods", true);
|
||||
map.put("allPublicMethods", true);
|
||||
map.put("allDeclaredFields", true);
|
||||
map.put("allPublicFields", true);
|
||||
return map;
|
||||
})
|
||||
.collect(toList());
|
||||
|
||||
String string = JsonOutput.prettyPrint(JsonOutput.toJson(json));
|
||||
Files.write(file.get().getAsFile().toPath(), string.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
@Input
|
||||
public final Provider<List<String>> getClasses() {
|
||||
return classes;
|
||||
}
|
||||
|
||||
@OutputFile
|
||||
public final RegularFileProperty getOutputJsonFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
public final void setFile(File value) {
|
||||
file.set(value);
|
||||
}
|
||||
|
||||
public final void setFile(Provider<RegularFile> regularFileProvider) {
|
||||
file.set(regularFileProvider);
|
||||
}
|
||||
|
||||
public final void add(String string) {
|
||||
classes.add(string);
|
||||
}
|
||||
|
||||
public final void add(Provider<String> value) {
|
||||
classes.add(value);
|
||||
}
|
||||
|
||||
public final void addAll(String... strings) {
|
||||
classes.addAll(strings);
|
||||
}
|
||||
}
|
|
@ -42,6 +42,10 @@ class GradleGraalEndToEndSpec extends IntegrationSpec {
|
|||
outputName 'hello-world'
|
||||
graalVersion '1.0.0-rc5'
|
||||
}
|
||||
|
||||
nativeImage {
|
||||
option '-H:Optimize=1'
|
||||
}
|
||||
'''
|
||||
|
||||
when:
|
||||
|
|
Loading…
Reference in a new issue