zyxist / chainsaw

Gradle plugin: adds support for building Java 9 modules.
Apache License 2.0
71 stars 4 forks source link

Please support having non-module-enabled / auto-modules sub-projects #15

Open Vampire opened 6 years ago

Vampire commented 6 years ago

If you mix module-enabled projects and non-module-enabled projects (auto-modules), your plugin fails during module-name detection. In my case the application subproject does not have a module-info.java. Not doing anything might still be the wrong way here, as e. g. the start scripts need manipulation non-the-less.

zyxist commented 6 years ago

Auto-modules were thought as a solution to use old JARs with Jigsaw, and I think that making a project that contains both modular code, and a non-modular application is a misuse. Is there any reason that your application subproject doesn't have a module descriptor?

Anyway, there is an easy workaround for that: create a subproject for all Jigsaw subprojects, and apply chainsaw there. The second subproject would group all non-modular subprojects, and chainsaw is not applied there.

Vampire commented 6 years ago

I'm just writing the build for the already existing project. I have to clarify why it is like that, but I think it would be nice if your plugin would support it as Java does support it.

I'm not sure your workaround would work, your plugin would then not modify the generated start scripts for example.

zyxist commented 6 years ago

OK, so basically - you want to have an automatic module with application project, but use Jigsaw --module-path instead of the classpath. I still have some objections against such a design, but they are rather theoretical, not practical. In other words, my objections don't come from a real-world example, and I want to make a plugin that is useful, and practical. So let's give your idea a try.

Let's say that the behavior could look like this:

I think that compiling the auto-module in Jigsaw mode makes little sense, because you would need a lot of extra flags to emulate the missing module descriptor, and you don't run a library. In case of application, you have some benefits of running JVM in Jigsaw mode, even if the main project is an auto-module.

Do you think such a design would solve your use case?

Vampire commented 6 years ago

I guess so. I'm trying to achieve that we also module-enable the application project actually. But I'm maybe not the only one with that case or can hit it again. Or there were reasons to do it like that I'm not yet aware of.

Vampire commented 6 years ago

Btw. while trying to make the application project a module, I found out why they did not and got another user-case where this here is necessary. log4j 2.10.0 has a bug, it forgot to declare two uses, so to use it with modules I need a --patch-module flag with a JAR that dynamically adds the uses declaration with Module#addUses which is only possible from within the same module. So I need a non-module JAR built that does this call and then use the module patching to add it to the module.

zyxist commented 6 years ago

Have you tried adding them, using a pre-JDK9 legacy mechanism? I mean putting an entry in META-INF/services.

https://docs.oracle.com/javase/7/docs/api/java/util/ServiceLoader.html

Vampire commented 6 years ago

That is only partly legacy. You still use the ServiceLoader to load the services that the consumer declares with uses and the provider declares with provides in the module-info.java. The problem is, if you use the ServiceLoader in a proper named module without declaring the uses in the module-info.java, the JRE chickens out and is gone.

zyxist commented 6 years ago

OK, just post me a link to the original Log4j issue, so that I could replicate it in the integration tests.

Vampire commented 6 years ago

The log4j issue is https://issues.apache.org/jira/browse/LOG4J2-2129, but it is not really directly relevant and I even got it working now differently, so the example was maybe not good. There the only problem now is that I have patch project(':log4j-api-patch') and javaModule.hacks { patches 'my.group:log4j-api-patch', 'org.apache.logging.log4j' } in the real project and thus you remove the project from all other dependencies and the JAR gets not build because of that. I needed to add compileJava.dependsOn project(':log4j-api-patch').jar to get it built when necessary, that could maybe improved in chainsaw. But the original problem here persist.