-
Notifications
You must be signed in to change notification settings - Fork 65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Include buildtool support for bundling reachability metadata into jar files #322
Conversation
Thank you for your pull request and welcome to our community! To contribute, please sign the Oracle Contributor Agreement (OCA).
To sign the OCA, please create an Oracle account and sign the OCA in Oracle's Contributor Agreement Application. When signing the OCA, please provide your GitHub username. After signing the OCA and getting an OCA approval from Oracle, this PR will be automatically updated. |
There are four commits in this pull-request. The first updates common support code to enable copying. The second adds Maven support and the third adds Gradle support. The fourth commit is a minor refactoring that attempts to remove duplicated code. It isn't directly related to this pull-request and could be dropped or submitted as another PR if required. |
1b36eb1
to
733d67b
Compare
approved by me as a contribution. Will let the engineers comment on the details :) |
Thanks for the PR, @philwebb ! I took a quick look at the PR and will submit some review comments. Regarding the feature itself, I think it's a reasonable thing to have an option to copy the metadata in some output directory, even if technically speaking, as we see today, this is not required for native image to build. It's interesting for debugging purposes, and possibly for what you are mentioning. However...
I'm still not convinced that bundling metadata in the jar is the right thing to do. I understand that this is aimed at final applications, not libraries, but it could create a precedence for what we ask folks not to do (have a jar provide metadata about transitive libraries).
I don't think that stands true.
This is only the case if you don't use the native build tools, right? Because we are reproducible: the repo has a default version, and if not using the default version, you need to provide the repository itself, which means that even if the repository changes, you would still build against the same version of the repository. So I understand this feature is in case you don't use a build tool to build the native image and try to emulate the feature. I wouldn't recommend, personally, to do this. For Micronaut for example, we provide a way to build native images in Docker, using the same build process, so it doesn't matter if you build locally or on CI. So this feature probably only makes sense if, for some reason, you plan to not use NBT, in which case you need:
So I'm not against this PR, but we should be clearer with regards to what it is suitable for, and I would not recommend to put the metadata in the jar (actually I would suggest to publish another artifact, possibly with a classifier, which only contains metadata, and possibly other "build reproducibility" metadata). |
The Maven goal and Gradle task are pretty generic at the moment, the only problem is the defaults that I picked. If we change things so that the destination always needs to be specified, would that be better? That way we're adding general purpose tasks/goals without guiding the user in potentially bad practices. I can also change the documentation to remove any suggestion of adding files to jars.
Right. If you're always using NBT then the metadata repository is pinned and things are repeatable. The reproducibility only happens if you want some other process to create the native image. In that case, for the other process to work it will either need the metadata, or it will need to know the GAVs of dependencies and the version of the metadata repository to use.
I think that's something we'd like to do eventually as well. There's a lot less ceremony in creating a Docker image for a native executable. It's basically a There is one benefit of having Source -> Jar -> Native Image, namely that you can take the same jar and create native images for lots of different architectures. As I understand it, you can't currently create an MacOS executable on a Linux OS.
If we make the goal/task general purpose then I think folks could use it to create copy the files wherever they see fit. I suspect it would be quite easy to configure a Gradle build to create a distinct artifact. I imagine it's also possible with Maven, albeit with more configuration. Thanks for taking the time to look it. I'll await your feedback then update the PR. |
...lvm-reachability-metadata/src/main/java/org/graalvm/reachability/DirectoryConfiguration.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have added comments on the implementation for the Gradle plugin, I haven't looked at the Maven side yet (possibly @alvarosanchez can look?).
native-gradle-plugin/src/main/java/org/graalvm/buildtools/gradle/NativeImagePlugin.java
Outdated
Show resolved
Hide resolved
...e-plugin/src/main/java/org/graalvm/buildtools/gradle/tasks/ReachabilityMetadataCopyTask.java
Outdated
Show resolved
Hide resolved
As long as we don't do something by default for the
Yes, that would be pretty straightforward.
No idea. |
733d67b
to
5504407
Compare
@melix I've forced pushed an update addressing the previous review comments. The only one I'm not too sure about is registering the task by default. I've gone with a simple I picked |
Not sure I would prefix pure metadata generation by I will discuss the |
It happens that we already have a So maybe, for this new task, we should use a different name like |
What about |
The task already exists as |
I like |
Update `DirectoryConfiguration` with a new `copy` method that can be used to copy matadata files into `META-INF/native-image` directories. The `DirectoryConfiguration` class now has group, artifact and version information so that it can write files into the appropriate folder. The `copy` method will also write a `reachability-metadata.properties` file that indicates if the 'override' property was set on the metadata.
5504407
to
65d3f63
Compare
Forced push with the suggested task name. |
65d3f63
to
dc74f77
Compare
@alvarosanchez do you have time to review the Maven side of this PR or should I give it a try? |
Update the maven plugin with a new `add-metadata-hints` goal that can be used to bundle hints obtained from the metadata repository into the jar.
Update the gradle plugin with a new `ReachabilityMetadataCopyTask` class that can be used to copy hints obtained from the metadata repository.
Refactor the `configureJvmReachabilityConfigurationDirectories` and `configureJvmReachabilityExcludeConfigArgs` to use a common method since they share the same logic.
dc74f77
to
9d6e9e8
Compare
Thanks everyone for the feedback and fast turnaround. |
Thanks to you for this epic contribution! |
I believe that this request was discussed recently with @bclozel who kindly wrote the following:
Motivation
Currently, Native Build Tools build plugins fetch reachability metadata from the official repository right before building a native image of the application.
While the library in charge of fetching the metadata repository is available and can be reused in different contexts, there is still a non-trivial amount of code required to do the following:
Frameworks using NBT can generate their own reachability metadata before packaging the application as a JAR.
It would be useful if vanilla or shaded JARs could be packaged with all the required reachability metadata (Framework + metadata repository) so that such JARs could be used by CI or cloud infrastructure to generate a native image directly.
This would provide the following advantages:
Requested behavior
The current change proposal would require a new build tool task, for the Maven and Gradle plugins. Those tasks would: