有效地为多个项目和配置使用Visual Studio项目属性

时间:2010-08-17 12:48:45

标签: c++ visual-studio-2010 visual-studio build projects-and-solutions

我一直使用内置GUI支持的Visual Studios来配置我的项目,通常使用属性表,以便多个项目将使用一个公共集。

我的主要抱怨之一是管理多个项目,配置和平台。如果您只使用主GUI(右键单击项目 - >属性)执行所有操作,它很快就会变得混乱,难以维护并容易出现错误(例如无法正确定义某些宏,或使用错误的运行时库等) 。处理不同的人将依赖库放在不同的地方(例如我的所有都存在于“C:\ Libs \ [C,C ++] \ [lib-name] \”)然后经常管理这些库的不同版本的事实不同的(发布,调试,x86,x64等)也是一个大问题,因为它使在新系统上设置它的时间大大复杂化,然后版本控制存在问题并且将每个人的路径分开。

属性表使这更好一点,但我不能让一张表有不同的配置和平台的单独设置(下拉框显示为灰色),导致我有许多表,如果以正确的顺序继承做什么我想要(“x86”,“x64”,“调试”,“发布”,“常见”,“目录”(通过定义像BoostX86LibDir这样的用户宏来处理前面提到的依赖问题)等,如果继承错误顺序(例如“x64”和“debug”之前的“common”)会导致尝试链接不正确的库版本或错误地命名输出等问题...

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

我知道转移到完全不同的系统,如CMake,创建所需的文件,然而这使其他地方的事情变得复杂,因为即使是简单的任务,如向项目添加新文件,然后需要在其他地方进行其他更改,这不是我非常满意的事情,除非有一些VS2010集成可以跟踪这些变化。

6 个答案:

答案 0 :(得分:77)

我刚刚发现了我认为不可能的事情(它没有被GUI公开),这有助于使属性表更有用。项目属性文件中许多标记的“Condition”属性,也可以在.props文件中使用!

我只是将以下内容放在一起作为测试,它运行良好,完成了5个(常见的,x64,x86,调试,发布)单独的属性表的任务!

<?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无法处理它,使用上述属性表的项目只报告目标的默认继承值,如“$(ProjectName)”。

答案 1 :(得分:27)

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

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

玩得开心!

答案 2 :(得分:11)

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

项目按其输出类型继承属性表,例如x64.Debug.Dynamic.Library.vsprops。此vsprops文件使用InheritedPropertySheets属性

继承其他属性表
<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"
    >

您还可以在属性表中使用变量(即UserMacro,其值可以是绝对值或甚至是环境变量),以根据您的需要自定义很多内容。例如,在Debug.vsprops中定义BIN变量

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

然后在vsprops系列中设置输出名称时,例如,Output.x64.Library.vsprops

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

$(BIN)变量将扩展为已设置的值(在本例中为Debug)。使用这种技术,您可以轻松构建一个很好的属性表层次结构,以满足您的需求。

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

答案 3 :(得分:5)

可以为每个配置创建单独的属性表。要做到这一点:

  1. 创建特定于配置的属性表
  2. 打开物业经理
  3. 右键单击要修改的配置(而不是项目)
  4. 点击“添加现有资产表”并添加工作表
  5. 这使您无需将条件插入单个工作表中以进行多种配置。如果您希望在配置之间共享某些公共属性,则创建层次结构。顶部工作表可用于所有配置,嵌套工作表仅包含特定于配置的属性

答案 4 :(得分:4)

就输出库而言,您可以选择所有项目,然后打开属性页面,选择所有配置,所有平台,然后将目标名称设置为:

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

将提供类似mylib-v100-x86-Debug.lib

的输出

我们也为其他库目录执行类似的操作,使用$(PlatformName)#(Configuration)选择正确的库路径,尽管它确实意味着对库的初始设置进行了一些处理。例如,我们已将其libs升级到boost/lib.Win32boost/lib.x64


关于图书馆以及在不同地方安装图书馆的人,有几种选择。如果您有一个非常强大的源代码控制系统,您可以将所有内容放在源代码管理中,位于源代码旁边的libs文件夹中。如果您使用多个库,或者它们特别大,那么这可能不会起作用。

我想到的另一个选项是在每个用户计算机上设置一个指向其库文件夹根目录的环境变量,例如LIB_ROOT=c:\libraries,然后您可以在Visual Studio中以{{1}访问它}}

答案 5 :(得分:0)

听起来值得检查构建工具 - 在我的位置我们使用自定义工具来监视文件和项目的变化,并计算依赖关系和编译顺序。添加新文件没什么大不了的 - 使用msbuild进行编译。

如果我必须编译多个项目,我会使用像nant这样的东西: http://nant.sourceforge.net/