繁体   English   中英

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

[英]Using Visual Studio project properties effectively for multiple projects and configurations

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

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

属性表使这更好一点,但我不能让一张表对不同的配置和平台有单独的设置(下拉框变灰),导致我有很多表,如果以正确的顺序继承,我想做的事( “x86”、“x64”、“debug”、“release”、“common”、“directories”(通过定义像 BoostX86LibDir 这样的用户宏来处理前面提到的依赖问题)等)并且如果以错误的顺序继承(例如“x64”和“debug”之前的“common”)会导致诸如尝试链接不正确的库版本或错误地命名输出之类的问题...

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

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

我只是发现了一些我认为不可能的事情(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)”。

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

<?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多个项目)有同样的痛苦。 我解决的方法是建立属性表的良好层次结构。

项目通过其输出类型(例如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)。 使用此技术,您可以轻松地构建良好的属性表层次结构来满足您的需求。

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

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

  1. 创建特定于配置的属性表
  2. 打开物业经理
  3. 右键单击要修改的配置 (不是项目)
  4. 单击“添加现有属性表”并添加您的表

这使您不必将条件插入到多个配置的单张纸中。 如果您要在配置之间共享某些通用属性,请创建一个层次结构。 顶层工作表可用于所有配置,并且嵌套工作表将仅包含特定于配置的属性

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

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

这将给出类似于mylib-v100-x86-Debug.lib的输出

对于其他库目录,我们也执行类似的操作,使用$(PlatformName)#(Configuration)选择正确的库路径,尽管这确实意味着对库的初始设置有些麻烦。 例如,我们已经将其库升压安装到boost/lib.Win32boost/lib.x64


关于库以及将它们安装在不同位置的人们,有两种选择。 如果您有一个非常强大的源代码管理系统,则可以将所有内容放入源代码管理中,位于源代码旁边的libs文件夹中。 如果您使用多个库,或者它们很大,那可能就行不通了。

想到的另一个选择是在每个用户计算机上设置一个指向其库文件夹根目录的环境变量,例如LIB_ROOT=c:\\libraries ,然后可以在Visual Studio中以$(LIB_ROOT)访问该环境变量。

听起来可能值得一试构建工具-在我这里,我们使用一个定制的工具,该工具可以监视文件和项目中的更改并计算依赖性和编译顺序。 添加新文件没什么大不了的-编译是通过msbuild完成的。

如果我不得不编译多个项目,那么我会使用类似nant的东西: http : //nant.sourceforge.net/

如果要定义一些对整个解决方案有效的 UserMacros:

  1. 在您的解决方案根文件夹中创建一个solution-global.props文件

  2. 在那里定义您的 UserMacros:

     <?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup Label="UserMacros" > <CommonUtilsDir>$(SolutionDir)Common\\Utils\\</CommonUtilsDir> <DriverBaseDir>$(SolutionDir)Common\\DriverBase\\</DriverBaseDir> </PropertyGroup> </Project>
  3. 在要使用自定义宏的每个*.vcxproj文件中插入此行:

    <Import Project="$(SolutionDir)solution-global.props" />

  4. 使用您的自定义宏:

    <AdditionalIncludeDirectories>$(CommonUtilsDir)\\Source;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

适用于 VS2015

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM