Freitag, 22. November 2013

Defining macros in Ant to read files

Ant is a scary build tool to compile Java code. It aims to be a better Make but it is just a sludge of everything without doing anything right. It implements a programming language with XML syntax, which is simply pain to write. But sometimes you have to use it, because Sun failed to design something better, when they designed Java.

Make files typically read some values or lists from other files. Because Make does not try to be a Shell like Ant, the Shell is used for this:

version = $(shell cat VERSION)
This reads the contents of the file "VERSION" into the variable "version". Although Ant tries to be a Shell it has no build-in function to do the same. Instead it provides you a way to define macros in XML syntax, to define a function. The following code defines an Ant function, which reads the contents of a file into a property without any new lines.
<macrodef name="loadfilevalue">
  <attribute name="property"/>
  <attribute name="file"/>
  <sequential>
    <loadfile property="@{property}" srcFile="@{file}">
      <filterchain><striplinebreaks/></filterchain>
    </loadfile>
  </sequential>
</macrodef>
With this macro it is possible to read the "VERSION" file:
<loadfilevalue property="version" file="VERSION"/>
Something similar can be done for lists of values. Ant provides a way to modify the contents of a file with regular expressions while reading it. This makes it possible to write a macro, which reads some lines from a file into a coma delimited property, which is usually required as the input to specify a list of files in Ant. This is the macro.
<macrodef name="loadfilelist">
  <attribute name="property"/>
  <attribute name="file"/>
  <sequential>
    <loadfile property="@{property}" srcFile="@{file}">
      <filterchain>
        <tokenfilter>
          <replaceregex pattern="$" replace=","/>
        </tokenfilter>
        <striplinebreaks/>
        <tokenfilter>
          <replaceregex pattern=",$" replace=""/>
        </tokenfilter>
      </filterchain>
    </loadfile>
  </sequential>
</macrodef>
And this shows how to use it.
<loadfilelist property="files" file="FILES"/>

Keine Kommentare: