Run maven compilation twice

2020-06-21 09:19发布

问题:

I'm in process of migrating ant project to maven and this project is quite unusual: it uses two compilation steps and code generation step between those compilation steps. The whole build process can be described as follows:

  1. Compile everything in src directory
  2. Run internal java tool, point java to the compiled classes and jars used to compile those classes. This tool generates code based on the compiled classes by using reflection.
  3. Compile generated classes and finally assemble a jar.

I found a few links that suggest to create a custom lifecycle but I've no idea where to start. If someone can point to similar project configuration that would be really great.

What would be the simplest way of achieving this with maven? I guess I should use ant maven plugin but I still don't understand how to make it compile sources twice and point it to the generated sources after first compilation step.

回答1:

OK, I finally figured out how to do that.

Basically I run compiler on different build phases so that compile happens on generate-sources phase, code is generated on process-sources phase and finally compiler makes final compilation on 'compile' phase.

Here is my configuration:

<build>
<plugins>
  <!-- Code generation, executed after the first compiler pass -->
  <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>1.2.1</version>
    <executions>
      <execution>
        <id>generateCode</id>
        <phase>process-sources</phase>
        <goals>
          <goal>java</goal>
        </goals>
        <configuration>
          <classpathScope>test</classpathScope>
          <mainClass>my.code.Generator</mainClass>
          <arguments>
            <argument>-target</argument>
            <argument>${project.build.directory}/generated-sources/java</argument>
            <argument>-source</argument>
            <argument>my.code.generator.Configuration</argument>
          </arguments>
        </configuration>
      </execution>
    </executions>
  </plugin>

  <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <version>1.1</version>
    <executions>
      <execution>
        <id>add-source</id>
        <phase>process-sources</phase>
        <goals>
          <goal>add-source</goal>
        </goals>
        <configuration>
          <sources>
            <source>${project.build.directory}/generated-sources/java</source>
          </sources>
        </configuration>
      </execution>
    </executions>
  </plugin>


  <!-- Custom compilation mode -->
  <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <executions>
      <execution>
        <id>default-compile</id>
        <phase>generate-sources</phase>
      </execution>
      <execution>
        <id>build-generated-code</id>
        <phase>compile</phase>
        <goals>
          <goal>compile</goal>
        </goals>
        <configuration>
          <generatedSourcesDirectory>${project.build.directory}/generated-sources/java</generatedSourcesDirectory>
        </configuration>
      </execution>
    </executions>
  </plugin>
</plugins>
</build>

Hope this will be helpful for someone.

UPDATE You may probably notice that compiler unnecessarily compiles all the sources on final compiler pass. To fine tune your particular compiler pass you may want to use 'exclude'/'include' configuration for your project.



回答2:

Example: Configuring compile to run twice

<plugin>
  <artifactId>maven-compiler-plugin</artifactId>
  <configuration>
    <source>1.5</source>
    <target>1.5</target>
  </configuration>
  <executions>
    <execution>
      <id>default-compile</id>
      <configuration>
        <excludes>
          <exclude>**/cli/*</exclude>
        </excludes>
      </configuration>
    </execution>
    <execution>
      <id>build-java14-cli</id>
      <phase>compile</phase>
      <goals>
        <goal>compile</goal>
      </goals>
      <configuration>
        <source>1.3</source>
        <target>1.3</target>
        <includes>
          <include>**/cli/*</include>
        </includes>
      </configuration>
    </execution>
  </executions>
</plugin>

Adjust this configuration to your needs



回答3:

I suggest you better create two separate Maven projects. Put the (static) Java sources into the first project. Put the dynamic stuff into the second project and add a reference to the first project:

<dependency>
  <groupId>org.yourgroup</groupId>
  <artifactId>sub-module-1</artifactId>
  <version>0.0.1-SNAPSHOT</version>
</dependency>

Now, build and install the first project:

mvn install

After that you should be able to build the second project.



标签: java maven ant