From 5d8f55ce2dc6003bd0529f9660b97c06d5c05176 Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Fri, 22 Oct 2021 14:44:55 +0200 Subject: [PATCH] Fix Native configuration not applied on modules This commit fixes a bug in the Maven plugin, when the extension is declared in a parent POM: the configuration wouldn't be applied to subprojects which use the plugin. Fixes #144 --- build.gradle.kts | 25 +++- docs/src/docs/asciidoc/index.adoc | 6 + ....build.maven-functional-testing.gradle.kts | 1 + .../reproducers/issue-144/child/pom.xml | 55 +++++++ .../java/org/graalvm/demo/Application.java | 11 ++ .../java/org/graalvm/demo/Calculator.java | 9 ++ .../java/org/graalvm/demo/CalculatorTest.java | 38 +++++ .../reproducers/issue-144/pom.xml | 134 ++++++++++++++++++ ...WithTestsAndParentPomFunctionalTest.groovy | 72 ++++++++++ .../buildtools/maven/NativeExtension.java | 97 +++++++------ .../AbstractGraalVMMavenFunctionalTest.groovy | 5 + 11 files changed, 400 insertions(+), 53 deletions(-) create mode 100644 native-maven-plugin/reproducers/issue-144/child/pom.xml create mode 100644 native-maven-plugin/reproducers/issue-144/child/src/main/java/org/graalvm/demo/Application.java create mode 100644 native-maven-plugin/reproducers/issue-144/child/src/main/java/org/graalvm/demo/Calculator.java create mode 100644 native-maven-plugin/reproducers/issue-144/child/src/test/java/org/graalvm/demo/CalculatorTest.java create mode 100644 native-maven-plugin/reproducers/issue-144/pom.xml create mode 100644 native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/issues/JavaAppWithTestsAndParentPomFunctionalTest.groovy diff --git a/build.gradle.kts b/build.gradle.kts index 80417ea98..fa5b53ee5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -105,15 +105,26 @@ tasks.register("releaseZip") { } } -tasks.register("updateSamples") { - inputDirectory.set(layout.projectDirectory.dir("samples")) - versions.put("native.gradle.plugin.version", libs.versions.nativeBuildTools.get()) - versions.put("native.maven.plugin.version", libs.versions.nativeBuildTools.get()) - versions.put("junit.jupiter.version", libs.versions.junitJupiter.get()) - versions.put("junit.platform.version", libs.versions.junitPlatform.get()) - versions.put("junit.platform.native.version", libs.versions.nativeBuildTools.get()) +val updateSamples by tasks.registering + +mapOf( + "updateSamplesDir" to "samples", + "updateMavenReprosDir" to "native-maven-plugin/reproducers" +).forEach { taskName, dir -> + val t = tasks.register(taskName) { + inputDirectory.set(layout.projectDirectory.dir(dir)) + versions.put("native.gradle.plugin.version", libs.versions.nativeBuildTools.get()) + versions.put("native.maven.plugin.version", libs.versions.nativeBuildTools.get()) + versions.put("junit.jupiter.version", libs.versions.junitJupiter.get()) + versions.put("junit.platform.version", libs.versions.junitPlatform.get()) + versions.put("junit.platform.native.version", libs.versions.nativeBuildTools.get()) + } + updateSamples.configure { + dependsOn(t) + } } + val cloneSnapshots = tasks.register("cloneSnapshotRepository") { repositoryUri.set("git@github.com:graalvm/native-build-tools.git") // repositoryUri.set(file(".").absolutePath) diff --git a/docs/src/docs/asciidoc/index.adoc b/docs/src/docs/asciidoc/index.adoc index acbb8d834..4b64040ab 100644 --- a/docs/src/docs/asciidoc/index.adoc +++ b/docs/src/docs/asciidoc/index.adoc @@ -15,6 +15,12 @@ If you are interested in contributing, please refer to our https://github.com/gr [[changelog]] == Changelog +=== Release 0.9.7 + +==== Bugfixes + +- Fixed https://github.com/graalvm/native-build-tools/issues/144[Maven plugin configuration not applied if declared in a parent POM]. + === Release 0.9.6 ==== Upgrade to JUnit 5.8 diff --git a/native-maven-plugin/build-plugins/src/main/kotlin/org.graalvm.build.maven-functional-testing.gradle.kts b/native-maven-plugin/build-plugins/src/main/kotlin/org.graalvm.build.maven-functional-testing.gradle.kts index ca4421b91..2f9d8d408 100644 --- a/native-maven-plugin/build-plugins/src/main/kotlin/org.graalvm.build.maven-functional-testing.gradle.kts +++ b/native-maven-plugin/build-plugins/src/main/kotlin/org.graalvm.build.maven-functional-testing.gradle.kts @@ -71,6 +71,7 @@ configurations { tasks.register("functionalTest") { // Any change to samples invalidates functional tests inputs.files(files("../samples")) + inputs.files(files("reproducers")) inputs.files(functionalTestCommonRepository) systemProperty("common.repo.url", functionalTestCommonRepository.incoming.files.files.first()) testClassesDirs = functionalTest.output.classesDirs diff --git a/native-maven-plugin/reproducers/issue-144/child/pom.xml b/native-maven-plugin/reproducers/issue-144/child/pom.xml new file mode 100644 index 000000000..d5c64d229 --- /dev/null +++ b/native-maven-plugin/reproducers/issue-144/child/pom.xml @@ -0,0 +1,55 @@ + + + + + + org.graalvm.buildtools.examples + maven + 1.0.0-SNAPSHOT + + 4.0.0 + + child + + diff --git a/native-maven-plugin/reproducers/issue-144/child/src/main/java/org/graalvm/demo/Application.java b/native-maven-plugin/reproducers/issue-144/child/src/main/java/org/graalvm/demo/Application.java new file mode 100644 index 000000000..27820c4b5 --- /dev/null +++ b/native-maven-plugin/reproducers/issue-144/child/src/main/java/org/graalvm/demo/Application.java @@ -0,0 +1,11 @@ +package org.graalvm.demo; + +public class Application { + static String getMessage() { + return "Hello, native!"; + } + + public static void main(String[] args) { + System.out.println(getMessage()); + } +} diff --git a/native-maven-plugin/reproducers/issue-144/child/src/main/java/org/graalvm/demo/Calculator.java b/native-maven-plugin/reproducers/issue-144/child/src/main/java/org/graalvm/demo/Calculator.java new file mode 100644 index 000000000..41e072c9b --- /dev/null +++ b/native-maven-plugin/reproducers/issue-144/child/src/main/java/org/graalvm/demo/Calculator.java @@ -0,0 +1,9 @@ +package org.graalvm.demo; + +public class Calculator { + + public int add(int a, int b) { + return a + b; + } + +} diff --git a/native-maven-plugin/reproducers/issue-144/child/src/test/java/org/graalvm/demo/CalculatorTest.java b/native-maven-plugin/reproducers/issue-144/child/src/test/java/org/graalvm/demo/CalculatorTest.java new file mode 100644 index 000000000..842385862 --- /dev/null +++ b/native-maven-plugin/reproducers/issue-144/child/src/test/java/org/graalvm/demo/CalculatorTest.java @@ -0,0 +1,38 @@ +package org.graalvm.demo; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class CalculatorTest { + + @Test + @DisplayName("1 + 1 = 2") + void addsTwoNumbers() { + Calculator calculator = new Calculator(); + assertEquals(2, calculator.add(1, 1), "1 + 1 should equal 2"); + } + + @Test + @DisplayName("1 + 2 = 3") + void addsTwoNumbers2() { + Calculator calculator = new Calculator(); + assertEquals(3, calculator.add(1, 2), "1 + 2 should equal 3"); + } + + @ParameterizedTest(name = "{0} + {1} = {2}") + @CsvSource({ + "0, 1, 1", + "1, 2, 3", + "49, 51, 100", + "1, 100, 101" + }) + void add(int first, int second, int expectedResult) { + Calculator calculator = new Calculator(); + assertEquals(expectedResult, calculator.add(first, second), + () -> first + " + " + second + " should equal " + expectedResult); + } +} diff --git a/native-maven-plugin/reproducers/issue-144/pom.xml b/native-maven-plugin/reproducers/issue-144/pom.xml new file mode 100644 index 000000000..2cdfb88df --- /dev/null +++ b/native-maven-plugin/reproducers/issue-144/pom.xml @@ -0,0 +1,134 @@ + + + + + 4.0.0 + + org.graalvm.buildtools.examples + maven + 1.0.0-SNAPSHOT + pom + + + child + + + + 1.8 + UTF-8 + 0.9.7-SNAPSHOT + 0.9.7-SNAPSHOT + example-app + org.graalvm.demo.Application + + + + + org.junit.jupiter + junit-jupiter + ${junit.jupiter.version} + test + + + + + + native + + + + org.graalvm.buildtools + native-maven-plugin + ${native.maven.plugin.version} + true + + + test-native + + test + + test + + + build-native + + build + + package + + + + false + ${imageName} + + --no-fallback + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + ${java.version} + 1.8 + + + true + ${mainClass} + + + + + + + + + + + diff --git a/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/issues/JavaAppWithTestsAndParentPomFunctionalTest.groovy b/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/issues/JavaAppWithTestsAndParentPomFunctionalTest.groovy new file mode 100644 index 000000000..12c9330cd --- /dev/null +++ b/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/issues/JavaAppWithTestsAndParentPomFunctionalTest.groovy @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2020, 2021 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.graalvm.buildtools.maven.issues + +import org.graalvm.buildtools.maven.AbstractGraalVMMavenFunctionalTest + +class JavaAppWithTestsAndParentPomFunctionalTest extends AbstractGraalVMMavenFunctionalTest { + def "can run tests in a native image with the Maven plugin"() { + withReproducer("issue-144") + + when: + mvn '-Pnative', 'test' + + then: + buildSucceeded + outputContains "[junit-platform-native] Running in 'test listener' mode" + outputContains """ +[ 3 containers found ] +[ 0 containers skipped ] +[ 3 containers started ] +[ 0 containers aborted ] +[ 3 containers successful ] +[ 0 containers failed ] +[ 6 tests found ] +[ 0 tests skipped ] +[ 6 tests started ] +[ 0 tests aborted ] +[ 6 tests successful ] +[ 0 tests failed ] +""".trim() + } + +} diff --git a/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/NativeExtension.java b/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/NativeExtension.java index b840e906c..e32306e45 100644 --- a/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/NativeExtension.java +++ b/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/NativeExtension.java @@ -47,6 +47,7 @@ import org.apache.maven.model.Plugin; import org.apache.maven.model.PluginExecution; import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.project.MavenProject; import org.codehaus.plexus.component.annotations.Component; import org.codehaus.plexus.util.xml.Xpp3Dom; import org.graalvm.buildtools.Utils; @@ -86,52 +87,56 @@ private static String agentOutputDirectoryFor(String context, String baseDir) { @Override public void afterProjectsRead(MavenSession session) throws MavenExecutionException { - Build build = session.getCurrentProject().getBuild(); - boolean hasAgent = hasAgent(session); - String target = build.getDirectory(); - String testIdsDir = testIdsDirectory(target); - withPlugin(build, "maven-surefire-plugin", surefirePlugin -> { - configureJunitListener(surefirePlugin, testIdsDir); - if (hasAgent) { - configureAgentForSurefire(surefirePlugin, "test", target); - } - }); - if (hasAgent) { - withPlugin(build, "exec-maven-plugin", execPlugin -> - updatePluginConfiguration(execPlugin, (exec, config) -> { - if ("java-agent".equals(exec.getId())) { - Xpp3Dom commandlineArgs = findOrAppend(config, "arguments"); - Xpp3Dom[] arrayOfChildren = commandlineArgs.getChildren(); - for (int i = 0; i < arrayOfChildren.length; i++) { - commandlineArgs.removeChild(0); - } - List children = new ArrayList<>(); - Collections.addAll(children, arrayOfChildren); - Xpp3Dom arg = new Xpp3Dom("argument"); - arg.setValue(buildAgentOption("exec", target)); - children.add(0, arg); - arg = new Xpp3Dom("argument"); - arg.setValue("-D" + NATIVEIMAGE_IMAGECODE + "=agent"); - children.add(1, arg); - for (Xpp3Dom child : children) { - commandlineArgs.addChild(child); - } - Xpp3Dom executable = findOrAppend(config, "executable"); - try { - executable.setValue(Utils.getNativeImage().getParent().resolve("java").toString()); - } catch (MojoExecutionException e) { - throw new RuntimeException(e); - } - } - }) - ); - withPlugin(build, "native-maven-plugin", nativePlugin -> - updatePluginConfiguration(nativePlugin, (exec, configuration) -> { - String context = exec.getGoals().stream().anyMatch("test"::equals) ? "test" : "exec"; - Xpp3Dom agentResourceDirectory = findOrAppend(configuration, "agentResourceDirectory"); - agentResourceDirectory.setValue(agentOutputDirectoryFor(context, target)); - }) - ); + for (MavenProject project : session.getProjects()) { + Build build = project.getBuild(); + boolean hasAgent = hasAgent(session); + String target = build.getDirectory(); + String testIdsDir = testIdsDirectory(target); + withPlugin(build, "native-maven-plugin", onlyApplyWhenNativePluginPresent -> { + withPlugin(build, "maven-surefire-plugin", surefirePlugin -> { + configureJunitListener(surefirePlugin, testIdsDir); + if (hasAgent) { + configureAgentForSurefire(surefirePlugin, "test", target); + } + }); + if (hasAgent) { + withPlugin(build, "exec-maven-plugin", execPlugin -> + updatePluginConfiguration(execPlugin, (exec, config) -> { + if ("java-agent".equals(exec.getId())) { + Xpp3Dom commandlineArgs = findOrAppend(config, "arguments"); + Xpp3Dom[] arrayOfChildren = commandlineArgs.getChildren(); + for (int i = 0; i < arrayOfChildren.length; i++) { + commandlineArgs.removeChild(0); + } + List children = new ArrayList<>(); + Collections.addAll(children, arrayOfChildren); + Xpp3Dom arg = new Xpp3Dom("argument"); + arg.setValue(buildAgentOption("exec", target)); + children.add(0, arg); + arg = new Xpp3Dom("argument"); + arg.setValue("-D" + NATIVEIMAGE_IMAGECODE + "=agent"); + children.add(1, arg); + for (Xpp3Dom child : children) { + commandlineArgs.addChild(child); + } + Xpp3Dom executable = findOrAppend(config, "executable"); + try { + executable.setValue(Utils.getNativeImage().getParent().resolve("java").toString()); + } catch (MojoExecutionException e) { + throw new RuntimeException(e); + } + } + }) + ); + withPlugin(build, "native-maven-plugin", nativePlugin -> + updatePluginConfiguration(nativePlugin, (exec, configuration) -> { + String context = exec.getGoals().stream().anyMatch("test"::equals) ? "test" : "exec"; + Xpp3Dom agentResourceDirectory = findOrAppend(configuration, "agentResourceDirectory"); + agentResourceDirectory.setValue(agentOutputDirectoryFor(context, target)); + }) + ); + } + }); } } diff --git a/native-maven-plugin/src/testFixtures/groovy/org/graalvm/buildtools/maven/AbstractGraalVMMavenFunctionalTest.groovy b/native-maven-plugin/src/testFixtures/groovy/org/graalvm/buildtools/maven/AbstractGraalVMMavenFunctionalTest.groovy index 875ced5df..45fe7d941 100644 --- a/native-maven-plugin/src/testFixtures/groovy/org/graalvm/buildtools/maven/AbstractGraalVMMavenFunctionalTest.groovy +++ b/native-maven-plugin/src/testFixtures/groovy/org/graalvm/buildtools/maven/AbstractGraalVMMavenFunctionalTest.groovy @@ -72,6 +72,11 @@ abstract class AbstractGraalVMMavenFunctionalTest extends Specification { executor.debug = true } + protected void withReproducer(String name) { + File sampleDir = new File("reproducers/$name") + copySample(sampleDir.toPath(), testDirectory) + } + protected void withSample(String name) { File sampleDir = new File("../samples/$name") copySample(sampleDir.toPath(), testDirectory)