Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GraalVM for JDK 21 support. #1236

Merged
merged 10 commits into from
Nov 29, 2023
4 changes: 0 additions & 4 deletions src/main/java/com/gluonhq/substrate/SubstrateDispatcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -379,10 +379,6 @@ public SubstrateDispatcher(Path buildRoot, ProjectConfiguration config) throws I
System.out.println("Configuration: " + this.config);
}

Version javaVersion = this.config.checkGraalVMJavaVersion();
this.config.checkGraalVMVersion(javaVersion);
this.config.checkGraalVMVendor();

Triplet targetTriplet = config.getTargetTriplet();

this.targetConfiguration = Objects.requireNonNull(getTargetConfiguration(targetTriplet),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, Gluon
* Copyright (c) 2021, 2023, Gluon
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -29,8 +29,6 @@

import com.oracle.svm.core.jdk.NativeLibrarySupport;
import com.oracle.svm.core.jdk.PlatformNativeLibrarySupport;
import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl;
import com.oracle.svm.hosted.c.NativeLibraries;
import org.graalvm.nativeimage.hosted.Feature;


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ public class InternalProjectConfiguration {
private boolean useJavaFX = false;
private boolean usePrismSW = false;
private boolean enableCheckHash = true;
private boolean usesJDK11 = false;
private boolean sharedLibrary = false;
private boolean staticLibrary = false;

Expand All @@ -75,12 +74,14 @@ public class InternalProjectConfiguration {
private List<String> releaseSymbolsList;

private final ProjectConfiguration publicConfig;
private final Version javaVersion;
private final Version graalVersion;

/**
* Private projects configuration, which includes everything, including public settings
* @param config public project configuration
*/
public InternalProjectConfiguration(ProjectConfiguration config) {
public InternalProjectConfiguration(ProjectConfiguration config) throws IOException {

this.publicConfig = Objects.requireNonNull(config);

Expand Down Expand Up @@ -115,13 +116,19 @@ public InternalProjectConfiguration(ProjectConfiguration config) {
}

performHostChecks();

javaVersion = findGraalVMJavaVersion();
graalVersion = findGraalVersion();
checkGraalVMJavaVersion();
checkGraalVMVersion();
checkGraalVMVendor();
}

public Path getGraalPath() {
return Objects.requireNonNull(this.publicConfig.getGraalPath(), "GraalVM Path is not defined");
}

public Version getGraalVersion() throws IOException {
private Version findGraalVersion() throws IOException {
String pattern = "GraalVM .*?(\\d\\d.\\d.\\d)";
ProcessRunner graalJava;
try {
Expand All @@ -140,6 +147,10 @@ public Version getGraalVersion() throws IOException {
return new Version(m.group(1));
}

public Version getGraalVersion() {
jperedadnr marked this conversation as resolved.
Show resolved Hide resolved
return graalVersion;
}

/**
* Returns the version string for the static JDK libs.
* If this has not been specified before, the default will be
Expand Down Expand Up @@ -469,16 +480,15 @@ public ReleaseConfiguration getReleaseConfiguration() {
}

public boolean usesJDK11() {
return usesJDK11;
return javaVersion.getMajor() == 11;
}

/**
* Check if the GraalVM provided by the configuration is supported
* @throws IOException if the GraalVM version is older than the minimum supported version
*/
public void checkGraalVMVersion(Version javaVersion) throws IOException {
private void checkGraalVMVersion() throws IOException {
if (isOldGraalVMVersioningScheme(javaVersion)) {
Version graalVersion = getGraalVersion();
if (graalVersion.compareTo(new Version(Constants.GRAALVM_MIN_VERSION)) < 0) {
throw new IOException("Current GraalVM version (" + graalVersion + ") not supported.\n" +
"Please upgrade to " + Constants.GRAALVM_MIN_VERSION + " or higher");
Expand All @@ -502,21 +512,18 @@ public boolean isOldGraalVMVersioningScheme(Version javaVersion) {
* Check if the GraalVM's java provided by the configuration is supported
* @throws IOException if the GraalVM's java version is older than the minimum supported version
*/
public Version checkGraalVMJavaVersion() throws IOException {
Version javaVersion = getGraalVMJavaVersion();
private void checkGraalVMJavaVersion() throws IOException {
if (javaVersion.compareTo(new Version(Constants.GRAALVM_JAVA_MIN_VERSION)) < 0) {
throw new IOException("Current GraalVM's java version (" + javaVersion + ") not supported.\n" +
"Please upgrade to " + Constants.GRAALVM_JAVA_MIN_VERSION + " or higher");
}
usesJDK11 = javaVersion.getMajor() == 11;
return javaVersion;
}

/**
* Check if Gluon is the vendor of the GraalVM build, or else logs a message.
* @throws IOException if the GraalVM path or the GraalVM/release file don't exist
*/
public void checkGraalVMVendor() throws IOException {
private void checkGraalVMVendor() throws IOException {
Path graalPath = getGraalPath();
if (!Files.exists(graalPath)) {
throw new IOException("Path provided for GraalVM doesn't exist: " + graalPath);
Expand Down Expand Up @@ -663,13 +670,13 @@ private void checkGraalVMPermissions(String graalvmHome) {
}

/**
* Gets the Java version that GraalVM bundles
* try to find the Java version that GraalVM bundles
jperedadnr marked this conversation as resolved.
Show resolved Hide resolved
* @return the Java version of the GraalVM's build
* @throws NullPointerException when the configuration is null
* @throws IllegalArgumentException when the configuration doesn't contain a property graalPath
* @throws IOException if the Java version can't be found
*/
public Version getGraalVMJavaVersion() throws IOException {
private Version findGraalVMJavaVersion() throws IOException {
ProcessRunner graalJava = null;
try {
graalJava = new ProcessRunner(getGraalVMBinPath().resolve("java").toString(), "-version");
Expand All @@ -693,6 +700,14 @@ public Version getGraalVMJavaVersion() throws IOException {
return new Version(m.group(1));
}

/**
jperedadnr marked this conversation as resolved.
Show resolved Hide resolved
* Gets the Java version that GraalVM bundles
* @return the Java version of the GraalVM build
*/
public Version getJavaVersion() {
return javaVersion;
}

jperedadnr marked this conversation as resolved.
Show resolved Hide resolved
@Override
public String toString() {
return "ProjectConfiguration{" +
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2022, Gluon
* Copyright (c) 2019, 2023, Gluon
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -74,8 +74,10 @@ public abstract class AbstractTargetConfiguration implements TargetConfiguration
"png", "jpg", "jpeg", "gif", "bmp", "ttf", "raw",
"xml", "fxml", "css", "gls", "json", "dat",
"license", "frag", "vert", "obj", "mtl", "js");
protected static final List<String> ENABLED_FEATURES =
jperedadnr marked this conversation as resolved.
Show resolved Hide resolved
new ArrayList<>(Arrays.asList("org.graalvm.home.HomeFinderFeature"));
/**
* Manual registration of the HomeFinderFeature required until GraalVM for JDK 21.
*/
private static final String HOME_FINDER_FEATURE = "org.graalvm.home.HomeFinderFeature";

private static final List<String> baseNativeImageArguments = Arrays.asList(
"-Djdk.internal.lambda.eagerlyInitialize=false",
Expand Down Expand Up @@ -122,10 +124,10 @@ public abstract class AbstractTargetConfiguration implements TargetConfiguration
public boolean compile() throws IOException, InterruptedException {
String substrateClasspath = "";
try {
substrateClasspath = new File(AbstractTargetConfiguration.class.getProtectionDomain()
substrateClasspath = new File(AbstractTargetConfiguration.class.getProtectionDomain()
.getCodeSource().getLocation().toURI()).getPath();
} catch (URISyntaxException ex) {
throw new IOException ("Can't locate Substrate.jar", ex);
throw new IOException("Can't locate Substrate.jar", ex);
}
String processedClasspath = validateCompileRequirements();

Expand All @@ -139,12 +141,14 @@ public boolean compile() throws IOException, InterruptedException {

baseNativeImageArguments.forEach(compileRunner::addArg);

compileRunner.addArgs(getNativeImageArguments());

if (!projectConfiguration.isSharedLibrary() ||
!projectConfiguration.getTargetTriplet().equals(Triplet.fromCurrentOS())) {
compileRunner.addArg("-H:+ExitAfterRelocatableImageWrite");
}

compileRunner.addArgs(getEnabledFeatures());
compileRunner.addArgs(getEnabledFeaturesArgs());

compileRunner.addArg(createTempDirectoryArg());

Expand Down Expand Up @@ -380,13 +384,8 @@ private String getJniPlatformArg() {

private String getJniPlatform() {
Triplet target = projectConfiguration.getTargetTriplet();
boolean graalVM221 = false;
try {
Version graalVersion = projectConfiguration.getGraalVersion();
graalVM221 = ((graalVersion.getMajor() > 21) && (graalVersion.getMinor() >0));
} catch (IOException ex) {
Logger.logFatal(ex, "Could not detect GraalVM version, stopping now.");
}
Version graalVersion = projectConfiguration.getGraalVersion();
boolean graalVM221 = ((graalVersion.getMajor() > 21) && (graalVersion.getMinor() > 0));
String os = target.getOs();
String arch = target.getArch();
switch (os) {
Expand Down Expand Up @@ -445,7 +444,7 @@ private void ensureClibs() throws IOException {
target.getOsArch2());
}
if (FileOps.isDirectoryEmpty(clibPath)) {
throw new IOException("No clibraries found for the required architecture in "+clibPath);
throw new IOException("No clibraries found for the required architecture in " + clibPath);
}
checkPlatformSpecificClibs(clibPath);
}
Expand Down Expand Up @@ -492,14 +491,27 @@ private String getNativeImagePath() {
.toString();
}

private List<String> getEnabledFeatures() {
return ENABLED_FEATURES.stream()
.map(feature -> "--features=" + feature)
.collect(Collectors.toList());
protected List<String> getNativeImageArguments() {
return List.of();
}

protected List<String> getEnabledFeatures() {
return List.of();
}

private List<String> getEnabledFeaturesArgs() {
List<String> args = new ArrayList<>();
if (projectConfiguration.getJavaVersion().getMajor() < 21) {
args.add("--features=" + HOME_FINDER_FEATURE);
}
for (String feature : getEnabledFeatures()) {
args.add("--features=" + feature);
}
return args;
}

private String createTempDirectoryArg() throws IOException {
Path tmpPath = paths.getTmpPath();
Path tmpPath = paths.getTmpPath();
FileOps.rmdir(tmpPath);
String tmpDir = tmpPath.toFile().getAbsolutePath();
return "-H:TempDirectory=" + tmpDir;
Expand Down Expand Up @@ -564,7 +576,7 @@ private List<String> getInitializeAtBuildTimeList(String suffix, ConfigResolver
private Path createReflectionConfig(String suffix, ConfigResolver configResolver) throws IOException {
Path gvmPath = paths.getGvmPath();
Path reflectionPath = gvmPath.resolve(
Strings.substitute( Constants.REFLECTION_ARCH_FILE, Map.of("archOs", suffix)));
Strings.substitute(Constants.REFLECTION_ARCH_FILE, Map.of("archOs", suffix)));
Files.deleteIfExists(reflectionPath);
try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(reflectionPath.toFile())))) {
bw.write("[\n");
Expand Down Expand Up @@ -677,10 +689,10 @@ private static void writeEntry(BufferedWriter bw, String javaClass, boolean excl
writeSingleEntry(bw, javaClass, exclude);
}

private static void writeSingleEntry (BufferedWriter bw, String javaClass, boolean exclude) throws IOException {
private static void writeSingleEntry(BufferedWriter bw, String javaClass, boolean exclude) throws IOException {
bw.write(" {\n");
bw.write(" \"name\" : \"" + javaClass + "\"");
if (! exclude) {
if (!exclude) {
bw.write(",\n");
bw.write(" \"allDeclaredConstructors\" : true,\n");
bw.write(" \"allPublicConstructors\" : true,\n");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2022, Gluon
* Copyright (c) 2019, 2023, Gluon
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -63,6 +63,13 @@ public class LinuxTargetConfiguration extends PosixTargetConfiguration {
"java", "nio", "zip", "net", "prefs", "j2pkcs11", "sunec", "extnet", "fdlibm",
"fontmanager", "javajpeg", "lcms", "awt_headless", "awt"
);
/**
* fdlibm no longer required, unsure since when
jperedadnr marked this conversation as resolved.
Show resolved Hide resolved
*/
private static final List<String> staticJavaLibs21 = Arrays.asList(
"java", "nio", "zip", "net", "prefs", "j2pkcs11", "sunec", "extnet",
"fontmanager", "javajpeg", "lcms", "awt_headless", "awt"
);

private static final List<String> staticJvmLibs = Arrays.asList(
"jvm", "libchelper"
Expand All @@ -89,6 +96,13 @@ public class LinuxTargetConfiguration extends PosixTargetConfiguration {
"-lWTF", "-licuuc", "-licudata"
);

private static final List<String> nativeImageArguments = List.of(
"--add-exports=org.graalvm.nativeimage.builder/com.oracle.svm.core.jdk=ALL-UNNAMED" // required for the GluonFeature
);
private static final List<String> enabledFeatures = List.of(
"com.gluonhq.substrate.feature.GluonFeature"
);

private String[] capFiles = {"AArch64LibCHelperDirectives.cap",
"AMD64LibCHelperDirectives.cap", "BuiltinDirectives.cap",
"JNIHeaderDirectives.cap", "LibFFIHeaderDirectives.cap",
Expand All @@ -108,7 +122,6 @@ public class LinuxTargetConfiguration extends PosixTargetConfiguration {
public LinuxTargetConfiguration(ProcessPaths paths, InternalProjectConfiguration configuration) throws IOException {
super(paths, configuration);
this.isAarch64 = projectConfiguration.getTargetTriplet().getArch().equals(Constants.ARCH_AARCH64);
ENABLED_FEATURES.add("com.gluonhq.substrate.feature.GluonFeature");
sysroot = fileDeps.getSysrootPath().toString();
}

Expand Down Expand Up @@ -229,7 +242,13 @@ List<String> getStaticJavaLibs() {
} catch (IOException ex) {
throw new RuntimeException ("No static java libs found, cannot continue");
}
return staticJavaLibs.stream()
List<String> libs;
if (projectConfiguration.getJavaVersion().getMajor() >= 21) {
libs = staticJavaLibs21;
} else {
libs = staticJavaLibs;
}
return libs.stream()
.map(lib -> javaStaticLibPath.resolve("lib" + lib + ".a").toString())
.collect(Collectors.toList());
}
Expand Down Expand Up @@ -258,6 +277,16 @@ protected List<Path> getLinkerLibraryPaths() throws IOException {
return linkerLibraryPaths;
}

@Override
protected List<String> getNativeImageArguments() {
return nativeImageArguments;
}

@Override
public List<String> getEnabledFeatures() {
return enabledFeatures;
}

@Override
List<String> getTargetSpecificLinkFlags(boolean useJavaFX, boolean usePrismSW) throws IOException, InterruptedException {
List<String> answer = new LinkedList<>();
Expand Down
Loading
Loading