8

我似乎无法从 Microsoft 找到任何有用的文档,说明在Visual Studio 的属性表文件中定义用户宏时如何使用元素中的DelimiterInheritsFromParent属性。UserMacro.vsprops

这是示例用法:

<UserMacro Name="INCLUDEPATH" Value="$(VCROOT)\Inc"
    InheritsFromParent="TRUE" Delimiter=";"/>

从上面的例子中,我猜“继承”实际上意味着“a)如果定义是非空的,那么附加分隔符,b)附加新定义”,其中非继承行为将简单地替换任何当前宏定义。有人有确切消息么?更好的是,有没有人有任何关于 Visual Studio.vsprops文件和宏的替代文档的建议来源?

注意:这元素的InheritedPropertySheets属性不同VisualStudioPropertySheet,例如:

<VisualStudioPropertySheet ... InheritedPropertySheets=".\my.vsprops">

在这种情况下,“继承”基本上意味着“包含”

4

3 回答 3

9

[回答我自己的问题]

InheritsFromParent意味着前置。为了验证这一点,我做了一个实验来揭示用户宏在 Visual Studio 2008 中是如何工作的。下面是设置:

  • 项目包括使用标签p.vcproj的属性表文件d.vsprops(“d”表示派生) 。InheritedPropertySheets
  • d.vsprops包括属性表文件b.vsprops('b' 表示base。)
  • p.vcproj还定义了转储环境的预构建事件。
  • 这两个.vsprops文件都包含用户宏定义。

b.vsprops

...
<UserMacro Name="NOENV" Value="B"/>
<UserMacro Name="OVERRIDE" Value="B" PerformEnvironmentSet="true"/>
<UserMacro Name="PREPEND" Value="B" PerformEnvironmentSet="true"/>
...

d.vsprops

...
<VisualStudioPropertySheet ... InheritedPropertySheets=".\b.vsprops">
<UserMacro Name="ENV" Value="$(NOENV)" PerformEnvironmentSet="true"/>
<UserMacro Name="OVERRIDE" Value="D" PerformEnvironmentSet="true"/>
<UserMacro Name="PREPEND" Value="D" InheritsFromParent="true"
    Delimiter="+" PerformEnvironmentSet="true"/>
...

p.vcproj

...
<Configuration ... InheritedPropertySheets=".\d.vsprops">
<Tool Name="VCPreBuildEventTool" CommandLine="set | sort"/>
...

构建输出

...
ENV=B
OVERRIDE=D
PREPEND=D+B
...

根据这些结果,我们可以得出以下结论:

  1. PerformEnvironmentSet="true"在用于构建事件的环境中定义用户宏是必需的。证明:NOENV构建输出中未显示。
  2. 用户宏总是从包含的属性表继承而来,不管PerformEnvironmentSetInheritsFromParent。证明: in b.vsprops,NOENV没有设置在环境中, ind.vsprops不需要InheritsFromParent.
  3. 用户宏的简单重新定义会覆盖任何先前的定义。证明:OVERRIDE设置为D尽管它之前被定义为B
  4. 重新定义用户宏InheritsFromParent="true" 新定义添加到任何先前的定义之前,由指定的Delimiter. 证明:PREPEND设置为D+B(not Dor B+D.)

以下是我发现的一些附加资源,用于解释 Visual Studio.vsprops文件和相关主题,它是几年前的,但它仍然很有帮助:

了解VC项目系统第一部分:文件和工具

了解 VC 项目系统第二部分:配置和项目属性页对话框

了解VC项目系统第三部分:宏、环境变量和分享

了解VC项目系统第四部分:属性和属性继承

理解VC项目系统第五部分:构建、工具和依赖

了解VC项目系统第六部分:自定义构建步骤和构建事件

了解 VC 项目系统第七部分:“makefile”项目和(重新)使用环境

于 2008-09-28T05:26:05.780 回答
0

这里有关于这个 UI 版本的文档。许多 XML 文件似乎都没有记录,通常只是给出一个模式文件。你对它们如何运作的猜测是非常正确的。

于 2008-09-27T17:14:50.750 回答
0

这不是故事的全部。

  • 分隔符不被继承。只有它们分隔的项目列表被继承:相同的用户宏在不同的属性表中可以有不同的分隔符,但只使用最后遇到的分隔符。(我写“最后遇到”是因为在项目级别,我们无法指定分隔符,并且在那里使用的是为该宏指定继承的最后一个属性表)
  • 分隔符仅在由单个字符组成时才有效。在某些情况下,长于一个字符的分隔符可能会去掉其第一个和/或最后一个字符,这是错误地尝试“加入”值列表。
  • $(Inherit) 似乎在用户宏中工作。与聚合
    属性一样,它用作
    父值的占位符,并且可以出现多次。当没有找到 $(Inherit) 时,如果设置了继承标志,则在开头隐含。
  • $(NoInherit) 似乎也适用于用户的宏(使 VC 的行为就像未选中复选框一样)。
  • 当用于构造属性表的路径时,用户宏(和一些内置函数)似乎可以工作(VC 自己的项目转换器使用该功能)。但是,在这种情况下,用户宏所采用的值并不总是直观的,特别是如果它在其他包含的属性表中重新定义时。
  • In general, what gets "inherited" or concatenated are formulae and not values (ie. you cannot use a user macro to take a snapshot the local value of (say) $(IntDir) in a property sheet and hope to "bubble up" that value through inheritance, because what gets inherited is actually the formula "$(IntDir)", whose value will eventually be resolved at the project/config/file level).
  • A property sheet already loaded is ignored (seem to avoid that the same property sheet has its user macros aggregated twice)
  • Both "/" and "\" appear to work in property sheet paths (and in most places where VS expects a path).
  • A property sheet path starting with "/" (after macros have been resolved) is assumed to be in "./", where '.' is the location of the calling sheet/project). Same if the path does not start with "./", "../" or "drive:/" (dunno about UNC).
于 2011-02-15T12:51:17.580 回答