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 Gradle rich output support, configure default metadata URL on Maven #249

Merged
merged 1 commit into from Jun 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -55,7 +55,7 @@
* and provide overrides for cases where configuration files
* are missing.
*/
public interface JvmReachabilityMetadataRepository {
public interface GraalVMReachabilityMetadataRepository {
/**
* Performs a generic query on the repository, returning a list of
* configuration directories. The query may be parameterized with
Expand Down
Expand Up @@ -40,7 +40,7 @@
*/
package org.graalvm.reachability.internal;

import org.graalvm.reachability.JvmReachabilityMetadataRepository;
import org.graalvm.reachability.GraalVMReachabilityMetadataRepository;
import org.graalvm.reachability.Query;
import org.graalvm.reachability.internal.index.artifacts.SingleModuleJsonVersionToConfigDirectoryIndex;
import org.graalvm.reachability.internal.index.artifacts.VersionToConfigDirectoryIndex;
Expand All @@ -55,7 +55,7 @@
import java.util.function.Supplier;
import java.util.stream.Collectors;

public class FileSystemRepository implements JvmReachabilityMetadataRepository {
public class FileSystemRepository implements GraalVMReachabilityMetadataRepository {

private final FileSystemModuleToConfigDirectoryIndex moduleIndex;
private final Logger logger;
Expand Down
Expand Up @@ -51,6 +51,9 @@
*/
public interface SharedConstants {
boolean IS_WINDOWS = System.getProperty("os.name", "unknown").contains("Windows");
boolean IS_CI = System.getenv("CI") != null;
boolean IS_DUMB_TERM = Arrays.asList(null, "", "dumb", "unknown").contains(System.getenv("TERM"));
boolean NO_COLOR = System.getenv("NO_COLOR") != null; // https://no-color.org/
String GRAALVM_EXE_EXTENSION = (IS_WINDOWS ? ".cmd" : "");
String EXECUTABLE_EXTENSION = (IS_WINDOWS ? ".exe" : "");
String NATIVE_IMAGE_EXE = "native-image" + GRAALVM_EXE_EXTENSION;
Expand All @@ -72,4 +75,5 @@ public interface SharedConstants {
String AGENT_SESSION_SUBDIR = "session-{pid}-{datetime}";
String AGENT_OUTPUT_DIRECTORY_MARKER = "{output_dir}";
String AGENT_OUTPUT_DIRECTORY_OPTION = "config-output-dir=";
String METADATA_REPO_URL_TEMPLATE = "https://github.com/graalvm/graalvm-reachability-metadata/releases/download/%1$s/graalvm-reachability-metadata-%1$s.zip";
}
2 changes: 1 addition & 1 deletion docs/src/docs/asciidoc/maven-plugin.adoc
Expand Up @@ -615,7 +615,7 @@ automatically added to your native build options.
[[metadata-support]]
== GraalVM Reachability Metadata Support

Since release 0.9.12, the plugin adds experimental support for the https://github.com/graalvm/jvm-reachability-metadata/[JVM reachability metadata repository].
Since release 0.9.12, the plugin adds experimental support for the https://github.com/graalvm/graalvm-reachability-metadata/[GraalVM reachability metadata repository].
This repository provides GraalVM metadata for libraries which do not officially support GraalVM native.

A metadata repository consists of configuration files for GraalVM.
Expand Down
1 change: 1 addition & 0 deletions docs/src/docs/snippets/gradle/groovy/build.gradle
Expand Up @@ -120,6 +120,7 @@ graalvmNative {
fallback = true // Sets the fallback mode of native-image, defaults to false
sharedLibrary = false // Determines if image is a shared library, defaults to false if `java-library` plugin isn't included
quickBuild = false // Determines if image is being built in quick build mode (alternatively use GRAALVM_QUICK_BUILD environment variable)
richOutput = false // Determines if native-image building should be done with rich output

systemProperties = [name1: 'value1', name2: 'value2'] // Sets the system properties to use for the native image builder
configurationFileDirectories.from(file('src/my-config')) // Adds a native image configuration file directory, containing files like reflection configuration
Expand Down
1 change: 1 addition & 0 deletions docs/src/docs/snippets/gradle/kotlin/build.gradle.kts
Expand Up @@ -78,6 +78,7 @@ graalvmNative {
fallback.set(true) // Sets the fallback mode of native-image, defaults to false
sharedLibrary.set(false) // Determines if image is a shared library, defaults to false if `java-library` plugin isn't included
quickBuild.set(false) // Determines if image is being built in quick build mode (alternatively use GRAALVM_QUICK_BUILD environment variable)
richOutput.set(false) // Determines if native-image building should be done with rich output

systemProperties.putAll(mapOf("name1" to "value1", "name2" to "value2")) // Sets the system properties to use for the native image builder
configurationFileDirectories.from(file("src/my-config")) // Adds a native image configuration file directory, containing files like reflection configuration
Expand Down
Expand Up @@ -75,10 +75,10 @@ class NativeConfigRepoFunctionalTest extends AbstractFunctionalTest {
outputContains "Hello, from reflection!"

and: "doesn't find a configuration directory for the current version"
outputContains "[jvm reachability metadata repository for org.graalvm.internal:library-with-reflection:1.5]: Configuration directory not found. Trying latest version."
outputContains "[graalvm reachability metadata repository for org.graalvm.internal:library-with-reflection:1.5]: Configuration directory not found. Trying latest version."

and: "but finds one thanks to the latest configuration field"
outputContains "[jvm reachability metadata repository for org.graalvm.internal:library-with-reflection:1.5]: Configuration directory is org/graalvm/internal/library-with-reflection/1"
outputContains "[graalvm reachability metadata repository for org.graalvm.internal:library-with-reflection:1.5]: Configuration directory is org/graalvm/internal/library-with-reflection/1"

where:
format | label
Expand Down Expand Up @@ -112,7 +112,7 @@ graalvmNative {
outputContains "Reflection failed"

and: "doesn't look for a configuration directory for the current version"
outputDoesNotContain "[jvm reachability metadata repository for org.graalvm.internal:library-with-reflection:1.5]: Configuration directory not found. Trying latest version."
outputDoesNotContain "[graalvm reachability metadata repository for org.graalvm.internal:library-with-reflection:1.5]: Configuration directory not found. Trying latest version."
}

def "can force a dependency to a specific config version"() {
Expand All @@ -139,7 +139,7 @@ graalvmNative {
outputContains "Reflection failed"

and: "looks for specific configuration version"
outputContains "[jvm reachability metadata repository for org.graalvm.internal:library-with-reflection:1.5]: Configuration is forced to version 2"
outputContains "[graalvm reachability metadata repository for org.graalvm.internal:library-with-reflection:1.5]: Configuration is forced to version 2"
}

}
Expand Up @@ -45,7 +45,7 @@
import org.graalvm.buildtools.agent.AgentConfiguration;
import org.graalvm.buildtools.agent.AgentMode;
import org.graalvm.buildtools.gradle.dsl.GraalVMExtension;
import org.graalvm.buildtools.gradle.dsl.JvmReachabilityMetadataRepositoryExtension;
import org.graalvm.buildtools.gradle.dsl.GraalVMReachabilityMetadataRepositoryExtension;
import org.graalvm.buildtools.gradle.dsl.NativeImageOptions;
import org.graalvm.buildtools.gradle.dsl.agent.AgentOptions;
import org.graalvm.buildtools.gradle.internal.AgentCommandLineProvider;
Expand All @@ -55,7 +55,7 @@
import org.graalvm.buildtools.gradle.internal.DeprecatedNativeImageOptions;
import org.graalvm.buildtools.gradle.internal.GraalVMLogger;
import org.graalvm.buildtools.gradle.internal.GradleUtils;
import org.graalvm.buildtools.gradle.internal.JvmReachabilityMetadataService;
import org.graalvm.buildtools.gradle.internal.GraalVMReachabilityMetadataService;
import org.graalvm.buildtools.gradle.internal.NativeConfigurations;
import org.graalvm.buildtools.gradle.internal.agent.AgentConfigurationFactory;
import org.graalvm.buildtools.gradle.tasks.BuildNativeImageTask;
Expand Down Expand Up @@ -129,6 +129,7 @@
import static org.graalvm.buildtools.gradle.internal.NativeImageExecutableLocator.graalvmHomeProvider;
import static org.graalvm.buildtools.utils.SharedConstants.AGENT_PROPERTY;
import static org.graalvm.buildtools.utils.SharedConstants.IS_WINDOWS;
import static org.graalvm.buildtools.utils.SharedConstants.METADATA_REPO_URL_TEMPLATE;

/**
* Gradle plugin for GraalVM Native Image.
Expand Down Expand Up @@ -307,10 +308,10 @@ private void configureAutomaticTaskCreation(Project project,
}

private void configureJvmReachabilityConfigurationDirectories(Project project, GraalVMExtension graalExtension, NativeImageOptions options, SourceSet sourceSet) {
JvmReachabilityMetadataRepositoryExtension repositoryExtension = reachabilityExtensionOn(graalExtension);
Provider<JvmReachabilityMetadataService> serviceProvider = project.getGradle()
GraalVMReachabilityMetadataRepositoryExtension repositoryExtension = reachabilityExtensionOn(graalExtension);
Provider<GraalVMReachabilityMetadataService> serviceProvider = project.getGradle()
.getSharedServices()
.registerIfAbsent("nativeConfigurationService", JvmReachabilityMetadataService.class, spec -> {
.registerIfAbsent("nativeConfigurationService", GraalVMReachabilityMetadataService.class, spec -> {
LogLevel logLevel = determineLogLevel();
spec.getParameters().getLogLevel().set(logLevel);
spec.getParameters().getUri().set(repositoryExtension.getUri());
Expand Down Expand Up @@ -353,8 +354,8 @@ private static LogLevel determineLogLevel() {
return logLevel;
}

private static JvmReachabilityMetadataRepositoryExtension reachabilityExtensionOn(GraalVMExtension graalExtension) {
return ((ExtensionAware) graalExtension).getExtensions().getByType(JvmReachabilityMetadataRepositoryExtension.class);
private static GraalVMReachabilityMetadataRepositoryExtension reachabilityExtensionOn(GraalVMExtension graalExtension) {
return ((ExtensionAware) graalExtension).getExtensions().getByType(GraalVMReachabilityMetadataRepositoryExtension.class);
}

private void deprecateExtension(Project project,
Expand Down Expand Up @@ -419,11 +420,11 @@ private GraalVMExtension registerGraalVMExtension(Project project) {
}

private void configureNativeConfigurationRepo(ExtensionAware graalvmNative) {
JvmReachabilityMetadataRepositoryExtension configurationRepository = graalvmNative.getExtensions().create("metadataRepository", JvmReachabilityMetadataRepositoryExtension.class);
GraalVMReachabilityMetadataRepositoryExtension configurationRepository = graalvmNative.getExtensions().create("metadataRepository", GraalVMReachabilityMetadataRepositoryExtension.class);
configurationRepository.getEnabled().convention(false);
configurationRepository.getUri().convention(configurationRepository.getVersion().map(v -> {
try {
return new URI("https://github.com/graalvm/graalvm-reachability-metadata/releases/download/" + v + "/graalvm-reachability-metadata-" + v + ".zip");
return new URI(String.format(METADATA_REPO_URL_TEMPLATE, v));
} catch (URISyntaxException e) {
return null;
}
Expand Down
Expand Up @@ -49,18 +49,18 @@
import java.net.URISyntaxException;

/**
* Extension used to configure the JVM reachability metadata repository.
* Extension used to configure the GraalVM reachability metadata repository.
*/
public interface JvmReachabilityMetadataRepositoryExtension {
public interface GraalVMReachabilityMetadataRepositoryExtension {
/**
* Property used to determine if the native configuration
* Property used to determine if the reachability metadata
* repository should be used.
* @return the enabled property
*/
Property<Boolean> getEnabled();

/**
* A URI pointing to a jvm reachability metadata repository. This must
* A URI pointing to a GraalVM reachability metadata repository. This must
* either be a local file or a remote URI. In case of remote
* files, only zip or tarballs are supported.
* @return the uri property
Expand All @@ -70,8 +70,8 @@ public interface JvmReachabilityMetadataRepositoryExtension {
/**
* An optional version of the remote repository: if specified,
* and that no URI is provided, it will automatically use a
* published repository from the official GraalVM configuration
* repository.
* published repository from the official GraalVM reachability
* metadata repository.
*
* @return the version of the repository to use
*/
Expand Down
Expand Up @@ -171,6 +171,14 @@ public interface NativeImageOptions extends Named {
@Input
Property<Boolean> getQuickBuild();

/**
* Gets the value which determines if image is being built with rich output.
*
* @return The value which determines if image is being built with rich output.
*/
@Input
Property<Boolean> getRichOutput();

/**
* Returns the toolchain used to invoke native-image. Currently pointing
* to a Java launcher due to Gradle limitations.
Expand Down
Expand Up @@ -44,6 +44,7 @@
import org.graalvm.buildtools.gradle.dsl.NativeImageOptions;
import org.graalvm.buildtools.gradle.dsl.NativeResourcesOptions;
import org.graalvm.buildtools.gradle.dsl.agent.DeprecatedAgentOptions;
import org.graalvm.buildtools.utils.SharedConstants;
import org.gradle.api.Action;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.model.ObjectFactory;
Expand Down Expand Up @@ -186,6 +187,14 @@ public String getName() {
@Input
public abstract Property<Boolean> getQuickBuild();

/**
* Gets the value which determines if image is being built with rich output.
*
* @return The value which determines if image is being built with rich output.
*/
@Input
public abstract Property<Boolean> getRichOutput();

/**
* Returns the toolchain used to invoke native-image. Currently, pointing
* to a Java launcher due to Gradle limitations.
Expand All @@ -195,7 +204,7 @@ public String getName() {
public abstract Property<JavaLauncher> getJavaLauncher();

/**
* Returns the list of configuration file directories (e.g resource-config.json, ...) which need
* Returns the list of configuration file directories (e.g. resource-config.json, ...) which need
* to be passed to native-image.
*
* @return a collection of directories
Expand Down Expand Up @@ -232,14 +241,14 @@ public BaseNativeImageOptions(String name,
getFallback().convention(false);
getVerbose().convention(false);
getQuickBuild().convention(false);
getRichOutput().convention(!SharedConstants.IS_CI && !SharedConstants.IS_WINDOWS && !SharedConstants.IS_DUMB_TERM && !SharedConstants.NO_COLOR);
getSharedLibrary().convention(false);
getImageName().convention(defaultImageName);
getUseFatJar().convention(false);
}

private static Provider<Boolean> property(ProviderFactory providers, String name) {
return providers.gradleProperty(name)
.forUseAtConfigurationTime()
.map(Boolean::valueOf)
.orElse(false);
}
Expand Down
Expand Up @@ -40,7 +40,7 @@
*/
package org.graalvm.buildtools.gradle.internal;

import org.graalvm.reachability.JvmReachabilityMetadataRepository;
import org.graalvm.reachability.GraalVMReachabilityMetadataRepository;
import org.graalvm.reachability.Query;
import org.graalvm.reachability.internal.FileSystemRepository;
import org.gradle.api.file.ArchiveOperations;
Expand All @@ -57,12 +57,12 @@
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.MessageDigest;
Expand All @@ -72,10 +72,10 @@
import java.util.function.Consumer;
import java.util.function.Supplier;

public abstract class JvmReachabilityMetadataService implements BuildService<JvmReachabilityMetadataService.Params>, JvmReachabilityMetadataRepository {
private static final Logger LOGGER = Logging.getLogger(JvmReachabilityMetadataService.class);
public abstract class GraalVMReachabilityMetadataService implements BuildService<GraalVMReachabilityMetadataService.Params>, GraalVMReachabilityMetadataRepository {
private static final Logger LOGGER = Logging.getLogger(GraalVMReachabilityMetadataService.class);

private final JvmReachabilityMetadataRepository repository;
private final GraalVMReachabilityMetadataRepository repository;

@Inject
protected abstract ArchiveOperations getArchiveOperations();
Expand All @@ -91,27 +91,27 @@ public interface Params extends BuildServiceParameters {
DirectoryProperty getCacheDir();
}

public JvmReachabilityMetadataService() throws URISyntaxException {
public GraalVMReachabilityMetadataService() throws URISyntaxException {
URI uri = getParameters().getUri().get();
this.repository = newRepository(uri);
}

private static String hashFor(URI uri) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] messageDigest = md.digest(md.digest(uri.toString().getBytes("utf-8")));
byte[] messageDigest = md.digest(md.digest(uri.toString().getBytes(StandardCharsets.UTF_8)));
BigInteger no = new BigInteger(1, messageDigest);
StringBuilder digest = new StringBuilder(no.toString(16));
while (digest.length() < 32) {
digest.insert(0, "0");
}
return digest.toString();
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
} catch (NoSuchAlgorithmException e) {
throw new UnsupportedOperationException(e);
}
}

private JvmReachabilityMetadataRepository newRepository(URI uri) throws URISyntaxException {
private GraalVMReachabilityMetadataRepository newRepository(URI uri) throws URISyntaxException {
String cacheKey = hashFor(uri);
String path = uri.getPath();
LogLevel logLevel = getParameters().getLogLevel().get();
Expand Down Expand Up @@ -163,11 +163,11 @@ private FileSystemRepository newRepositoryFromDirectory(Path path, LogLevel logL
return new FileSystemRepository(path, new FileSystemRepository.Logger() {
@Override
public void log(String groupId, String artifactId, String version, Supplier<String> message) {
LOGGER.log(logLevel, "[jvm reachability metadata repository for {}:{}:{}]: {}", groupId, artifactId, version, message.get());
LOGGER.log(logLevel, "[graalvm reachability metadata repository for {}:{}:{}]: {}", groupId, artifactId, version, message.get());
}
});
} else {
throw new IllegalArgumentException("JVM reachability metadata repository URI must point to a directory");
throw new IllegalArgumentException("GraalVM reachability metadata repository URI must point to a directory");
}
}

Expand Down
Expand Up @@ -112,6 +112,7 @@ 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");

if (getOutputDirectory().isPresent()) {
cliArgs.add("-H:Path=" + getOutputDirectory().get());
Expand Down