4

I have a scenario where I'm trying to reuse the same build.xml file across multiple projects. In each case, the finaly target is a dist that JARs everything up. The only difference is that some of the projects have a src/main/java/META-INF/* directory, and others don't (and just have a src/main/java/* directory).

I want to use the Ant-Contrib <if/> task to optionally define a META-INF/ directory if the build sees a src/main/java/META-INF/* directory available. So something like this:

<jar jarfile="myapp.jar">
    <if>
        <available file="src/main/java/META-INF" />
        <then>
            <!--
                Copy everything from src/main/java/META-INF into
                the JAR's META-INF directory.

                But how?!?
            -->
            <echo message="I'm trying to copy META-INF!" />
        </then>
    </if>
</jar>

But I am choking on two things here:

  1. When I run this target, I get a build exception stating that I can't nest an <if/> inside the <jar/> task; and
  2. I'm not sure how to configure the <jar/> task to create a META-INF directory at the root of the classpath, and copy all of the src/main/java/META-INF contents into it.

Any thoughts? Thanks in advance.

  • 1
    So you're including classes in the jar from other directory, and you want to optionally also include the contents of src/main/java/META-INF as META-INF? If so, you may be able to use the metainf nested element within the jar task. Is the manifest one of the files? – martin clayton Feb 02 '13 at 08:02
  • Thanks @martin clayton (+1) - I'm certainly not opposed to having a `MANIFEST.MF` but currently my projects don't have one (at least not one that I explicitly define). So if I have to create a dummy/blank manfiest, or let Ant create one for me, I'm fine with that. But to answer your question: no the manifest isn't currently one of the files. –  Feb 02 '13 at 09:37

3 Answers3

4

You're making it harder than necessary. Just use the following task, and the META-INF folder will be included in the jar if it exists, and ignored if it doesn't:

<target name="dist">
    <jar destfile="test.jar">
        <fileset dir="classes"/> <-- or whatever directory you want to put in the jar -->
        <metainf dir="src/main/java/META-INF" erroronmissingdir="false"/>
    </jar>
</target>
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
1

The message is correct, in that <if> is itself a task and you can't nest other tasks inside the <jar> task. However what you can do is use the <if> task to define a suitable fileset with an ID, then use refid to include this in the JAR:

<if>
    <available file="src/main/java/META-INF" />
    <then>
        <fileset id="src.metainf" dir="src/main/java/META-INF" />
    </then>
    <else>
        <fileset id="src.metainf" dir="." excludes="**/*" />
    </else>
</if>

<jar destfile="myapp.jar">
    <metainf refid="src.metainf" />
</jar>

As JB Nizet points out you don't actually need this to answer this specific question, but it's a useful trick to be aware of for other situations. I find it more useful when defining <path> elements rather than filesets.

Community
  • 1
  • 1
Ian Roberts
  • 120,891
  • 16
  • 170
  • 183
1

It sounds like you want to take advantage of a more modular build configuration. How about having two targets:

<target name="jar">
    <!-- Normal JAR tasks like you currently have (sans the metainf stuff). -->
</target>

<target name="jar-with-metainf">
    <jar destfile="test.jar">
        <fileset dir="classes"/>
        <metainf dir="src/main/java/META-INF"/>
    </jar>
</target>

Then, when you want to build your META-INF/-containing projects, you just run jar-with-metainf.

Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315
IAmYourFaja
  • 55,468
  • 181
  • 466
  • 756