Taming Third Party SDKs and Visual Studio

Visual Studio fan or not, its ubiquity in game development means that sooner or later you will have to deal with its shortcomings. It is the de facto standard IDE for the de facto standard game development operating system.

One of its weak points is the project file property editor. While it does wrangle compile and link flags pretty well, it tends to break when organizing include and lib paths in large codebases. The knee jerk thing to do is to laundry list each include and lib path that every project needs in each project file. This can be a real pain when moving to a different version of an SDK or library (since you have to update it in every project where it is referenced).

The built-in solution to this problem is Visual Studio Property Sheets. Property Sheets are separate files of config data that each of your Visual Studio projects reference (or inherit from since they can be nested). Property Sheets let you define your own macros that can be expanded using the standard $(Macro) syntax. Using property sheet macros to path to the include and lib folders of your libraries and SDKs allows for updating all your project’s SDK dependencies by editing one shared property sheet file.

Insomniac’s property sheets are organized like this:
Root.vsprops
> SDK.vsprops
>> Windows.vsprops

Root.vsprops defines for top level macros, SDK.vsprops defines macros that path to versioned SDKs and libraries checked into revision control, and Windows.vsprops defines macros and build settings for projects that target the Windows platform. We also have a simple perl script (getsdk.pl) that syncs SDKs specified by SDK.vsprops by reading that file in directly (vsprops files are really XML files).

Another tricky bit of dealing with Visual Studio comes from its lack of a real compiler plugin API. Each of the major build system integrations on the market (Incredibuild, SN Systems ProDG VSI) have to essentially hack your Visual Studio installation to function as a replacement for stock features. When using these plugins Visual Studio still thinks its calling cl.exe and link.exe but really its calling a replacement program that either does the plugin’s bidding or falls back to the real stock program.

This creates an interesting situation with SN System’s ProDG VSI because it needs to know which version of the PS3 compiler to use when you go to build a project. The VSI plugin looks to environment variables of Visual Studio’s devenv.exe to find the compiler to call from the replacement cl.exe and link.exe. Since most of us like to branch our code, defining which PS3 SDK to use as a global environment variable is a pain because you have to update that environment variable on every machine that builds code every time you change SDKs.

Sadly one cannot use property sheet macros to solve this problem. Even when the “Set in build environment” option is checked the user macros are never sourced into devenv.exe environment and will not be defined when the VSI goes to build your PS3 project. VSI will then error out that its unable to find the PS3 compiler. Presumably this option only causes the macro to be in the environment when Visual Studio calls out to external build tools when it is running its own builds (and not the builds of a hacked-in plugin like Incredibuild or VSI). If Visual Studio had a real plugin architecture for alternate platforms then this would probably “just work” since the proper integration would be able to use the Visual Studio build system to call out to 3rd party compilers without unfortunate file swapping hacks.

A handy solution to this problem is to use Workspace Whiz’s Solution Build Environment to read environments variable from a text file in the same folder as the solution file. The text file just needs to use a basename that matches the solution file (Foo.sln would have a corresponding Foo.slnenv file). This will allow you to specify the proper environment variables and have them be loaded into devenv.exe’s environment and be ready for VSI to utilize when it needs to build your PS3 projects. Since this file can be checked into revision control you don’t have to ever worry about setting a machine-wide environment variable for VSI to do its job.

