views:

951

answers:

2

My project generates source code using the Rats! parser generator. Rats! doesn't have a Maven plugin that I'm aware of, so I'm trying to build the parser using an Ant Java task, like so:

 <plugin>
   <artifactId>maven-antrun-plugin</artifactId>
   <executions>
     <execution>
       <phase>generate-sources</phase>
       <configuration>
         <tasks>
           <mkdir dir="${project.build.directory}/generated-sources/main/java/" />
           <java classpath="lib/xtc.jar" classname="xtc.parser.Rats">
             <arg line="-in ${project.build.sourceDirectory}" />
             <arg line="-out ${project.build.directory}/generated-sources/main/java/" />
             <arg path="${project.build.sourceDirectory}/Dot.rats" />
           </java>
         </tasks>
         <sourceRoot>
           ${project.build.directory}/generated-sources/main/java
         </sourceRoot>
       </configuration>
       <goals>
         <goal>run</goal>
       </goals>
     </execution>
   </executions>
 </plugin>

The details of what Rats! does aren't important: the end result is that the above generates Dot.java and places it in target/generated-sources/main/java. It works fine.

The problem is that, with this plugin element in my pom.xml, none of the Java files in the project get compiled.

I generated a project using "mvn archetype:create -DgroupId=foo -DartifactId=bar" and added the file src/main/java/Dot.rats:

module Dot;

public void Dot = "." !_ ;

(This is a grammar that accepts only files with a single dot.)

If I run "mvn compile" without the plugin element, I get:

$ mvn compile
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building bar
[INFO]    task-segment: [compile]
[INFO] ------------------------------------------------------------------------
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] Compiling 1 source file to
/home/chris/src/tests/maven/project1/bar/target/classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1 second
[INFO] Finished at: Wed Jul 01 18:57:08 EDT 2009
[INFO] Final Memory: 6M/67M
[INFO] ------------------------------------------------------------------------

Where the one Java file being compiled is src/main/java/foo/App.java, a Java class created by the archetype (i.e., not a generated source file).

If I do "mvn clean" then add the plugin element invoking Rats!, I get:

$ mvn compile
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building bar
[INFO]    task-segment: [compile]
[INFO] ------------------------------------------------------------------------
[INFO] [antrun:run {execution: default}]
[INFO] Executing tasks
   [mkdir] Created dir:
/home/chris/src/tests/maven/project1/bar/target/generated-sources/main/java
Rats! Parser Generator, v. 1.14.2, (C) 2004-2008 Robert Grimm
Processing /home/chris/src/tests/maven/project1/bar/src/main/java/Dot.rats ...

I.e., Maven is running Rats! (which is not failing, AFAICT) but not compiling any Java classes, not even the pre-existing class App.java. After the run, I have target/generated-sources/main/java/Dot.java but no target/classes.

I've tried other kinds of Ant tasks and they don't interfere with Java compilation. For example, if I replace the task element above with an echo task

<tasks>
  <mkdir dir="${project.build.directory}/generated-sources/main/java/" />
  <echo file="${project.build.directory}/generated-sources/main/java/Dot.java">
     public class Dot { }
  </echo>
</tasks>

I get

$ mvn compile
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building bar
[INFO]    task-segment: [compile]
[INFO] ------------------------------------------------------------------------
[INFO] [antrun:run {execution: default}]
[INFO] Executing tasks
[INFO] Executed tasks
[INFO] Registering compile source root
/home/chris/src/tests/maven/project1/bar/target/generated-sources/main/java
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] Compiling 2 source files to
/home/chris/src/tests/maven/project1/bar/target/classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2 seconds
[INFO] Finished at: Wed Jul 01 19:03:34 EDT 2009
[INFO] Final Memory: 7M/79M
[INFO] ------------------------------------------------------------------------

Obviously there's something I'm not understanding about how Maven executes the java task. Is there something simple that I'm doing wrong? Is there an alternative way to accomplish this task that I should try (perhaps a more "Maven-native" way)?

[UPDATE] Funny story. I tried replacing the Ant task with a Maven plugin, by writing a RatsMojo class that invokes xtc.parser.Rats directly and replacing the plugin element above with

  <plugin>
    <groupId>edu.nyu.xtc</groupId>
    <artifactId>maven-xtc-plugin</artifactId>
    <executions>
      <execution>
        <phase>generate-sources</phase>
        <goals>
          <goal>rats</goal>
        </goals>
        <configuration>
          <inputDirectory>${project.build.sourceDirectory}</inputDirectory>
          <outputDirectory> ${project.build.directory}/generated-sources/main/java</outputDirectory>
          <grammarFile>${project.build.sourceDirectory}/Dot.rats</grammarFile>
        </configuration>
      </execution>
    </executions>
  </plugin>

It does the exact same thing: it runs Rats! then terminates without compiling any of the Java files in the project.

+1  A: 

You need to add the new directory to the maven source directories. It can be done using the buildhelper-maven-plugin. Add this to your pom:

  <build>
   <plugins>
     <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>build-helper-maven-plugin</artifactId>
        <executions>
          <execution>
            <id>add-source</id>
            <phase>generate-sources</phase>
            <goals>
              <goal>add-source</goal>
            </goals>
            <configuration>
              <sources>
                <source>${project.build.directory}/generated-sources/main/java/</source>
              </sources>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
David Rabinowitz
I wasn't clear in my question: it's not compiling *any* Java files. Not the generated files and not the files that were there to begin with. The sourceRoot element does add the generated sources directory to the compile path (e.g., the generated files do get compiled in the echo example).
Chris Conway
I should add that I did try adding this plugin configuration and it didn't change anything: still no Java compilation.
Chris Conway
+1  A: 

The problem seems to be that Rats! calls System.exit() (or similar), terminating the JVM. I would have thought that Ant would wrap this (the java task is copied over from a build.xml and it doesn't terminate the Ant build), but the following works by forcing the Rats! process into a separate JVM:

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>exec-maven-plugin</artifactId>
  <version>1.1</version>
  <executions>
    <execution>
      <phase>generate-sources</phase>
      <goals>
        <goal>exec</goal>
      </goals>
    </execution>
  </executions>
  <configuration>
    <executable>java</executable>
    <arguments>
      <argument>-classpath</argument>
      <argument>${basedir}/lib/xtc.jar</argument>
      <argument>xtc.parser.Rats</argument>
      <argument>-in</argument>
      <argument>${project.build.sourceDirectory}</argument> 
      <argument>-out</argument>
      <argument>${project.build.directory}/generated-sources/main/java/</argument>
      <argument>${project.build.sourceDirectory}/Dot.rats</argument>
    </arguments>
  </configuration>
</plugin>

or, just add fork="true" to the java task in the antrun plugin.

Chris Conway