Skip to content

Commit

Permalink
Migrate away from experimental hosted options.
Browse files Browse the repository at this point in the history
  • Loading branch information
fniephaus committed Sep 5, 2023
1 parent 07e22c0 commit c02c205
Show file tree
Hide file tree
Showing 11 changed files with 96 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,7 @@ abstract class NativeTestArgumentProvider implements CommandLineArgumentProvider
"-cp", classpath.asPath,
"--no-fallback",
"--features=org.graalvm.junit.platform.JUnitPlatformFeature",
"-H:Name=native-image-tests",
"-H:Class=org.graalvm.junit.platform.NativeImageJUnitLauncher",
"-o", "native-image-tests",
"-Djunit.platform.listeners.uid.tracking.output.dir=${testIdsDir.get().asFile.absolutePath}"
]
if (agentOutputDir.isPresent()) {
Expand All @@ -110,12 +109,15 @@ abstract class NativeTestArgumentProvider implements CommandLineArgumentProvider
}

args << "-H:ConfigurationFileDirectories=${outputDir.absolutePath}/agentOutput"
args << "-H:+AllowIncompleteClasspath"
}

if (discovery.get()) {
args << "-DtestDiscovery"
}

// Main class comes last
args << "org.graalvm.junit.platform.NativeImageJUnitLauncher"

args.collect { it.toString() }
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,7 @@ abstract class NativeTestArgumentProvider implements CommandLineArgumentProvider
"-cp", classpath.asPath,
"--no-fallback",
"--features=org.graalvm.junit.platform.JUnitPlatformFeature",
"-H:Name=native-image-tests",
"-H:Class=org.graalvm.junit.platform.NativeImageJUnitLauncher",
"-o", "native-image-tests",
"-Djunit.platform.listeners.uid.tracking.output.dir=${testIdsDir.get().asFile.absolutePath}"
]
if (agentOutputDir.isPresent()) {
Expand All @@ -108,12 +107,15 @@ abstract class NativeTestArgumentProvider implements CommandLineArgumentProvider
}

args << "-H:ConfigurationFileDirectories=${outputDir.absolutePath}/agentOutput"
args << "-H:+AllowIncompleteClasspath"
}

if (discovery.get()) {
args << "-DtestDiscovery"
}

// Main class comes last
args << "org.graalvm.junit.platform.NativeImageJUnitLauncher"

