[ 
https://issues.apache.org/jira/browse/MCOMPILER-320?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16329558#comment-16329558
 ] 

David M. Lloyd commented on MCOMPILER-320:
------------------------------------------

Thanks for the feedback.  A new "compile-only" scope would definitely be good 
but it would not solve either of my two present immediate use cases.

Case 1 is that if you build a project in Java 9, and use {{--release=8}} (i.e. 
{{<release>8</release>}}) then the sun.misc and sun.reflect packages are not 
included in the class path.  They must be stubbed, however you absolutely do 
_not_ want to have the stubs appear in _any_ context other than the exact 
compilation, otherwise severe problems will occur: the JVM could even crash.  A 
new scope _almost_ solves this, but not quite, because you might only want to 
include the stub in one execution.  What if you have more than one?  Which 
brings us to case 2.

Case 2 is that currently the best way of building an MR JAR can be done by way 
of multiple executions.  But in order to do this, the overlay executions must 
include, on the class path, each earlier execution's output classes.

Here's an example of both cases being done at once; this is using a version of 
the plugin which contains my proposed patch:

{code:xml}
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.7.1-SNAPSHOT</version>
                <executions>
                    <!-- here I'm disabling the default compilation because of 
my parent POM; you could make the Java 8 step be the default though -->
                    <execution>
                        <id>default-compile</id>
                        <phase>none</phase>
                    </execution>
                    <!-- this compiles the base layer; however the release=8 
option prevents sun.misc from being visible -->
                    <execution>
                        <id>compile-java8</id>
                        <phase>compile</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                        <configuration>
                            <release>8</release>
                            
<buildDirectory>${project.build.directory}</buildDirectory>
                            
<compileSourceRoots>${project.compileSourceRoots}</compileSourceRoots>
                            
<outputDirectory>${project.build.outputDirectory}</outputDirectory>
                            <!-- this dependency is manually downloaded using 
the dependency plugin below -->
                            <additionalCompilePathItems>
                                
<additionalCompilePathItem>${project.build.directory}/sun-misc.jar</additionalCompilePathItem>
                            </additionalCompilePathItems>
                        </configuration>
                    </execution>
                    <!-- this compiles the Java 9 layer; sun.misc is not a 
problem here but we also need to include our base classes in the compilation -->
                    <execution>
                        <id>compile-java9</id>
                        <phase>compile</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                        <configuration>
                            <release>9</release>
                            
<buildDirectory>${project.build.directory}</buildDirectory>
                            
<compileSourceRoots>${project.basedir}/src/main/java9</compileSourceRoots>
                            <!-- we can output directly into the appropriate 
target directory; this works out nicely -->
                            
<outputDirectory>${project.build.directory}/classes/META-INF/versions/9</outputDirectory>
                            <!-- here is where we include the base classes -->
                            <additionalCompilePathItems>
                                
<additionalCompilePathItem>${project.build.outputDirectory}</additionalCompilePathItem>
                            </additionalCompilePathItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <!-- here we download the stubbed out sun.misc and 
sun.reflect into target for use up above -->
                    <execution>
                        <id>fetch-misc</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>get</goal>
                            <goal>copy</goal>
                        </goals>
                        <configuration>
                            
<artifact>org.jboss:sun-misc:1.Final-SNAPSHOT</artifact>
                            
<outputDirectory>${project.build.directory}</outputDirectory>
                            <stripVersion>true</stripVersion>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
{code}

This makes use of several basic defining features of Maven: the ability to have 
multiple executions, the usage of maven-dependency-plugin to fetch dependencies 
by way of specific goals, etc.

The only missing piece is the ability to add class path entries.

I am enormously skeptical that a practical high-level solution to MR JARs will 
appear in Maven _ever_.  Even if I was wrong and it would happen, I am 
extremely confident that it would be inadequate for any non-trivial case, and 
furthermore, as a maintainer of many frameworks, I contend that most any case 
where a framework _would_ require MR JARs would be a non-trivial case.  This is 
due to the fact that some of the key APIs that are motivating factors in 
producing MR JARs - namely sun.misc.Unsafe and sun.reflect.ReflectionFactory - 
have to be specially handled in the way that I have done above.  It is unlikely 
that a single compiler plugin pass, no matter how enhanced, would be able to 
cope with this situation, nor would it be able to cope with any other situation 
where different layers of the JAR would require different compiler parameters - 
a situation that seems inevitable to me.  I don't think there is a better 
solution to MR JAR than the one I've worked up in this example.

We could maintain our own fork of this plugin, but that would be a bit 
ridiculous: nothing in this proposed change opposes what I would call a 
rational interpretation of the spirit of Maven's design, or of the design of 
javac.

> Allow additional class path items to be given during compilation
> ----------------------------------------------------------------
>
>                 Key: MCOMPILER-320
>                 URL: https://issues.apache.org/jira/browse/MCOMPILER-320
>             Project: Maven Compiler Plugin
>          Issue Type: New Feature
>            Reporter: David M. Lloyd
>            Priority: Major
>
> At present it is very difficult to include additional class path items during 
> compilation that are not dependencies.  But this is a very useful capability, 
> especially when doing partial builds, MR JARs, JDK API stubbing, including 
> dependency items that cannot be included in any other build phase or 
> execution, etc.
> This enhancement and pull request are to request the addition of a 
> {{additionalCompilePathItems}} property in CompilerMojo or 
> AbstractCompilerMojo which includes additional filesystem paths in the 
> compilation class path.



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

Reply via email to