This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-compiler-plugin.git


The following commit(s) were added to refs/heads/master by this push:
     new 0506647  Rename `META-INF/versions` as `META-INF/versions-modular` for 
the non-standard case (#998)
0506647 is described below

commit 050664790af28be9107aff6172f8e61adcb8ed8a
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Thu Nov 20 16:24:02 2025 +0100

    Rename `META-INF/versions` as `META-INF/versions-modular` for the 
non-standard case (#998)
    
    Rename the `META-INF/versions` subdirectory as `versions-modular`
    for projects that are both multi-module and multi-release.
    As of October 2025, there is no standard directory layout for this case.
    The intend is to avoid confusion with the standard case, 
`META-INF/versions`,
    which is multi-release but not multi-module.
---
 src/it/multirelease-with-modules/verify.groovy     |  4 +--
 .../apache/maven/plugin/compiler/CompilerMojo.java |  7 +++--
 .../maven/plugin/compiler/SourceDirectory.java     | 33 ++++++++++++++++------
 .../apache/maven/plugin/compiler/ToolExecutor.java |  4 +--
 4 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/src/it/multirelease-with-modules/verify.groovy 
b/src/it/multirelease-with-modules/verify.groovy
index a4d068a..146fa96 100644
--- a/src/it/multirelease-with-modules/verify.groovy
+++ b/src/it/multirelease-with-modules/verify.groovy
@@ -27,8 +27,8 @@ assert baseVersion == getMajor(new File( basedir, 
"target/classes/foo.bar/foo/Ot
 assert baseVersion == getMajor(new File( basedir, 
"target/classes/foo.bar/foo/YetAnotherFile.class"))
 assert baseVersion == getMajor(new File( basedir, 
"target/classes/foo.bar.more/more/MainFile.class"))
 assert baseVersion == getMajor(new File( basedir, 
"target/classes/foo.bar.more/more/OtherFile.class"))
-assert nextVersion == getMajor(new File( basedir, 
"target/classes/META-INF/versions/16/foo.bar/foo/OtherFile.class"))
-assert nextVersion == getMajor(new File( basedir, 
"target/classes/META-INF/versions/16/foo.bar.more/more/OtherFile.class"))
+assert nextVersion == getMajor(new File( basedir, 
"target/classes/META-INF/versions-modular/16/foo.bar/foo/OtherFile.class"))
+assert nextVersion == getMajor(new File( basedir, 
"target/classes/META-INF/versions-modular/16/foo.bar.more/more/OtherFile.class"))
 
 int getMajor(File file)
 {
diff --git a/src/main/java/org/apache/maven/plugin/compiler/CompilerMojo.java 
b/src/main/java/org/apache/maven/plugin/compiler/CompilerMojo.java
index a62e2ec..373f073 100644
--- a/src/main/java/org/apache/maven/plugin/compiler/CompilerMojo.java
+++ b/src/main/java/org/apache/maven/plugin/compiler/CompilerMojo.java
@@ -267,7 +267,8 @@ public class CompilerMojo extends AbstractCompilerMojo {
     @Override
     protected Path getOutputDirectory() {
         if (SUPPORT_LEGACY && multiReleaseOutput && release != null) {
-            return 
SourceDirectory.outputDirectoryForReleases(outputDirectory).resolve(release);
+            return SourceDirectory.outputDirectoryForReleases(false, 
outputDirectory)
+                    .resolve(release);
         }
         return outputDirectory;
     }
@@ -340,7 +341,7 @@ public class CompilerMojo extends AbstractCompilerMojo {
      */
     @Deprecated(since = "4.0.0")
     private TreeMap<SourceVersion, Path> getOutputDirectoryPerVersion() throws 
IOException {
-        final Path root = 
SourceDirectory.outputDirectoryForReleases(outputDirectory);
+        final Path root = SourceDirectory.outputDirectoryForReleases(false, 
outputDirectory);
         if (Files.notExists(root)) {
             return null;
         }
@@ -365,7 +366,7 @@ public class CompilerMojo extends AbstractCompilerMojo {
     }
 
     /**
-     * Adds the compilation outputs of previous Java releases to the 
class-path ot module-path.
+     * Adds the compilation outputs of previous Java releases to the 
class-path of module-path.
      * This method should be invoked only when compiling a multi-release 
<abbr>JAR</abbr> in the
      * old deprecated way.
      *
diff --git 
a/src/main/java/org/apache/maven/plugin/compiler/SourceDirectory.java 
b/src/main/java/org/apache/maven/plugin/compiler/SourceDirectory.java
index 45f0505..bb4ee92 100644
--- a/src/main/java/org/apache/maven/plugin/compiler/SourceDirectory.java
+++ b/src/main/java/org/apache/maven/plugin/compiler/SourceDirectory.java
@@ -140,9 +140,9 @@ final class SourceDirectory {
      * This is the MOJO output directory with sub-directories appended 
according the following rules, in that order:
      *
      * <ol>
-     *   <li>If {@link #moduleName} is non-null, then the module name is 
appended.</li>
-     *   <li>If {@link #isVersioned} is {@code true}, then the next elements 
in the paths are
+     *   <li>If {@link #isVersioned} is {@code true}, then the relative part 
of the path starts with
      *       {@code "META-INF/versions/<n>"} where {@code <n>} is the release 
number.</li>
+     *   <li>If {@link #moduleName} is non-null, then the module name is 
appended.</li>
      * </ol>
      *
      * @see #getOutputDirectory()
@@ -194,6 +194,8 @@ final class SourceDirectory {
      * Potentially adds the {@code META-INF/versions/} part of the path to the 
output directory.
      * This method can be invoked only after the base version has been 
determined, which happens
      * after all other source directories have been built.
+     *
+     * @param baseVersion the Java release target by the non-versioned classes
      */
     private void completeIfVersioned(SourceVersion baseVersion) {
         @SuppressWarnings("LocalVariableHidesMemberVariable")
@@ -204,32 +206,45 @@ final class SourceDirectory {
                 release = SourceVersion.latestSupported();
                 // `this.release` intentionally left to null.
             }
-            outputDirectory = outputDirectoryForReleases(outputDirectory, 
release);
+            outputDirectory = outputDirectoryForReleases(moduleName != null, 
outputDirectory, release);
         }
     }
 
     /**
-     * Returns the directory where to write the compilation for a specific 
Java release.
+     * Returns the directory where to write the compiled class files for a 
specific Java release.
+     * The standard path is {@code META-INF/versions/${release}} where {@code 
${release}} is the
+     * numerical value of the {@code release} argument. However if {@code 
modular} is {@code true},
+     * then the returned path is rather {@code 
META-INF/versions-modular/${release}}. The latter is
+     * non-standard because there is no standard multi-module <abbr>JAR</abbr> 
formats as of 2025.
+     * The use of {@code "versions-modular"} is for allowing other plugins 
such as Maven JAR plugin
+     * to avoid confusion with the standard case.
      *
+     * @param modular whether each version directory contains module names
      * @param outputDirectory usually the value of {@link #outputDirectory}
      * @param release the release, or {@code null} for the default release
+     * @return the directory for the classes of the specified version
      */
-    static Path outputDirectoryForReleases(Path outputDirectory, SourceVersion 
release) {
+    static Path outputDirectoryForReleases(boolean modular, Path 
outputDirectory, SourceVersion release) {
         if (release == null) {
             release = SourceVersion.latestSupported();
         }
         String version = release.name(); // TODO: replace by runtimeVersion() 
in Java 18.
         version = version.substring(version.lastIndexOf('_') + 1);
-        return outputDirectoryForReleases(outputDirectory).resolve(version);
+        return outputDirectoryForReleases(modular, 
outputDirectory).resolve(version);
     }
 
     /**
-     * Returns the directory where to write the compilation for a specific 
Java release.
+     * Returns the directory where to write the compiled class files for all 
Java releases.
+     * The standard path (when {@code modular} is {@code false}) is {@code 
META-INF/versions}.
      * The caller shall add the version number to the returned path.
+     *
+     * @param modular whether each version directory contains module names
+     * @param outputDirectory usually the value of {@link #outputDirectory}
+     * @return the directory for all versions
      */
-    static Path outputDirectoryForReleases(Path outputDirectory) {
+    static Path outputDirectoryForReleases(boolean modular, Path 
outputDirectory) {
         // TODO: use Path.resolve(String, String...) with Java 22.
-        return outputDirectory.resolve("META-INF").resolve("versions");
+        return outputDirectory.resolve("META-INF").resolve(modular ? 
"versions-modular" : "versions");
     }
 
     /**
diff --git a/src/main/java/org/apache/maven/plugin/compiler/ToolExecutor.java 
b/src/main/java/org/apache/maven/plugin/compiler/ToolExecutor.java
index c32d7bf..1a9b1f2 100644
--- a/src/main/java/org/apache/maven/plugin/compiler/ToolExecutor.java
+++ b/src/main/java/org/apache/maven/plugin/compiler/ToolExecutor.java
@@ -614,8 +614,8 @@ public class ToolExecutor {
                     }
                     outputForRelease = outputDirectory; // Modified below if 
compiling a non-base release.
                     if (isVersioned) {
-                        outputForRelease = Files.createDirectories(
-                                
SourceDirectory.outputDirectoryForReleases(outputForRelease, unit.release));
+                        outputForRelease = 
Files.createDirectories(SourceDirectory.outputDirectoryForReleases(
+                                isModularProject, outputForRelease, 
unit.release));
                         if (isClasspathProject) {
                             /*
                              * For a non-modular project, this block is 
executed at most once par compilation unit.

Reply via email to