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 5de3ff87efa81..0b9475319c7e5 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 @@ -108,11 +108,14 @@ protected Map getBuildOutputDirectories() { case LEGACY_JAR: case LEGACY: outputs.put("fast-jar", fastJar()); - outputs.put("legacy-lib", buildDir.toPath().resolve("lib").toFile()); + outputs.put("legacy-lib", gradleBuildDir().resolve("lib").toFile()); + break; + case NATIVE: + outputs.put("native-source", nativeSources()); + outputs.put("fast-jar", fastJar()); break; case JAR: case FAST_JAR: - case NATIVE: outputs.put("fast-jar", fastJar()); break; case MUTABLE_JAR: @@ -136,23 +139,20 @@ protected Map getBuildOutputFiles() { Map outputs = new HashMap<>(); PackageConfig.BuiltInType packageType = packageType(); switch (packageType) { + case UBER_JAR: case LEGACY_JAR: case LEGACY: - outputs.put("legacy-jar", runnerJar()); - outputs.put("artifact-properties", artifactProperties()); - break; - case JAR: - case FAST_JAR: - case MUTABLE_JAR: - case NATIVE_SOURCES: + outputs.put("runner-jar", runnerJar()); outputs.put("artifact-properties", artifactProperties()); break; case NATIVE: outputs.put("native-runner", nativeRunner()); outputs.put("artifact-properties", artifactProperties()); break; - case UBER_JAR: - outputs.put("uber-jar", runnerJar()); + case JAR: + case FAST_JAR: + case MUTABLE_JAR: + case NATIVE_SOURCES: outputs.put("artifact-properties", artifactProperties()); break; default: @@ -196,7 +196,7 @@ private void runnerAndArtifactsInputs(Consumer buildInputs, Path sourceDir buildInputs.accept(sourceDir.resolve(nativeRunnerFileName()).toFile()); buildInputs.accept(sourceDir.resolve(runnerJarFileName()).toFile()); // TODO jib-image* ?? - buildInputs.accept(sourceDir.resolve(runnerBaseName() + "-native-image-source-jar").toFile()); + buildInputs.accept(sourceDir.resolve(nativeImageSourceJarDirName()).toFile()); } @TaskAction @@ -320,7 +320,7 @@ private void copyRunnersAndArtifactProperties(Path sourceDir) { runnerJarFileName(), "jib-image*", NATIVE_SOURCES, - runnerBaseName() + "-native-image-source-jar/**")); + nativeImageSourceJarDirName() + "/**")); } private String expandConfigurationKey(String shortKey) { diff --git a/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusBuildTask.java b/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusBuildTask.java index 957169688101a..e0b3145b6e278 100644 --- a/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusBuildTask.java +++ b/devtools/gradle/gradle-application-plugin/src/main/java/io/quarkus/gradle/tasks/QuarkusBuildTask.java @@ -1,8 +1,6 @@ package io.quarkus.gradle.tasks; import java.io.File; -import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; import java.util.Map; import java.util.stream.Collectors; @@ -61,16 +59,20 @@ PackageConfig.BuiltInType packageType() { return extension().baseConfig().packageType(); } + Path gradleBuildDir() { + return buildDir.toPath(); + } + Path genBuildDir() { - return buildDir.toPath().resolve(QUARKUS_BUILD_GEN_DIR); + return gradleBuildDir().resolve(QUARKUS_BUILD_GEN_DIR); } Path appBuildDir() { - return buildDir.toPath().resolve(QUARKUS_BUILD_APP_DIR); + return gradleBuildDir().resolve(QUARKUS_BUILD_APP_DIR); } Path depBuildDir() { - return buildDir.toPath().resolve(QUARKUS_BUILD_DEP_DIR); + return gradleBuildDir().resolve(QUARKUS_BUILD_DEP_DIR); } File artifactProperties() { @@ -114,6 +116,10 @@ String runnerName() { return runnerBaseName() + runnerSuffix(); } + String nativeImageSourceJarDirName() { + return runnerBaseName() + "-native-image-source-jar"; + } + String runnerBaseName() { BaseConfig baseConfig = extension().baseConfig(); return baseConfig.packageConfig().outputName.orElseGet(() -> extension().finalName()); @@ -139,19 +145,54 @@ ApplicationModel resolveAppModelForBuild() { return appModel; } + /** + * Runs the Quarkus-build in the "well known" location, Gradle's {@code build/} directory. + * + *

+ * It would be easier to run the Quarkus-build directly in {@code build/quarkus-build/gen} to have a "clean + * target directory", but that breaks already existing Gradle builds for users, which have for example + * {@code Dockerfile}s that rely on the fact that build artifacts are present in {@code build/}. + * + *

+ * This requires this method to + *

    + *
  1. "properly" clean the directories that are going to be populated by the Quarkus build, then + *
  2. run the Quarkus build with the target directory {@code build/} and then + *
  3. populate the + *
+ */ void generateBuild() { + Path buildDir = gradleBuildDir(); Path genDir = genBuildDir(); PackageConfig.BuiltInType packageType = packageType(); getLogger().info("Building Quarkus app for package type {} in {}", packageType, genDir); - // Caching and "up-to-date" checks depend on the inputs, this 'delete()' should ensure that the up-to-date - // checks work against "clean" outputs, considering that the outputs depend on the package-type. - getFileSystemOperations().delete(delete -> delete.delete(genDir)); - try { - Files.createDirectories(genDir); - } catch (IOException e) { - throw new GradleException("Could not create directory " + genDir, e); - } + getFileSystemOperations().delete(delete -> { + // Caching and "up-to-date" checks depend on the inputs, this 'delete()' should ensure that the up-to-date + // checks work against "clean" outputs, considering that the outputs depend on the package-type. + delete.delete(genDir); + + // Delete directories inside Gradle's build/ dir that are going to be populated by the Quarkus build. + switch (packageType) { + case JAR: + case FAST_JAR: + delete.delete(buildDir.resolve(nativeImageSourceJarDirName())); + // fall through + case NATIVE: + case NATIVE_SOURCES: + delete.delete(fastJar()); + break; + case LEGACY_JAR: + case LEGACY: + delete.delete(buildDir.resolve("lib")); + break; + case MUTABLE_JAR: + case UBER_JAR: + break; + default: + throw new GradleException("Unsupported package type " + packageType); + } + }); ApplicationModel appModel = resolveAppModelForBuild(); Map configMap = extension().buildEffectiveConfiguration(appModel.getAppArtifact()).configMap(); @@ -161,7 +202,7 @@ void generateBuild() { if (getLogger().isEnabled(LogLevel.INFO)) { getLogger().info("Effective properties: {}", configMap.entrySet().stream() - .filter(e -> e.getKey().startsWith("quarkus.")).map(e -> "" + e) + .filter(e -> e.getKey().startsWith("quarkus.")).map(Object::toString) .sorted() .collect(Collectors.joining("\n ", "\n ", ""))); } @@ -171,10 +212,42 @@ void generateBuild() { workQueue.submit(BuildWorker.class, params -> { params.getBuildSystemProperties().putAll(configMap); params.getBaseName().set(extension().finalName()); - params.getTargetDirectory().set(genDir.toFile()); + params.getTargetDirectory().set(buildDir.toFile()); params.getAppModel().set(appModel); }); workQueue.await(); + + // Copy built artifacts from `build/` into `build/quarkus-build/gen/` + getFileSystemOperations().copy(copy -> { + copy.from(buildDir); + copy.into(genDir); + switch (packageType) { + case NATIVE: + copy.include(nativeRunnerFileName()); + copy.include(nativeImageSourceJarDirName() + "/**"); + // fall through + case JAR: + case FAST_JAR: + copy.include(outputDirectory() + "/**"); + copy.include(QUARKUS_ARTIFACT_PROPERTIES); + break; + case LEGACY_JAR: + case LEGACY: + copy.include("lib/**"); + // fall through + case MUTABLE_JAR: + case UBER_JAR: + copy.include(QUARKUS_ARTIFACT_PROPERTIES); + copy.include(runnerJarFileName()); + break; + case NATIVE_SOURCES: + copy.include(QUARKUS_ARTIFACT_PROPERTIES); + copy.include(nativeImageSourceJarDirName() + "/**"); + break; + default: + throw new GradleException("Unsupported package type " + packageType); + } + }); } }