将Visual Studio项目属性有效地用于多个项目和configuration

我一直使用Visual Studio构build的Visual Studio来configuration我的项目,通常使用属性表,以便几个项目将使用一个公共集合。

我的主要抱怨之一是pipe理多个项目,configuration和平台。 如果你只是用主GUI(右键点击项目 – >属性)做所有事情,它很快就会变得混乱,难以维护并容易出错(比如不能正确地定义一些macros,或者使用错误的运行库等)。 处理不同的人在不同的地方放置依赖库的事实(例如我的所有生活在“C:\ Libs \ [C,C ++] \ [lib-name] \”),然后经常pipe理这些库的不同版本不同的(发行版,debugging版,x86,x64等)也是一个大问题,因为它将时间设置在一个新系统上大大复杂化,然后存在版本控制问题,并且保持每个人的path不同。 。

属性表使这个更好一点,但我不能有一个工作表有不同的configuration和平台(下拉框变灰)的单独设置,导致我有许多工作表,如果inheritance按照正确的顺序做我想要的“x86”,“x64”,“debug”,“release”,“common”,“directories”(通过定义像BoostX86LibDir这样的用户macros来处理前面提到的依赖性问题)等等),如果以错误的顺序“x64”和“debug”之前的“common”)会导致像试图链接不正确的库版本或错误地命名输出的问题…

我想要的是一种处理所有这些分散的依赖关系的方法,并设置了一系列解决scheme中我所有项目所使用的“规则”,比如将输出库命名为“mylib- [vc90,vc100] – [x86 ,x64] [ – d] .lib“,而不必为每个单独的项目,configuration和平台组合执行所有操作,然后保持它们全部正确同步。

我知道移动到像CMake这样的完全不同的系统来创build所需的文件,然而这使得其他地方的事情变得复杂,即使是简单的任务,如添加一个新的文件到项目,然后需要额外的改变,这不是我完全满意,除非有一些与VS2010集成,可以跟踪这些变化。

我只是发现了一些我认为不可能的东西(它没有被GUI所暴露),这有助于使属性表更加有用。 项目属性文件中的许多标签的“条件”属性,它也可以在.props文件中使用!

我只是把以下内容作为一个testing,它工作得很好,并做了5(常见的,X64,x86,debugging,发布)的任务分开属性表!

<?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> 

唯一的问题是属性GUI不能处理它,使用上述属性表的项目只报告目标的默认inheritance值,如“$(ProjectName)”。

我做了一些改进,可能对某人有用

 <?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> 

玩的开心!

我之前对我公司的产品(200多个项目)也有同样的痛苦。 我解决这个问题的方法是build立一个很好的属性表层次结构。

项目通过输出typesinheritance属性表,如x64.Debug.Dynamic.Library.vsprops。 这个vsprops文件只是使用InheritedPropertySheets属性inheritance其他属性表

 <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" > 

您还可以在属性表中使用variables(即UserMacro,其值可以是绝对的甚至是环境variables),以根据您的需要定制许多事物。 例如,在Debug.vsprops中定义一个BINvariables

 <UserMacro name="BIN" Value="Debug" /> 

那么当你在一系列vsprop中设置输出名时,比如Output.x64.Library.vsprops

 <VisualStudioPropertySheet ProjectType="Visual C++" Version="8.00" OutputDirectory="$(BIN)" > 

$(BIN)variables将被扩展为已经设置的内容(在这种情况下,debugging)。 使用这种技术,您可以轻松地构build一个很好的属性表层次结构来满足您的需求。

现在还有一件事情你可能想做:build立你自己的项目模板,使用你的属性表集。 真正困难的部分是强制正确使用模板和属性表。 我个人的经验是,即使设置了一切,有人仍然会忘记使用模板来创build新项目。

就输出库而言,您可以select所有项目,然后调出属性页面,selectAll Configurations,All Platforms,然后将Target Name设置为:

$(ProjectName)-$(PlatformToolset)-$(PlatformShortName)-$(Configuration)

这将产生像mylib-v100-x86-Debug.lib这样的输出

对于其他库目录,我们使用$(PlatformName)#(Configuration)来select正确的库path,尽pipe这样做意味着对库的初始设置有些混乱。 例如我们有提升安装它的库boost/lib.Win32boost/lib.x64


对于图书馆和在不同地方安装的人来说,有两个select。 如果你有一个非常强大的源代码pipe理系统,你可以把所有东西都放在源代码控制之中,放在源代码旁边的libs文件夹中。 如果您使用的库不止一个,或者它们特别大,那么这可能不起作用。

另一个想到的方法是在每个用户机器上指定一个环境variables,指向它们的库文件夹的根目录,例如LIB_ROOT=c:\libraries ,然后可以在$(LIB_ROOT) Visual Studio中以$(LIB_ROOT)访问它。

可以为每个configuration创build一个单独的属性表。 去做这个:

  1. 创build一个configuration特定的属性表
  2. 打开物业经理
  3. 右键单击您想要修改的configuration (不是项目)
  4. 点击“添加现有的属性表”,并添加您的工作表

这可以免除将条件插入到多个configuration的单个工作表中。 如果您想要在configuration之间共享某些常用属性,请创build一个层次结构。 顶部表单可以用于所有configuration,嵌套表单将只包含特定于configuration的属性

这听起来像是值得检查一个构build工具 – 在我的地方,我们使用一个定制的工具,监视文件和项目的变化,并计算依赖和编译顺序。 添加一个新文件并不是什么大事,编译是用msbuild完成的。

如果我不得不编译一堆以上的项目,我会使用像nant这样的东西: http : //nant.sourceforge.net/