7 thoughts on “Taming Third Party SDKs and Visual Studio

  1. Seems complex. We just launch devenv.exe from the environment with correct SCE* envvar.
    Also you don’t need vsprops if you generate your vcproj files from something else – which we do, since vcproj files themselves became non-mergeable for us (4 platforms x 3 configurations = 12 configuration sections in the file, VS sometimes shuffles/reformats them for no reason even when no changes to the configurations are made (only added/removed files), which can’t be merged with a non-XML-aware merger). This also guarantees consistent preprocessor defines & compilation flags.

  2. We used to do that too. We got sick of building systems to configure the environment certain ways and wanted something that ‘just worked’ if you open the sln file from anywhere, including build server environments.

    Manipulating environment variables isn’t something that is easy to do well as explorer.exe is the only application in the universe that actually listens to the environment changed broadcast windows message (since it has to). For us changing the environment of a machine variables leads to folks having to shutdown all their apps and shells when vars need to change when syncing revisions from source control that need to update vars that drive libs and sdks.

    On the command line interface side you are basically pinned to wrapping any command that needs to change the calling prompts environment to using batch files which are the only thing that can modify the environment since child processes cannot change parent environment variables without serious process invasion (like dll injection). This makes updating the calling shells environment from scripting hosts impossible.

    Generating vcproj and sln files isn’t something that we have tried… I have heard of premake and CMake and they seem cool, but at face value its hard to really flip everything on its head like that unless one really needs to be cross platform on the compile side.

  3. >its ubiquity in game development means that sooner or later you will have to deal with its shortcomings

    And if the company policy is to install visual on everyone’s machine, it doesn’t help :-( (fortunately not the case here).

    In the context of cross platform dev., I think if some people tried using something like slickedit seriously for a year or 2, they would have a hard time using visual studio ever again after that…of course it’s not for everyone and it has its problems.

    IMHO it is saner to make a totally separate custom build system (something make, python or C# based for instance) and call it from the IDE, rather than letting a rigid IDE (ex: vsprops system etc.) dictate how you must organize things, or force you to implement all sorts of workarounds for solving the most basic build issues.

  4. Too long since I looked over here and read the many good articles. Good to see the new look, and great to see a lot of good articles to read.

    VS is at least partially defacto because as I hear it, it comes with the 360 dev kit licenses, making it both a cheap(free) and comericially proven option for many companies. It’s far from perfect, but darn good at getting its foot in the door and making it considerably more effort and cost to consider other options.

    We use VSProps very heavily at Crystal. I think we have about 30 of them that can be stacked to generally get all the core settings by standard on any new tools project. This has worked pretty darn good for us and tends to map very well to tools layouts where we don’t want to have to have to touch 200 files to change one setting on all release tool builds. One thing I keep wanting to write is to leverage the vcproj template options in VS to make constructing a new tool largely clicking a few checkboxes.

    For the game itself, we go the generative route for the solution/vcproj files, an inhouse VS solution generator tool I wrote that handles making sure all the settings. This tends to work better for having 50 people adding/removing/changing files at the same time without worrying about merge problems. It helps make it easy to make sweeping optimizations and changes as well such as “All files in this subfolder should now build with these settings”, “for the six ps3 configurations, add this additional library”, etc while at the same time getting a fully functional IDE where settings changes can still be made for local adjustments (Something that often is entirely disabled when using a combination make system + VS IDE, such as SCons + IDE). It got written originally just to optimize the performance going into Incredibuild, but it’s such a shift moving back into static projects from it that it feels like moving through sludge. It also really does help with our 21+ configs and various other exotic configurations folks want to whip up.

    Dunno if others have run into this, but I find VS actually gets pretty nasty with multiple platforms and 8+ configurations, so the other side advantage of generating is to generate solutions that have what folks need to work on rather than a static solution that has everything anyone might ever need to work on (Or not what someone needs to work on right now).

    The ps3 VSI issues seem kind of foreign to me. I suppose partially that’s resolved here by having a company wide lock-step on those tools (they all go through me, and I don’t let them move out of sync) and partially resolved by using an environment spawner where all development is done in. By spawning environment from config files, all the machines can come out of IT identically and be tossed between different branches and and teams without worrying at all on whether the right environment variables are there. In either case, I can’t remember a point where I’ve had to be conscious of what version is in the environment. Only had been conscious on whether the version is correct at all.

    Of course, an environment spawner does entirely have the problem that changing the variables requires closing down relevant programs and that does bite people from time to time, but overall it’s worked well and wide spanning environment changes really are quite rare. We’re not using batch files though in most cases. We have an executable that can take a command line to run and does it. I forget the internal details(it’s pretty tiny), but it’s used all over in tons of scripts, so it has no issue whatsoever with being run in automated context from anywhere. Our build servers generally just spawn envtool -spawn=”realprogram” processes without any prior special configuration on the machines.

    Ah I blather :) anyhow, neat to read others thoughts on it.

  5. This sounds brilliant, and inspired me to try it out, we have 4 platforms and 3 configurations, and multiple projects just on my team, so any simplification is very welcome :D

    However I’ve got a problem I’m sure you must have resolved.
    Just to specify, for instance, linker input I seem to have to create a properties file per platform configuration combo because there are no platforms/configurations in the .vsprops file, as a result I have 12 vsprops files that I have to hook into the project.
    Those 12 files will all inherit from base files, so it’s looking like we’ll have a directory of about 20 files once I’m done is that the sort of number you’re ending up with.

  6. That’s not really an odd number, especially if you’re having a few platform specific linking combinations that need to be directed identically across several projects.

    That said, vsprops really show their strengths when used to dictate settings for tens-hundreds of project which are largely similar in overall settings layout. They can feel a bit awkward for just a few projects because you end up often writing more property sheets than you have projects. Doesn’t hurt in any case and getting it in early helps later.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>