VC++ 2010 Property Sheets (high level guide)
by Raphael Gervaise · in Torque Game Builder · 07/31/2011 (1:21 pm) · 2 replies
Hi all -
I wanted to add some libraries to my T2D engine when I realised that build settings were defined on a "per-project" basis instead of using property sheets.
I find property sheets very useful, as they save a lot of time when you need to make sure that all code generation settings are consistent across projects, when you want different optimisation values to propagate to all modules, etc. As a result, I spent some time upgrading my T2D VC++ solution to use property sheets, by extracting and removing all the projects specific overrides.
I thought I'd make a short post of it, in case others could be interested. This is a very high level guide, so this is more targeted to programmers already familiar with the VC++ IDE who are happy to experiment with settings and are happy to spend time in the docs finding stuff by themselves.
If I hadn't make so many changes to my Torque engine (switching to VS2010, replacing modules, adding libraries, etc.) I would have put the modified project files as a "Resource", which would have been much more practical for everybody... :/
Anyway... Here we go :
. Access the "property manager" in the "view" menu ; this displays all core settings and property sheets for all projects
. You can remove the "default" property sheets (upgrades from VC7, etc.) ; they are useless and add to the complexity of the whole thing
. Property sheets are "cascading", which means they are layered on top of each other, and each sheet can define new properties that are cumulative with all the previous sheets. A sheet can also either override settings defined in previous sheets, or "inherit" properties from the previous layers (think of it as layers in Photoshop were the layer on top can occlude part of the underlying one, or be transparent)
. I'd recommend creating at least 3 sheets, working in pairs. A "base" sheet for all "universal" settings that don't change across build configurations (that's where I set my $(Target) paths, use of RTTI, target machines, SSE2, etc.), and 2 "Debug" and "Release" sheets (for build specific optimisations ; I set my debug to have browse info and no optims, and my release to favor small size, with no debug/browse). Obviously, if you have more configurations, you'll need extra sheets (I've got a "single-compilation-unit" config, but that reuses the Release sheet, in my case). Add these sheets to all your projects.
This gives you a "Base > Debug" or "Base > Release" flexible configuration
. You can also have a "3-layer" system, which is quite popular when dealing with lots of libraries, where you set it up as "Base > Lib > Debug" , "Base > Dll > Release", "Base > Application > Profile", and so on.
. For each sheet, you want to "extract" the relevant settings from the existing projects. By "extract", I mean copy the values from the projects into the sheets (or set them to whatever value you fancy, assuming you know what you're doing), and change the projects settings to "<inherit>" from these settings.
. You want to use all "configuration variables" (things like $(Platform), $(ProjectName), etc) as much as possible, so that you can write generic settings that will work for all your projects, instead of relying on hard-coded paths and values
. Basically, it means abstracting and moving all shared settings into reusable sheets. When you change a setting in your sheet, it propagates automatically to all your projects based on that sheet (a bit like "styles" in a word processing software)
. All you want to keep as "project overrides" is probably additional include paths and libs. And maybe some "compile as C/C++" for some libs.
Having completely restructured my solution with this approach, I end up with things like this:
Base
(note the warning level 1 that I'm not very happy with... I'll probably override that in my libs to be w4, at least locally)
Release
(this is a generic Release profile, a proper version for final verion would use the profile guided optimisation features of the compiler)
Thanks for reading, hopefully this might even be of some use to some people :)
Regards
I wanted to add some libraries to my T2D engine when I realised that build settings were defined on a "per-project" basis instead of using property sheets.
I find property sheets very useful, as they save a lot of time when you need to make sure that all code generation settings are consistent across projects, when you want different optimisation values to propagate to all modules, etc. As a result, I spent some time upgrading my T2D VC++ solution to use property sheets, by extracting and removing all the projects specific overrides.
I thought I'd make a short post of it, in case others could be interested. This is a very high level guide, so this is more targeted to programmers already familiar with the VC++ IDE who are happy to experiment with settings and are happy to spend time in the docs finding stuff by themselves.
If I hadn't make so many changes to my Torque engine (switching to VS2010, replacing modules, adding libraries, etc.) I would have put the modified project files as a "Resource", which would have been much more practical for everybody... :/
Anyway... Here we go :
. Access the "property manager" in the "view" menu ; this displays all core settings and property sheets for all projects
. You can remove the "default" property sheets (upgrades from VC7, etc.) ; they are useless and add to the complexity of the whole thing
. Property sheets are "cascading", which means they are layered on top of each other, and each sheet can define new properties that are cumulative with all the previous sheets. A sheet can also either override settings defined in previous sheets, or "inherit" properties from the previous layers (think of it as layers in Photoshop were the layer on top can occlude part of the underlying one, or be transparent)
. I'd recommend creating at least 3 sheets, working in pairs. A "base" sheet for all "universal" settings that don't change across build configurations (that's where I set my $(Target) paths, use of RTTI, target machines, SSE2, etc.), and 2 "Debug" and "Release" sheets (for build specific optimisations ; I set my debug to have browse info and no optims, and my release to favor small size, with no debug/browse). Obviously, if you have more configurations, you'll need extra sheets (I've got a "single-compilation-unit" config, but that reuses the Release sheet, in my case). Add these sheets to all your projects.
This gives you a "Base > Debug" or "Base > Release" flexible configuration
. You can also have a "3-layer" system, which is quite popular when dealing with lots of libraries, where you set it up as "Base > Lib > Debug" , "Base > Dll > Release", "Base > Application > Profile", and so on.
. For each sheet, you want to "extract" the relevant settings from the existing projects. By "extract", I mean copy the values from the projects into the sheets (or set them to whatever value you fancy, assuming you know what you're doing), and change the projects settings to "<inherit>" from these settings.
. You want to use all "configuration variables" (things like $(Platform), $(ProjectName), etc) as much as possible, so that you can write generic settings that will work for all your projects, instead of relying on hard-coded paths and values
. Basically, it means abstracting and moving all shared settings into reusable sheets. When you change a setting in your sheet, it propagates automatically to all your projects based on that sheet (a bit like "styles" in a word processing software)
. All you want to keep as "project overrides" is probably additional include paths and libs. And maybe some "compile as C/C++" for some libs.
Having completely restructured my solution with this approach, I end up with things like this:
Base
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<OutDir>../../Link/$(Configuration).$(Platform)/</OutDir>
</PropertyGroup>
<PropertyGroup>
<IntDir>$(OutDir)$(ProjectName)/</IntDir>
<_PropertySheetDisplayName>Base</_PropertySheetDisplayName>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile />
<ClCompile />
<ClCompile />
<ClCompile>
<TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<CompileAsManaged>false</CompileAsManaged>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<FloatingPointExceptions>false</FloatingPointExceptions>
<DisableLanguageExtensions>false</DisableLanguageExtensions>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<CompileAs>CompileAsCpp</CompileAs>
<UseUnicodeForAssemblerListing>false</UseUnicodeForAssemblerListing>
<FunctionLevelLinking>true</FunctionLevelLinking>
<CreateHotpatchableImage>false</CreateHotpatchableImage>
<BrowseInformation>true</BrowseInformation>
<WarningLevel>Level1</WarningLevel>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<PreventDllBinding>
</PreventDllBinding>
</Link>
<Lib>
<TargetMachine>MachineX86</TargetMachine>
</Lib>
<Lib>
<SubSystem>Windows</SubSystem>
</Lib>
</ItemDefinitionGroup>
<ItemGroup />
</Project>(note the warning level 1 that I'm not very happy with... I'll probably override that in my libs to be w4, at least locally)
Release
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup>
<ClCompile>
<Optimization>MinSpace</Optimization>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup>
<ClCompile>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup>
<ClCompile>
<WholeProgramOptimization>true</WholeProgramOptimization>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
<Lib>
<LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>
</Lib>
</ItemDefinitionGroup>
<ItemGroup />
</Project>(this is a generic Release profile, a proper version for final verion would use the profile guided optimisation features of the compiler)
Thanks for reading, hopefully this might even be of some use to some people :)
Regards
About the author
#2
I realised I posted this in the TGB forum, maybe this would be better moved to a more generic/tech forum.
08/01/2011 (12:53 am)
Thanks - I realised I posted this in the TGB forum, maybe this would be better moved to a more generic/tech forum.
Torque 3D Owner Novack
CyberianSoftware