编辑: 我分析了给出的答案。特别是我测试了Till Brychcy的假设,这个假设似乎成立了,但开了更多问题。 我在以下大分隔符之后将分析添加到问题的结尾: “-----------分析Till Brychcy的回答----------”
它以某种方式编译并在IJ中运行,但是mvn clean install
无法编译测试
我有一个包含2个模块的java 9 maven项目:apimod
和clientmod
。
模块clientmod
依赖于模块apimod
(这些模块都是Maven模块和Java 9模块)。
此外,我希望模块clientmod
不仅能够重用apimod
的生产代码,还能重用测试代码。
这是一种常见的模式,我在Java 8中多次使用过。
使用Java 9(它与Java 10相同)它也可以正常工作,只要我不声明module-info.java
(也就是说,只要我不运行模块系统)。
但是,只要我这样做,启用测试依赖项似乎会禁用生成依赖项:api.Base
(src/main
模块apimod
类)不再可见{{1 (client.test.DerivedTest
模块src/test
类。测试不再编译。
这是Maven还是Java 9中的错误?这是最新版本:Java 9.0.4(与Java 10相同),Maven 3.5.3,maven-compiler-plugin 3.7.0
源代码位于:
clientmod
我在分支机构中测试失败的问题“二分”:
git clone https://github.com/vandekeiser/wires.git
- > BUILD FAIL(git checkout MINIMIZE_ISSUE
`mvn clean install`
的测试中的编译错误)
我希望模块clientmod
不仅能够重用clientmod
的生产代码,还能重用测试代码。使用Maven,你可以这样做(apimod
):
clientmod/pom.xml
<dependency>
<groupId>fr.cla</groupId>
<artifactId>apimod</artifactId>
<version>${project.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
使用Java 9,如果我声明测试范围的依赖项和Java 9模块,则测试不再编译(module apimod {
exports api;
}
module clientmod {
requires apimod;
}
输出):
mvn clean install
就好像启用测试依赖项([ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.7.0:testCompile (default-testCompile) on project clientmod: Compilation failure
[ERROR] /G:/projets/wires/wires/wires/clientmod/src/test/java/client/test/DerivedTest.java:[8,22] cannot access api.Base
[ERROR] class file for api.Base not found
)会禁用生产依赖项(src/test
)。我知道在这种情况下,Maven应该使用javac src/main
标志。
所以我只使用javac(使用--patch-module
的调试输出)重现了这个问题:
相同的编译,跳过Maven:
mvn -X
相同的编译错误:
javac "G:\projets\wires\wires\wires\clientmod\src\test\java\client\test\DerivedTest.java" \
-d "G:\projets\wires\wires\wires\clientmod\target\test-classes" \
-classpath "G:\projets\wires\wires\wires\clientmod\target\test-classes;" \
--module-path "G:\projets\wires\wires\wires\apimod\target\apimod-1.0-SNAPSHOT-tests.jar;G:\projets\wires\wires\wires\clientmod\target\classes;G:\projets\wires\wires\wires\apimod\target\apimod-1.0-SNAPSHOT.jar;" \
-sourcepath "G:\projets\wires\wires\wires\clientmod\src\test\java;" \
--release 9 \
-Xlint:all \
--patch-module clientmod="G:\projets\wires\wires\wires\clientmod\target\classes;G:\projets\wires\wires\wires\clientmod\src\test\java;"
我尝试使用应该禁用模块系统的javac标志,但它们似乎不存在于我的64位Windows Oracle JVM中? (Java HotSpot(TM)64位服务器VM(版本9.0.4 + 11,混合模式):
G:\projets\wires\wires\wires\clientmod\src\test\java\client test\DerivedTest.java:8: error: cannot access Base
new Derived().equals(null); ^
class file for api.Base not found
1 error
添加(逻辑上不需要,绝望中完成)导出或读取也不会改变任何内容:
javac --illegal-access=warn
javac: invalid flag: --permit-illegal-access
javac --permit-illegal-access
javac: invalid flag: --illegal-access=warn
mvn -version的输出:
--add-reads apimod=ALL-UNNAMED \
--add-reads clientmod=ALL-UNNAMED \
--add-exports apimod/api=ALL-UNNAMED \
--add-exports clientmod/client=ALL-UNNAMED \
感谢您的详细解答,基本上就是“看起来maven还不支持这个用例”
- &gt;所以让我们尝试重现没有maven的问题。我为这些试验创建了分支Apache Maven 3.5.3 (3383c37e1f9e9b3bc3df5050c29c8aff9f295297; 2018-02-24T20:49:05+01:00)
Maven home: G:\software\apache-maven-3.5.3
Java version: 9.0.4, vendor: Oracle Corporation
Java home: C:\Program Files\Java\jdk-9.0.4
Default locale: fr_FR, platform encoding: Cp1252
OS name: "windows 7", version: "6.1", arch: "amd64", family: "windows"
(抱歉这个令人困惑的分支名称)。
调整我以前的maven记录的命令行,即:
TRY_ADAPT_khmarbaise-MINIMIZE_ISSUE
我从javac "G:\projets\wires\wires\wires\clientmod\src\test\java\client\test\DerivedTest.java"
-d "G:\projets\wires\wires\wires\clientmod\target\test-classes"
-classpath "G:\projets\wires\wires\wires\clientmod\target\test-classes;"
--module-path "G:\projets\wires\wires\wires\apimod\target\apimod-1.0-SNAPSHOT-tests.jar;G:\projets\wires\wires\wires\clientmod\target\classes;G:\projets\wires\wires\wires\apimod\target\apimod-1.0-SNAPSHOT.jar;"
-sourcepath "G:\projets\wires\wires\wires\clientmod\src\test\java;"
--release 9
-Xlint:all
--patch-module clientmod="G:\projets\wires\wires\wires\clientmod\target\classes;G:\projets\wires\wires\wires\clientmod\src\test\java;"
--add-reads apimod=ALL-UNNAMED
--add-reads clientmod=ALL-UNNAMED
--add-exports apimod/api=ALL-UNNAMED
--add-exports clientmod/client=ALL-UNNAMED
--add-modules apimod
G:\projets\wires\wires\wires\apimod\target\apimod-1.0-SNAPSHOT-tests.jar;
我将其添加到--module-path
,给我:
--patch-module clientmod
- &gt;好的,它现在编译!所以你的假设maven-compiler-plugin或maven不支持这个似乎已经过验证。 但是我认为它应该在我使用的版本中得到支持,这是最新版本。我想知道从哪里开始检查..
无论如何,与此同时,我尝试明确配置maven-compiler-plugin,但无济于事。 我试过的一般结构是(maven-compiler-plugin.version = 3.7.0):
javac "G:\projets\wires\wires\wires\clientmod\src\test\java\client\test\DerivedTest.java" \
-d "G:\projets\wires\wires\wires\clientmod\target\test-classes" \
-classpath "G:\projets\wires\wires\wires\clientmod\target\test-classes;" \
--module-path "G:\projets\wires\wires\wires\clientmod\target\classes;G:\projets\wires\wires\wires\apimod\target\apimod-1.0-SNAPSHOT.jar;" \
-sourcepath "G:\projets\wires\wires\wires\clientmod\src\test\java;" \
--release 9 \
-Xlint:all \
--patch-module clientmod="G:\projets\wires\wires\wires\clientmod\target\classes;G:\projets\wires\wires\wires\clientmod\src\test\java;G:\projets\wires\wires\wires\apimod\target\apimod-1.0-SNAPSHOT-tests.jar;" \
--add-reads apimod=ALL-UNNAMED \
--add-reads clientmod=ALL-UNNAMED \
--add-exports apimod/api=ALL-UNNAMED \
--add-exports clientmod/client=ALL-UNNAMED \
--add-modules apimod
我尝试了以下<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<release>${java.version}</release>
<compilerArgs>
[...]
</compilerArgs>
</configuration>
</plugin>
(xml注释中相应的mvn clean install错误):
1:
compilerArgs
2:
<!--1. Syntaxically OK, but:-->
<!--[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.7.0:compile (default-compile) on project apimod: Compilation failure: Compilation failure:-->
<!--[ERROR] /G:/projets/wires/wires/wires/apimod/src/main/java/api/Base.java:[1,1]-->
<!--file should be on source path, or on patch path for module-->
<!--[ERROR] /G:/projets/wires/wires/wires/apimod/src/main/java/module-info.java:[1,1]-->
<!--file should be on source path, or on patch path for module-->
<compilerArgs>
<arg>--class-path=/G/projets/wires/wires/wires/clientmod/target/test-classes;</arg>
<arg>
--module-path=/G/projets/wires/wires/wires/clientmod/target/classes;/G/projets/wires/wires/wires/apimod/target/apimod-1.0-SNAPSHOT.jar;
</arg>
<arg>--source-path=/G/projets/wires/wires/wires/clientmod/src/test/java;</arg>
<arg>-Xlint:all</arg>
<arg>
--patch-module=clientmod=/G/projets/wires/wires/wires/clientmod/target/classes;/G/projets/wires/wires/wires/clientmod/src/test/java;/G/projets/wires/wires/wires/apimod/target/apimod-1.0-SNAPSHOT-tests.jar;
</arg>
<arg>--add-reads=apimod=ALL-UNNAMED</arg>
<arg>--add-reads=clientmod=ALL-UNNAMED</arg>
<arg>--add-exports=apimod/api=ALL-UNNAMED</arg>
<arg>--add-exports=clientmod/client=ALL-UNNAMED</arg>
<arg>--add-modules=apimod</arg>
</compilerArgs>
答案 0 :(得分:2)
看起来maven还没有支持这个用例。
问题是apimod-1.0-SNAPSHOT-tests.jar
被视为自动模块,其自动模块名称(从文件名派生)是&#34; apimod
&#34;,因此实际模块{{ <{1}}中的{}}(稍后出现在模块路径上)将被忽略。
Maven应检测到apimod
属于apimod-1.0-SNAPSHOT.jar
并使用apimod-1.0-SNAPSHOT-tests.jar
而非使其成为apimod
的一部分
答案 1 :(得分:1)
现在可以使用!在那里有所有解释:https://issues.apache.org/jira/browse/MCOMPILER-348
问题是名称冲突:在问题减少分支和main-dev分支中,将maven模块的名称更改为不同于修复它的Java模块的名称。
尽管如此,我仍然有一个警告(请参阅链接),现在我忽略了它,但是它需要继续。
---------------如果JIRA消失了,链接内容的副本-----------
Robert Scholte : 我的猜测是apimod-1.0-SNAPSHOT-tests.jar应该在类路径上,而不是在模块路径上。我能想到的唯一原因就是它的自动模块名称也是apimod。 将名称更改为与自动模块名称不冲突的名称可解决此问题(例如info.example.apimod) 通常,请选择一个更唯一的模块名,它必须是全局唯一的(就像classpath上的类一样)。添加reverseDNS或共享软件包。 永久链接编辑删除
我: 是的,非常感谢!我以为这是一个bug(但是,可能还有一些较小的bug?我还需要进一步研究,但是仍然有javac警告-请参阅结尾)。此评论)。
它固定了二分法分支和主分支: -在二分法分支中,我为java模块添加了前缀 -回到主分支后,我将Maven模块wires.core-> wires-core等重命名,并将java模块重命名为共享根包,也避免了名称冲突
用“ Java迷惑者”的术语来说,这也许是双重的: -对于API(Maven)的用户:请遵循命名约定:我不应该用'来命名Maven模块。分隔器。我会不考虑名称就避免冲突。 -对于API的设计人员:如果您可以检测到此冲突,则可能会记录一条有意义的消息,因为很难看到它何时发生
最后,我仍然收到javac警告。因此,现在我必须忽略出口警告。
我尚未对此进行调查,但是这里是:
[WARNING] COMPILATION WARNING :
[INFO] -------------------------------------------------------------
[WARNING] /G:/projets/wires/wires/wires/wires-core/src/test/java/fr/cla/wires/core/MavenVsJavaModulesReproduceTest.java:[9,54] class fr.cla.wires.support.oo.ddd.AbstractValueObjectTest in module is not exported
[INFO] 1 warning
[INFO] -------------------------------------------------------------
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] /G:/projets/wires/wires/wires/wires-core/src/test/java/fr/cla/wires/core/MavenVsJavaModulesReproduceTest.java: warnings found and -Werror specified
[INFO] 1 error
要重现它,请在master分支(https://github.com/vandekeiser/wires.git)中检出标签WARN_IF_UNCOMMENT并在以下位置删除导出异常: -Xlint:所有,串行,导出
我不能(也不必)从fr.cla.wires.support.oo.ddd添加出口;进入module-info.java,因为它引用的是src / test中的软件包
那是现在的地方