MSBuild: Output properties from imported projects

2019-08-28 21:48发布

问题:

Let's say I have a build.proj like this:

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

    <PropertyGroup>
        <CustomAfterMicrosoftCSharpTargets>$(MSBuildThisFileDirectory)Common.Build.targets</CustomAfterMicrosoftCSharpTargets>
        <Configuration>Release</Configuration>
        <Platform>Any CPU</Platform>
        <ProjectProperties>
            Configuration=$(Configuration);
            Platform=$(Platform);
            CustomAfterMicrosoftCSharpTargets=$(CustomAfterMicrosoftCSharpTargets);
        </ProjectProperties>
    </PropertyGroup>

    <ItemGroup>
        <ProjectToBuild Include="$(MSBuildThisFileDirectory)src\Proj\MyApp.csproj" />
    </ItemGroup>

    <Target Name="Build">
        <MSBuild Targets="Build"
                 Projects="@(ProjectToBuild)"
                 Properties="$(ProjectProperties)" />
    </Target>

    <Target Name="AfterBuild" DependsOn="Build">
        <Message Text="ChildProperty: $(ChildProperty)" />
    </Target>
</Project>

In Common.Build.targets, I have a Target that creates a property:

<Target Name="DoSomethingUseful">
    <!-- Do something useful -->
    <CreateProperty Value="SomeComputedThingy">
        <Output TaskParameter="Value" PropertyName="ChildProperty"/>
    </CreateProperty>
</Target>

Now if I build build.proj, I do not see the value of ChildProperty in the message. The output is blank: ChildProperty:.

I was under the impression that any output for a target is merged back to global context after its execution. But it seems that it only applies to anything within that target file.

How do I make ChildProperty bubble up to the parent build.proj?

回答1:

When you are calling <MSBuild> task on dependent projects, read TargetOutputs output parameter of the task. See example from MSDN:

<Target Name="BuildOtherProjects">
    <MSBuild
        Projects="@(ProjectReferences)"
        Targets="Build">
        <Output
            TaskParameter="TargetOutputs"
            ItemName="AssembliesBuiltByChildProjects" />
    </MSBuild>
</Target>

You will also need to ensure the target you are calling in dependent projects correctly populates Returns or Output parameter (Returns takes precedence if used). E.g.:

<Target Name="MyTarget" Inputs="..." Outputs="..." Returns="$(MyOutputValue)">
    <PropertyGroup>
        <MyOutputValue>set it here</MyOutputValue>
    </PropertyGroup>
</Target>


标签: msbuild