WiX Compile Time Directory Harvesting And Variables

I'm a bit confused about the interaction of these tools at the moment and I need a little helping ironing out my appraoch (or being told I'm being daft).

I have a VS2010 solution with two WiX projects. I have a a .WXI file in a solution folder that contains a number of global variables that I would like to use in multiple projects (more will be added in the future).

I include the .WXI file in my main Product.wxs project using the standard syntax like this:

<?include ..\Shared\Common.wxi?>

This is working great and all the variables are available. However as part of this build process I also need to run heat.exe in order to generate a large fragment automatically on each rebuild.

I use a command like this:

"Heat.exe" dir %sourcedir% -sfrag -sreg -suid -gg -ke -template fragment -out %wixfile% -dr INSTALLFOLDER -cg MyInstall -var var.MyFileSource

In my included variables file I have this:

<?define MyFileSource= "$(var.SolutionDir)..\..\..\..\mydir\bindist" ?>

However I get an error like this:

Undefined preprocessor variable '$(var.MyFileSource)'.

As you would expect as the fragment file does not contain a line that references the file Common.wxi but the problem is this fragment file is going to be replaced each build prior to compilation so it's completely inpractical to hand edit this fragment in order to add it each time (not to mention impossible anyway).

My question is am I approaching this completely incorrectly? If not, what is the best way to get this working correctly?

What is confusing is that there is the -var switch to create a variable reference in the fragment file but no way to then enable the variable referencing from an include file (unless I've missed that somewhere in the docs).

Answers


Instead of placing the variables in a separate wxi file and include it in all possible places, you can supply candle.exe with the variables you need. You can do this either from command line (using -dVarName=VarValue syntax), or with any of the supported build tools, NAnt or MSBuild.

I can see the following advantages:

  • the WiX authoring are not polluted with <?include?> stuff here and there
  • you don't have to mess the heat harvested authoring
  • variables defined once from the command line are available in any wxs file of your project

I also have such an include-file that centralizes my configuration during the build. As I also use variables in the files produced by heat this is very convenient, as I have to define them just once. To be able to use these variables also in the heat-output you can transform the output created by heat using a xslt-transformation. Just add -t myTransformFile.xslt to the command-line of heat, so the output will be transformed according to the stylesheet defined in myTransformFile.xslt.

In the myTransformFile.xslt-file just add the following, which will basically copy everything and also add the Include-directive:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:wix="http://schemas.microsoft.com/wix/2006/wi"
        xmlns="http://schemas.microsoft.com/wix/2006/wi"
        exclude-result-prefixes="wix">

        <xsl:template match="wix:Wix">
          <xsl:copy>
            <!-- The following enters the directive for adding the Common.wxi include file to the dynamically generated file -->
            <xsl:processing-instruction name="include">$(sys.CURRENTDIR)..\Shared\Common.wxi</xsl:processing-instruction>
            <xsl:apply-templates select="@*" />
            <xsl:apply-templates />
          </xsl:copy>
        </xsl:template>

        <xsl:template match="@*|node()">
          <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
          </xsl:copy>
        </xsl:template>

    </xsl:stylesheet>

You have to adjust the path to your Common.wxi of course so that it can be found at build-time.

Edit: forgot a part of the XSLT-file that copied also other elements.


Need Your Help

Accessing XSL inside jQuery

javascript jquery html xslt

I may be asking a very basic question. I searched many posts but didn't find correct information. Please point me in the right direction.

Close UIAlertView and Replace with Another

iphone service location uialertview

I'm running an application that requires LocationServices be enabled. I'm checking if they are by making a call to the service and catching the error. In the error case, I want to pop up an alert...