args.collect { it.toString() }
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ public class NativeImageUtils {

private static final Pattern graalvmVersionPattern = Pattern.compile("^(GraalVM|native-image) ([0-9]+)\\.([0-9]+)\\.([0-9]+).*");

private static final Pattern SAFE_SHELL_ARG = Pattern.compile("[A-Za-z0-9@%_\\-+=:,./]+");

public static void maybeCreateConfigureUtilSymlink(File configureUtilFile, Path nativeImageExecutablePath) {
if (!configureUtilFile.exists()) {
// possibly the symlink is missing
Expand Down Expand Up @@ -102,16 +104,22 @@ public static List<String> convertToArgsFile(List<String> cliArgs, Path outputDi
}
}


/**
* See https://github.com/oracle/graal/blob/f011d4d056a7ed78fe9669cc38062e6d09c14bed/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java#L1447C47-L1447C60.
*/
public static String escapeArg(String arg) {
if (!(arg.startsWith("\\Q") && arg.endsWith("\\E"))) {
arg = arg.replace("\\", "\\\\");
if (arg.contains(" ")) {
arg = "\"" + arg + "\"";
}
if (arg.isEmpty()) {
return "''";
}
return arg;
Matcher m = SAFE_SHELL_ARG.matcher(arg);
if (m.matches()) {
return arg;
}
return "'" + arg.replace("'", "'\"'\"'") + "'";
}


/**
*
* @param requiredVersion Required version can be {@code MAJOR}, {@code MAJOR.MINOR} or {@code MAJOR.MINOR.PATCH}
Expand Down Expand Up @@ -164,4 +172,12 @@ public static void checkVersion(String requiredVersion, String versionToCheck) {
}
}
}

public static int getMajorJDKVersion(String versionString) {
Matcher matcher = graalvmVersionPattern.matcher(versionString.trim());
if (matcher.matches()) {
return Integer.parseInt(matcher.group(2));
}
return -1;
}
}
1 change: 1 addition & 0 deletions docs/src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ If you are using alternative build systems, see <<alternative-build-systems.adoc
=== Release 0.9.26

* Relax GraalVM version check for dev versions
* Prepare plugins for release of *GraalVM for JDK 21*. They no longer deploy any experimental options.

==== Gradle plugin

Expand Down
2 changes: 1 addition & 1 deletion docs/src/docs/snippets/gradle/groovy/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ graalvmNative {
excludeConfig.put(file("path/to/artifact.jar"), listOf("^/META-INF/native-image/.*", "^/config/.*"))

// Advanced options
buildArgs.add('-H:Extra') // Passes '-H:Extra' to the native image builder options. This can be used to pass parameters which are not directly supported by this extension
buildArgs.add('--link-at-build-time') // Passes '--link-at-build-time' to the native image builder options. This can be used to pass parameters which are not directly supported by this extension
jvmArgs.add('flag') // Passes 'flag' directly to the JVM running the native image builder

// Runtime options
Expand Down
2 changes: 1 addition & 1 deletion docs/src/docs/snippets/gradle/kotlin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ graalvmNative {
excludeConfig.put(file("path/to/artifact.jar"), listOf("^/META-INF/native-image/.*", "^/config/.*"))

// Advanced options
buildArgs.add("-H:Extra") // Passes '-H:Extra' to the native image builder options. This can be used to pass parameters which are not directly supported by this extension
buildArgs.add("--link-at-build-time") // Passes '--link-at-build-time' to the native image builder options. This can be used to pass parameters which are not directly supported by this extension
jvmArgs.add("flag") // Passes 'flag' directly to the JVM running the native image builder

// Runtime options
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class JavaLibraryFunctionalTest extends AbstractFunctionalTest {
doesNotContain ':build'
}

outputContains "-H:+SharedLibrary"
outputContains "--shared"

and:
library.exists()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,23 +67,26 @@ public class NativeImageCommandLineProvider implements CommandLineArgumentProvid

private final Provider<NativeImageOptions> options;
private final Provider<String> executableName;
private final Provider<String> outputDirectory;
private final Provider<String> workingDirectory;
private final Provider<String> outputDirectory;
private final Provider<RegularFile> classpathJar;
private final Provider<Boolean> useArgFile;
private final Provider<Integer> majorJDKVersion;

public NativeImageCommandLineProvider(Provider<NativeImageOptions> options,
Provider<String> executableName,
Provider<String> workingDirectory,
Provider<String> outputDirectory,
Provider<RegularFile> classpathJar,
Provider<Boolean> useArgFile) {
Provider<Boolean> useArgFile,
Provider<Integer> majorJDKVersion) {
this.options = options;
this.executableName = executableName;
this.workingDirectory = workingDirectory;
this.outputDirectory = outputDirectory;
this.classpathJar = classpathJar;
this.useArgFile = useArgFile;
this.majorJDKVersion = majorJDKVersion;
}

@Nested
Expand Down Expand Up @@ -119,13 +122,15 @@ public List<String> asArguments() {
appendBooleanOption(cliArgs, options.getVerbose(), "--verbose");
appendBooleanOption(cliArgs, options.getSharedLibrary(), "--shared");
appendBooleanOption(cliArgs, options.getQuickBuild(), "-Ob");
appendBooleanOption(cliArgs, options.getRichOutput(), "-H:+BuildOutputColorful");
appendBooleanOption(cliArgs, options.getRichOutput(), majorJDKVersion.getOrElse(-1) >= 21 ? "--color" : "-H:+BuildOutputColorful");
appendBooleanOption(cliArgs, options.getPgoInstrument(), "--pgo-instrument");

String targetOutputPath = getExecutableName().get();
if (getOutputDirectory().isPresent()) {
cliArgs.add("-H:Path=" + getOutputDirectory().get());
targetOutputPath = getOutputDirectory().get() + File.separator + targetOutputPath;
}
cliArgs.add("-H:Name=" + getExecutableName().get());
cliArgs.add("-o");
cliArgs.add(targetOutputPath);

options.getSystemProperties().get().forEach((n, v) -> {
if (v != null) {
Expand All @@ -145,9 +150,6 @@ public List<String> asArguments() {
if (!configFiles.isEmpty()) {
cliArgs.add("-H:ConfigurationFileDirectories=" + configFiles);
}
if (options.getMainClass().isPresent()) {
cliArgs.add("-H:Class=" + options.getMainClass().get());
}
if (Boolean.FALSE.equals(options.getPgoInstrument().get()) && options.getPgoProfilesDirectory().isPresent()) {
FileTree files = options.getPgoProfilesDirectory().get().getAsFileTree();
Set<File> profiles = files.filter(f -> f.getName().endsWith(".iprof")).getFiles();
Expand All @@ -156,12 +158,20 @@ public List<String> asArguments() {
}
}
cliArgs.addAll(options.getBuildArgs().get());

List<String> actualCliArgs;
if (useArgFile.getOrElse(true)) {
Path argFileDir = Paths.get(workingDirectory.get());
return NativeImageUtils.convertToArgsFile(cliArgs, argFileDir, argFileDir);
actualCliArgs = new ArrayList<>(NativeImageUtils.convertToArgsFile(cliArgs, argFileDir, argFileDir));
} else {
actualCliArgs = cliArgs;
}
return Collections.unmodifiableList(cliArgs);

/* Main class comes last. It is kept outside argument files as GraalVM releases before JDK 21 fail to detect the mainClass in these files. */
if (options.getMainClass().isPresent()) {
actualCliArgs.add(options.getMainClass().get());
}
return Collections.unmodifiableList(actualCliArgs);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ public BuildNativeImageTask() {
getDisableToolchainDetection().convention(false);
}

private List<String> buildActualCommandLineArgs() {
private List<String> buildActualCommandLineArgs(int majorJDKVersion) {
getOptions().finalizeValue();
return new NativeImageCommandLineProvider(
getOptions(),
Expand All @@ -189,7 +189,8 @@ private List<String> buildActualCommandLineArgs() {
// a mapped value before the task was called, when we are actually calling it...
getProviders().provider(() -> getOutputDirectory().getAsFile().get().getAbsolutePath()),
getClasspathJar(),
getUseArgFile()).asArguments();
getUseArgFile(),
getProviders().provider(() -> majorJDKVersion)).asArguments();
}

// This property provides access to the service instance
Expand All @@ -203,18 +204,22 @@ public void exec() {
NativeImageOptions options = getOptions().get();
GraalVMLogger logger = GraalVMLogger.of(getLogger());

List<String> args = buildActualCommandLineArgs();
if (options.getVerbose().get()) {
logger.lifecycle("Args are: " + args);
}
File executablePath = NativeImageExecutableLocator.findNativeImageExecutable(
options.getJavaLauncher(),
getDisableToolchainDetection(),
getGraalVMHome(),
getExecOperations(),
logger,
diagnostics);
checkRequiredVersionIfNeeded(executablePath, options);
String versionString = getVersionString(getExecOperations(), executablePath);
if (options.getRequiredVersion().isPresent()) {
NativeImageUtils.checkVersion(options.getRequiredVersion().get(), versionString);
}
int majorJDKVersion = NativeImageUtils.getMajorJDKVersion(versionString);
List<String> args = buildActualCommandLineArgs(majorJDKVersion);
if (options.getVerbose().get()) {
logger.lifecycle("Args are: " + args);
}
for (String diagnostic : diagnostics.getDiagnostics()) {
logger.lifecycle(diagnostic);
}
Expand All @@ -240,19 +245,14 @@ public void exec() {
}
}

private void checkRequiredVersionIfNeeded(File executablePath, NativeImageOptions options) {
if (!options.getRequiredVersion().isPresent()) {
return;
}
public static String getVersionString(ExecOperations execOperations, File executablePath) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ExecResult execResult = getExecOperations().exec(spec -> {
ExecResult execResult = execOperations.exec(spec -> {
spec.setStandardOutput(outputStream);
spec.args("--version");
spec.setExecutable(executablePath.getAbsolutePath());
});
execResult.assertNormalExitValue();
String versionToCheck = new String(outputStream.toByteArray(), StandardCharsets.UTF_8);
NativeImageUtils.checkVersion(options.getRequiredVersion().get(), versionToCheck);
return new String(outputStream.toByteArray(), StandardCharsets.UTF_8);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,8 @@ protected List<String> getBuildArgs() throws MojoExecutionException {
cliArgs.add("-Ob");
}

cliArgs.add("-H:Path=" + outputDirectory.toPath().toAbsolutePath());
cliArgs.add("-H:Name=" + imageName);
cliArgs.add("-o");
cliArgs.add(outputDirectory.toPath().toAbsolutePath() + File.separator + imageName);

if (systemProperties != null) {
for (Map.Entry<String, String> entry : systemProperties.entrySet()) {
Expand All @@ -240,21 +240,25 @@ protected List<String> getBuildArgs() throws MojoExecutionException {
);
}

if (mainClass != null && !mainClass.equals(".")) {
cliArgs.add("-H:Class=" + mainClass);
}

if (buildArgs != null && !buildArgs.isEmpty()) {
for (String buildArg : buildArgs) {
cliArgs.addAll(Arrays.asList(buildArg.split("\\s+")));
}
}

List<String> actualCliArgs;
if (useArgFile) {
Path tmpDir = Paths.get("target", "tmp");
return NativeImageUtils.convertToArgsFile(cliArgs, tmpDir);
actualCliArgs = new ArrayList<>(NativeImageUtils.convertToArgsFile(cliArgs, tmpDir));
} else {
actualCliArgs = cliArgs;
}
return Collections.unmodifiableList(cliArgs);

/* Main class comes last. It is kept outside argument files as GraalVM releases before JDK 21 fail to detect the mainClass in these files. */
if (mainClass != null && !mainClass.equals(".")) {
actualCliArgs.add(mainClass);
}
return Collections.unmodifiableList(actualCliArgs);
}

protected Path processSupportedArtifacts(Artifact artifact) throws MojoExecutionException {
Expand Down Expand Up @@ -453,12 +457,6 @@ protected void maybeAddGeneratedResourcesConfig(List<String> into) {
String value = configDirs.map(File::getAbsolutePath).collect(Collectors.joining(","));
if (!value.isEmpty()) {
into.add("-H:ConfigurationFileDirectories=" + value);
if (agentResourceDirectory != null && agentResourceDirectory.isDirectory()) {
// The generated reflect config file contains references to java.*
// and org.apache.maven.surefire that we'd need to remove using
// a proper JSON parser/writer instead
into.add("-H:+AllowIncompleteClasspath");
}
}
}
}
Expand Down
Loading

0 comments on commit c02c205

Please sign in to comment.