There are examples on the web on how you can integrate MakeCab.exe into the build pipeline of your SharePoint solution so that you no longer have to build your solution packages manually. For the WSS3 Workflow Tools
Chris and I are developing we of course are doing the same, but the samples you find online do have a few small gotchas which is why I am writing this.
The most important gotcha is in de DDF file containing the instructions for makecab.exe. A common excerpt of a DDF file is shown below, try and spot the issue
.set DiskDirectoryTemplate=CDROM
.Set CompressionType=MSZIP
.Set UniqueFiles=Off
.Set Cabinet=On
manifest.xml
bin\debug\TPG.SharePoint.Workflow.dll
...
If you didn't spot it… the DDF references the DLL to put in the solution package, but it is doing this using a hardcoded reference to the output of the debug configuration. If you now want to create a release build, you will forget about this, and accidentally package the debug build instead (or perhaps you didn't forget, and now have to update the DDF for a release build, and then change it back when going back to developer mode) One solution is to have each build configuration (debug / release commonly) output to the same directory, but of course this means that you lose some separation of build configurations. We can do better than that!
So, time to parameterize!
The DDF file format supports the use of parameters which you can define inside the DDF and on the command line. This means we can alter the DDF file to look like the following sample:
.set DiskDirectoryTemplate=CDROM
.Set CompressionType=MSZIP
.Set UniqueFiles=Off
.Set Cabinet=On
manifest.xml
%BinFolder%\TPG.SharePoint.Workflow.dll
...
The 'BinFolder' parameter will be supplied by our build tasks and will contain a different value for each build configuration. The following MSBuild task displays how you can call Makecab.exe and pass in the BinFolder independent of the build configuration. The way in which it works is that you pass in the $(OutputPath) parameter (common to MSBuild) to MakeCab.exe.
<Exec
Command="$(MakeCabPath)
/F "$(MSBuildProjectDirectory)\Solution.ddf"
/D CabinetNameTemplate=$(MSBuildProjectName).wsp
/D DiskDirectory1=$(OutputPath)
/D BinFolder=$(OutputPath)"/>
Note that this sample has been formatted, in reality new-lines should be removed and the entire <Exec…> statement should go on one line.
Parameter | Function |
/F "$(MSBuildProjectDirectory)\Solution.ddf" | Point to the DDF file in the project folder. The DDF is not copied to the output directory but remains in the main project folder (it isn't output, but input, so it's a small improvement) |
/D CabinetNameTemplate=$(MSBuildProjectName).wsp | Sets the CabinetNameTemplate parameter for MakeCab.exe, using the project name as part of the name for the WSP file |
/D DiskDirectory1=$(OutputPath) | Sets the DiskDirectory1 parameter for MakeCab.exe, sending the solution package to the build configuration output folder |
/D BinFolder=$(OutputPath) | Sets the BinFolder custom parameter for MakeCab.exe, specifying the output directory which is used by the build configuration. This is what makes it configuration independent |
Since most of the steps you need to build a solution package using the DDF file is already described by Andrew in quite some detail I will refrain from repeating the same steps here. There are still a few things that I would like to improve on, namely to embed a version number in the WSP file name, and to pass in the name of the DLL instead of the DLL folder. More on that later.
In the WSS3 Workflow build process we have another few demands to make testing easier. For debug builds it is handy to copy the SharePoint components to their location inside the 12-hive, install the features and push the DLL to the Global Assembly Cache. For Release builds we only want to build a solution package, no copying or installation. The following three <Exec> directives enable this. Note that each uses a condition to only execute the directive on debug builds.
<!-- Copy the source files to the 12 hive -->
<Exec
Command="xcopy "$(MSBuildProjectDirectory)\RootFiles" $(SharePointPath) /E /Y"
Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "/>
<!-- Copy the DLL to the GAC (forcefully) -->
<Exec
Command="$(GacUtilPath) /i $(OutputPath)\TPG.SharePoint.Workflow.dll /f"
Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "/>
<!-- Install the feature (forcefully) -->
<Exec
Command="$(StsAdmPath) -o installfeature -name WSS3Workflow -force"
Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "/>
Hope it helps!