Skip to content

native-image-maven-plugin: Optionally read mainClass from resources #2568

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

Closed
jkroepke opened this issue Jun 15, 2020 · 15 comments
Closed

native-image-maven-plugin: Optionally read mainClass from resources #2568

jkroepke opened this issue Jun 15, 2020 · 15 comments
Assignees
Labels

Comments

@jkroepke
Copy link

Feature request

Please include the following information:

Is your feature request related to a problem? Please describe.
If I want to use native-image-maven-plugin I have to define the main class by myself.

Describe the solution you'd like.
Some framework like spring boot provide additional dependency the enrich the native-image experience. Currently there is no away that a dependency (like spring-graalvm-native) can define the main-class.

Currently its possible that such plugins can set build argument via META-INF like this:

https://github.com/spring-projects-experimental/spring-graalvm-native/blob/6e4825f471a52a40abc8edb4b6cb306953f30511/spring-graalvm-native/src/main/resources/META-INF/native-image/org.springframework.experimental/spring-graal-native/native-image.properties#L1

A lot of framework like spring or quarkus requires such annotation like QuarkusMain or SpringBootApplications on the main classes.

Build plugin like https://github.com/spring-projects-experimental/spring-graalvm-native cloud detect such classes and can write the information to flies target/classes/META-INF/native-image/main-class.

The native-image-maven-plugin should read such files and set it -H:Class to the content if this file.

Describe who do you think will benefit the most.
Less manual configuration. More works out of the box.

Describe alternatives you've considered.
Plugin like native-image-maven-plugin could call native-image directly (like quarkus) but each framework need to implement this.

Additional context.
spring-attic/spring-native#179

@olpaw
Copy link
Member

olpaw commented Jun 16, 2020

The native-image-maven-plugin already supports several ways to automatically detect what the main-class should be:
https://github.com/oracle/graal/blob/master/substratevm/src/native-image-maven-plugin/src/main/java/com/oracle/substratevm/NativeImageMojo.java#L365-L373
Using any of these standard maven plugins (maven-shade-plugin, maven-assembly-plugin or maven-jar-plugin) to specify the main-class is enough to make native-image-maven-plugin guess the correct main-class.

Also nothing prevents a user from specifying the main class in a native-image.properties file. E.g. using

Args = --no-server -H:Class=my.App

will ensure native-image builds with my.App as the main class. With a native-image.properties like that you only need the following in your pom-file to build the image.

<plugin>
    <groupId>org.graalvm.nativeimage</groupId>
    <artifactId>native-image-maven-plugin</artifactId>
    <version>${graalvm.version}</version>
    <executions>
        <execution>
            <goals>
                <goal>native-image</goal>
            </goals>
            <phase>package</phase>
        </execution>
    </executions>
</plugin>

@webfolderio
Copy link

webfolderio commented Jun 16, 2020

Graal shouldn't adapt itself to frameworks. Framework should find a proper way to integrate to native-image. The problem is frameworks not Graal. They do many magic thinks and broke the standard Java features. The only way to start Java application is defining standard main method. These magic frameworks broke the standard way and Developers complaint that my framework didnt work with Graal.

@jkroepke
Copy link
Author

Hi @olpaw

thanks for response. I saw the code for reading the main class from the pom.xml already before opened this PR.

Append the -H:Class= option to the native-image.properties file is good idea, maybe a little bit fragile.

What did you think about a property called MainClass like ImageName property?

@olpaw
Copy link
Member

olpaw commented Jun 16, 2020

What did you think about a property called MainClass like ImageName property?

We already have that for the MacroOptions usecase of native-image.properties files:

String imageClass = enabledOption.getProperty(config, "ImageClass");

Feel free to contribute a PR that also unlocks that property for the META-INF/native-image usecase of native-image.properties files.

@jkroepke
Copy link
Author

Feel free to contribute a PR that also unlocks that property

This is the correct place to add it?

Map<String, String> properties = loadProperties(Files.newInputStream(resourcePath));
String imageNameValue = properties.get("ImageName");
if (imageNameValue != null) {
addCustomImageBuilderArgs(oHName + resolver.apply(imageNameValue));
}
forEachPropertyValue(properties.get("JavaArgs"), this::addImageBuilderJavaArgs, resolver);
forEachPropertyValue(properties.get("Args"), args, resolver);

