maven-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "David M. Lloyd (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (MCOMPILER-320) Allow additional class path items to be given during compilation
Date Wed, 17 Jan 2018 22:07:00 GMT

    [ 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)

Mime
View raw message