通过在 Maven 中运行项目的 java 类来生成源

问题描述 投票:0回答:6

我正在将一个较大的 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。

java maven-2 code-generation
6个回答
9
投票

您可以在generate-sources阶段执行maven-compile-plugin。只需在现有执行之前添加另一个执行并配置它,以便它只获取生成器的源。

或者将项目一分为二:使用单独的 POM 构建生成器,并将生成器库作为生成源的 POM 的依赖项包含在内。

我个人会拆分该项目。保持构建文件更干净且更易于维护。


9
投票

我不想有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
投票

为了在一个项目中做到这一点,需要执行 3 个步骤:

  1. 编译生成器代码

    我们可以在

    generate-sources
    阶段使用
    maven-compiler-plugin
    来完成。您还可以排除其他源文件。

  2. 运行生成器生成代码

    我们可以在

    process-sources
    阶段使用
    exec-maven-plugin
    来完成。

  3. 编译项目

下面是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>

1
投票

我们也面临同样的问题。我们希望尽可能尊重 Maven 的行为,避免插件出现问题等等……对抗 Maven 的成本太高了!

我们意识到生成的代码的“更新频率”通常与我们手动编写的代码非常不同,因此分离代码对于构建来说具有非常好的性能特征。因此,我们接受将生成的类作为手动编写的依赖项。 我们采用了以下结构,与常规 Maven 配置相比只有一点点变化,即源目录的更改。

父项目:Generations

我们为我们每一代人创建了一个

父项目

如果包含要编译的代码,则具有 JAR 类型,否则为 POM。
  • 我们的生成代码位于 /src 中。
  • 它可以照常在/target中编译。
  • 它运行生成,每个生成器在 /target 的子目录中生成代码。
注意:如果您想将多个生成的结果放在同一个 jar 中,只需将它们放在同一个子目录中即可。

子 jar 项目:生成

    它是Generations项目的子目录。
  • 它有一个JAR类型。
  • 源目录指向父级目标中的子目录。
  • <sourceDirectory>../target/generated1</sourceDirectory>

    
    

  • 它在自己的/target目录中正常编译。
该结构使我们能够:

对标准 Maven 布局进行尽可能少的修改,以便每个 Maven 命令和插件都能正常工作。
  • 如果您有多个发电机,则可以很好地扩展,
  • 如果您想生成多个 jar,则可以很好地扩展(我们有一个案例 wsdl2java,其中一个生成器生成的代码应拆分为多个 jar;每个子生成的项目将具有相同的源目录,但将配置一个
  • <includes>
  • 仅处理部分课程)。
    
        

1
投票
https://github.com/baloise/inlinesourcecodegenerator

它使用 build-helper 编译器和 exec 插件,并且所有代码都在同一个项目中。


0
投票
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

© www.soinside.com 2019 - 2024. All rights reserved.