如何在使用其他规则的属性时设置自定义构建规则的输出属性? [英] How do I set the Outputs Property of a Custom Build Rule when it uses an other rule's Property ?

查看:97
本文介绍了如何在使用其他规则的属性时设置自定义构建规则的输出属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述





我设法用VS2008构建自定义构建规则并在VS2010中升级它。

但我有一个问题在VS2010中使用规则的输出属性。



基本上,我添加了一个自定义属性名称OutputSubDir(String),我想在Outputs属性中使用它,就像这样:$(Target)%(OutputSubDir)%(Filename).txt



当我为OutputSubDir设置默认值(在props文件中)时,我的自定义构建规则即使我为项目中的选定项目设置了一个新值,也使用了这个值。

唯一的方法,我让MSBuild使用新的一个是覆盖Outputs属性(使用相同的值)作为默认值!)



看起来像:

- 项目项有输出属性,然后使用项目项的OutputSubDir属性

- Project Item没有Outputs属性,使用Project的Outputs属性然后在同一位置使用OutputSubDir属性输出属性(即:在项目级别=默认值)



看起来MSBuild不允许对其项目进行多态性。



您是否知道我如何配置属性,规则和/或目标以使用良好的值来生成输出?



你知道VS2013问题是否仍然存在吗?



我可以提供样本文件(.props,.xml& .targets)但是很长时间才将它们直接放在问题中。 (我不知道是否可以在这里上传它们)



以下是文件:

TestRule.xml

Hi,

I manage to build a custom build rule with VS2008 and upgrade it in VS2010.
But I have a problem with the Outputs Property of the Rule in VS2010.

Basically, I add a custom property name OutputSubDir (String) and I want to use it in the Outputs property like this : $(Target)%(OutputSubDir)%(Filename).txt

When I put a default value (in the props file) for OutputSubDir, my Custom Build Rule used this value even if I set a new one for the selected item in the project.
The only way, I made MSBuild use the new one is to override the Outputs property as well (using the same value as the default one !)

It looks like :
- Project Item has Outputs property, then use the OutputSubDir Property of the Project Item
- Project Item does not have Outputs property, use the Outputs property of the Project then use the OutputSubDir property at the same location of the Outputs property (i.e.: at the Project level = default value)

It looks like MSBuild does not allow Polymorphism on its Items.

Do you have any idea how can I configure the properties, the rule, and/or the target to make the Outputs using the good value ?

Do you know if the problem still exists with VS2013 ?

