如果由 maven-assembly-plugin 构建,则手动附加主要工件
Manually attach main artifact if built by maven-assembly-plugin
我在构建 Maven 项目时遇到问题。我需要生成 确定性 jar 文件,这些文件必须在不同的构建和版本之间保持二进制一致,以防这些构建之间没有源代码更改。为此,我使用 this article 作为指导。
我已经成功构建了我的罐子,它们符合我的要求。这是我的配置:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>step-1-remove-timestamp</id>
<phase>prepare-package</phase>
<configuration>
<target>
<touch datetime="01/01/2015 00:10:00 am">
<fileset dir="target/classes"/>
<fileset dir="src"/>
</touch>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
<execution>
<id>step-3-rename-assembly</id>
<phase>package</phase>
<configuration>
<target>
<copy file="${project.build.directory}/${project.build.finalName}-deterministic.zip"
tofile="${project.build.directory}/${project.build.finalName}.jar"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2.1</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly/zip.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>step-2-make-assembly</id>
<phase>prepare-package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
在上面的代码中,我将 jar 构建并打包为 zip,然后将 zip 复制到预期的 jar 工件上。
上面的问题是,maven 仍然执行 maven-jar-plugin
,因此手动组装的 jar 被 maven-jar-plugin
之一覆盖。我不想使用这个jar,因为它不符合我的要求。
所以,我禁用了 maven-jar-plugin
执行,通过将其显式设置为 运行 来表示无效阶段,如下所示:(从 other posts here 看到的)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>default-jar</id>
<phase>never</phase>
<configuration>
<finalName>unwanted</finalName>
<classifier>unwanted</classifier>
</configuration>
</execution>
</executions>
</plugin>
一切似乎都很好,直到我发现我的主要 jar 工件从未安装在 .m2
目录中。为了纠正这个问题,我还添加了 maven-helper-plugin
以便我手动附加我从汇编程序插件生成的任何工件:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.9.1</version>
<executions>
<execution>
<id>attach-instrumented-jar</id>
<phase>verify</phase>
<goals>
<goal>attach-artifact</goal>
</goals>
<configuration>
<artifacts>
<artifact>
<file>${project.build.directory}/${project.build.finalName}.jar</file>
<type>jar</type>
</artifact>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
这导致了一个我无法解决的错误:
[ERROR] Failed to execute goal org.codehaus.mojo:build-helper-maven-plugin:1.9.1:attach-artifact (attach-instrumented-jar) on project my-project: Execution attach-instrumented-jar of goal org.codehaus.mojo:build-helper-maven-plugin:1.9.1:attach-artifact failed: For artifact {full-name-of-my-project.jar}: An attached artifact must have a different ID than its corresponding main artifact. -> [Help 1]
有办法解决这个问题吗?我已经检查了解决方案,大多数建议使用分类器,但我想像 maven-jar-plugin
一样安装主要工件。我们正在开发的其他软件将需要标准的 jar 依赖,我们希望避免通过不合理地引入分类器使我们的设置复杂化。
经过更多的尝试和失败后,我碰巧提出了一个可行的解决方案。
我将其张贴在这里,希望对我有用,或者对我有任何问题,因为我不确定这是否是一种可靠的方法。
所以,我收到的错误
An attached artifact must have a different ID than its corresponding main artifact.
对我来说意味着我无法手动安装 "again" 主要工件。由于 maven-jar-plugin
不再生成该工件,因此即使该文件存在(antrun 复制任务生成具有相同名称的 jar)也永远不会安排安装。
令人惊讶的是,它需要一些小技巧才能再次运行:
按原样重新启用 maven-jar-plugin
:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>default-jar</id>
<phase>package</phase>
</execution>
</executions>
</plugin>
这将在 package
阶段生成标准 jar,最重要的是,让 maven 知道它会在 install
阶段安装。
调整 maven-antrun-plugin
复制任务以 覆盖 已经生成的带有确定性 zip 的 jar。设置与我的问题几乎相同,所以我只添加差异:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>...</execution>
<execution>
<id>step-3-rename-assembly-and-sources</id>
<phase>package</phase>
<configuration>
<target>
<copy file="${project.build.directory}/${project.build.finalName}-deterministic.zip"
tofile="${project.build.directory}/${project.build.finalName}.jar"
overwrite="true"/>
</target>
</configuration>
</execution>
. . .
</executions>
</plugin>
复制操作现在已指定 overwrite="true"
。最初,复制操作似乎忽略目标中的文件(如果它们已经存在),发生的情况是 maven-jar-plugin
在复制发生时已经生成了默认的 jar 工件。设置此选项后,maven-antrun-plugin
现在用确定性的 jar 覆盖前一个 jar,而后者成为 maven install
阶段的主题。
从 build-helper-maven-plugin 中删除了设置,这样主 jar 工件就不会被复制第二次:
<artifact>
<file>${project.build.directory}/${project.build.finalName}.jar</file>
<type>jar</type>
</artifact>
就是这样,正确的 jar 安装在 .m2
目录中。
如果您没有为您创建和附加主要工件的插件,Groovy Maven 插件有一个更通用的解决方案:
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>groovy-maven-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<id>set-main-artifact</id>
<phase>package</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
project.artifact.setFile(new File(project.build.directory, project.build.finalName + ".zip"))
</source>
</configuration>
</execution>
</executions>
</plugin>
灵感来自 post many thanks to https://whosebug.com/users/1314907/lukasz-guminski
我在构建 Maven 项目时遇到问题。我需要生成 确定性 jar 文件,这些文件必须在不同的构建和版本之间保持二进制一致,以防这些构建之间没有源代码更改。为此,我使用 this article 作为指导。
我已经成功构建了我的罐子,它们符合我的要求。这是我的配置:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>step-1-remove-timestamp</id>
<phase>prepare-package</phase>
<configuration>
<target>
<touch datetime="01/01/2015 00:10:00 am">
<fileset dir="target/classes"/>
<fileset dir="src"/>
</touch>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
<execution>
<id>step-3-rename-assembly</id>
<phase>package</phase>
<configuration>
<target>
<copy file="${project.build.directory}/${project.build.finalName}-deterministic.zip"
tofile="${project.build.directory}/${project.build.finalName}.jar"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2.1</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly/zip.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>step-2-make-assembly</id>
<phase>prepare-package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
在上面的代码中,我将 jar 构建并打包为 zip,然后将 zip 复制到预期的 jar 工件上。
上面的问题是,maven 仍然执行 maven-jar-plugin
,因此手动组装的 jar 被 maven-jar-plugin
之一覆盖。我不想使用这个jar,因为它不符合我的要求。
所以,我禁用了 maven-jar-plugin
执行,通过将其显式设置为 运行 来表示无效阶段,如下所示:(从 other posts here 看到的)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>default-jar</id>
<phase>never</phase>
<configuration>
<finalName>unwanted</finalName>
<classifier>unwanted</classifier>
</configuration>
</execution>
</executions>
</plugin>
一切似乎都很好,直到我发现我的主要 jar 工件从未安装在 .m2
目录中。为了纠正这个问题,我还添加了 maven-helper-plugin
以便我手动附加我从汇编程序插件生成的任何工件:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.9.1</version>
<executions>
<execution>
<id>attach-instrumented-jar</id>
<phase>verify</phase>
<goals>
<goal>attach-artifact</goal>
</goals>
<configuration>
<artifacts>
<artifact>
<file>${project.build.directory}/${project.build.finalName}.jar</file>
<type>jar</type>
</artifact>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
这导致了一个我无法解决的错误:
[ERROR] Failed to execute goal org.codehaus.mojo:build-helper-maven-plugin:1.9.1:attach-artifact (attach-instrumented-jar) on project my-project: Execution attach-instrumented-jar of goal org.codehaus.mojo:build-helper-maven-plugin:1.9.1:attach-artifact failed: For artifact {full-name-of-my-project.jar}: An attached artifact must have a different ID than its corresponding main artifact. -> [Help 1]
有办法解决这个问题吗?我已经检查了解决方案,大多数建议使用分类器,但我想像 maven-jar-plugin
一样安装主要工件。我们正在开发的其他软件将需要标准的 jar 依赖,我们希望避免通过不合理地引入分类器使我们的设置复杂化。
经过更多的尝试和失败后,我碰巧提出了一个可行的解决方案。 我将其张贴在这里,希望对我有用,或者对我有任何问题,因为我不确定这是否是一种可靠的方法。
所以,我收到的错误
An attached artifact must have a different ID than its corresponding main artifact.
对我来说意味着我无法手动安装 "again" 主要工件。由于 maven-jar-plugin
不再生成该工件,因此即使该文件存在(antrun 复制任务生成具有相同名称的 jar)也永远不会安排安装。
令人惊讶的是,它需要一些小技巧才能再次运行:
按原样重新启用
maven-jar-plugin
:<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>2.5</version> <executions> <execution> <id>default-jar</id> <phase>package</phase> </execution> </executions> </plugin>
这将在
package
阶段生成标准 jar,最重要的是,让 maven 知道它会在install
阶段安装。调整
maven-antrun-plugin
复制任务以 覆盖 已经生成的带有确定性 zip 的 jar。设置与我的问题几乎相同,所以我只添加差异:<plugin> <artifactId>maven-antrun-plugin</artifactId> <version>1.7</version> <executions> <execution>...</execution> <execution> <id>step-3-rename-assembly-and-sources</id> <phase>package</phase> <configuration> <target> <copy file="${project.build.directory}/${project.build.finalName}-deterministic.zip" tofile="${project.build.directory}/${project.build.finalName}.jar" overwrite="true"/> </target> </configuration> </execution> . . . </executions> </plugin>
复制操作现在已指定
overwrite="true"
。最初,复制操作似乎忽略目标中的文件(如果它们已经存在),发生的情况是maven-jar-plugin
在复制发生时已经生成了默认的 jar 工件。设置此选项后,maven-antrun-plugin
现在用确定性的 jar 覆盖前一个 jar,而后者成为 maveninstall
阶段的主题。从 build-helper-maven-plugin 中删除了设置,这样主 jar 工件就不会被复制第二次:
<artifact>
<file>${project.build.directory}/${project.build.finalName}.jar</file>
<type>jar</type>
</artifact>
就是这样,正确的 jar 安装在 .m2
目录中。
如果您没有为您创建和附加主要工件的插件,Groovy Maven 插件有一个更通用的解决方案:
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>groovy-maven-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<id>set-main-artifact</id>
<phase>package</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
project.artifact.setFile(new File(project.build.directory, project.build.finalName + ".zip"))
</source>
</configuration>
</execution>
</executions>
</plugin>
灵感来自 post many thanks to https://whosebug.com/users/1314907/lukasz-guminski