On Wed, 2 Oct 2024 at 11:29, Martin Desruisseaux
<martin.desruisse...@geomatys.com> wrote:
> The problem with module-info in both tests and main is that it works
> awkward. The previous compiler plugin had to took the project structure
> upside-down: the test code was considered the main code, and the main
> code was considered the patch. I just checked by compiling and running a
> dummy project with `java` and `javac` directly (without Maven) and I
> confirm: even if a `module-info` is present in the test output, it is
> ignored by the `java` command (the `module-info` of the main code has
> precedence) unless we pretend that the test are the main code and the
> main code are patching the tests. The behavior of `javac` is a little
> bit more complicated, but basically we also have to put things upside
> down to make it works.
>
> If nevertheless we still want to support having `module-info` in both
> main and test, I found a trick this morning for getting `javac` to
> compile the test `module-info` without putting the project structure
> upside-down. But it is undocumented and I don't know how reliable it
> would be. I can implement this trick (or try other tricks) if this is
> important, but I think that we should stop recommending the approach of
> overwriting `module-info`, or recommend to use it in last resort only.
> The alternative (compiler options) is indeed tedious, but this is
> precisely a major goal of this JPMS work to make that task easier than
> it currently is.

This issue remains hugely painful not just in Maven, but across Java.
It is a key part of why JPMS adoption is so painful.

The key principle here is that tests for a Maven module should be
located *within* the same Maven module of the main source code.
Forcing developers to write a separate Maven module just for tests is
not an acceptable solution.

1) Classpath testing with one (main) module-info.java file.
IIUC, this is what you are planning for maven-compiler-plugin and
maven-surefire-plugin to support.
It tests with the main code on the modulepath and the test code on the
classpath.
While this is fine for many use cases, sometimes you really need to
run the tests on the modulepath, so this is not sufficient by itself.

2) Blackbox testing with two module-info.java files.
This is supported by IntelliJ and Gradle IIUC. Maven must support this IMO.

For maven-compiler-plugin, Blackbox tests are fine AFAICT. All the
files in src/test/java are in a different package, and the
module-info.java file refers to a different module name, so there are
no clashes. The maven-surefire-plugin would just put the main module
and the test module on the modulepath, and everything ought to be
fine.

I believe Gradle recommends src/integrationTest for blackbox tests,
and I think that convention makes a lot of sense. It offers up the
potential for a single Maven module to contain both whitebox and
blackbox tests, which is incredibly powerful.

3) Whitebox testing with two module-info.java files.
This has yet to achieve an agreed approach in the community, despite
JPMS being out for many years.

To work effectively, it might be beneficial for the module-info file
to be named module-info-whitebox.java, or alternatively be in
src/whitebox.

Option A) "Parse and Patch"
maven-compiler-plugin would find the whitebox module-info source file,
parse it directly and convert it to command line options based on
--patch-module.
maven-compiler-plugin would then compile the test classes excluding
the whitebox module-info source file using the derived command line
options.
maven-surefire-plugin would use the same derived command line options.

Option B) "Merge and Recompile"
maven-compiler-plugin would compile the test classes by including both
src/main/java and src/test/java as inputs, excluding the
src/main/java/module-info.java file
maven-surefire-plugin would run only with target/test-classes, not
target/classes

Option C) "Copy before Compile"
maven-compiler-plugin would first copy target/classes to
target/test-classes excluding target/classes/module-info.class
maven-compiler-plugin then compiles src/test/java to
target/test-classes, without using target/classes as an input
maven-surefire-plugin would run only with target/test-classes, not
target/classes

I believe Option A is more desirable, and more in the spirit of JPMS,
and more in the spirit of Maven.

I understand that you want to make defining patch-module directives
easier in pom.xml. While that's a lovely idea, I think it is
fundamentally flawed in usability. There is no connection in the mind
of a developer between module-info directives and the matching command
line arguments. By contrast developers know exactly how to setup the
module-info.java file.

The only real difference I'm proposing is that the patch-module
directives are not defined in pom.xml, but are instead defined in a
java-like source file, eg module-info-whitebox.java. Think of it as a
Maven config file which happens to look like a java source file and it
really isn't that scary.

( I think it makes sense for this to be part of maven-compiler-plugin,
but it could also be a separate plugin that runs before
maven-compiler-plugin, or a separate goal. For example, it could be
thought of as a converter/compiler from module-info-whitebox.java to
module-info-whitebox.javac.args)

Stephen

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@maven.apache.org
For additional commands, e-mail: users-h...@maven.apache.org

Reply via email to