WiX

A case study for .wixlibs.

The Visual Studio setup is composed of over 30,000 source files that get compiled into over 250 MSI files. Needless to say it is a large code base. The problem is that a lot of the code was machine generated and is now very difficult to maintain. A few months ago, I started a large scale restructuring effort to improve the code and build process. I thought I'd share one of the key aspects in my restructuring effort.

The most glaring issue, thus the first problem I tackled, was the monolithic build. Each MSI was built by a .wixproj that listed the full path to all of the source files necessary to build the MSI. This isn’t necessarily a problem except that significant number of the source files are shared across multiple MSIs.

That leads to two problems:

  1. Inefficient Compile - every .wixproj gets its own intermediate folder so every .wxs file is compiled into a unique .wixproj. That means thousands of files are being recompiled across MSIs. This is a relatively minor issue because the WiX compiler is pretty fast but at large scale it’s a waste that adds up.

    Before you suggest compiling to the same intermediate folder, know that there are many (way too many) preprocessor variables used in the VS source files. Thus you’d need to be very careful that each compile of a .wxs with different preprocessor variables generated a uniquely named .wixobj. Again, doable but non-trivial at large scales.

  2. Tight Coupling - given the direct references to source files in .wixprojs, changing the structure of your .wxs files (for example, splitting a file into two or merging multiple files into a single file) requires updating all .wixprojs that refer to the files. For example, I made a one line change to a .wxs file (added a dependency to a related file) that then required me to modify 200+ .wixproj files. As you might expect, most developers shy away from (properly) refactoring their setup code because it is so costly.

To make matter worse, these two problems feed on each other. The compile times are longer because files are not correctly factored. Refactoring is avoided because so many files must updated and the compile times take a long time. It’s a vicious cycle.

Fortunately, the solution is straight forward and only requires some determination (and, in my case, lots of typing) to implement. The solution derives from this simple axiom:

A .wxs file should be referenced by one and only one .wixproj.

I used the world “should” in the axiom only because someone will manufacture a situation where the axiom is not the ideal. In the 98% case follow the axiom. A .wxs file lives in one .wixproj.

How?

Simple, create .wixlibs. But you probably guessed that was the solution from the title of this post. Next time, I’ll spell out exactly what I did.

In the meantime, keep coding. You know I am!