如何从msbuild项目文件本身中使用不同参数调用同一msbuild目标两次
我有以下一段msbuild代码:如何从msbuild项目文件本身中使用不同参数调用同一msbuild目标两次,msbuild,msbuild-task,Msbuild,Msbuild Task,我有以下一段msbuild代码: <PropertyGroup> <DirA>C:\DirA\</DirA> <DirB>C:\DirB\</DirB> </PropertyGroup> <Target Name="CopyToDirA" Condition="Exists('$(DirA)') AND '@(FilesToCopy)' != ''"
<PropertyGroup>
<DirA>C:\DirA\</DirA>
<DirB>C:\DirB\</DirB>
</PropertyGroup>
<Target Name="CopyToDirA"
Condition="Exists('$(DirA)') AND '@(FilesToCopy)' != ''"
Inputs="@(FilesToCopy)"
Outputs="@(FilesToCopy -> '$(DirA)%(Filename)%(Extension)')">
<Copy SourceFiles="@(FilesToCopy)" DestinationFolder="$(DirA)" />
</Target>
<Target Name="CopyToDirB"
Condition="Exists('$(DirB)') AND '@(FilesToCopy)' != ''"
Inputs="@(FilesToCopy)"
Outputs="@(FilesToCopy -> '$(DirB)%(Filename)%(Extension)')">
<Copy SourceFiles="@(FilesToCopy)" DestinationFolder="$(DirB)" />
</Target>
<Target Name="CopyFiles" DependsOnTargets="CopyToDirA;CopyToDirB"/>
C:\DirA\
C:\DirB\
因此,调用目标CopyFiles
会将相关文件复制到$(DirA)
和$(DirB)
,前提是这些文件尚未存在且是最新的
但是目标CopyToDirA
和CopyToDirB
看起来相同,除了一个复制到$(DirA)
和另一个复制到$(DirB)
。是否可以将它们统一到一个目标中,首先使用$(DirA)
调用,然后使用$(DirB)
调用
谢谢。您应该能够生成一个包含目录的项目组,然后在该项目组上生成%
<ItemGroup>
<Dirs Include="C:\DirA\;C:\DirB\">
</ItemGroup>
<Target Name="CopyFiles"
Condition="Exists('%(Dirs)') AND '@(FilesToCopy)' != ''"
Inputs="@(FilesToCopy)"
Outputs="@(FilesToCopy -> '%(Dirs)%(Filename)%(Extension)')">
<Copy SourceFiles="@(FilesToCopy)" DestinationFolder="%(Dirs)" />
</Target>
或者,您可以执行两个显式调用:
<Target Name="CopyFiles">
<MsBuild Projects="$(MSBuildProjectFullPath)" Targets="CopyASetOfFiles" Properties="FilesToCopy=@(FilesToCopy);DestDir=$(DirA)" />
<MsBuild Projects="$(MSBuildProjectFullPath)" Targets="CopyASetOfFiles" Properties="FilesToCopy=@(FilesToCopy);DestDir=$(DirB)" />
</Target>
<Target Name="CopyASetOfFiles"
Condition="Exists('$(DestDir)') AND '@(FilesToCopy)' != ''"
Inputs="@(FilesToCopy)"
Outputs="@(FilesToCopy -> '$(DestDir)%(Filename)%(Extension)')">
<Copy SourceFiles="@(FilesToCopy)" DestinationFolder="$(DestDir)" />
</Target>
这两种语法我都没有测试过,但我对第二种语法相对比较有信心
(答案,如果有的话,在我桌上的Sayed Hashimi书中——你必须等到第一个:
是的,您需要的是在MSBuild中称为批处理。
;%(Dirs.Identity)
在输出中定义的将导致对Dirs项目组中的每个项目执行此任务
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="CopyFiles"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
ToolsVersion="3.5">
<ItemGroup>
<Dirs Include="C:\DirA" />
<Dirs Include="C:\DirB" />
</ItemGroup>
<Target Name="CopyFiles"
Inputs="@(FilesToCopy);@(Dirs)"
Outputs="@(FilesToCopy -> '%(Dirs.Identity)%(Filename)%(Extension)');%(Dirs.Identity)" >
<Message Text="%(Dirs.Identity)" />
</Target>
</Project>
将消息任务更改为具有以下条件的复制任务,即完成:
Condition="Exists('%(Dirs.Identity)') AND '@(FilesToCopy)' != ''"
正如有人已经提到的,答案是批处理 以下是一些链接:
$(MSBuildProjectFile)
替换为$(MSBuildProjectFullPath)
为了更清楚地说明CopyFiles目标正在派生另一个MSBuild来调用正下方的目标
,因此(除非有初始目标
),将运行的唯一目标是CopyASetOfFiles
,它只需要传递两个属性
(即FilesToCopy
和DestDir
)。对我来说,解决这个问题的关键是BuildInParallel=“true”
和%
-对目录进行批处理,使其可并行化。希望你同意我的推理,我没有遗漏任何东西!@Pete:解决方案2的主要问题是,如果唯一关心的是复制文件和/或做任何可以在目标
中批处理的事情,那就没有意义了e需要进行复制和粘贴,并稍微修改目标
或fork另一个MSBuild比我们想象的要少得多,即#1更为惯用:D
Condition="Exists('%(Dirs.Identity)') AND '@(FilesToCopy)' != ''"