Add Sandcastle doc generation to your NAnt builds


A critical step in your automated build process is documentation generation. This article explains how to add documentation generation to NAnt scripts using Sandcastle.
By: Brett Burch Spacer (www.brettresources.net) Spacer Date: June 13, 2007Spacer Printer Friendly Version

Assuming you have a tree structure as follows, adding automated generation through the September CTP of Sandcastle into your NAnt build process is very painless. Even if you don't have an identical structure, you can change a few lines of text and be on your way. Here is that structure shown graphically via WinCVS.

source structure shown in WinCVS

I have included the Sandcastle icons, scripts, and styles that come with the download in my CVS tree. Also stored in CVS are a .bat file which NAnt fires up and a sandcastle.config file slightly different than the example provided with the download. NAnt pulls the documentation generation items out of CVS and then runs a batch file to create the documentation from those items. The NAnt target of interest is simply

<target name="docs" depends="build">
  <call target="cvs_doc" cascade="false" />
  <exec program="${path::combine(build.dir, project::get-name() 
    + '')}/doc/GenerateDocumentation_tokenreplaced.bat"/>
</target>

There are a few targets that this target requires in addition to the obvious build target. They are included below for reference.

<target name="cvs_doc" depends="init,cvs_passfile" description="checks out doc items">
  <cvs-checkout 
    destination="${build.dir}" 
    cvsroot="${cvs.root}" 
    module="${cvs.module.doc}" 
    passfile="${cvs.passfile.location}"
    cvsfullpath="${cvs.exe.location}"
  />
  <call target="cvs_doc_replacetoken" />
</target>
<target name="cvs_doc_replacetoken" description="sets token to text in doc bat file">
  <copy file="${path::combine(build.dir, project::get-name()
     + '')}/doc/GenerateDocumentation.bat" 
     tofile="${path::combine(build.dir, project::get-name()
     + '')}/doc/GenerateDocumentation_tokenreplaced.bat" overwrite="true">
    <filterchain>
      <replacetokens>
        <token key="BUILDDIR" value="${build.dir}" />
      </replacetokens>
    </filterchain>
  </copy>
</target>

The critical piece which generates the documentation for you (following the build of your source) is the GenerateDocumentation_tokenreplaced.bat file. That file assumes you tell it the root of your folder / tree structure via NAnt’s replacetokens feature, you have installed Sandcastle in the default location, and your sandcastle.config file is slightly modified from the supplied CTP example.

Here is that .bat file in its entirety:

@echo off
echo start documentation generation

cd @BUILDDIR@\SalesForce\doc
if not exist comments mkdir comments

:: comment XML files need copied to the comments folder
copy ..\..\bin\SalesForce*.xml comments

MRefBuilder "..\..\bin\SalesForce*.*" /out:reflection.org 

/dep:"c:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Configuration.dll"
XslTransform /xsl:"C:\Program Files\Sandcastle\ProductionTransforms\AddOverloads.xsl" reflection.org 

/xsl:"C:\Program Files\Sandcastle\ProductionTransforms\AddGuidFilenames.xsl" /out:reflection.xml
XslTransform /xsl:"C:\Program Files\Sandcastle\ProductionTransforms\ReflectionToManifest.xsl" 

reflection.xml /out:manifest.xml

if not exist Output mkdir Output
::kill the current Output\html folder if it exists
if exist Output\html RMDIR Output\html /s /Q
if not exist Output\html mkdir Output\html

::the next 6 lines are only required if you do not store Sandcastle items in source control
if not exist Output\icons mkdir Output\icons
if not exist Output\scripts mkdir Output\scripts
if not exist Output\styles mkdir Output\styles
copy "C:\Program Files\Sandcastle\Presentation\Prototype\icons\*" Output\icons
copy "C:\Program Files\Sandcastle\Presentation\Prototype\scripts\*" Output\scripts
copy "C:\Program Files\Sandcastle\Presentation\Prototype\styles\*" Output\styles

BuildAssembler /config:sandcastle.config manifest.xml

::Generate HTML help project -- do not rename from test
XslTransform /xsl:"C:\Program Files\Sandcastle\ProductionTransforms\ReflectionToChmProject.xsl" 

reflection.xml /out:Output\Test.hhp

::Generate table of contents for HTML help project -- do not rename from test
XslTransform /xsl:"C:\Program Files\Sandcastle\ProductionTransforms\ReflectionToChmContents.xsl" 

reflection.xml /arg:html=Output\html /out:Output\Test.hhc

::Generate Index information -- do not rename from test
XslTransform /xsl:"C:\Program Files\Sandcastle\ProductionTransforms\ReflectionToChmIndex.xsl" 

reflection.xml /out:Output\Test.hhk

"%ProgramFiles%\HTML Help Workshop\hhc.exe" Output\Test.hhp
::put the final deliverable in the correct location
copy Output\Test.chm ..\..\doc\SalesForce.chm

echo end documentation generation

The change to the sandcastle.config file mentioned comes in line 53 of the sample file, where

<data files="comments.xml" />

becomes

<data files="comments\*.xml" />

. This is to ensure documentation from all assemblies is compiled into your CHM file. I have also changed the relative path references so the .bat file can be run from anywhere as long as Sandcastle is installed. The entire modified file is available at http://www.brettresources.net/dotnet/samples/sandcastle.config.xml

(note the file extension change). Your final result should be as shown below.

result CHM output shown in correct directory

I am not employed by or affiliated with SalesForce.com in any way. This is purely an example.

This is also posted at the Sandcastle blog.