Everyone likes to do things their own way, and deciding where to place a project, solution or SDK that makes sense to them is no exception. When setting up a build environment using Microsoft’s Visual Studio, one of the most useful items I’ve found, when considering development teams, are the Build Command Macros (BCM), e.g. $(ProjectDir) or $(SolutionDir). They can be used for Include and Lib paths, parameters to scripts and utilities for Pre and Post Build Events, etc. BCMs ease the conflicts between people who can’t agree on whether the project should be in their C:\Dev, C:\GameDev or F:\Projects\Games\XBox360 directory. They also make it easier to change the location when you want to do multiple checkouts on the same machine to run some what-if scenarios simultaneously. The problem I kept running into was that it appeared specifying or naming new BCMs appeared to be reserved solely for Microsoft.
In the past, setting up paths for anything that wasn’t pre-defined by a BCM usually came down to asking every dev to set a few environment variables, and this has always seemed, at best, messy to me; especially since this doesn’t include a nice way to distribute new macros with source control checkouts. One work-around is to have a batch file that gets hooked in, but then you have to make sure everyone has the proper entry that hooks the batch file in (still messy). Another alternative is to create Make files and define some macros in the top-level make file that everyone can set to their system settings (better, but now we’ve spread a bunch of make files all over the place, and are requiring the dev to manage the build in multiple places, when that was part of what the IDE was supposedly built to help simplify for us).
Web searches for ways to create BCMs usually end up in off-topic forums about recording macros. Responses from other devs using MS Visual Studio, when asked if they knew of a way to create a User Defined Build Command Macro in the Visual Studio IDE, ranged from “No idea” to “Can’t be done.” Ever the persistent bugger, these answers have never satisfied me. It has always seemed logical to me that any good IDE with an associated build environment, should allow its users to extend the interface. Recently I discovered, Microsoft does allow the user to define their own BCMs on a per project basis in Visual Studio 2010 and here is how it is done (I assume the reader is familiar with Visual Studio 2010, and is capable of creating/configuring a simple solution/project).
First, either open your solution/project, or create a new one to test with in Visual Studio 2010. Then go to the View menu, Other Windows sub-menu and select Property Manager (If you do not find Property Manager under the Other Windows sub-menu, check directly under the View menu, Cort Stratton reported it there in his Professional edition of Visual Studio 2010). In the Property Manager window that appears, right-click on the name of your project and select Add New Project Property Sheet from the context menu. When the dialog appears, enter a name for your property sheet and click OK (I’ve named mine User Defined Property Sheet). This will add the Property Sheet to all build configurations, you could also have created specialized property sheets for each build configuration by right-clicking on them individually and adding a new property sheet to each one.
Add a User Macro
Next double-click on the newly created Property Sheet, and this will open the Property Pages dialog for the Property Sheet. In the left-hand tree-view, select User Macros. In the right-hand pane that appears click the Add Macro button, which will display the Add User Macro dialog to enter the name of your Macro as well as the definition and click OK (it gives you the option here to Set the macro as an environment variable in the build environment, but why anyone would want to do that when that is the very thing it is being used to avoid, escapes me). In my example, I’ve setup a macro called SDK_BOOST, since I’m setting up the Boost library for a test project. You don’t need to surround your macro name by the dollar-sign and parenthesis $(), Visual Studio will add those for you. Repeat the process of clicking the Add Macro button, entering your macros and clicking OK for any other macros you want. Then after you’re done entering macros, click the OK button on the Property Pages dialog. Note: Don’t forget the trailing backslash in your paths.
Using the User Macro
Now whenever you define a path, parameter, etc. in your Project Properties, where macros are allowed, you can use your macro. For example in the Project Properties, VC++ Directories, I’ve specified the Include directory for the Boost library using my macro. One other benefit is that the macro will also appear in the list of available macros when you choose to expand the Edit dialog for properties like the Include directories or Pre or Post Build Events.
So this is neat and all, but one of my original issues was that the environment variables weren’t something that could be distributed using source control checkouts. Well, the Property Sheet we created is a .props file that was created in the Project directory, using the name we gave the Property Sheet, and this file can be checked into source control (Tada). It’s not much different than having a bunch of .make files spread throughout the directories, but this keeps the management in the IDE, hopefully making our lives easier.