Faster parallel MXMLC compilation using Ant
February 9, 2010
Whenever you have a Flex project consisting of several modules, you can take advantage of compiling those modules in parallel – provided that they don’t depend on each other – using Ant and the Ant-Contrib tasks. In a project with five modules, I’ve seen a speed increase of about 30% compared to normal sequential compilation. I haven’t tested yet how this setup performs with more modules but I guess you could run into memory problems when compiling too many of them in parallel (you could still compile them in batches then). Below is part of an Ant script which does the job…here a few notes:
- At the top, the Ant-Contrib tasks are included. They provide a few useful tasks Ant doesn’t support out of the box, for example for-loops…
- The second section sets up a fileset which is used to declare all source files and later check if anything has changed and needs recompilation.
- The third section is where a single module is compiled using a macrodef task. If you haven’t used macrodef yet: It allows you to define kind of a general template for a custom task and substitute certain attributes or elements when you call the task (very useful!). The incremental option instructs mxmlc to generate cache files for faster recompilation. This example only toggles the incremental and debug options on when you compile for debugging. Additionally, the task checks if the source-files have changed and only then mxmlc will be started…
- The fourth section is where the actual parallel compilation of all modules happens: The for-task loops over a comma-separated list of modules (you could also dynamically generate this list depending on your folder structure) and compiles all modules (more or less) at the same time since the parallel flag is set to true. Before the compilation of all modules, the main file of the application is compiled. This can be useful if you want to generate a link-report based on your main application classes which is then fed into your module compilations with the load-externs option. Be careful not to use any operations in the for-loop which depend on the order of execution because things can get messed up when the parallel attribute is set.
- The last section simply calls the compile-all task with the debug flag set to true.
Of course, you can also run this script on a CI-Server but if you want to use the IDE for parallel compilation: IntelliJ, for example, will support parallel compilation in the next update. Another way to speed things up is the HFCD compiler which I haven’t tried yet…
Here’s the Ant snippet (left out the property definitions):
<taskdef resource="net/sf/antcontrib/antlib.xml"> <classpath> <pathelement location="libs/ant/ant-contrib-1.0b3.jar"/> </classpath> </taskdef> <fileset id="flex.source.files" dir="${flex.source.dir}"> <include name="**/*.as"/> <include name="**/*.mxml"/> <include name="**/*.css"/> </fileset> <macrodef name="compile-app"> <attribute name="debug" default="true"/> <attribute name="appName"/> <sequential> <outofdate> <sourcefiles> <fileset refid="flex.source.files"/> </sourcefiles> <targetfiles path="${flex.release.dir}/@{appName}.swf"/> <sequential> <java jar="${flex.sdk.dir}/lib/mxmlc.jar" fork="true" failonerror="true"> <arg value="-debug=@{debug}"/> <arg value="-incremental=@{debug}"/> <!-- rest of mxmlc options --> </java> </sequential> </outofdate> </sequential> </macrodef> <macrodef name="compile-all"> <attribute name="debug" default="true"/> <sequential> <compile-app appName="main" debug="@{debug}"/> <for list="${flex.modules}" param="module.name" parallel="true"> <sequential> <compile-app appName="@{module.name}" debug="@{debug}"/> </sequential> </for> </sequential> </macrodef> <target name="compile-all-debug"> <compile-all debug="true"/> </target>
Filed under: Flash Platform, Software Development
Hi,
could you post the properties section as well, please?
Thanx, flo;
Hi Flo,
the properties and values depend on your project setup but for the simplified example above they could be:
Hi, I almost got the example working, however, I’m hitting a wall when it comes to the config.xml.
If I add this to the mxmlc options:
The ${flexlib} token to the configuration file is coming in incorrectly as “.” so no files using the token could be found. I can’t just set this to be absolute because the default flex config.xml has the incorrect token as well.
If you have any ideas, it would make me very happy :)
I think I figured it out –
you have to add:
So the compiler understands the ${flexlib} token.
What exactly is a “module”? I’ve never seen that term used at all in the Flex development so far so I’m a little unsure of how to go about using this.
Not sure how you figure this to be running in parallel, and faster than a sequential build script. Probably worth checking how your code works beforehand or even glancing at the Ant documentation.
Your running everything in ‘sequential’ blocks which according to the Ant document runs each task one after another, what you want to use is ‘parallel’ which as the name suggestions runs things at the same time rather than in sequence. The way your using the ‘sequential’ task is pointless, Ant is going to run things in that order anyway since your never entering a parallel state. http://ant.apache.org/manual/Tasks/sequential.html
Would also be better to use the Ant tasks provided by the Flex SDK rather than calling the jars.
Nevermind, missed that you had the parallel attribute on the for loop, though your use of sequential is still excessive. Once your in a sequential state, you stuck in until your finished.
Nice Article!
Now, i can build multiple modules using script.
My problem is with custom component.
Some of my modules use custom component (created in same project).
At the time of build, i am getting following error.
[mxmlc] C:\FxProject\src\Module\Module1.mxml(9): Error: Definition components:comp1 could not be found.
[mxmlc] import components.comp1;
If anyone have idea, please suggest solution.