RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Cross-platform Builds Made Easy: From Microsoft Visual Studio to ARMCC Using Ant and XSL : Page 2

Tired of keeping embedded make files in sync with your Microsoft Visual Studio project? Use Ant's XSL processor to convert Microsoft Visual Studio project files on-the-fly before cross-platform builds!

Transforming the VCPROJ to Ant's XML Vocabulary Using XSL
Ant supports XML style transformations through the use of the integrated Xalan processor. To convert the .vcproj to an Ant build script, you must:
  1. Define build property values for each of the environment variables.
  2. Transform the list of source files from the .vcproj file to the Ant build script vocabulary, reconciling the .vcproj's format for relative paths as appropriate.
  3. Create a top-level Ant project.
  4. Insert a task directive to invoke the target compiler.
In addition to these tasks, the transformation must take into account the specific build tools—we use an internally built Ant task called armcc that invokes the ARM RealView Developer Suite (ARM RVDS) command-line tools akin to ccTask for Ant. You may find that you can use ccTask, or you can write your own Ant task. You may also be able to get what you need by using Ant's exec task alone to invoke specific compiler tools.

Listing 2 shows the transformation used to manage an incoming .vcproj such as the one you saw in Listing 1. Like most XSL documents, it's pretty dense, so it may be helpful to walk through it step by step.

It opens with the typical preamble for an XSL document, pointing to the World Wide Web Consortium's schema for XSL. The next two lines specify information about the output of the transformation, namely, that the output is indented XML (making it easier to read as you debug the transformation) and that white space is to be preserved when parsing the source's XML for the incoming .vcproj vocabulary.

The next block, consisting of two <xsl:variable> declarations, defines variables to contain the name of the project and the name of the target output. These are taken directly from the incoming .vcproj file; the project.name variable is assigned the value of the Name property of the VisualStudioProject tag in the .vcproj file, while the target.name variable is assigned a value giving a unique name for the resulting Ant script (after the transformation) based on the project name specified in the .vcproj file.

There are four template directives within the XSL document: one to match the top-level Microsoft Visual Studio Project (corresponding to the VisualStudioProject tag in .vcproj), one to match the build configuration (corresponding to the <Configuration> tag in .vcproj), and two to match the <Files> tag in the .vcproj, which actually constructs the bulk of the transformed build script.

The first template directive, matching the VisualStudioProject tag, transforms the VisualStudioProject tag in a .vcproj file to an Ant project tag. As it does this, it includes the Ant task definition for the armcc task, as well as specifies the name for the target, based on the value of the target.name variable created in the variable definitions. Finally, it applies all subsequent templates to the contents of the VisualStudioProject tag in the source .vcproj file.

The second template pulls the configuration settings out of .vcproj's Configuration tag, selecting the <Configuration> tag with the attribute named Debug|Win32, (the default named debug build configuration in our environment). The settings it captures are the desired output directory as well as the include paths for the project. Capturing and transforming these values is a little tricky: here's a close look at the include directory, cleaned up some from the initial listing for readability:

<property name="armcc.includedirs">
  <xsl:attribute name="value"> 
    <xsl:value-of select="translate(Tool/@AdditionalIncludeDirectories, ';', ',')"/> 

This snippet sets the Ant build property armcc.includedirs to be the value of the value of the AdditionalIncludeDirectories attribute of the Tool tag in the incoming .vcproj file, and converts the Microsoft Visual Studio semicolon-delimited list into a comma-delimited list, which is required by Ant.

If the responsibility of the first template is to produce the Ant project, and the second template's is to harvest and prepare the ouput directory and include directory list, the third template performs the bulk of the work in the transformation. Matching the <Files> tag within the Debug build configuration of the .vcproj, it converts the list of C files to an Ant filelist tag. In converting the .vcproj <Files> entry to an Ant filelist tag, it:

  1. Generates build-time status output by inserting Ant echo tags indicating the name of the project, the resource build step, and the source build steps.
  2. Creates an Ant filelist tag containing the list of files, giving this tag the and id armcc-Slideshow.files.source.
  3. Generates a call to the armcc task passing it the id of the Ant filelist along with compile-time defines, the include path, and the output directory.
The last step is optional—you can just as easily pull compile-time defines from the .vcproj. It's a little easier to do it this way (even if it means that tweaking in Microsoft Developer Studio must be carried over to the style sheet) because some defines for the environment (such as -DAEE_SIMULATOR) differ between the emulation and target hardware. Another point to note is an artifact of the armcc task: it doesn't selectively rebuild object files, but rather performs a clean build on each invocation; this ensures that the build server is always generating a truly fresh build at the expense of some CPU cycles.

The final template directive is the simplest; it must merely map from the RelativePath attribute of each of the .vcproj file's <File> tags to an Ant file tag and its name attribute.

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date