@olpaw
Copy link
Member

olpaw commented Jun 16, 2020

This is the correct place to add it?

Yup

@jkroepke
Copy link
Author

Hm, maybe someone with an already signed OCA can adopt my pull request.

sdeleuze added a commit to spring-attic/spring-native that referenced this issue Feb 27, 2021
Does not work because Maven plugin passes -H:Class=${start-class} upfront
when mainClass is not defined.

Using manifest file is not possible for our use case because it is controlled
by the Jar plugin.

I tries to write Maven configuration with Xpp3Dom API but it seems not taken
account (I guess by default).

So I am out of option without a change on GraalVM side.

See oracle/graal#2568 and
oracle/graal#2593.
sdeleuze added a commit to spring-attic/spring-native that referenced this issue Feb 27, 2021
Does not work because Maven plugin passes -H:Class=${start-class} upfront
when mainClass is not defined.

Using manifest file is not possible for our use case because it is controlled
by the Jar plugin.

I tries to write Maven configuration with Xpp3Dom API but it seems not taken
account (I guess by design).

So I am out of option without a change on GraalVM side.

See oracle/graal#2568 and
oracle/graal#2593.
@sdeleuze
Copy link
Collaborator

@olpaw I have tried to move forward on that on Spring Native side, but I think I am blocked.

My draft commit tried to add -H:Class=FooApplication to native-image.properties but it does not work because, I think, Maven plugin passes -H:Class=${start-class} upfront when mainClass is not defined. So I get Error: Main entry point class '${start-class}' not found.

Using manifest file is not possible for our use case because it is controlled by the Jar plugin.

I tries to write Maven configuration with Xpp3Dom API but it seems not taken account (I guess by design).

So I am out of option without a change on GraalVM side.

I am not sure if the solution is #2593 contributed by @jkroepke, or if you just need to avoid setting -H:Class=${start-class} on Maven plugin side when not defined. But I would like a way to move forward on this for Spring if possible.

@jkroepke
Copy link
Author

Feel free to adopt #2593, the OCA sign process is to complicated and I'm not going to sign it, expect there is an online only solution.

@thomaswue
Copy link
Member

OK, thank you. There is btw now a new online only version that went live just today: https://oca.opensource.oracle.com/

@olpaw
Copy link
Member

olpaw commented Mar 5, 2021

@sdeleuze, fyi, @gradinac is currently fixing this by making sure our plugin evaluates ${start-class} before using its value.

@jkroepke
Copy link
Author

jkroepke commented Mar 5, 2021

@olpaw does this mean, my PR is obsolete?

@olpaw
Copy link
Member

olpaw commented Mar 5, 2021

@jkroepke the problem @sdeleuze described in #2568 (comment) is better addressed by making the native-image-maven-plugin behave correctly when it looks up the <mainClass> node from maven-shade-plugin, maven-assembly-plugin, maven-jar-plugin configurations (in that order) in the pom. So far the value of that node was always taken literally instead of evaluating it first with the PluginParameterExpressionEvaluator.

Your PR extends what can be used in native-image.properties. So it's something else.

@wirthi
Copy link
Member

wirthi commented Jan 24, 2024

I assume this can be closed. #2593 has been closed 3 years ago, and a new major version with Spring Boot been release.

If this is still a problem with current version, please let us know the details (either reopening this issue or creating a new one).

@wirthi wirthi closed this as completed Jan 24, 2024
@sarnobat
Copy link

sarnobat commented Aug 14, 2024

Graal shouldn't adapt itself to frameworks. Framework should find a proper way to integrate to native-image. The problem is frameworks not Graal. They do many magic thinks and broke the standard Java features. The only way to start Java application is defining standard main method. These magic frameworks broke the standard way and Developers complaint that my framework didnt work with Graal.

Apologies if I've not followed everything in this discussion but since Main-Class inside a MANIFEST.MF is a standard, shouldn't downstream tools be smart enough to read it?

It would be nice if you could just take an executable jar and convert it into a native image without having to know anything about the internals of the executable jar. It should be a pipeline style build process, not going back and understanding logic in step (n-2). Conceivably, the builder of the native image may be far removed from the author of the jar (ok I admit this is simplistic since reflection makes it necessary to understand what classes for the linker to retain, which we specify in properties; I guess I mean in a perfect world...i.e. future version 😄 ).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

8 participants