diff --git a/docs/src/docs/asciidoc/gradle-plugin.adoc b/docs/src/docs/asciidoc/gradle-plugin.adoc index 396f75494..2abc253f4 100644 --- a/docs/src/docs/asciidoc/gradle-plugin.adoc +++ b/docs/src/docs/asciidoc/gradle-plugin.adoc @@ -361,14 +361,14 @@ This repository provides https://www.graalvm.org/22.2/reference-manual/native-im NOTE: This version of the plugin defaults to the using the metadata repository in version {metadata-repository-version}. There is nothing for you to configure if you are fine with this version. The repository is also published on Maven Central at the following coordinates: `org.graalvm.buildtools:graalvm-reachability-metadata:graalvm-reachability-metadata` with the `repository` classifier and `zip` extension, e.g. `graalvm-reachability-metadata-{gradle-plugin-version}-repository.zip`. -=== Enabling the metadata repository +=== Configuring the metadata repository -Support needs to be enabled explicitly: +Metadata repository support is enabled by default. Support can be disabled explicitly: -.Enabling the metadata repository +.Disabling the metadata repository [source, groovy, role="multi-language-sample"] ---- -include::../snippets/gradle/groovy/build.gradle[tags=enable-metadata-repository] +include::../snippets/gradle/groovy/build.gradle[tags=disable-metadata-repository] ---- [source, kotlin, role="multi-language-sample"] @@ -403,9 +403,7 @@ include::../snippets/gradle/groovy/build.gradle[tags=specify-metadata-repository include::../snippets/gradle/kotlin/build.gradle.kts[tags=specify-metadata-repository-file] ---- -=== Configuring the metadata repository - -Once activated, for each library included in the native image, the plugin will automatically search for GraalVM reachability metadata in the repository. +For each library included in the native image, the plugin will automatically search for GraalVM image build configuration metadata in the repository. In some cases, you may need to exclude a particular module from the search. This can be done by adding it to the exclude list: diff --git a/docs/src/docs/asciidoc/index.adoc b/docs/src/docs/asciidoc/index.adoc index fd18357a1..365556154 100644 --- a/docs/src/docs/asciidoc/index.adoc +++ b/docs/src/docs/asciidoc/index.adoc @@ -19,6 +19,17 @@ If you are using alternative build systems, see <` element: +Metadata repository is enabled by default. Support can be disabled by including the following into the `` element: -.Enabling the metadata repository +.Disabling the metadata repository [source,xml,indent=0] ---- -include::../../../../samples/metadata-repo-integration/pom.xml[tag=metadata-default] +include::../../../../samples/metadata-repo-integration/pom.xml[tag=metadata-disable] ---- Alternatively, you can use a _remote repository_, in which case you can specify the URL of the ZIP file: @@ -658,10 +658,8 @@ include::../../../../samples/native-config-integration/pom.xml[tag=metadata-loca ---- <1> The local path can point to an _exploded_ directory, or to a compressed ZIP file. -=== Configuring the metadata repository - -Once activated, for each library included in the native image, the plugin will automatically search for GraalVM reachability metadata in the repository that was released together with the plugin. -In case you want to use another verion of the metadata use: +For each library included in the native image, the plugin will automatically search for GraalVM image build configuration metadata in the repository that was released together with the plugin. +In case you want to use another version of the metadata use: .Choosing a version for the metadata repository [source,xml,indent=0] diff --git a/docs/src/docs/snippets/gradle/groovy/build.gradle b/docs/src/docs/snippets/gradle/groovy/build.gradle index aef5ca687..8f2e3dc6f 100644 --- a/docs/src/docs/snippets/gradle/groovy/build.gradle +++ b/docs/src/docs/snippets/gradle/groovy/build.gradle @@ -166,13 +166,13 @@ graalvmNative { } // end::disable-test-support[] -// tag::enable-metadata-repository[] +// tag::disable-metadata-repository[] graalvmNative { metadataRepository { - enabled = true + enabled = false } } -// end::enable-metadata-repository[] +// end::disable-metadata-repository[] // tag::specify-metadata-repository-version[] graalvmNative { diff --git a/native-gradle-plugin/src/functionalTest/groovy/org/graalvm/buildtools/gradle/OfficialMetadataRepoFunctionalTest.groovy b/native-gradle-plugin/src/functionalTest/groovy/org/graalvm/buildtools/gradle/OfficialMetadataRepoFunctionalTest.groovy index c00b9fc47..79c543bd8 100644 --- a/native-gradle-plugin/src/functionalTest/groovy/org/graalvm/buildtools/gradle/OfficialMetadataRepoFunctionalTest.groovy +++ b/native-gradle-plugin/src/functionalTest/groovy/org/graalvm/buildtools/gradle/OfficialMetadataRepoFunctionalTest.groovy @@ -46,7 +46,7 @@ import org.gradle.api.logging.LogLevel class OfficialMetadataRepoFunctionalTest extends AbstractFunctionalTest { - def "the application runs when using the official metadata repository"() { + def "the application runs when using the official metadata repository by default"() { given: withSample("metadata-repo-integration") debug = true @@ -65,4 +65,18 @@ class OfficialMetadataRepoFunctionalTest extends AbstractFunctionalTest { outputDoesNotContain "Falling back to the default repository at" } + def "the application doesn't run when usage of the official metadata repository is disabled"() { + given: + withSample("metadata-repo-integration") + debug = true + + when: + run 'nativeRun', "-Pmetadata.repo.enabled=false", "-D${NativeImagePlugin.CONFIG_REPO_LOGLEVEL}=${LogLevel.LIFECYCLE}" + + then: + tasks { + failed ':nativeCompile' + } + } + } diff --git a/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/NativeImagePlugin.java b/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/NativeImagePlugin.java index a23976514..dc4ca181f 100644 --- a/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/NativeImagePlugin.java +++ b/native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/NativeImagePlugin.java @@ -585,7 +585,7 @@ private GraalVMExtension registerGraalVMExtension(Project project) { private void configureNativeConfigurationRepo(ExtensionAware graalvmNative) { GraalVMReachabilityMetadataRepositoryExtension configurationRepository = graalvmNative.getExtensions().create("metadataRepository", GraalVMReachabilityMetadataRepositoryExtension.class); - configurationRepository.getEnabled().convention(false); + configurationRepository.getEnabled().convention(true); configurationRepository.getVersion().convention(VersionInfo.METADATA_REPO_VERSION); configurationRepository.getUri().convention(configurationRepository.getVersion().map(serializableTransformerOf(this::getReachabilityMetadataRepositoryUrlForVersion))); configurationRepository.getExcludedModules().convention(Collections.emptySet()); diff --git a/native-gradle-plugin/src/testFixtures/groovy/org/graalvm/buildtools/gradle/fixtures/AbstractFunctionalTest.groovy b/native-gradle-plugin/src/testFixtures/groovy/org/graalvm/buildtools/gradle/fixtures/AbstractFunctionalTest.groovy index 810dc3ee3..f48277344 100644 --- a/native-gradle-plugin/src/testFixtures/groovy/org/graalvm/buildtools/gradle/fixtures/AbstractFunctionalTest.groovy +++ b/native-gradle-plugin/src/testFixtures/groovy/org/graalvm/buildtools/gradle/fixtures/AbstractFunctionalTest.groovy @@ -269,6 +269,13 @@ abstract class AbstractFunctionalTest extends Specification { } } + void failed(String... tasks) { + tasks.each { task -> + contains(task) + assert result.task(task).outcome == TaskOutcome.FAILED + } + } + void skipped(String... tasks) { tasks.each { task -> contains(task) diff --git a/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/MetadataRepositoryFunctionalTest.groovy b/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/MetadataRepositoryFunctionalTest.groovy index abc06cc30..341e50f7e 100644 --- a/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/MetadataRepositoryFunctionalTest.groovy +++ b/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/MetadataRepositoryFunctionalTest.groovy @@ -87,7 +87,7 @@ class MetadataRepositoryFunctionalTest extends AbstractGraalVMMavenFunctionalTes outputContains NATIVE_IMAGE_EXE + " --exclude-config dummy/path/to/file.jar \"*\"" } - void "if the path doesn't exist it throws an error"() { + void "if the path doesn't exist, the repository cannot be pulled"() { given: withSample("native-config-integration") @@ -95,9 +95,8 @@ class MetadataRepositoryFunctionalTest extends AbstractGraalVMMavenFunctionalTes mvn '-Pnative,metadataMissing', '-DquickBuild', '-DskipTests', 'package', 'exec:exec@native' then: - buildSucceeded - outputContains "GraalVM reachability metadata repository path does not exist" - outputContains "Reflection failed" + buildFailed + outputContains "Cannot pull GraalVM reachability metadata repository either from the one specified in the configuration or the default one" } void "it can exclude dependencies"() { @@ -163,7 +162,7 @@ class MetadataRepositoryFunctionalTest extends AbstractGraalVMMavenFunctionalTes outputContains "[graalvm reachability metadata repository for org.graalvm.internal:library-with-reflection:1.5]: Configuration directory is org.graalvm.internal" + File.separator + "library-with-reflection" + File.separator + "1" } - void "when pointing to a missing URL, reflection fails"() { + void "when pointing to a missing URL, the repository cannot be pulled"() { given: withSample("native-config-integration") withLocalServer() @@ -172,9 +171,8 @@ class MetadataRepositoryFunctionalTest extends AbstractGraalVMMavenFunctionalTes mvn '-Pnative,metadataUrl', '-DquickBuild', "-Dmetadata.url=https://google.com/notfound", '-DskipTests', 'package', 'exec:exec@native' then: - buildSucceeded - outputContains "Reflection failed" - outputContains "Failed to download from https://google.com/notfound: 404 Not Found" + buildFailed + outputContains "Cannot pull GraalVM reachability metadata repository either from the one specified in the configuration or the default one" } void "it can include hints in jar"() { diff --git a/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/OfficialMetadataRepositoryFunctionalTest.groovy b/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/OfficialMetadataRepositoryFunctionalTest.groovy index d289175f7..c386d09df 100644 --- a/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/OfficialMetadataRepositoryFunctionalTest.groovy +++ b/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/OfficialMetadataRepositoryFunctionalTest.groovy @@ -44,6 +44,7 @@ package org.graalvm.buildtools.maven import spock.lang.IgnoreIf class OfficialMetadataRepositoryFunctionalTest extends AbstractGraalVMMavenFunctionalTest { + @IgnoreIf({ os.windows }) void "the application runs when using the official metadata repository"() { given: @@ -82,4 +83,35 @@ class OfficialMetadataRepositoryFunctionalTest extends AbstractGraalVMMavenFunct outputContains "[graalvm reachability metadata repository for com.h2database:h2:" outputContains "Configuration directory is com.h2database" + File.separator + "h2" + File.separator } + + @IgnoreIf({ os.windows }) + void "the application uses specified version of metadata repository without explicit enable"() { + given: + withSample("metadata-repo-integration") + + when: + mvn '-PenableMetadataByDefault', '-DquickBuild', '-DskipTests', 'package', 'exec:exec@native' + + then: + buildSucceeded + + and: "the run succeeded and retrieved data from the database" + outputContains "Customers in the database" + + and: "finds metadata in the remote repository" + outputContains "[graalvm reachability metadata repository for com.h2database:h2:" + outputContains "Configuration directory is com.h2database" + File.separator + "h2" + File.separator + } + + @IgnoreIf({ os.windows }) + void "the application doesn't run when metadata repository is disabled"() { + given: + withSample("metadata-repo-integration") + + when: + mvn '-PdisabledMetadataRepo', '-DquickBuild', '-DskipTests', 'package', 'exec:exec@native' + + then: + buildFailed + } } diff --git a/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/AbstractNativeMojo.java b/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/AbstractNativeMojo.java index 78ee005ef..bfe70a5d5 100644 --- a/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/AbstractNativeMojo.java +++ b/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/AbstractNativeMojo.java @@ -123,78 +123,112 @@ protected AbstractNativeMojo() { } protected boolean isMetadataRepositoryEnabled() { - return metadataRepositoryConfiguration != null && metadataRepositoryConfiguration.isEnabled(); + return metadataRepositoryConfiguration == null || metadataRepositoryConfiguration.isEnabled(); } protected void configureMetadataRepository() { - if (isMetadataRepositoryEnabled()) { - Path repoPath = null; - Path destinationRoot = reachabilityMetadataOutputDirectory.toPath(); - if (Files.exists(destinationRoot) && !Files.isDirectory(destinationRoot)) { - throw new RuntimeException("Metadata repository must be a directory, please remove regular file at: " + destinationRoot); - } + if (!isMetadataRepositoryEnabled()) { + logger.warn("GraalVM reachability metadata repository is disabled"); + return; + } + + Path destinationRoot = reachabilityMetadataOutputDirectory.toPath(); + if (Files.exists(destinationRoot) && !Files.isDirectory(destinationRoot)) { + throw new RuntimeException("Metadata repository must be a directory, please remove regular file at: " + destinationRoot); + } + try { + Files.createDirectories(destinationRoot); + } catch (IOException e) { + throw new RuntimeException(e); + } + + Path repoPath = metadataRepositoryConfiguration != null ? getRepo(destinationRoot) : getDefaultRepo(destinationRoot); + if (repoPath == null) { + throw new RuntimeException("Cannot pull GraalVM reachability metadata repository either from the one specified in the configuration or the default one.\n" + + "Note: Since the repository is enabled by default, you can disable it manually in your pom.xml file (see this: " + + "https://graalvm.github.io/native-build-tools/latest/maven-plugin.html#_configuring_the_metadata_repository)"); + } else { + metadataRepository = new FileSystemRepository(repoPath, new FileSystemRepository.Logger() { + @Override + public void log(String groupId, String artifactId, String version, Supplier message) { + logger.info(String.format("[graalvm reachability metadata repository for %s:%s:%s]: %s", groupId, artifactId, version, message.get())); + } + }); + } + } + + private Path getDefaultRepo(Path destinationRoot) { + // try to get default Metadata Repository from Maven Central + URL targetUrl = resolveDefaultMetadataRepositoryUrl(); + if (targetUrl == null) { + logger.warn("Unable to find the GraalVM reachability metadata repository in Maven repository. " + + "Falling back to the default repository."); + String metadataUrl = String.format(METADATA_REPO_URL_TEMPLATE, VersionInfo.METADATA_REPO_VERSION); try { - Files.createDirectories(destinationRoot); - } catch (IOException e) { + targetUrl = new URI(metadataUrl).toURL(); + // TODO investigate if the following line is necessary (Issue: https://github.com/graalvm/native-build-tools/issues/560) + metadataRepositoryConfiguration.setUrl(targetUrl); + } catch (URISyntaxException | MalformedURLException e) { throw new RuntimeException(e); } + } - if (metadataRepositoryConfiguration.getLocalPath() != null) { - Path localPath = metadataRepositoryConfiguration.getLocalPath().toPath(); - Path destination = destinationRoot.resolve(FileUtils.hashFor(localPath.toUri())); - repoPath = unzipLocalMetadata(localPath, destination); - } else { - URL targetUrl = metadataRepositoryConfiguration.getUrl(); - if (targetUrl == null) { - String version = metadataRepositoryConfiguration.getVersion(); - if (version == null) { - // Both the URL and version are unset, so we want to use - // the version from Maven Central - targetUrl = resolveDefaultMetadataRepositoryUrl(); - if (targetUrl == null) { - logger.warn("Unable to find the GraalVM reachability metadata repository in Maven repository. " + - "Falling back to the default repository."); - version = VersionInfo.METADATA_REPO_VERSION; - } - } - if (version != null) { - String metadataUrl = String.format(METADATA_REPO_URL_TEMPLATE, version); - try { - targetUrl = new URI(metadataUrl).toURL(); - metadataRepositoryConfiguration.setUrl(targetUrl); - } catch (URISyntaxException | MalformedURLException e) { - throw new RuntimeException(e); - } + return downloadMetadataRepo(destinationRoot, targetUrl); + } + + private Path getRepo(Path destinationRoot) { + if (metadataRepositoryConfiguration.getLocalPath() != null) { + Path localPath = metadataRepositoryConfiguration.getLocalPath().toPath(); + Path destination = destinationRoot.resolve(FileUtils.hashFor(localPath.toUri())); + return unzipLocalMetadata(localPath, destination); + } else { + URL targetUrl = metadataRepositoryConfiguration.getUrl(); + if (targetUrl == null) { + String version = metadataRepositoryConfiguration.getVersion(); + if (version == null) { + // Both the URL and version are unset, so we want to use + // the version from Maven Central + targetUrl = resolveDefaultMetadataRepositoryUrl(); + if (targetUrl == null) { + logger.warn("Unable to find the GraalVM reachability metadata repository in Maven repository. " + + "Falling back to the default repository."); + version = VersionInfo.METADATA_REPO_VERSION; } } - Path destination; - try { - destination = destinationRoot.resolve(FileUtils.hashFor(targetUrl.toURI())); - } catch (URISyntaxException e) { - throw new RuntimeException(e); - } - if (Files.exists(destination)) { - repoPath = destination; - } else { - Optional download = downloadMetadata(targetUrl, destination); - if (download.isPresent()) { - logger.info("Downloaded GraalVM reachability metadata repository from " + targetUrl); - repoPath = unzipLocalMetadata(download.get(), destination); + if (version != null) { + String metadataUrl = String.format(METADATA_REPO_URL_TEMPLATE, version); + try { + targetUrl = new URI(metadataUrl).toURL(); + // TODO investigate if the following line is necessary (Issue: https://github.com/graalvm/native-build-tools/issues/560) + metadataRepositoryConfiguration.setUrl(targetUrl); + } catch (URISyntaxException | MalformedURLException e) { + throw new RuntimeException(e); } } } - if (repoPath == null) { - logger.warn("GraalVM reachability metadata repository is enabled, but no repository has been configured"); - } else { - metadataRepository = new FileSystemRepository(repoPath, new FileSystemRepository.Logger() { - @Override - public void log(String groupId, String artifactId, String version, Supplier message) { - logger.info(String.format("[graalvm reachability metadata repository for %s:%s:%s]: %s", groupId, artifactId, version, message.get())); - } - }); + return downloadMetadataRepo(destinationRoot, targetUrl); + } + } + + private Path downloadMetadataRepo(Path destinationRoot, URL targetUrl) { + Path destination; + try { + destination = destinationRoot.resolve(FileUtils.hashFor(targetUrl.toURI())); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + if (Files.exists(destination)) { + return destination; + } else { + Optional download = downloadMetadata(targetUrl, destination); + if (download.isPresent()) { + logger.info("Downloaded GraalVM reachability metadata repository from " + targetUrl); + return unzipLocalMetadata(download.get(), destination); } } + + return null; } /** diff --git a/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/config/MetadataRepositoryConfiguration.java b/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/config/MetadataRepositoryConfiguration.java index d63610721..66b1aa5ed 100644 --- a/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/config/MetadataRepositoryConfiguration.java +++ b/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/config/MetadataRepositoryConfiguration.java @@ -53,8 +53,8 @@ public class MetadataRepositoryConfiguration { - @Parameter(defaultValue = "false") - private boolean enabled; + @Parameter(defaultValue = "true") + private boolean enabled = true; @Parameter private String version; diff --git a/samples/metadata-repo-integration/build.gradle b/samples/metadata-repo-integration/build.gradle index 863a42bc8..89aaa3201 100644 --- a/samples/metadata-repo-integration/build.gradle +++ b/samples/metadata-repo-integration/build.gradle @@ -71,7 +71,9 @@ graalvmNative { defaultMode = "standard" } metadataRepository { - enabled = true + if (providers.gradleProperty("metadata.repo.enabled").isPresent()) { + enabled = providers.gradleProperty("metadata.repo.enabled").map { value -> value.toBoolean()} + } } binaries.all { verbose = true diff --git a/samples/metadata-repo-integration/pom.xml b/samples/metadata-repo-integration/pom.xml index fb976562a..e369b66d8 100644 --- a/samples/metadata-repo-integration/pom.xml +++ b/samples/metadata-repo-integration/pom.xml @@ -94,6 +94,28 @@ native + + + + org.graalvm.buildtools + native-maven-plugin + ${native.maven.plugin.version} + true + + + build-native + + compile-no-fork + + package + + + + + + + + nativeVersioned @@ -111,18 +133,48 @@ - + true + 0.2.3 - + - nativeVersioned + disabledMetadataRepo + + + + org.graalvm.buildtools + native-maven-plugin + ${native.maven.plugin.version} + true + + + build-native + + compile-no-fork + + package + + + + + + false + + + + + + + + + enableMetadataByDefault @@ -140,12 +192,9 @@ - - true 0.2.3 -