Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / All-Topics

Building NHunspell with PowerShell Build Tools

5.00/5 (1 vote)
24 Nov 2014Public Domain3 min read 7.4K  
How to build NHunspell with PowerShell Build Tools

The PowerShell Build Tools are a toolbox for build, test and deployment automation. The Build Tools combine XML configuration and PowerShell scripting in a new way to get the best of both worlds. NHunspell is a wrapper for the Open Office Spell Checker Hunspell. Although NHunspell is a small project, it has a rather complex build and deployment workflow due to its native assemblies. We want to make this a bit easier so we switched the NHunspell build process to our new PowerShell based Build Tools.

NHunspell Build and Deployment

These are the steps that should be performed during a NHunspell build:

  1. Version Update
    Update all version strings in the solution to match the current build
  2. Compile the 32Bit Native DLL
  3. Compile the 64Bit Native DLL
  4. Compile the NHunspell Assembly
  5. Check the Files
    Check if all files are compiled and have the correct version resource
  6. Run the Unit Tests
  7. Create Zip Files
  8. Create NuGet Packages
  9. Test Deploy the Packages

So these steps are automated using the PowerShell Build Tools.

PowerShell Build Tools in Action

In this video, we show how NHunspell is built from PowerShell, within Visual Studio and on a Jenkins Build Server. It also shows how the build configuration can be edited and debugged.

Watch directly on Youtube - Building the NHunspell Spell Checker with PowerShell Build Tools

Build Configuration

The PowerShell Build Tools use a XML configuration file with the default name BuildConfig.xml. Here are the most important parts from the NHunspell  BuildConfig.xml:

XML Declaration

This XML declaration is as follows:

XML
<?xml version="1.0" encoding="utf-8"?>
<!-- Build configuration for NHunspell -->
<BuildConfig xmlns="http://www.crawler-lib.net/build-tools"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.crawler-lib.net/build-tools 
http://download.crawler-lib.net/BuildTools/BuildConfig.xsd?action=view">

It links to the current build tools schema definition and can be used to enable IntelliSense in Visual Studio.

Build Labeling

XML
<Label>
  <BuildRevisionTimestamp/>
</Label>

The Build is labeled with the Build/Revision Timestamp tool. It works the same way as assemblies are versioned when *.* is specified as build and revision numbers.

Credentials for the Build Steps

XML
<Credentials>
<Plain>
NuGetFeed=http://buildserver:8050/nuget/Test
NuGetApiKey=b763316f-25c2-4d17-bf0a-1c22e071eb05
</Plain>
</Credentials>

The credentials section allows to specify credentials for use in the build steps later.

Solutions and Versions

XML
<Solutions>
  <!-- The NHunspell solution to build, not to be confused with a visual studio solution -->
  <Solution Name="NHunspell">

  <Version>
    <AppendLabel>1.2</AppendLabel>
  </Version>
  ...

The PowerShell Build Tools are able to build a bunch of solutions during one build. The typical use case for this are solutions that need to have the same build label, but use different versioning. The versioning tool is specified for each solution and in this case, it appends simply the build label to a fully qualified version.

Build Sequences

XML
<BuildSequences>

The build sequences are collections of build steps that can be executed to get to a certain stage in the build process. The PowerShell Build Tools use an incremental approach to get a build done. There is a special sequence called "Clear-Build" that clears the current build and forces a completely new build.

New-Build Sequence  

XML
<BuildSequence Name="New-Build">

<!-- Patching the version of the projects to the current build version -->
<Autover Path="..\HunspellWindows\HunspellWindows.sln" />
<Autover Path="NHunspell.sln" />

<!-- Compiling the native hunspell DLLs for Windows -->
<MSBuild Path="..\HunspellWindows\HunspellWindows.sln" 
Configuration="Release" Platform="x86" />
<MSBuild Path="..\HunspellWindows\HunspellWindows.sln" 
Configuration="Release" Platform="x64" />

<!-- Compiling NHunspell itself -->
<MSBuild Path="NHunspell.sln" 
Configuration="Release" Platform="Any CPU" />

