簡體   English   中英

MSBuild 17:項目文件中的屬性和項是否有scope?

[英]MSBuild 17: do properties and items have scope within a project file?

我對 MSBuild 項目中的屬性 scope 有點困惑。 我的理解是,在目標外部聲明的屬性在項目文件中將是全局的。 例如:

  <PropertyGroup>
    <TestProp>Unassigned</TestProp>
  </PropertyGroup>

  <ItemGroup>
    <TestEnvironments Include="Development;UAT;Production" />
  </ItemGroup>
  
  <Target Name="TestScope">
    <PropertyGroup>
      <TestProp>Some test data</TestProp>
    </PropertyGroup>

    <Message Text="Test property scope $(TestProp)" />
    
    <CallTarget Targets="ForEachTestScope" />
  </Target>

  <Target Name="ForEachTestScope" Inputs="@(TestEnvironments)" Outputs="%(Identity).done">

    <Message Text="Test property scope $(TestProp)" />
    <Message Text="Selected environment: @(TestEnvironments)" />

  </Target>

執行 TestScope 目標時,output 是:

TestScope:
  Test property scope Some test data
ForEachTestScope:
  Test property scope Unassigned
  Selected environment: Development
ForEachTestScope:
  Test property scope Unassigned
  Selected environment: UAT
ForEachTestScope:
  Test property scope Unassigned
  Selected environment: Production

我本來期望被調用目標 ForEachTestScope 中 $(TestProp) 的值是在調用目標中設置的值,即Some TestData

“本地”聲明的 PropertyGroup(或 ItemGroup)的 scope 是否始終是包含聲明的目標的 scope?

首先,MSBuild 是一種聲明性語言。 MSBuild 中不要使用CallTarget嘗試編寫過程式代碼。目標不是子例程, CallTarget也不是子例程調用。 沒有堆棧框架向被調用目標提供 scope。

給定以下 test.proj 文件,它只在目標中定義TestProp

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <Target Name="Test0">
        <PropertyGroup>
            <TestProp Condition="'$(TestProp)' != ''">$(TestProp);Some test data</TestProp>
            <TestProp Condition="'$(TestProp)' == ''">Some test data</TestProp>
        </PropertyGroup>
        <Message Text="$(TestProp)" />
    </Target>

    <Target Name="Test1">
        <PropertyGroup>
            <TestProp Condition="'$(TestProp)' != ''">$(TestProp);Some other test data</TestProp>
            <TestProp Condition="'$(TestProp)' == ''">Some other test data</TestProp>
        </PropertyGroup>
        <Message Text="$(TestProp)" />
    </Target>
</Project>

命令msbuild test.proj /t:"test0;test1"msbuild test.proj /t:"test1;test0"將產生不同的輸出。

輸出將是

Test0:
  Some test data
Test1:
  Some test data;Some other test data

Test1:
  Some other test data
Test0:
  Some other test data;Some test data

分別。

回到CallTarget ,任務文檔解釋說

使用 CallTarget 時,MSBuild 在新的 scope 中評估被調用目標,而不是從中調用的相同 scope。 這意味着被調用目標中的任何項目和屬性更改對調用目標都是不可見的。 要將信息傳遞給調用目標,請使用 TargetOutputs output 參數。

您使用ForEachTestScope2進行的測試證明了這一點。

重寫您的代碼以不使用CallTarget可能如下所示(但我猜測您的意圖)。

    <ItemDefinitionGroup>
        <TestEnvironments>
            <TestProp>Unassigned</TestProp>
        </TestEnvironments>
    </ItemDefinitionGroup>

    <ItemGroup>
        <TestEnvironments Include="Development;UAT;Production" />
    </ItemGroup>

    <Target Name="TestEnvironment" DependsOnTargets="SetTestData" Inputs="@(TestEnvironments)" Outputs="%(Identity).done">
        <Message Text="Selected environment: @(TestEnvironments->'Test %(identity) with %(TestProp)')" />
    </Target>

    <Target Name="SetTestData">
        <Message Text="in SetTestData"/>
        <ItemGroup>
            <TestEnvironments Condition="'%(identity)' == 'Development'">
                <TestProp>Some development test data</TestProp>
            </TestEnvironments>
            <TestEnvironments Condition="'%(identity)' != 'Development'">
                <TestProp>Some test data</TestProp>
            </TestEnvironments>
        </ItemGroup>
    </Target>

運行TestEnvironment目標會產生:

SetTestData:
  in SetTestData
TestEnvironment:
  Selected environment: Test Development with Some development test data
TestEnvironment:
  Selected environment: Test UAT with Some test data
TestEnvironment:
  Selected environment: Test Production with Some test data

請注意,為TestProp創建了默認值Unassigned SetTestData目標僅運行一次並且正在更改TestProp的值。 SetTestData可以為不同的環境設置不同的值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM