我正在将一个较大的 Ant 构建转换为 Maven。作为 Ant 构建的一部分,我们有几个步骤通过调用项目的类之一来创建 Java 类,简化为:
javac SomeGenerator.java
java SomeGenerator generated # generate classes in generated/
javac generated/*.java
我已将每个生成器拆分为自己的 Maven 模块,但我遇到了无法运行生成器的问题,因为它尚未在
generate-sources
阶段编译。
我尝试过类似的方法
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.1.1</version>
<executions>
<execution>
<id>generate-model</id>
<goals>
<goal>java</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<mainClass>DTOGenerator</mainClass>
<arguments>
<argument>${model.generated.dir}</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
遗憾的是,由于上述原因,这不起作用。将代码生成器分成两个项目,一个用于编译生成器,另一个用于生成 DTO 似乎有些过分了。
有哪些替代方案?
使用 Maven 2.2.1。
您可以在generate-sources阶段执行maven-compile-plugin。只需在现有执行之前添加另一个执行并配置它,以便它只获取生成器的源。
或者将项目一分为二:使用单独的 POM 构建生成器,并将生成器库作为生成源的 POM 的依赖项包含在内。
我个人会拆分该项目。保持构建文件更干净且更易于维护。
我不想有2个不同的项目,所以我尝试设置Maven以将生成的编译代码添加到最终的jar包中。
这是我使用过的工作解决方案:
process-classes
阶段(在 compile
阶段之后执行):
exec-maven-plugin
用于执行主类,能够在 target/generated-sources/java
文件夹中生成源文件(在我的具体情况下,我使用 Roaster 库 来生成源代码);build-helper-maven-plugin
用于将生成的源添加到正确的位置prepare-package
阶段:
maven-compiler-plugin
,为了检测更改并重新编译模块maven-jar-plugin
用于制作jar包这是我的pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<phase>process-classes</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>com.example.MyClassWriter</mainClass>
<arguments>
<argument>${project.basedir}</argument>
<argument>${project.build.directory}</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>process-classes</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-sources/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<phase>prepare-package</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
为了在一个项目中做到这一点,需要执行 3 个步骤:
编译生成器代码
我们可以在
generate-sources
阶段使用maven-compiler-plugin
来完成。您还可以排除其他源文件。运行生成器生成代码
我们可以在
process-sources
阶段使用 exec-maven-plugin
来完成。编译项目
下面是pom.xml的关键部分
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
<executions>
<execution>
<id>compile-generator</id>
<phase>generate-sources</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<includes>
<include>source/file/of/generator/*.java</include>
</includes>
<excludes>
<exclude>other/source/files/*.java</exclude>
</excludes>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<id>generate-codes</id>
<goals>
<goal>java</goal>
</goals>
<phase>process-sources</phase>
<configuration>
<mainClass>your.main.class.of.generator</mainClass>
</configuration>
</execution>
</executions>
</plugin>
我们也面临同样的问题。我们希望尽可能尊重 Maven 的行为,避免插件出现问题等等……对抗 Maven 的成本太高了!
我们意识到生成的代码的“更新频率”通常与我们手动编写的代码非常不同,因此分离代码对于构建来说具有非常好的性能特征。因此,我们接受将生成的类作为手动编写的依赖项。 我们采用了以下结构,与常规 Maven 配置相比只有一点点变化,即源目录的更改。
父项目:Generations
。
如果包含要编译的代码,则具有 JAR 类型,否则为 POM。子 jar 项目:生成
<sourceDirectory>../target/generated1</sourceDirectory>
对标准 Maven 布局进行尽可能少的修改,以便每个 Maven 命令和插件都能正常工作。
<includes>
pom.xml
,它将允许在同一项目中生成代码,同时确保事后正确清理:
<build>
<plugins>
<!-- Compile XyzGenerator.java to XyzGenerator.class -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<executions>
<execution>
<id>parser-generator</id>
<phase>generate-sources</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<includes>
<include>com/project/codegen/XyzGenerator.java</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
<!-- Execute XyzGenerator.class to generate Xyz.Java -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<id>parser-generator</id>
<phase>generate-sources</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<classpathScope>compile</classpathScope>
<mainClass>com.project.codegen.CodeGenerator</mainClass>
<commandlineArgs>target/codegen/main/java/com/project/</commandlineArgs>
</configuration>
</execution>
</executions>
</plugin>
<!-- Include the path to Xyz.java for compilation -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.5.0</version>
<executions>
<execution>
<id>parser-generator</id>
<phase>process-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>target/codegen</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<!-- Package the application in a JAR file -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>default-jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<excludes>
<!-- Exclude the XyzGenerator.class file from the JAR -->
<exclude>com/project/codegen/*.*</exclude>
<exclude>com/project/codegen</exclude>
</excludes>
<archive>
<manifest>
<!-- Add the name of main class -->
<addClasspath>true</addClasspath>
<mainClass>com.project.Main</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
main
文件中的
CodeGenerator
类中的XyzGenerator.java
函数将输出目录作为第一个命令行参数;上面,这是在 <commandlineArgs>
标签中传递的。文件结构为:
src
'- main
'- java
'- com
'- project
'- Main.class
'- codegen
'- XyzGenerator.java
target
'- codegen
'- main
'- java
'- com
'- project