I'm using cmake/cpack to build my project with WiX.
cmake runs heat.exe (or something similar) which produces files.wxs that contains the files of my project in the following format:
We'll assume a single file named a.txt inside a folder named "bin". The project is built in NewFolder on the Desktop.
<DirectoryRef Id="CM_DP_bin">
<Component Id="CM_CP_bin.a.txt" Guid="*">
<File Id="CM_FP_bin.a.txt" Source="C:/Users/mindlessbot/Desktop/NewFolder/_CPack_Packages/WIX/packageName/bin/a.txt" KeyPath="yes"/>
</Component>
</DirectoryRef>
After the MSI is created, the whole NewFolder is moved in a different directory (on our server). As a result, when I try to create a WiX Patch using the output .wixpdb, I get the following error:
error PYRO0103 : The system cannot find the file 'C:/Users/mindlessbot/Desktop/NewFolder/_CPack_Packages/WIX/packageName/bin/a.txt'
After some googling, I found out that the .wixpdb contains references to the files, which have changed location, so of course it can't find them. I found a thread where someone provided the commands to use bindpaths, however since I'm using cpack I can't directly call them.
So how should I got about doing this?
Some additional info:
My project contains multiple wxs files (not sure if it makes any difference)
The cpack command is:
path/to/cpack.exe -G WIX --config path/to/config.cmake
The patch command is run separately:
torch.exe -p -xi path/to/oldInstaller.wixpdb path/to/newInstaller.wixpdb -out path/to/patch.wixmst
candle.exe path/to/patch.wxs -out path/to/patch.wixobj
light.exe path/to/patch.wixobj -out path/to/patch/wixmsp
pyro.exe path/to/patch.wixmsp -out path/to/patch.msp -t PatchBaselineID path/to/patch/wixmst
In the event that you would like to build your MSIs on one machine, but build the patch on another, I recommend using the .wixout
approach rather than relying on the .wixpdb
approach. A .wixout
file may be generated by the same WiX Toolset CLI tool that is used to build the MSIs, light.exe
. The .wixout
Full documentation on the WiX Toolset linker, light.exe
, may be found here. The following is an example use of light.exe
to build a .wixout
file:
"C:\Program Files (x86)\WiX Toolset v3.11\bin\light.exe" "/path/to/Some.wixobj" "/path/to/Another.wixobj" "/path/to/AndYetAnother.wixlib" -bf -xo -out "/path/to/MyInstaller_v1.wixout"
So now let's breakdown what these command line parameters are for:
"/path/to/Some.wixobj" "/path/to/Another.wixobj" "/path/to/AndYetAnother.wixlib"
- These are the compiled outputs of WiX source files, they may be either .wixobj
files (generated through candle.exe
) or .wixlib
files (generated through lit.exe
, a way of consolidating .wixobj
files into one, shareable library).
-bf
- This switch causes all of the files to be bound int the resulting .wixout
file. This is what removes the need to have the exact folder structure on the target machine when building patches, because the files are carried with the .wixout
file.
-xo
- This switch tells the linker to output an XML representation of the MSI, instead of the actual MSI. This is required to use the -bf
switch.
-out "/path/to/MyInstaller_v1.wixout"
- This tells the linker where to output the .wixout
file.
Once you have the capability of generating .wixout
files, the torch.exe
command can be modified to run based on .wixout
files instead of .wixpdb
files and their associated folder structures. The following is how I would modify your torch.exe
command to use .wixout
files as opposed to .wixpdb
files:
torch.exe -p -xi "path/to/oldInstaller.wixout" "path/to/newInstaller.wixout" -out "path/to/patch.wixmst"
So, all in all I really like this approach, and generally I make my build process produce both an .msi
and a .wixout
file. This allows us to cache various builds/versions of our installer as .wixout
files, and then the process of creating a patch between various versions of the .wixout
files becomes relatively easy.