From eace14038f30bffd2f4f5c014f75da569fb0a7af Mon Sep 17 00:00:00 2001 From: Antonio Costa Date: Tue, 10 Jan 2023 10:34:56 +0100 Subject: [PATCH] implement output-name/add-runner-suffix on Gradle --- .../extension/QuarkusPluginExtension.java | 67 ++++++++++++------ .../io/quarkus/gradle/tasks/QuarkusBuild.java | 4 +- .../nativeimage/BasicJavaNativeBuildIT.java | 70 +++++++++++++++++++ .../nativeimage/NativeIntegrationTestIT.java | 18 +++++ 4 files changed, 136 insertions(+), 23 deletions(-) diff --git a/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/extension/QuarkusPluginExtension.java b/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/extension/QuarkusPluginExtension.java index 925eec91f0979f..90cdd871310175 100644 --- a/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/extension/QuarkusPluginExtension.java +++ b/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/extension/QuarkusPluginExtension.java @@ -1,18 +1,12 @@ package io.quarkus.gradle.extension; -import java.io.File; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.StringJoiner; -import java.util.stream.Collectors; - -import javax.annotation.Nullable; - +import io.quarkus.bootstrap.BootstrapConstants; +import io.quarkus.bootstrap.model.ApplicationModel; +import io.quarkus.bootstrap.resolver.AppModelResolver; +import io.quarkus.gradle.AppModelGradleResolver; +import io.quarkus.gradle.tasks.QuarkusGradleUtils; +import io.quarkus.gradle.tooling.ToolingUtils; +import io.quarkus.runtime.LaunchMode; import org.gradle.api.Action; import org.gradle.api.Project; import org.gradle.api.file.FileCollection; @@ -25,13 +19,20 @@ import org.gradle.api.tasks.testing.Test; import org.gradle.jvm.tasks.Jar; -import io.quarkus.bootstrap.BootstrapConstants; -import io.quarkus.bootstrap.model.ApplicationModel; -import io.quarkus.bootstrap.resolver.AppModelResolver; -import io.quarkus.gradle.AppModelGradleResolver; -import io.quarkus.gradle.tasks.QuarkusGradleUtils; -import io.quarkus.gradle.tooling.ToolingUtils; -import io.quarkus.runtime.LaunchMode; +import javax.annotation.Nullable; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Properties; +import java.util.Set; +import java.util.StringJoiner; +import java.util.stream.Collectors; public class QuarkusPluginExtension { private final Project project; @@ -85,7 +86,8 @@ public void beforeTest(Test task) { task.environment(BootstrapConstants.TEST_TO_MAIN_MAPPINGS, fileList); project.getLogger().debug("test dir mapping - {}", fileList); - final String nativeRunner = task.getProject().getBuildDir().toPath().resolve(finalName() + "-runner") + final String nativeRunner = task.getProject().getBuildDir().toPath() + .resolve(buildNativeRunnerName(props)) .toAbsolutePath() .toString(); props.put("native.image.path", nativeRunner); @@ -94,6 +96,29 @@ public void beforeTest(Test task) { } } + public String buildNativeRunnerName(final Map taskSystemProps) { + Properties properties = new Properties(taskSystemProps.size()); + properties.putAll(taskSystemProps); + quarkusBuildProperties.entrySet().forEach(buildEntry -> properties.putIfAbsent(buildEntry.getKey(), buildEntry.getValue())); + System.getProperties().entrySet() + .forEach(propEntry -> properties.putIfAbsent(propEntry.getKey(), propEntry.getValue())); + System.getenv().entrySet().forEach( + envEntry -> properties.putIfAbsent(envEntry.getKey(), envEntry.getValue())); + StringBuilder nativeRunnerName = new StringBuilder(); + + if (properties.containsKey("quarkus.package.output-name")) { + nativeRunnerName.append(properties.get("quarkus.package.output-name")); + } else { + nativeRunnerName.append(finalName()); + } + if (!properties.containsKey("quarkus.package.add-runner-suffix") + || (properties.containsKey("quarkus.package.add-runner-suffix") + && Boolean.parseBoolean((String) properties.get("quarkus.package.add-runner-suffix")))) { + nativeRunnerName.append("-runner"); + } + return nativeRunnerName.toString(); + } + public Property getFinalName() { return finalName; } diff --git a/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusBuild.java b/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusBuild.java index ff7f3372ccd5cb..5013ce21a6693d 100644 --- a/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusBuild.java +++ b/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusBuild.java @@ -129,12 +129,12 @@ public QuarkusBuild manifest(Action action) { @OutputFile public File getRunnerJar() { - return new File(getProject().getBuildDir(), extension().finalName() + "-runner.jar"); + return new File(getProject().getBuildDir(), String.format("%s.jar", extension().buildNativeRunnerName(Map.of()))); } @OutputFile public File getNativeRunner() { - return new File(getProject().getBuildDir(), extension().finalName() + "-runner"); + return new File(getProject().getBuildDir(), extension().buildNativeRunnerName(Map.of())); } @OutputDirectory diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/nativeimage/BasicJavaNativeBuildIT.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/nativeimage/BasicJavaNativeBuildIT.java index c61f9c8135d174..b846cb793f5028 100644 --- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/nativeimage/BasicJavaNativeBuildIT.java +++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/nativeimage/BasicJavaNativeBuildIT.java @@ -48,6 +48,76 @@ public void shouldBuildNativeImage() throws Exception { } + @Test + public void shouldBuildNativeImageWithCustomName() throws Exception { + final File projectDir = getProjectDir("basic-java-native-module"); + + final BuildResult build = runGradleWrapper(projectDir, "clean", "quarkusBuild", "-Dquarkus.package.type=native", + "-Dquarkus.package.output-name=test"); + + assertThat(build.getTasks().get(":quarkusBuild")).isEqualTo(BuildResult.SUCCESS_OUTCOME); + final String buildOutput = build.getOutput(); + // make sure the output log during the build contains some expected logs from the native-image process + CharSequence[] expectedOutput; + if (buildOutput.contains("Version info:")) { // Starting with 22.0 the native-image output changed + expectedOutput = new CharSequence[] { "Initializing...", "Performing analysis...", + "Finished generating 'test-runner' in" }; + } else { + expectedOutput = new CharSequence[] { "(clinit):", "(typeflow):", "[total]:" }; + } + assertThat(buildOutput) + .withFailMessage("native-image build log is missing certain expected log messages: \n\n %s", buildOutput) + .contains(expectedOutput) + .doesNotContain("Finished generating '" + NATIVE_IMAGE_NAME + "' in"); + Path nativeImagePath = projectDir.toPath().resolve("build").resolve("test-runner"); + assertThat(nativeImagePath).exists(); + Process nativeImageProcess = runNativeImage(nativeImagePath.toAbsolutePath().toString()); + try { + final String response = DevModeTestUtils.getHttpResponse("/hello"); + assertThat(response) + .withFailMessage("Response %s for /hello was expected to contain the hello, but didn't", response) + .contains("hello"); + } finally { + nativeImageProcess.destroy(); + } + + } + + @Test + public void shouldBuildNativeImageWithCustomNameWithoutSuffix() throws Exception { + final File projectDir = getProjectDir("basic-java-native-module"); + + final BuildResult build = runGradleWrapper(projectDir, "clean", "quarkusBuild", "-Dquarkus.package.type=native", + "-Dquarkus.package.output-name=test", "-Dquarkus.package.add-runner-suffix=false"); + + assertThat(build.getTasks().get(":quarkusBuild")).isEqualTo(BuildResult.SUCCESS_OUTCOME); + final String buildOutput = build.getOutput(); + // make sure the output log during the build contains some expected logs from the native-image process + CharSequence[] expectedOutput; + if (buildOutput.contains("Version info:")) { // Starting with 22.0 the native-image output changed + expectedOutput = new CharSequence[] { "Initializing...", "Performing analysis...", + "Finished generating 'test' in" }; + } else { + expectedOutput = new CharSequence[] { "(clinit):", "(typeflow):", "[total]:" }; + } + assertThat(buildOutput) + .withFailMessage("native-image build log is missing certain expected log messages: \n\n %s", buildOutput) + .contains(expectedOutput) + .doesNotContain("Finished generating '" + NATIVE_IMAGE_NAME + "' in"); + Path nativeImagePath = projectDir.toPath().resolve("build").resolve("test"); + assertThat(nativeImagePath).exists(); + Process nativeImageProcess = runNativeImage(nativeImagePath.toAbsolutePath().toString()); + try { + final String response = DevModeTestUtils.getHttpResponse("/hello"); + assertThat(response) + .withFailMessage("Response %s for /hello was expected to contain the hello, but didn't", response) + .contains("hello"); + } finally { + nativeImageProcess.destroy(); + } + + } + private Process runNativeImage(String nativeImage) throws IOException { final ProcessBuilder processBuilder = new ProcessBuilder(nativeImage); processBuilder.inheritIO(); diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/nativeimage/NativeIntegrationTestIT.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/nativeimage/NativeIntegrationTestIT.java index b387532b8ab23b..b22b4eab2df071 100644 --- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/nativeimage/NativeIntegrationTestIT.java +++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/nativeimage/NativeIntegrationTestIT.java @@ -19,4 +19,22 @@ public void nativeTestShouldRunIntegrationTest() throws Exception { assertThat(testResult.getTasks().get(":testNative")).isEqualTo(BuildResult.SUCCESS_OUTCOME); } + @Test + public void runNativeTestsWithOutputName() throws Exception { + final File projectDir = getProjectDir("it-test-basic-project"); + + final BuildResult testResult = runGradleWrapper(projectDir, "clean", "testNative", + "-Dquarkus.package.output-name=test"); + assertThat(testResult.getTasks().get(":testNative")).isEqualTo(BuildResult.SUCCESS_OUTCOME); + } + + @Test + public void runNativeTestsWithoutRunnerSuffix() throws Exception { + final File projectDir = getProjectDir("it-test-basic-project"); + + final BuildResult testResult = runGradleWrapper(projectDir, "clean", "testNative", + "-Dquarkus.package.add-runner-suffix=false"); + assertThat(testResult.getTasks().get(":testNative")).isEqualTo(BuildResult.SUCCESS_OUTCOME); + } + }