I have always used Visual Studios built in GUI support for configuring my projects, often using property sheets so that several projects will use a common set.
One o
I had same pain for the product of my company (200+ projects) before. The way I solved it is to build a nice hierarchy of the property sheets.
The projects inherits the property sheet by its output type, say x64.Debug.Dynamic.Library.vsprops. This vsprops file simply inherits other property sheets using the InheritedPropertySheets attribute
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
Name="x64.Debug.Dynamic.Binary"
InheritedPropertySheets=".\Common.vsprops;.\x64.vsprops;.\Debug.vsprops;.\Runtime.Debug.Dynamic.vsprops;.\Output.x64.Library.vsprops"
>
You can also use variables (i.e. UserMacro, whose value can be absolute or even environment variables) in property sheets to customize a lot of things based on your need. For example, defining a BIN variable in Debug.vsprops
<UserMacro name="BIN" Value="Debug" />
then when you set the output name in the series of vsprops, say, Output.x64.Library.vsprops
<VisualStudioPropertySheet
ProjectType="Visual C++"
Version="8.00"
OutputDirectory="$(BIN)"
>
The $(BIN) variable will be expanded to what's been set (in this case, Debug). Use this technique you can easily construct a nice hierarchy of property sheets to meet your demand.
Now there's one more thing you might want to do: build your own project templates that uses your property sheet set. The real difficult part is to enforce proper usage of the templates and property sheets. My personal experience is that even if everything is setup, somebody will still forget to use the template to create new projects ...
As far as the output library goes, you can select all your projects, then bring up the property pages, select All Configurations, All Platforms and then set the Target Name to:
$(ProjectName)-$(PlatformToolset)-$(PlatformShortName)-$(Configuration)
which would give an output like mylib-v100-x86-Debug.lib
We do something similar to this for Additional Library Directories as well, using $(PlatformName)
and #(Configuration)
to pick out the right library paths, although it does mean some messing around with initial setup of the libraries. eg we have boost install its libs to boost/lib.Win32
or boost/lib.x64
.
With regards to libraries, and people installing them in different places, there are a couple of options. If you have a very robust source control system, you can just put everything in source control, living in a libs folder next to your source. That probably won't work if you use more than a few libraries though, or if they are particularly large.
The other option that comes to mind is to set an environment variable on each user machine that points to the root of their libraries folder, eg LIB_ROOT=c:\libraries
, and you can then access that in Visual Studio as $(LIB_ROOT)
.
I made some improvements, may be useful for somebody
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="UserMacros">
<!--IsDebug: search for 'Debug' in Configuration-->
<IsDebug>$([System.Convert]::ToString( $([System.Text.RegularExpressions.Regex]::IsMatch($(Configuration), '[Dd]ebug'))))</IsDebug>
<!--ShortPlatform-->
<ShortPlatform Condition="'$(Platform)' == 'Win32'">x86</ShortPlatform>
<ShortPlatform Condition="'$(Platform)' == 'x64'">x64</ShortPlatform>
<!--build parameters-->
<BUILD_DIR>$(registry:HKEY_CURRENT_USER\Software\MyCompany\@BUILD_DIR)</BUILD_DIR>
</PropertyGroup>
<Choose>
<When Condition="$([System.Convert]::ToBoolean($(IsDebug)))">
<!-- debug macroses -->
<PropertyGroup Label="UserMacros">
<MyOutDirBase>Debug</MyOutDirBase>
<DebugSuffix>-d</DebugSuffix>
</PropertyGroup>
</When>
<Otherwise>
<!-- other/release macroses -->
<PropertyGroup Label="UserMacros">
<MyOutDirBase>Release</MyOutDirBase>
<DebugSuffix></DebugSuffix>
</PropertyGroup>
</Otherwise>
</Choose>
<Choose>
<When Condition="Exists($(BUILD_DIR))">
<PropertyGroup Label="UserMacros">
<MyOutDir>$(BUILD_DIR)\Bin\$(MyOutDirBase)_$(ShortPlatform)\</MyOutDir>
<MyIntDir>$(BUILD_DIR)\Build\$(Configuration)_$(ShortPlatform)_$(PlatformToolset)\$(ProjectGuid)\</MyIntDir>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup Label="UserMacros">
<MyOutDir>$(SolutionDir)\Bin\$(MyOutDirBase)_$(ShortPlatform)\</MyOutDir>
<MyIntDir>$(SolutionDir)\Build\$(Configuration)_$(ShortPlatform)_$(PlatformToolset)\$(ProjectGuid)\</MyIntDir>
</PropertyGroup>
</Otherwise>
</Choose>
<PropertyGroup>
<OutDir>$(MyOutDir)</OutDir>
<IntDir>$(MyIntDir)</IntDir>
<!-- some common for projects
<CharacterSet>Unicode</CharacterSet>
<LinkIncremental>false</LinkIncremental>
-->
</PropertyGroup>
</Project>
have fun!
It is possible to create a separate property sheet for each configuration. To do this:
This relieves you from inserting conditions into a single sheet for multiple configurations. If you have some common attributes that you would like to share between configurations, then create a hierarchy. The top sheet can be used in all configurations and the nested sheets will only contain the configuration-specific attribut
It sounds like it could be worth checking out a build tool - at my place we use a custom made tool that watches files and projects for changes and figures the dependencies and compile order. Adding a new file is no big deal - compilation is done with msbuild.
If i had to compile more than a bunch of projects I would use something like nant: http://nant.sourceforge.net/
I just found out somthing I didnt think was possible (it is not exposed by the GUI) that helps make property sheet far more useful. The "Condition" attribute of many of the tags in the project property files and it can be used in the .props files as well!
I just put together the following as a test and it worked great and did the task of 5 (common,x64,x86,debug,release) separate property sheets!
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="UserMacros">
<!--debug suffix-->
<DebugSuffix Condition="'$(Configuration)'=='Debug'">-d</DebugSuffix>
<DebugSuffix Condition="'$(Configuration)'!='Debug'"></DebugSuffix>
<!--platform-->
<ShortPlatform Condition="'$(Platform)' == 'Win32'">x86</ShortPlatform>
<ShortPlatform Condition="'$(Platform)' == 'x64'">x64</ShortPlatform>
<!--toolset-->
<Toolset Condition="'$(PlatformToolset)' == 'v90'">vc90</Toolset>
<Toolset Condition="'$(PlatformToolset)' == 'v100'">vc100</Toolset>
</PropertyGroup>
<!--target-->
<PropertyGroup>
<TargetName>$(ProjectName)-$(Toolset)-$(ShortPlatform)$(DebugSuffix)</TargetName>
</PropertyGroup>
</Project>
Only issue is the properties GUI cant handle it, a project that uses the above property sheet just reports default inherited values like "$(ProjectName)" for the target.