我正在尝试为我们的源树编写构建脚本。该树由(大量)解决方案组成,它们之间具有程序集引用。我创建了一个包含所有解决方案的 ItemGroup,并对该 ItemGroup 进行批处理以构建解决方案。
我也需要复制some项目输出到“exes 输出”文件夹,每个文件夹都在自己的文件夹中。我已将一些元数据附加到解决方案项,指向我想要从中获取输出的项目。由于每个解决方案可能会输出多个项目,因此我通过向元数据提供传递给 ItemGroup 的 Include 的值来单独创建一个 ItemGroup 来实现这一点。这工作得很愉快,我能够对这个动态创建的 ItemGroup 进行批处理。
我想做的最后一步,这让我头疼,是some在这些输出项目中,我想指定一个特殊的文件夹名称。现在,我可以通过更改正在执行工作的目标内的元数据来做到这一点,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
DefaultTargets="Build">
<!-- Define all the solutions to build, and any projects we want to handle the output of -->
<ItemGroup>
<SolutionsToBuild Include="$(MSBuildProjectDirectory)\Solution1\Solution1.sln">
<ProjectsToOutput>
$(MSBuildProjectDirectory)\Solution1\Project1A\Project1A.csproj;
$(MSBuildProjectDirectory)\Solution1\Project1B\Project1B.csproj;
</ProjectsToOutput>
</SolutionsToBuild>
<SolutionsToBuild Include="$(MSBuildProjectDirectory)\Solution2\Solution2.sln">
<ProjectsToOutput>
$(MSBuildProjectDirectory)\Solution2\Project2A\Project2A.csproj;
$(MSBuildProjectDirectory)\Solution2\Project2B\Project2B.csproj;
</ProjectsToOutput>
</SolutionsToBuild>
</ItemGroup>
<Target Name="Build">
<CallTarget Targets="DoBuild" />
</Target>
<Target Name="DoBuild" Outputs="%(SolutionsToBuild.Identity)">
<Message Text="Building project: %(SolutionsToBuild.FullPath)" />
<!-- e.g. <MSBuild Projects="%(SolutionsToBuild.FullPath)" /> -->
<PropertyGroup>
<ProjectsToOutputIncludeMask>%(SolutionsToBuild.ProjectsToOutput)</ProjectsToOutputIncludeMask>
</PropertyGroup>
<ItemGroup>
<OutputProjects Include="$(ProjectsToOutputIncludeMask)" />
<!-- Now create the OutputTo metadata -->
<!-- Default to the same name as the project file -->
<OutputProjects>
<OutputTo>%(OutputProjects.FileName)</OutputTo>
</OutputProjects>
<!-- Now override specific projects OutputTo metadata -->
<OutputProjects Condition="'%(OutputProjects.FileName)' == 'Project1A'">
<OutputTo>ArbitraryFolder1</OutputTo>
</OutputProjects>
<OutputProjects Condition="'%(OutputProjects.FileName)' == 'Project2B'">
<OutputTo>ArbitraryFolder2</OutputTo>
</OutputProjects>
</ItemGroup>
<Message Text=" Outputting project: %(OutputProjects.FullPath) -> %(OutputTo)" />
</Target>
</Project>
然而,这个构建脚本需要由团队中的所有开发人员维护,并非所有人都熟悉 MSBuild。因此,我想在脚本顶部定义另一个 ItemGroup 来定义任何特殊名称。然后,他们可以忽略所有目标和任务,只维护 ItemGroup,如下所示:
<ItemGroup>
<SolutionsToBuild Include="$(MSBuildProjectDirectory)\Solution1\Solution1.sln">
<ProjectsToOutput>
$(MSBuildProjectDirectory)\Solution1\Project1A\Project1A.csproj;
$(MSBuildProjectDirectory)\Solution1\Project1B\Project1B.csproj;
</ProjectsToOutput>
</SolutionsToBuild>
<SolutionsToBuild Include="$(MSBuildProjectDirectory)\Solution2\Solution2.sln">
<ProjectsToOutput>
$(MSBuildProjectDirectory)\Solution2\Project2A\Project2A.csproj;
$(MSBuildProjectDirectory)\Solution2\Project2B\Project2B.csproj;
</ProjectsToOutput>
</SolutionsToBuild>
<OutputNames Include="Project1A">
<OutputFolder>ArbitraryFolder1</OutputFolder>
</OutputNames>
<OutputNames Include="Project2B">
<OutputFolder>ArbitraryFolder2</OutputFolder>
</OutputNames>
</ItemGroup>
然而,我尝试让 DoBuild 目标更新元数据的任何方法都失败了。我想我可以这样做:
<!-- Now override specific projects OutputTo metadata -->
<OutputProjects Condition="'%(OutputProjects.FileName)' == '%(OutputNames.Identity)'">
<OutputTo>%(OutputNames.OutputFolder)</OutputTo>
</OutputProjects>
但是该代码对 OutputProjects 项目组进行批处理,并且then在 OutputNames 项组上,因此条件永远不会为真(比较的参数之一始终为空)。
不幸的是,现阶段我无法更改解决方案结构或输出文件夹结构要求。我缺少的 MSBuild 技巧是否可以在这里帮助我?我并不反对包含自定义任务来完成这项工作,但如果可能的话,我更喜欢直接的 MSBuild 解决方案。
如果有什么区别,我正在使用 MSBuild v4。