<!-- Test if all files exist, have the correct file and product versions and are newly build --> 
<VerifyFile Path="UnitTests\bin\release\Hunspellx86.dll" 
FileVersion="true" ProductVersion="true" New="true"/>
<VerifyFile Path="UnitTests\bin\release\Hunspellx86.pdb" 
FileVersion="false" ProductVersion="false" New="true"/>
<VerifyFile Path="UnitTests\bin\release\Hunspellx64.dll" 
FileVersion="true" ProductVersion="true" New="true"/>
<VerifyFile Path="UnitTests\bin\release\Hunspellx64.pdb" 
FileVersion="false" ProductVersion="false" New="true"/>
<VerifyFile Path="UnitTests\bin\release\NHunspell.dll" 
FileVersion="true" ProductVersion="true" New="true"/>
<VerifyFile Path="UnitTests\bin\release\NHunspell.pdb" 
FileVersion="false" ProductVersion="false" New="true"/>
<VerifyFile Path="UnitTests\bin\release\UnitTests.exe" 
FileVersion="true" ProductVersion="true" New="true"/> 

</BuildSequence>

The NHunspell build uses the New-Build Sequence to patch the versions of all projects in the solutions with the Autover tool. After that, the native DLLs and NHunspell is compiled using MSBuild. Least it is checked if the generated files are new and if they have the correct version.

Test-Build Sequence

XML
<BuildSequence Name="Test-Build" 
Depends="New-Build" NewBuild="false">
<!-- Performing several tests with the new files -->
<NUnit Path="UnitTests\bin\release\UnitTests.exe" />
<FxCop Path="UnitTests\bin\release\NHunspell.dll" /> 
</BuildSequence> 

The Test-Build Sequence runs NUnit and FxCop to test NHunspell. The Test-Build sequence depends on the New-Build sequence. If the build is clear, the Build Tools will execute the New-Build sequence first. If there is a current build with a successful New-Build sequence, the Test-Build sequence will use the current build and perform the tests on the already available build results. This concept allows to modularize the steps and cuts down the time needed to develop a certain build sequence.  

Complete-Build Sequence

XML
<BuildSequence Name="Complete-Build" 
Depends="Test-Build" NewBuild="false">
<!-- Make a zipped release package -->
<Zip Path="UnitTests\bin\release\Hunspellx86.dll" Target="Hunspellx86.dll" 
Output="NHunspell.$($context.PackageVersion).zip" />
<Zip Path="UnitTests\bin\release\Hunspellx86.pdb" Target="Hunspellx86.pdb" 
Output="NHunspell.$($context.PackageVersion).zip" />
<Zip Path="UnitTests\bin\release\Hunspellx64.dll" Target="Hunspellx64.dll" 
Output="NHunspell.$($context.PackageVersion).zip" />
<Zip Path="UnitTests\bin\release\Hunspellx64.pdb" Target="Hunspellx64.pdb" 
Output="NHunspell.$($context.PackageVersion).zip" />
<Zip Path="UnitTests\bin\release\NHunspell.dll" Target="NHunspell.dll" 
Output="NHunspell.$($context.PackageVersion).zip" />
<Zip Path="UnitTests\bin\release\NHunspell.pdb" Target="NHunspell.pdb" 
Output="NHunspell.$($context.PackageVersion).zip" />

<!-- Write Release Info file --> 
<AppendText Output="NHunspell.$($context.PackageVersion).zip.info.xml">
<![CDATA[<?xml version=`"1.0`" encoding=`"utf-8`" ?>
<infos>
<summary>NHunspell Release Version $($context.Version)</summary>
<description>
<a href=`"http://www.crawler-lib.net/nhunspell`">NHunspell</a> 
Release Version $($context.Version)
</description>
</infos>]]>
</AppendText>

<!-- Update the version and dependencies versions in the NuSpec file -->
<NuSpecUpdate>
<NuSpec Path ="NHunspell.nuspec" />
</NuSpecUpdate>

<!-- Pack the NuGet package -->
<NuGetPack Path ="NHunspell.nuspec"/> 
</BuildSequence> 

The Complete-Build sequence depends on the Test-Build sequence, so the build can only be completed if successfully tested. In the Complete-Build sequence, the Zip- and NuGet packages are created. As you can see, some string values contain PowerShell code which is escaped with the dollar sign ($) as usual in PowerShell. 

Publish-Build Sequence

XML
<!-- Publishes the previously created build -->
<BuildSequence Name="Publish-Build" 
Depends="Test-Build" NewBuild="false">
<NuGetPush Path ="NHunspell.$($context.PackageVersion).nupkg" 
	ApiKey="$($context.Credentials.NuGetApiKey)" 
	Feed="$($context.Credentials.NuGetFeed)"/>
</BuildSequence> 

</BuildSequences>
</Solution>
</Solutions>
</BuildConfig> 

The Publish-Build sequence performs a publish step on our internal test NuGet feed.

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication