Part 6: Continuous Integration - The CodeDocumentationBuild using Sandcastle
This is the sixth post in a series where I document how to setup a Continuous Integration (CI) process using open source tools like CruiseControl.NET, NCover, NUnit, Subversion and Sandcastle together with MSBuild and VS 2005. Part 6 covers the CodeDocumentationBuild and the targets and tasks used by the CodeDocumentationBuild. The CodeDocumentationBuild shows how to create MSDN style help documentation from the XML code comments.
Post Updates
- 11/12/2007: Updated the CC.Net configuration to use build queues and entity references.
Tools
I used the following tools to generate the MSDN style documentation:
- HTML Help Workshop for building HTML help 1.x files.
- Visual Studio .NET Help Integration Kit 2003 for building help files that can integrate into Visual Studio.
- Sandcastle June 2007 CTP to generate the help file content from the XML code comments.
- Sandcastle Help File Builder (SHFB) to set the options for the help file and to bootstrap the document creation process.
- Sandcastle Presentation File Patches to solve some issues with the Sandcastle June CTP. Extract the contents of the ZIP archive to the Sandcastle installation directory.
Process
Before automating the process via MSBuild and CC.NET, I used SHFB's GUI to create a .shfb help file project that contains all the settings required to build our help file. Settings like the assemblies to document, the help file styles to use, member accessibility (public/private/internal/protected) to document, namespaces to document etc. can all be set via the GUI. I then added the .shfb file to a \Documentation folder (see Part 1 for our directory structure) and verified the documentation output by compiling the project using the SHFB GUI.
MSBuild Scripts
Getting the project integrated into MSBuild was quite easy as SHFB comes with a console runner that can be used to bootstrap the whole document generation process. I simply had to add a BuildDocumentation target and a few additional settings to our build file to get it running:
1 <Target Name="BuildDocumentation"
2 DependsOnTargets="BuildCode"
3 Condition=" '$(Configuration)' == 'Release' ">
4
5 <!-- Build source code docs -->
6 <Exec Command="$(DOUBLE_QUOTES)$(SandCastleHFBCmd)$(DOUBLE_QUOTES) $(DOUBLE_QUOTES)$(DocFolder)\$(SandCastleHFBProject)$(DOUBLE_QUOTES)" />
7
8 </Target>
9
Observations:
- Line 1-3: The BuildDocumentation target depends on the BuildCode target (see Part 3) and only runs if the code is compiled in Release mode. This is required as we only generate the XML code comments as part of doing release builds.
- Line 6: The SHFB Console runner is called using our settings file to generated the documentation. The output is stored in the \Documentation\Help folder.
CruiseControl.NET Configuration
As the document generation process can take quite a while to complete, I decided to create a separate CodeDocumentationBuild CC.NET project to generate the documentation. This way we don't incur the overhead of generating the documentation on every build. Here is the CruiseControl.NET Configuration:
1 <project name="CodeDocumentationBuild" queue="CCNet.Demo" queuePriority="4">
2 &header;
3 <category>CodeDocumentation</category>
4 <artifactDirectory>C:\Projects\CCNet.Demo\Builds\CodeDocumentationBuild\Artifacts</artifactDirectory>
5
6 <triggers />
7
8 &svn;
9
10 <state type="state" />
11
12 <labeller type="defaultlabeller"/>
13
14 <!-- Remove the log files from the previous build as we are creating a complete new build -->
15 <prebuild>
16 <exec>
17 <executable>clean.bat</executable>
18 <baseDirectory>C:\Projects\CCNet.Demo\Builds\CodeDocumentationBuild</baseDirectory>
19 </exec>
20 </prebuild>
21
22 <tasks>
23 <msbuild>
24 <executable>C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe</executable>
25 <workingDirectory>C:\Projects\CCNet.Demo</workingDirectory>
26 <projectFile>CCNET.Demo.proj</projectFile>
27 <buildArgs>/noconsolelogger /v:normal /p:SolutionName=CCNet.Demo.sln;Configuration=Release;Platform=AnyCPU;DeploymentBuild=false;RunCodeAnalysis=false</buildArgs>
28 <targets>BuildDocumentation,CommitBuildChanges</targets>
29 <timeout>3600</timeout> <!-- 1 hour -->
30 <logger>C:\Program Files\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MSBuild.dll</logger>
31 </msbuild>
32 </tasks>
33
34 <publishers>
35
36 <statistics>
37 <statisticList>
38 <firstMatch name="Svn Revision" xpath="//modifications/modification/changeNumber" />
39 </statisticList>
40 </statistics>
41
42 <!-- Revert changes that may still exist because the build failed -->
43 &svnrevert;
44
45 &pub;
46 </publishers>
47
48 &links;
49 </project>
50
Observations:
- Line 6: The build makes use of a force trigger, i.e. it needs to be manually invoked.
- Line 27: The solution is compiled in Release mode to generate the XML code comments but RunCodeAnalysis is turned off to prevent running FxCop that is also turned on in Release mode.
- Line 28: The BuildDocumentation target is invoked to build the documentation and the latest version of the help file is committed to the repository by calling the CommitChanges target. As we generate a single .chm help file this is a feasible approach. For projects where a MSDN style documentation web site is created, a better approach would be to deploy the web site contents onto a server for publication.
Next Steps
As you can see it was quite easy to add the document generation to our build. I also found
this handy resource that shows you how to use all the possible XML code documentation tags to create decent code documentation. The
next post will highlight all the targets required for the
QtpBuild. Keep watching this space