I have two possible solutions:
- write my own antcall task that handles logging differently
- forget about the console and use record to control logging to a file
I'm going to go with the second because it is the easiest to implement and because I'm probably moving to gradle later on where I'll solve this a different way (but probably following a similar pattern)
The main ant task will use record to turn on and off logging to a build.log. Prior to parallel it will disable logging, let the sub-ant log to files. After they complete ant will load and echo the output. The console output continues to be blended and the build.log is serialized.
It's a little klunky but not too bad.
<project name="antExperiments" default="para" basedir=".">
<!-- Logging Control -->
<property name="build.log.dir" location="${basedir}/logs"/>
<!-- - - - - - - - - - - - - - - - - -
macro: activate logging (defaults to ${build.log.dir}/build.log)
- - - - - - - - - - - - - - - - - -->
<macrodef name="start.log">
<attribute name="name" default="build"/>
<attribute name="dir" default="${build.log.dir}"/>
<attribute name="append" default="false"/>
<sequential>
<record action="start" append="@{append}" name="@{dir}/@{name}.log"/>
</sequential>
</macrodef>
<!-- - - - - - - - - - - - - - - - - -
macro: deactivate logging (defaults to ${build.log.dir}/build.log)
- - - - - - - - - - - - - - - - - -->
<macrodef name="stop.log">
<attribute name="name" default="build"/>
<attribute name="dir" default="${build.log.dir}"/>
<attribute name="append" default="false"/>
<sequential>
<record action="stop" append="@{append}" name="@{dir}/@{name}.log"/>
</sequential>
</macrodef>
<target name="clean">
<delete dir="${build.log.dir}"/>
<mkdir dir="${build.log.dir}"/>
</target>
<!-- - - - - - - - - - - - - - - - - -
target: main.init
Initialization for Top Level build - not used by subants
- - - - - - - - - - - - - - - - - -->
<target name="main.init">
<start.log/>
</target>
<!-- =================================
target: para
top level build runs 2 jobs in parallel producing interleaved hard to read
on to standard output and non interleaved more easily understood logging
to build.log
================================= -->
<target name="para" depends="main.init,clean">
<stop.log/> <!-- disable top level logging -->
<parallel threadcount="4" pollinterval="50">
<ant output="${build.log.dir}/proc1.log" target="proc1">
<property name="proc" value="proc1"/>
</ant>
<ant output="${build.log.dir}/proc2.log" target="proc2">
<property name="proc" value="proc2"/>
</ant>
</parallel>
<start.log/> <!-- enable top level logging -->
<!-- Non interleaved output -->
<loadfile property="p1" srcfile="${build.log.dir}/proc1.log"/>
<loadfile property="p2" srcfile="${build.log.dir}/proc2.log"/>
<echo>
--------------------------
BuildJob: proc1
OUTPUT: ******************
${p1}
**************************
--------------------------
BuildJob: proc2
OUTPUT: ******************
${p2}
**************************
BUILD LOG: ${build.log.dir}/build.log
</echo>
</target>
<target name="init">
<echo>Init called by ${proc}</echo>
</target>
<target name="proc1" depends="init">
<echo>PROC1.......................
</echo>
<exec dir="${basedir}" executable="cmd">
<arg line="/c dir \"/>
</exec>
</target>
<target name="proc2" depends="init">
<echo>PROC2..........2222222.......
</echo>
<exec dir="${basedir}" executable="cmd">
<arg line="/c dir \sandbox"/>
</exec>
</target>
</project>