I can provide sample files (.props, .xml & .targets) but there are quite long to put them directly in the question. (and I don't know if it is possible to upload them here)

Here are the files :
TestRule.xml

<?xml version="1.0" encoding="utf-8"?>
<ProjectSchemaDefinitions xmlns="clr-namespace:Microsoft.Build.Framework.XamlTypes;assembly=Microsoft.Build.Framework" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:transformCallback="Microsoft.Cpp.Dev10.ConvertPropertyCallback">
  <Rule

    Name="TestRule"

    PageTemplate="tool"

    DisplayName="Test Rule"

    Order="200">
    <Rule.DataSource>
      <DataSource

        Persistence="ProjectFile"

        ItemType="TestRule" />
    </Rule.DataSource>
    <Rule.Categories>
      <Category

        Name="General">
        <Category.DisplayName>
          <sys:String>General</sys:String>
        </Category.DisplayName>
      </Category>
      <Category

        Name="Command Line"

        Subtype="CommandLine">
        <Category.DisplayName>
          <sys:String>Command Line</sys:String>
        </Category.DisplayName>
      </Category>
    </Rule.Categories>
    <StringListProperty

      Name="Inputs"

      Category="Command Line"

      IsRequired="true"

      Switch=" ">
      <StringListProperty.DataSource>
        <DataSource

          Persistence="ProjectFile"

          ItemType="TestRule"

          SourceType="Item" />
      </StringListProperty.DataSource>
    </StringListProperty>
    <StringProperty

      Name="OutputSubDir"

      Category="General"

      HelpContext="0"

      DisplayName="Output SubDir"

      Description="Sub Folder of $(Target) where output file should be"

      Switch="[value]" />
    <StringProperty

      Name="CommandLineTemplate"

      DisplayName="Command Line"

      Visible="False"

      IncludeInCommandLine="False" />
    <DynamicEnumProperty

      Name="TestRuleBeforeTargets"

      Category="General"

      EnumProvider="Targets"

      IncludeInCommandLine="False">
      <DynamicEnumProperty.DisplayName>
        <sys:String>Execute Before</sys:String>
      </DynamicEnumProperty.DisplayName>
      <DynamicEnumProperty.Description>
        <sys:String>Specifies the targets for the build customization to run before.</sys:String>
      </DynamicEnumProperty.Description>
      <DynamicEnumProperty.ProviderSettings>
        <NameValuePair

          Name="Exclude"

          Value="^TestRuleBeforeTargets|^Compute" />
      </DynamicEnumProperty.ProviderSettings>
      <DynamicEnumProperty.DataSource>
        <DataSource

          Persistence="ProjectFile"

          HasConfigurationCondition="true" />
      </DynamicEnumProperty.DataSource>
    </DynamicEnumProperty>
    <DynamicEnumProperty

      Name="TestRuleAfterTargets"

      Category="General"

      EnumProvider="Targets"

      IncludeInCommandLine="False">
      <DynamicEnumProperty.DisplayName>
        <sys:String>Execute After</sys:String>
      </DynamicEnumProperty.DisplayName>
      <DynamicEnumProperty.Description>
        <sys:String>Specifies the targets for the build customization to run after.</sys:String>
      </DynamicEnumProperty.Description>
      <DynamicEnumProperty.ProviderSettings>
        <NameValuePair

          Name="Exclude"

          Value="^TestRuleAfterTargets|^Compute" />
      </DynamicEnumProperty.ProviderSettings>
      <DynamicEnumProperty.DataSource>
        <DataSource

          Persistence="ProjectFile"

          ItemType=""

          HasConfigurationCondition="true" />
      </DynamicEnumProperty.DataSource>
    </DynamicEnumProperty>
    <StringListProperty

      Name="Outputs"

      DisplayName="Outputs"

	    Visible="True"

      IncludeInCommandLine="False"/>
    <StringProperty

      Name="ExecutionDescription"

      DisplayName="Execution Description"

      IncludeInCommandLine="False" />
    <StringListProperty

      Name="AdditionalDependencies"

      DisplayName="Additional Dependencies"

      Visible="False"

      IncludeInCommandLine="False" />
    <StringProperty

      Subtype="AdditionalOptions"

      Name="AdditionalOptions"

      Category="Command Line"

      Visible="False">
      <StringProperty.DisplayName>
        <sys:String>Additional Options</sys:String>
      </StringProperty.DisplayName>
      <StringProperty.Description>
        <sys:String>Additional Options</sys:String>
      </StringProperty.Description>
    </StringProperty>
  </Rule>
  <ItemType

    Name="TestRule"

    DisplayName="Test Rule" />
  <FileExtension

    Name="*.ext"

    ContentType="TestRule" />
  <ContentType

    Name="TestRule"

    DisplayName="Test Rule"

    ItemType="TestRule" />
</ProjectSchemaDefinitions>





TestRule.props



TestRule.props

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup

    Condition="'$(TestRuleBeforeTargets)' == '' and '$(TestRuleAfterTargets)' == '' and '$(ConfigurationType)' != 'Makefile'">
    <TestRuleBeforeTargets>Midl</TestRuleBeforeTargets>
    <TestRuleAfterTargets>CustomBuild</TestRuleAfterTargets>
  </PropertyGroup>
  <PropertyGroup>
    <TestRuleDependsOn

      Condition="'$(ConfigurationType)' != 'Makefile'">_SelectedFiles;$(TestRuleDependsOn)</TestRuleDependsOn>
  </PropertyGroup>
  <ItemDefinitionGroup>
    <TestRule>
      <CommandLineTemplate>
        ECHO OutputDir should be $(TargetDir)[OutputSubDir]%(Filename).txt
      </CommandLineTemplate>
      <Outputs>$(TargetDir)%(OutputSubDir)%(Filename).txt</Outputs>
      <ExecutionDescription>Test Rule</ExecutionDescription>
    </TestRule>
  </ItemDefinitionGroup>
</Project>





TestRule.targets



TestRule.targets

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <PropertyPageSchema

      Include="$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml" />
    <AvailableItemName

      Include="TestRule">
      <Targets>_TestRule</Targets>
    </AvailableItemName>
  </ItemGroup>
  <UsingTask

    TaskName="TestRule"

    TaskFactory="XamlTaskFactory"

    AssemblyName="Microsoft.Build.Tasks.v4.0">
    <Task>$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml</Task>
  </UsingTask>
  <Target

    Name="_TestRule"

    BeforeTargets="$(TestRuleBeforeTargets)"

    AfterTargets="$(TestRuleAfterTargets)"

    Condition="'@(TestRule)' != ''"

    DependsOnTargets="$(TestRuleDependsOn);ComputeTestRuleOutput"

    Outputs="%(TestRule.Outputs)"

    Inputs="%(TestRule.Identity);%(TestRule.AdditionalDependencies);$(MSBuildProjectFile)">
    <ItemGroup

      Condition="'@(SelectedFiles)' != ''">
      <TestRule

        Remove="@(TestRule)"

        Condition="'%(Identity)' != '@(SelectedFiles)'" />
    </ItemGroup>
    <ItemGroup>
      <TestRule_tlog

        Include="%(TestRule.Outputs)"

        Condition="'%(TestRule.Outputs)' != '' and '%(TestRule.ExcludedFromBuild)' != 'true'">
        <Source>@(TestRule, '|')</Source>
      </TestRule_tlog>
    </ItemGroup>
    <Message

      Importance="High"

      Text="%(TestRule.ExecutionDescription)" />
	<Message

		Importance="High"

		Text="OutputSubDir = %(TestRule.OutputSubDir)" />
	<Message

		Importance="High"

		Text="Outputs = %(TestRule.Outputs)" />
    <WriteLinesToFile

      Condition="'@(TestRule_tlog)' != '' and '%(TestRule_tlog.ExcludedFromBuild)' != 'true'"

      File="$(IntDir)$(ProjectName).write.1.tlog"

      Lines="^%(TestRule_tlog.Source);@(TestRule_tlog->'%(Fullpath)')" />
    <TestRule

      Condition="'@(TestRule)' != '' and '%(TestRule.ExcludedFromBuild)' != 'true'"

      CommandLineTemplate="%(TestRule.CommandLineTemplate)"

      OutputSubDir="%(TestRule.OutputSubDir)"

      AdditionalOptions="%(TestRule.AdditionalOptions)"

      Inputs="%(TestRule.Identity)" />
  </Target>
  <PropertyGroup>
    <ComputeLinkInputsTargets>
            $(ComputeLinkInputsTargets);
            ComputeTestRuleOutput;
          </ComputeLinkInputsTargets>
    <ComputeLibInputsTargets>
            $(ComputeLibInputsTargets);
            ComputeTestRuleOutput;
          </ComputeLibInputsTargets>
  </PropertyGroup>
  <Target

    Name="ComputeTestRuleOutput"

    Condition="'@(TestRule)' != ''">
    <ItemGroup>
      <TestRuleDirsToMake

        Condition="'@(TestRule)' != '' and '%(TestRule.ExcludedFromBuild)' != 'true'"

        Include="%(TestRule.Outputs)" />
      <Link

        Include="%(TestRuleDirsToMake.Identity)"

        Condition="'%(Extension)'=='.obj' or '%(Extension)'=='.res' or '%(Extension)'=='.rsc' or '%(Extension)'=='.lib'" />
      <Lib

        Include="%(TestRuleDirsToMake.Identity)"

        Condition="'%(Extension)'=='.obj' or '%(Extension)'=='.res' or '%(Extension)'=='.rsc' or '%(Extension)'=='.lib'" />
      <ImpLib

        Include="%(TestRuleDirsToMake.Identity)"

        Condition="'%(Extension)'=='.obj' or '%(Extension)'=='.res' or '%(Extension)'=='.rsc' or '%(Extension)'=='.lib'" />
    </ItemGroup>
    <MakeDir

      Directories="@(TestRuleDirsToMake->'%(RootDir)%(Directory)')" />
  </Target>
</Project>





and the Extract of .VCXPROJ :



and the Extract of .VCXPROJ :

<ItemGroup>
  <TestRule Include="test.ext">
    <OutputSubDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">info\</OutputSubDir>
    <FileType>Document</FileType>
  </TestRule>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
  <Import Project="TestRule.targets" />
</ImportGroup>





I discovered something else:



I discovered something else:

<ItemGroup>
  <TestRule Include="test.ext">
    <OutputSubDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">info\</OutputSubDir>
    <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(TargetDir)%(OutputSubDir).dll\</Outputs>
    <FileType>Document</FileType>
  </TestRule>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
  <Import Project="TestRule.targets" />
</ImportGroup>





is not the same as:



is not the same as:

<ItemGroup>
  <TestRule Include="test.ext">
    <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(TargetDir)%(OutputSubDir).dll\</Outputs>
    <OutputSubDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">info\</OutputSubDir>
    <FileType>Document</FileType>
  </TestRule>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
  <Import Project="TestRule.targets" />
</ImportGroup>





In the first case, the Outputs will use the value of OutputSubDir but not in the second case where it will use the value defined in the props file.

MSBuild looks to be sequential

推荐答案

(Target)%(OutputSubDir)%(Filename).txt



When I put a default value (in the props file) for OutputSubDir, my Custom Build Rule used this value even if I set a new one for the selected item in the project.

The only way, I made MSBuild use the new one is to override the Outputs property as well (using the same value as the default one !)



It looks like :

- Project Item has Outputs property, then use the OutputSubDir Property of the Project Item

- Project Item does not have Outputs property, use the Outputs property of the Project then use the OutputSubDir property at the same location of the Outputs property (i.e.: at the Project level = default value)



It looks like MSBuild does not allow Polymorphism on its Items.



Do you have any idea how can I configure the properties, the rule, and/or the target to make the Outputs using the good value ?
$b $b

Do you know if the problem still exists with VS2013 ?



I can provide sample files (.props, .xml & .targets) but there are quite long to put them directly in the question. (and I don’t know if it is possible to upload them here)



Here are the files :

TestRule.xml

(Target)%(OutputSubDir)%(Filename).txt

When I put a default value (in the props file) for OutputSubDir, my Custom Build Rule used this value even if I set a new one for the selected item in the project.
The only way, I made MSBuild use the new one is to override the Outputs property as well (using the same value as the default one !)

It looks like :
- Project Item has Outputs property, then use the OutputSubDir Property of the Project Item
- Project Item does not have Outputs property, use the Outputs property of the Project then use the OutputSubDir property at the same location of the Outputs property (i.e.: at the Project level = default value)

It looks like MSBuild does not allow Polymorphism on its Items.

Do you have any idea how can I configure the properties, the rule, and/or the target to make the Outputs using the good value ?

Do you know if the problem still exists with VS2013 ?

I can provide sample files (.props, .xml & .targets) but there are quite long to put them directly in the question. (and I don't know if it is possible to upload them here)

Here are the files :
TestRule.xml
<?xml version="1.0" encoding="utf-8"?>
<ProjectSchemaDefinitions xmlns="clr-namespace:Microsoft.Build.Framework.XamlTypes;assembly=Microsoft.Build.Framework" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:transformCallback="Microsoft.Cpp.Dev10.ConvertPropertyCallback">
  <Rule

    Name="TestRule"

    PageTemplate="tool"

    DisplayName="Test Rule"

    Order="200">
    <Rule.DataSource>
      <DataSource

        Persistence="ProjectFile"

        ItemType="TestRule" />
    </Rule.DataSource>
    <Rule.Categories>
      <Category

        Name="General">
        <Category.DisplayName>
          <sys:String>General</sys:String>
        </Category.DisplayName>
      </Category>
      <Category

        Name="Command Line"

        Subtype="CommandLine">
        <Category.DisplayName>
          <sys:String>Command Line</sys:String>
        </Category.DisplayName>
      </Category>
    </Rule.Categories>
    <StringListProperty

      Name="Inputs"

      Category="Command Line"

      IsRequired="true"

      Switch=" ">
      <StringListProperty.DataSource>
        <DataSource

          Persistence="ProjectFile"

          ItemType="TestRule"

          SourceType="Item" />
      </StringListProperty.DataSource>
    </StringListProperty>
    <StringProperty

      Name="OutputSubDir"

      Category="General"

      HelpContext="0"

      DisplayName="Output SubDir"

      Description="Sub Folder of


(Target) where output file should be\"

Switch=\"[value]\" />
<StringProperty

Name=\"CommandLineTemplate\"

DisplayName=\"Command Line\"

Visible=\"False\"

IncludeInCommandLine=\"False\" />
<DynamicEnumProperty

Name=\"TestRuleBeforeTargets\"

Category=\"General\"

EnumProvider=\"Targets\"

IncludeIn CommandLine=\"False\">
<DynamicEnumProperty.DisplayName>
<sys:String>Execute Before</sys:String>
</DynamicEnumProperty.DisplayName>
<DynamicEnumProperty.Description>
<sys:String>Specifies the targets for the build customization to run before.</sys:String>
</DynamicEnumProperty.Description>
<DynamicEnumProperty.ProviderSettings>
<NameValuePair

Name=\"Exclude\"

Value=\"^TestRuleBeforeTargets|^Compute\" />
</DynamicEnumProperty.ProviderSettings>
<DynamicEnumProperty.DataSource>
<DataSource

Persistence=\"ProjectFile\"

HasConfigurationCondition=\"true\" />
</DynamicEnumProperty.DataSource>
</DynamicEnumProperty>
<DynamicEnumProperty

Name=\"TestRuleAfterTargets\"

Category=\"General\"

< span class=\"code-attribute\"> EnumProvider=\"Targets\"

IncludeInCommandLine=\"False\">
<DynamicEnumProperty.DisplayName>
<sys:String>Execute After</sys:String>
</DynamicEnumProperty.DisplayName>
<DynamicEnumProperty.Description>
<sys:String>Specifies the targets for the build customization to run after.</sys:String>
</Dynam icEnumProperty.Description>
<DynamicEnumProperty.ProviderSettings>
<NameValuePair

Name=\"Exclude\"

Value=\"^TestRuleAfterTargets|^Compute\" />
</DynamicEnumProperty.ProviderSettings>
<DynamicEnumProperty.DataSource>
<DataSource

Persistence=\"ProjectFile\"

ItemType=\"\"

HasConfigurationCondition=\"true\" />
</DynamicEnumProperty.D ataSource>
</DynamicEnumProperty>
<StringListProperty

Name=\"Outputs\"

< span class=\"code-attribute\"> DisplayName=\"Outputs\"

\t Visible=\"True\"

IncludeInCommandLine=\"False\"/>
<StringProperty

Name=\"ExecutionDescription\"

DisplayName=\"Execution Description\"

IncludeInCommandLine=\"False\" />
<StringListProperty

Name=\"AdditionalDependencies\"

DisplayName=\"Additional Dependencies\"

Visible=\"False \"

IncludeInCommandLine=\"False\" />
<StringProperty

Subtype =\"AdditionalOptions\"

Name=\"AdditionalOptions\"

Category=\"Command Line\"

Visible=\"False\">
<StringProperty.DisplayName>
<sys:String>Additional Options</sys:String>
</StringProperty.DisplayName>
<StringProperty.Description>
<sys:String>Additional Options</sys:String>
</StringProperty.Description>
</StringProperty>
</Rule>
<ItemType

Name=\"TestRule\"

DisplayName=\"Test Rule\" />
<FileExtension

Name=\"*.ext\"

ContentType=\"TestRule\" />
<ContentType

Name=\"TestRule\"

DisplayName=\"Test Rule\"

ItemType=\"TestRule\" />
</ProjectSchemaDefinitions>
(Target) where output file should be" Switch="[value]" /> <StringProperty Name="CommandLineTemplate" DisplayName="Command Line" Visible="False" IncludeInCommandLine="False" /> <DynamicEnumProperty Name="TestRuleBeforeTargets" Category="General" EnumProvider="Targets" IncludeInCommandLine="False"> <DynamicEnumProperty.DisplayName> <sys:String>Execute Before</sys:String> </DynamicEnumProperty.DisplayName> <DynamicEnumProperty.Description> <sys:String>Specifies the targets for the build customization to run before.</sys:String> </DynamicEnumProperty.Description> <DynamicEnumProperty.ProviderSettings> <NameValuePair Name="Exclude" Value="^TestRuleBeforeTargets|^Compute" /> </DynamicEnumProperty.ProviderSettings> <DynamicEnumProperty.DataSource> <DataSource Persistence="ProjectFile" HasConfigurationCondition="true" /> </DynamicEnumProperty.DataSource> </DynamicEnumProperty> <DynamicEnumProperty Name="TestRuleAfterTargets" Category="General" EnumProvider="Targets" IncludeInCommandLine="False"> <DynamicEnumProperty.DisplayName> <sys:String>Execute After</sys:String> </DynamicEnumProperty.DisplayName> <DynamicEnumProperty.Description> <sys:String>Specifies the targets for the build customization to run after.</sys:String> </DynamicEnumProperty.Description> <DynamicEnumProperty.ProviderSettings> <NameValuePair Name="Exclude" Value="^TestRuleAfterTargets|^Compute" /> </DynamicEnumProperty.ProviderSettings> <DynamicEnumProperty.DataSource> <DataSource Persistence="ProjectFile" ItemType="" HasConfigurationCondition="true" /> </DynamicEnumProperty.DataSource> </DynamicEnumProperty> <StringListProperty Name="Outputs" DisplayName="Outputs" Visible="True" IncludeInCommandLine="False"/> <StringProperty Name="ExecutionDescription" DisplayName="Execution Description" IncludeInCommandLine="False" /> <StringListProperty Name="AdditionalDependencies" DisplayName="Additional Dependencies" Visible="False" IncludeInCommandLine="False" /> <StringProperty Subtype="AdditionalOptions" Name="AdditionalOptions" Category="Command Line" Visible="False"> <StringProperty.DisplayName> <sys:String>Additional Options</sys:String> </StringProperty.DisplayName> <StringProperty.Description> <sys:String>Additional Options</sys:String> </StringProperty.Description> </StringProperty> </Rule> <ItemType Name="TestRule" DisplayName="Test Rule" /> <FileExtension Name="*.ext" ContentType="TestRule" /> <ContentType Name="TestRule" DisplayName="Test Rule" ItemType="TestRule" /> </ProjectSchemaDefinitions>





TestRule.props



TestRule.props

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup

    Condition="'


(TestRuleBeforeTargets)' == '' and '
(TestRuleBeforeTargets)' == '' and '


这篇关于如何在使用其他规则的属性时设置自定义构建规则的输出属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