Search code examples
c++visual-studiocompilationpre-build-event

Visual Studio 2015 - Pre build event to determine which projects to compile


Motivation

PreBuild to disable compilation of redundant projects for faster compilation cycle.

Background

I have a VS15 ALL solution that contains many projects.

I have a single project, PreBuild, that all the other projects are dependent on, meaning, this PreBuild compiles first.
In addition, we also have a PostBuild project that do some more work once binaries are ready.

All projects are configured to build in Release mode (which is desired).
When a team member wants to release some binaries, he hits F7, Build Solution.
Now, the PreBuild, activates a separate dedicated process that calculates which projects should be released. The nature of the calculation is irrelevant to this discussion.

Problem

Out of the many many projects, it is often the case that only a few projects needs to be released. However, once the PreBuild process is done, ALL the projects are will compile which is very time consuming.

Question

Is it possible, after a solution build had started, to change the released projects?

Suggested unwanted approaches

  1. A developer handpicks only the relevant projects and only build those.
  2. PreBuild Kill & Revive. Once desired projects are calculated, PreBuild kills the VS15 process and activate a cmd compiling only the relevant projects.

Suggested approach

Change file ALL.sln and remove the the unwanted projects. This would work had I changed that file prior to the process start but I'm not sure it would work if this change occurs during the process.


Solution

  • The simplest way I can think of, while still keeping most of the current infrastructure in place: have a dedicated project which invokes the release build (by calculating dependencies and invoking msbuild) and configure VS so it can be select just that project for a build. All from within your ALL.sln so the rest of the features remain. Steps:

    Get rid of the PreBuild/PostBuild projects. I assume the PostBuild you mention is also meant for the actual release builds; if not just leave it there. Note by not requiring all projects to depend on the PreBuild project you already got rid of one maintainance burden.

    Add one single project which will do the release building, say ReleaseBuild. Such name is also better than having PreBuild/PostBuild projects since it clearly states the intent of the project. A Makefile project is suitable, though technically it could be as simple as an msbuild file with just one Build target. Configure the build command line to do whatever is needed, i.e. figuring out what to build then build. For the sake of an example: say you use Powershell to do this you would configure the build commandline to be

    Powershell -NoProfile -File BuildRelease.ps1 $(Platform)

    and BuildRelease.ps1 contains something like

    $projectsToRelease = CalculateMyProjectsForRelease()
    $platform = $Args[0]
    $projectsToRelease | %{& msbuild $_ "/p:Configuration=Release;Platform=$platform"}
    

    In Configuration Manager add an extra Configuration called Deploy or so. This will be used to select what to build: you probably have Debug and Release configurations now already. Those stay in place, and are simply used to build everything. The idea is this extra configuration will take care of building the actual release. This is fairly consistent with the standard way of working in VS and easy to discover and understand for newcomers. Using the checkboxes, make it so that when the Deploy configuration is selected only the ReleaseBuild is built and none of the others whereas when Debug or Release is selected the ReleaseBuild project is not built. Looks like this: enter image description here

    To build a release, select Deploy from the configuration drop down menu in the VS toolbar and hit F7 (or whatever way you use to invoke Build Solution). Any build errors/warnings will be parsed and shown as usual in the Error List.

    This is also easy to extend: suppose you only have a couple of release build versions just add more configurations like DeployA DeployB DeployC and adjust the build command line for them.