Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/it/multirelease-with-modules/verify.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,8 @@ protected Set<String> getIncrementalExcludes() {
@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;
}
Expand Down Expand Up @@ -340,7 +341,7 @@ final boolean hasModuleDeclaration(final List<SourceDirectory> roots) throws IOE
*/
@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;
}
Expand All @@ -365,7 +366,7 @@ private TreeMap<SourceVersion, Path> getOutputDirectoryPerVersion() throws IOExc
}

/**
* 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.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -194,6 +194,8 @@ private 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")
Expand All @@ -204,32 +206,45 @@ private void completeIfVersioned(SourceVersion baseVersion) {
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");
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -614,8 +614,8 @@ public boolean compile(final JavaCompiler compiler, final Options configuration,
}
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.
Expand Down