diff --git a/docs/src/docs/asciidoc/index.adoc b/docs/src/docs/asciidoc/index.adoc index 3ff1fc8e4..e4c20f0b7 100644 --- a/docs/src/docs/asciidoc/index.adoc +++ b/docs/src/docs/asciidoc/index.adoc @@ -16,17 +16,26 @@ If you are using alternative build systems, see <.ja specified in the `` node of the plugin. When `mvn -Pnative package` completes, an executable is ready for use, generated in the `target` directory of the project. +NOTE: Building native image without attaching to the `package` phase can be done by invoking the forking `compile` goal directly, e.g. `mvn native:compile` + [TIP] .Testing pre-releases ==== diff --git a/native-maven-plugin/build-plugins/src/main/java/org/graalvm/build/maven/MavenTask.java b/native-maven-plugin/build-plugins/src/main/java/org/graalvm/build/maven/MavenTask.java index a5a8842c3..cdb97ac6e 100644 --- a/native-maven-plugin/build-plugins/src/main/java/org/graalvm/build/maven/MavenTask.java +++ b/native-maven-plugin/build-plugins/src/main/java/org/graalvm/build/maven/MavenTask.java @@ -90,12 +90,12 @@ protected void executeMaven() { spec.setClasspath(getMavenEmbedderClasspath()); spec.getMainClass().set("org.apache.maven.cli.MavenCli"); spec.systemProperty("maven.multiModuleProjectDirectory", projectdir.getAbsolutePath()); + spec.systemProperty("org.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener", "warn"); prepareSpec(spec); List arguments = new ArrayList<>(); arguments.addAll(Arrays.asList( "--errors", "-U", - "-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn", "--batch-mode", "--settings", settingsFile.getAbsolutePath(), "--file", pomFile.getAbsolutePath() diff --git a/native-maven-plugin/build.gradle.kts b/native-maven-plugin/build.gradle.kts index 6ec3e59af..5fdf8c481 100644 --- a/native-maven-plugin/build.gradle.kts +++ b/native-maven-plugin/build.gradle.kts @@ -63,6 +63,7 @@ dependencies { implementation(libs.utils) implementation(libs.jackson.databind) implementation(libs.jvmReachabilityMetadata) + implementation(libs.graalvm.svm) compileOnly(libs.maven.pluginApi) compileOnly(libs.maven.core) diff --git a/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/JavaApplicationFunctionalTest.groovy b/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/JavaApplicationFunctionalTest.groovy index 021b3a16f..8f08c22b0 100644 --- a/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/JavaApplicationFunctionalTest.groovy +++ b/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/JavaApplicationFunctionalTest.groovy @@ -100,7 +100,7 @@ class JavaApplicationFunctionalTest extends AbstractGraalVMMavenFunctionalTest { withSample("java-application-with-custom-packaging") when: - mvn 'package', '-Dpackaging=native-image', 'exec:exec@native' + mvnDebug 'package', '-Dpackaging=native-image', 'exec:exec@native' then: buildSucceeded diff --git a/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/JavaApplicationWithAgentFunctionalTest.groovy b/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/JavaApplicationWithAgentFunctionalTest.groovy index cff916220..a0db0dcf8 100644 --- a/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/JavaApplicationWithAgentFunctionalTest.groovy +++ b/native-maven-plugin/src/functionalTest/groovy/org/graalvm/buildtools/maven/JavaApplicationWithAgentFunctionalTest.groovy @@ -54,7 +54,7 @@ class JavaApplicationWithAgentFunctionalTest extends AbstractGraalVMMavenFunctio when: // Run Maven in debug mode (-X) in order to capture the command line arguments // used to launch Surefire with the agent. - mvn '-X', '-Pnative', 'test', '-DskipNativeTests' + mvnDebug '-Pnative', 'test', '-DskipNativeTests' then: // Agent is used with Surefire @@ -85,7 +85,7 @@ class JavaApplicationWithAgentFunctionalTest extends AbstractGraalVMMavenFunctio when: // Run Maven in debug mode (-X) in order to capture the command line arguments // used to launch Surefire with the agent. - mvn '-X', '-Pnative', 'test' + mvnDebug '-Pnative', 'test' then: outputContains """ @@ -162,7 +162,7 @@ class JavaApplicationWithAgentFunctionalTest extends AbstractGraalVMMavenFunctio when: // Run Maven in debug mode (-X) in order to capture the command line arguments // used to launch Surefire with the agent. - mvn '-X', '-Pnative', '-DagentOptions=periodic-config', 'test' + mvnDebug '-Pnative', '-DagentOptions=periodic-config', 'test' then: outputContains """ @@ -214,7 +214,7 @@ class JavaApplicationWithAgentFunctionalTest extends AbstractGraalVMMavenFunctio withSample("java-application-with-reflection") when: - mvn '-X', '-Pnative', '-DskipTests=true', '-DskipNativeBuild=true', 'package', 'exec:exec@java-agent' + mvnDebug '-Pnative', '-DskipTests=true', '-DskipNativeBuild=true', 'package', 'exec:exec@java-agent' then: ['jni', 'proxy', 'reflect', 'resource', 'serialization'].each { name -> @@ -246,7 +246,7 @@ class JavaApplicationWithAgentFunctionalTest extends AbstractGraalVMMavenFunctio withSample("java-application-with-reflection") when: - mvn '-X', '-Pnative', '-Dagent=false', '-DskipTests=true', '-DskipNativeBuild=true', 'package', 'exec:exec@java-agent' + mvnDebug '-Pnative', '-Dagent=false', '-DskipTests=true', '-DskipNativeBuild=true', 'package', 'exec:exec@java-agent' then: outputDoesNotContain '-agentlib:native-image-agent' @@ -263,7 +263,7 @@ class JavaApplicationWithAgentFunctionalTest extends AbstractGraalVMMavenFunctio withSample("java-application-with-reflection") when: - mvn '-X', '-Pnative', '-DagentOptions=periodic-config', '-DskipTests=true', '-DskipNativeBuild=true', 'package', 'exec:exec@java-agent' + mvnDebug '-Pnative', '-DagentOptions=periodic-config', '-DskipTests=true', '-DskipNativeBuild=true', 'package', 'exec:exec@java-agent' then: ['jni', 'proxy', 'reflect', 'resource', 'serialization'].each { name -> 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 073525851..a55b604d6 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 @@ -323,8 +323,9 @@ protected void warnIfWrongMetaInfLayout(Path jarFilePath, Artifact artifact) thr valid = valid && relativeSubDir.getName(0).toString().equals(artifact.getGroupId()); valid = valid && relativeSubDir.getName(1).toString().equals(artifact.getArtifactId()); if (!valid) { - String example = NATIVE_IMAGE_META_INF + "/${groupId}/${artifactId}/" + NATIVE_IMAGE_PROPERTIES_FILENAME; - logger.warn(nativeImageProperty.toUri() + " does not match recommended " + example + " layout."); + String example = NATIVE_IMAGE_META_INF + "/%s/%s/" + NATIVE_IMAGE_PROPERTIES_FILENAME; + example = String.format(example, artifact.getGroupId(), artifact.getArtifactId()); + logger.warn("Properties file at '" + nativeImageProperty.toUri() + "' does not match the recommended '" + example + "' layout."); } } } diff --git a/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/NativeCompileMojo.java b/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/NativeCompileMojo.java index 0fed1ccb0..3cc083afb 100644 --- a/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/NativeCompileMojo.java +++ b/native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/NativeCompileMojo.java @@ -49,7 +49,7 @@ /** * This goal builds native images. - * It can be invoked using `mvn native:compile`. + * It should be invoked from the command line as a single goal (`mvn native:compile`). */ @Mojo(name = "compile", defaultPhase = LifecyclePhase.PACKAGE, requiresDependencyResolution = ResolutionScope.RUNTIME, @@ -57,5 +57,4 @@ @Execute(phase = LifecyclePhase.PACKAGE) @SuppressWarnings("unused") public class NativeCompileMojo extends NativeCompileNoForkMojo { - // no-op } 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 1caf2a3d0..39c5e9967 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 @@ -73,7 +73,7 @@ public class NativeExtension extends AbstractMavenLifecycleParticipant implement private static final String JUNIT_PLATFORM_LISTENERS_UID_TRACKING_OUTPUT_DIR = "junit.platform.listeners.uid.tracking.output.dir"; private static final String NATIVEIMAGE_IMAGECODE = "org.graalvm.nativeimage.imagecode"; - private Logger logger; + private static Logger logger; @Override public void enableLogging(Logger logger) { @@ -92,6 +92,8 @@ static String testIdsDirectory(String baseDir) { return baseDir + File.separator + "test-ids"; } + private static String graalvmJava; + static String buildAgentArgument(String baseDir, Context context, List agentOptions) { List options = new ArrayList<>(agentOptions); String effectiveOutputDir = agentOutputDirectoryFor(baseDir, context); @@ -115,6 +117,12 @@ static String agentOutputDirectoryFor(String baseDir, Context context) { @Override public void afterProjectsRead(MavenSession session) { + try { + graalvmJava = Utils.getNativeImage(logger).getParent().resolve("java").toString(); + } catch (MojoExecutionException e) { + throw new RuntimeException(e); + } + for (MavenProject project : session.getProjects()) { Build build = project.getBuild(); withPlugin(build, "native-maven-plugin", nativePlugin -> { @@ -159,12 +167,7 @@ public void afterProjectsRead(MavenSession session) { for (Xpp3Dom child : children) { commandlineArgs.addChild(child); } - Xpp3Dom executable = findOrAppend(config, "executable"); - try { - executable.setValue(Utils.getNativeImage(logger).getParent().resolve("java").toString()); - } catch (MojoExecutionException e) { - throw new RuntimeException(e); - } + findOrAppend(config, "executable").setValue(graalvmJava); } }) ); @@ -318,6 +321,7 @@ private static void configureAgentForSurefire(Plugin surefirePlugin, String agen Xpp3Dom argLine = new Xpp3Dom("argLine"); argLine.setValue(agentArgument); configuration.addChild(argLine); + findOrAppend(configuration, "jvm").setValue(graalvmJava); }); } diff --git a/native-maven-plugin/src/seeding-build/pom.xml b/native-maven-plugin/src/seeding-build/pom.xml index 66f15a79c..e314da800 100644 --- a/native-maven-plugin/src/seeding-build/pom.xml +++ b/native-maven-plugin/src/seeding-build/pom.xml @@ -52,6 +52,7 @@ 1.8 UTF-8 5.8.1 + 22.0.0 org.graalvm.demo.Application @@ -62,6 +63,11 @@ ${junit.jupiter.version} test + + org.graalvm.nativeimage + svm + ${graalvm.version} + 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 47fa9fdd7..07798cc0b 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 @@ -139,24 +139,61 @@ abstract class AbstractGraalVMMavenFunctionalTest extends Specification { } void mvn(List args) { - mvn(args as String[]) + Map systemProperties = [ + "org.apache.http" : "off", + "org.apache.http.wire" : "off", + ].collectEntries { key, value -> + ["org.slf4j.simpleLogger.log.${key}".toString(), value] + } + mvn(args, systemProperties) } void mvn(String... args) { - System.out.println("Running copy of maven project `" + testOrigin + "` with `" + args + "`"); + mvn(args.toList()) + } + + void mvn(List args, Map systemProperties) { + System.out.println("Running copy of maven project `" + testOrigin + "` with " + args); + var resultingSystemProperties = [ + "common.repo.uri": System.getProperty("common.repo.uri"), + "seed.repo.uri": System.getProperty("seed.repo.uri"), + "maven.repo.local": testDirectory.resolve("local-repo").toFile().absolutePath + ] + resultingSystemProperties.putAll(systemProperties) + result = executor.execute( testDirectory.toFile(), - [ - "org.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener": "warn", - "common.repo.uri": System.getProperty("common.repo.uri"), - "seed.repo.uri": System.getProperty("seed.repo.uri"), - "maven.repo.local": testDirectory.resolve("local-repo").toFile().absolutePath - ], + resultingSystemProperties, [*injectedSystemProperties, *args], new File(System.getProperty("maven.settings")) ) System.out.println("Exit code is ${result.exitCode}") + + } + + void mvnDebug(String... args) { + Map systemProperties = [ + "org.apache.http" : "off", + "org.apache.http.wire" : "off", + "org.apache.maven.cli.transfer.Slf4jMavenTransferListener" : "warn", + "org.eclipse.aether.internal.impl.DefaultTransporterProvider" : "error", + "org.eclipse.aether.internal.impl.DefaultRepositoryConnectorProvider": "error", + "org.eclipse.aether.internal.impl.TrackingFileManager" : "error", + "org.eclipse.aether.internal.impl.DefaultArtifactResolver" : "error", + "org.codehaus.plexus.PlexusContainer" : "error", + "org.apache.maven.plugin.internal.DefaultPluginDependenciesResolver" : "error", + "org.apache.maven.shared.filtering.DefaultMavenFileFilter" : "error", + "org.codehaus.mojo.exec.ExecMojo" : "debug", + // This is THE logger we need for checking java execution + "org.apache.maven.lifecycle.internal.LifecycleDebugLogger" : "error" + ].collectEntries { key, value -> + ["org.slf4j.simpleLogger.log.${key}".toString(), value] + } + + ArrayList resultingArgs = args.toList() + resultingArgs.add(0, "-X") + mvn(resultingArgs, systemProperties) } boolean isDidNotCrash() {