2

I'm creating a build script for a large PHP application. I'm using an Ant script, being run by Jenkins.

I want to include tools such as PHP_CodeSniffer and PHPMD (PHP Mess Detector) in the build script, so I have code like this:

<target name="php-codesniffer">
    <exec executable="phpcs" dir="${basedir}" output="${basedir}/build/logs/checkstyle.xml">
        <arg line="--report=checkstyle --standard=PEAR ${basedir}/"/>
    </exec>
</target>
<target name="phpmd">
    <exec executable="phpmd" dir="${basedir}" output="${basedir}/build/logs/phpmd.xml">
        <arg line="${basedir} xml codesize,unusedcode,naming"/>
    </exec>
</target>

However both these tools take an excessively long period of time to run, even on small subsets of our code base, so I'm trying to find ways I can use them, but without the performance penalty.

My current thought is to run them only on files which have been modified in the current build, but I don't know Ant well enough to get it to do this.

So the question is how can I modify the above Ant targets such that the <exec> calls only run for files which have been modified in the current build? (or alternatively in the last X minutes if Ant doesn't know about the current build).

Thanks for any help.

SDC
  • 14,192
  • 2
  • 35
  • 48

1 Answers1

3

Take a look at the question How to execute ANT tasks on only files that have been modified, and in particular this answer which illustrates use of the modified selector.

It looks like phpcs takes either a list of files and/or a directories. It recurses into directories.

If you are going to stick with specifying a single directory and have phpcs recurse into it, then you could first find target files (using the modified selector) and copy to a temporary dir. Then point phpcs to that dir. One downside of that is that you are adding disk i/o for the copy into your build time.

Probably better, you could pathcovert a fileset selected using the modified selector. Use a space as the pathsep for this. That will give you a property the value of which is a space separated list of your target files. The downside of this one could be that you end up with too long a list of args.


To answer your follow up question in comments, here is a simple example of how you could use pathconvert to create a space-separated list of files and pass them to an executable (in this case the Windows dir command):

<project default="test">

  <target name="test">
    <pathconvert property="file.list" pathsep=" ">
      <fileset dir="src">
        <include name="a.txt"/>
        <include name="b.txt"/>
      </fileset>
    </pathconvert>
    <echo message="file.list: ${file.list}"/>
    <exec executable="cmd">
      <arg value="/c"/>
      <arg value="dir"/>
      <arg line="${file.list}"/>
    </exec>
  </target>

</project>

(Note that I used line rather than value to pass the file list in the exec.)

Here is the content of the dir which files are selected from (one is not included):

C:\tmp\ant>dir src
 Volume in drive C has no label.
 Volume Serial Number is 1773-83D6

 Directory of C:\tmp\ant\src

30/11/2011  12:21    <DIR>          .
30/11/2011  12:21    <DIR>          ..
30/11/2011  12:09                 0 a.txt
30/11/2011  12:09                 0 b.txt
30/11/2011  12:09                 0 c.txt
               3 File(s)              0 bytes
               2 Dir(s)  435,642,912,768 bytes free

Here is the output:

C:\tmp\ant>ant
Buildfile: C:\tmp\ant\build.xml

test:
     [echo] file.list: C:\tmp\ant\src\a.txt C:\tmp\ant\src\b.txt
     [exec]  Volume in drive C has no label.
     [exec]  Volume Serial Number is 1773-83D6
     [exec]
     [exec]  Directory of C:\tmp\ant\src
     [exec]
     [exec] 30/11/2011  12:09                 0 a.txt
     [exec]
     [exec]  Directory of C:\tmp\ant\src
     [exec]
     [exec] 30/11/2011  12:09                 0 b.txt
     [exec]                2 File(s)              0 bytes
     [exec]                0 Dir(s)  435,642,896,384 bytes free

BUILD SUCCESSFUL
Total time: 1 second
Community
  • 1
  • 1
ewan.chalmers
  • 16,145
  • 43
  • 60
  • Thanks for the answer. Re your first suggestion (copying to a temp dir): yes; that was how I was thinking of doing it. I did see that previous question, but wasn't sure how to relate it to my case. Your answer has helped me with that, so thank you. Re the `pathconvert` suggestion: that does sound better. However I'm finding the Ant documentation quite hard to follow. Could you give me an example that includes how I would use the generated path within the ``? Thank you. – SDC Nov 28 '11 at 17:24
  • Thank you so much for the help. Very much appreciated. I've accepted the answer (can't upvote yet; not enough score). I'll play around with it some more and see how things go. I think you've given me plenty to be working with. Thanks. – SDC Nov 30 '11 at 16:13