Skip to main content

Wouter

Go Search
Home
Contact Me
  

Wouter > Posts > Combining MakeCab and MSBuild, the enterprise edition
Combining MakeCab and MSBuild, the enterprise edition

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
&quot;$(MSBuildProjectDirectory)\Solution.ddf&quot;
/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 &quot;$(MSBuildProjectDirectory)\Solution.ddf&quot;

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 &quot;$(MSBuildProjectDirectory)\RootFiles&quot; $(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!

Comments

Shawn

I'm discovered this very problem in some code built for us by contractors. We're not using MSBuild, but based on this post I tried the following: mywebpart.dff: .OPTION EXPLICIT ; Generate errors ;... ; other .Set statements ;... ; I've tried this both with the following line and without .Set Configuration=Debug ;** Assemblies to be deployed bin\%Configuration%\mywebpart.dll Post-Build Event: cd $(ProjectDir) makecab /F Solution\mywebpart.ddf /D Configuration=$(ConfigurationName) The error I get on build is: Option Explicit and variable not defined: Configuration any ideas?
at 9/10/2008 4:00 AM

Ryan

This looks very helpful, but how do you use Variables in path definitions when your path might have spaces in it and need to be enclosed in quotes? It seems to take "Sub Folder\%variable%\item.dll" literally and doesn't do the variable exchange. Thanks!
at 10/2/2008 9:41 PM

Add Comment

Items on this list require content approval. Your submission will not appear in public views until approved by someone with proper rights. More information on content approval.

Name (required) *


Your Url

Type the Web address: (Click here to test)  

Type the description: 

Comments (required) *

Attachments