Skip to content

Commit bcfa736

Browse files
committed
Add exclusions to Maven plugin
This commit adds an `exclusions` parameter to the Maven plugin, which can be used to exclude dependencies from the compile classpath of native image. It can be used to remove some dependencies from compilation, such as these injected by Spring Boot for development. Note, however, that if the main jar is configured to have the manifest with `addClaspath` to true, then the manifest file will still reference the jar, and native compile will issue a warning (because the jar will be missing from classpath). Fixes #612
1 parent cbb3776 commit bcfa736

File tree

7 files changed

+247
-3
lines changed

7 files changed

+247
-3
lines changed

docs/src/docs/asciidoc/changelog.adoc

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77

88
- Added options to override parameters from command line
99

10+
=== Maven plugin
11+
12+
- Add support for dependency exclusions
13+
1014
== Release 0.10.5
1115

1216
- Add missing getters to `DirectoryConfiguration`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
~ Copyright (c) 2020, 2021 Oracle and/or its affiliates. All rights reserved.
4+
~ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
~
6+
~ The Universal Permissive License (UPL), Version 1.0
7+
~
8+
~ Subject to the condition set forth below, permission is hereby granted to any
9+
~ person obtaining a copy of this software, associated documentation and/or
10+
~ data (collectively the "Software"), free of charge and under any and all
11+
~ copyright rights in the Software, and any and all patent rights owned or
12+
~ freely licensable by each licensor hereunder covering either (i) the
13+
~ unmodified Software as contributed to or provided by such licensor, or (ii)
14+
~ the Larger Works (as defined below), to deal in both
15+
~
16+
~ (a) the Software, and
17+
~
18+
~ (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
19+
~ one is included with the Software each a "Larger Work" to which the Software
20+
~ is contributed by such licensors),
21+
~
22+
~ without restriction, including without limitation the rights to copy, create
23+
~ derivative works of, display, perform, and distribute the Software and make,
24+
~ use, sell, offer for sale, import, export, have made, and have sold the
25+
~ Software and the Larger Work(s), and to sublicense the foregoing rights on
26+
~ either these or other terms.
27+
~
28+
~ This license is subject to the following condition:
29+
~
30+
~ The above copyright notice and either this complete permission notice or at a
31+
~ minimum a reference to the UPL must be included in all copies or substantial
32+
~ portions of the Software.
33+
~
34+
~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
35+
~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
36+
~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
37+
~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
38+
~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
39+
~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
40+
~ SOFTWARE.
41+
-->
42+
43+
<project xmlns="http://maven.apache.org/POM/4.0.0"
44+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
45+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
46+
<groupId>org.graalvm.buildtools.examples</groupId>
47+
<artifactId>issue-612</artifactId>
48+
<version>1.0.0-SNAPSHOT</version>
49+
<modelVersion>4.0.0</modelVersion>
50+
<properties>
51+
<java.version>1.8</java.version>
52+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
53+
<native.maven.plugin.version>0.10.5-SNAPSHOT</native.maven.plugin.version>
54+
<imageName>example-app</imageName>
55+
<mainClass>org.graalvm.demo.Application</mainClass>
56+
</properties>
57+
58+
<dependencies>
59+
<dependency>
60+
<groupId>org.yaml</groupId>
61+
<artifactId>snakeyaml</artifactId>
62+
<version>2.3</version>
63+
<scope>runtime</scope>
64+
</dependency>
65+
</dependencies>
66+
67+
<profiles>
68+
<profile>
69+
<id>native</id>
70+
<build>
71+
<plugins>
72+
<plugin>
73+
<groupId>org.graalvm.buildtools</groupId>
74+
<artifactId>native-maven-plugin</artifactId>
75+
<version>${native.maven.plugin.version}</version>
76+
<extensions>true</extensions>
77+
<executions>
78+
<execution>
79+
<id>build-native</id>
80+
<goals>
81+
<goal>compile-no-fork</goal>
82+
</goals>
83+
<phase>package</phase>
84+
</execution>
85+
</executions>
86+
<configuration>
87+
<skip>false</skip>
88+
<imageName>${imageName}</imageName>
89+
<fallback>false</fallback>
90+
<exclusions>
91+
<exclusion>
92+
<groupId>org.yaml</groupId>
93+
<artifactId>snakeyaml</artifactId>
94+
</exclusion>
95+
</exclusions>
96+
</configuration>
97+
</plugin>
98+
<plugin>
99+
<groupId>org.apache.maven.plugins</groupId>
100+
<artifactId>maven-surefire-plugin</artifactId>
101+
<version>3.0.0-M5</version>
102+
</plugin>
103+
<plugin>
104+
<groupId>org.apache.maven.plugins</groupId>
105+
<artifactId>maven-compiler-plugin</artifactId>
106+
<version>3.8.1</version>
107+
<configuration>
108+
<source>${java.version}</source>
109+
<target>1.8</target>
110+
</configuration>
111+
</plugin>
112+
<plugin>
113+
<groupId>org.apache.maven.plugins</groupId>
114+
<artifactId>maven-jar-plugin</artifactId>
115+
<version>3.2.2</version>
116+
<configuration>
117+
<archive>
118+
<manifest>
119+
<addClasspath>false</addClasspath>
120+
<mainClass>${mainClass}</mainClass>
121+
</manifest>
122+
</archive>
123+
</configuration>
124+
</plugin>
125+
</plugins>
126+
</build>
127+
</profile>
128+
</profiles>
129+
130+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package org.graalvm.demo;
2+
3+
public class Application {
4+
static String getMessage() {
5+
return "Hello, native!";
6+
}
7+
8+
public static void main(String[] args) {
9+
System.out.println(getMessage());
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.graalvm.demo;
2+
3+
public class Calculator {
4+
5+
public int add(int a, int b) {
6+
return a + b;
7+
}
8+
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright (c) 2020, 2021 Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
42+
package org.graalvm.buildtools.maven.issues
43+
44+
import org.graalvm.buildtools.maven.AbstractGraalVMMavenFunctionalTest
45+
46+
class ExcludeDependenciesFunctionalTest extends AbstractGraalVMMavenFunctionalTest {
47+
def "can exclude dependencies from native image classpath"() {
48+
withReproducer("issue-612")
49+
50+
when:
51+
mvn '-Pnative', '-Ddebug', '-Dverbose', '-DquickBuild', 'package'
52+
53+
then:
54+
buildSucceeded
55+
var imagecpLineIdx = outputLines.findIndexOf { it.startsWith('-imagecp') }
56+
var imagecpLine = outputLines[imagecpLineIdx+1]
57+
imagecpLine != null
58+
imagecpLine.contains("issue-612-1.0.0-SNAPSHOT.jar")
59+
!imagecpLine.contains("snakeyaml")
60+
}
61+
62+
}

native-maven-plugin/src/main/java/org/graalvm/buildtools/maven/AbstractNativeImageMojo.java

+27-3
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343

4444
import org.apache.maven.artifact.Artifact;
4545
import org.apache.maven.execution.MavenSession;
46+
import org.apache.maven.model.Exclusion;
4647
import org.apache.maven.plugin.MojoExecution;
4748
import org.apache.maven.plugin.MojoExecutionException;
4849
import org.apache.maven.plugin.descriptor.PluginDescriptor;
@@ -56,7 +57,6 @@
5657
import org.graalvm.buildtools.utils.SharedConstants;
5758

5859
import javax.inject.Inject;
59-
6060
import java.io.BufferedReader;
6161
import java.io.File;
6262
import java.io.IOException;
@@ -78,6 +78,7 @@
7878
import java.util.Map;
7979
import java.util.Optional;
8080
import java.util.Set;
81+
import java.util.function.Consumer;
8182
import java.util.regex.Pattern;
8283
import java.util.stream.Collectors;
8384
import java.util.stream.Stream;
@@ -173,6 +174,9 @@ public abstract class AbstractNativeImageMojo extends AbstractNativeMojo {
173174
@Parameter(property = "requiredVersion")
174175
protected String requiredVersion;
175176

177+
@Parameter(property = "exclusions")
178+
protected List<Exclusion> exclusions;
179+
176180
@Component
177181
protected ToolchainManager toolchainManager;
178182

@@ -306,7 +310,9 @@ protected Path processArtifact(Artifact artifact, String... artifactTypes) throw
306310
}
307311

308312
protected void addArtifactToClasspath(Artifact artifact) throws MojoExecutionException {
309-
Optional.ofNullable(processSupportedArtifacts(artifact)).ifPresent(imageClasspath::add);
313+
if (!isExcluded(artifact)) {
314+
Optional.ofNullable(processSupportedArtifacts(artifact)).ifPresent(imageClasspath::add);
315+
}
310316
}
311317

312318
private static FileSystem openFileSystem(URI uri) throws IOException {
@@ -367,6 +373,22 @@ protected void addDependenciesToClasspath() throws MojoExecutionException {
367373
}
368374
}
369375

376+
@Override
377+
protected void maybeAddDependencyMetadata(Artifact dependency, Consumer<File> excludeAction) {
378+
if (isExcluded(dependency)) {
379+
return;
380+
}
381+
super.maybeAddDependencyMetadata(dependency, excludeAction);
382+
}
383+
384+
protected boolean isExcluded(Artifact dependency) {
385+
if (exclusions == null) {
386+
return false;
387+
}
388+
return exclusions.stream()
389+
.anyMatch(e -> e.getGroupId().equals(dependency.getGroupId()) && e.getArtifactId().equals(dependency.getArtifactId()));
390+
}
391+
370392
/**
371393
* Returns path to where application classes are stored, or jar artifact if it is produced.
372394
* @return Path to application classes
@@ -404,7 +426,9 @@ protected void populateClasspath() throws MojoExecutionException {
404426
}
405427

406428
protected String getClasspath() throws MojoExecutionException {
407-
populateClasspath();
429+
if (imageClasspath.isEmpty()) {
430+
populateClasspath();
431+
}
408432
if (imageClasspath.isEmpty()) {
409433
throw new MojoExecutionException("Image classpath is empty. " +
410434
"Check if your classpath configuration is correct.");

native-maven-plugin/src/testFixtures/groovy/org/graalvm/buildtools/maven/AbstractGraalVMMavenFunctionalTest.groovy

+4
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,10 @@ abstract class AbstractGraalVMMavenFunctionalTest extends Specification {
228228
!normalizeString(result.stdOut).contains(normalizeString(text))
229229
}
230230

231+
List<String> getOutputLines() {
232+
return normalizeString(result.stdOut).split("\n")
233+
}
234+
231235
static boolean matches(String actual, String expected) {
232236
normalizeString(actual) == normalizeString(expected)
233237
}

0 commit comments

Comments
 (0)