1.自定义Msbuild target
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
DefaultTargets="CompileAll"
ToolsVersion="3.5">
<!-- import system common Task targets-->
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- Import Project="c:\.net3.5\Microsoft.Csharp.targets" / -->
<PropertyGroup>
<!-- This AppName thing is the base name of your DLL or EXE -->
<AppName>YourAppNameHere</AppName>
</PropertyGroup>
<!-- This build file compiles each .cs file into its own exe -->
<PropertyGroup Condition="'$(Configuration)'==''">
<Configuration>Debug</Configuration>
<!-- Default -->
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<Optimize>false</Optimize>
<DebugSymbols>true</DebugSymbols>
<!-- <OutputPath>.\bin</OutputPath> -->
<OutputPath>.\</OutputPath>
<OutDir>.\</OutDir>
<IntermediateOutputPath>.\</IntermediateOutputPath>
</PropertyGroup>
<!-- Specify the inputs by type and file name -->
<ItemGroup>
<CSFile Include="*.cs"/>
</ItemGroup>
<!-- specify reference assemblies for all builds in this project -->
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
<Reference Include="System.Data.Linq" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.ServiceModel.Web" />
<Reference Include="System.Runtime.Serialization" />
<!-- <Reference Include=".\ObjectDumper.dll" /> -->
</ItemGroup>
<Target Name="CompileAll"
<!-- ResolveAssemblyReferences will resolve $(Reference) to generate $(ReferencePath) -->
DependsOnTargets="ResolveAssemblyReferences">
<Message Text="Reference = @(Reference)" />
<Message Text="ReferencePath = @(ReferencePath)" />
<!-- Message Text="MS Build Tools path: $(MSBuildToolsPath)" / -->
<!-- Run the Visual C# compilation on all the .cs files. -->
<CSC Sources="@(CSFile)"
References="@(ReferencePath)"
OutputAssembly="$(OutputPath)\$(AppName).exe"
EmitDebugInformation="$(DebugSymbols)"
TargetType="exe"
Toolpath="$(MSBuildToolsPath)"
Nologo="true"
/>
</Target>
<!-- redefine the Clean target, from the Microsoft.csharp.targets file. (Last definition wins) -->
<Target Name="Clean">
<Delete Files="$(OutputPath)\$(AppName).exe"/>
<Delete Files="$(OutputPath)\$(AppName).pdb"/>
<Delete Files="%(CSFile.identity)~"/>
<Delete Files="build.xml~"/>
</Target>
</Project>
2.使用官方MSbuild构建项目
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<PropertyGroup>
<OutputType>exe</OutputType>
<PlatformTarget>AnyCPU</PlatformTarget>
<OutputPath>bin\</OutputPath>
<AssemblyName>$(CsFile)</AssemblyName>
</PropertyGroup>
<ItemGroup>
<Reference Include="System.dll"/>
<Reference Include="..\libs\customdll.dll"/>
</ItemGroup>
<ItemGroup>
<Compile Include="$(CsFile)" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
msbuild在编译完毕后执行其他任务的几种方式
- 用PreBuild和PostBuild这2个事件,这个适合调用简单的脚本的需求,比如复制文件,或者调用一个外部命令,直接用这个就行了。这个可以直接在Visual Studio里设置,相对容易。
- 重写默认的AfterBuild Target。说到Target,就要顺带提一下Task。Task和Target是msbuild里专门用来执行任务的元素,具体区别是task是msbuild里可以执行的最小单元任务,targets则是一系列的task的组合。AfterBuild target默认会在编译完毕后触发,我们可以通过取消csproj文件里的AfterBuild Target的注释来加上我们要在编译完跑的脚本。有一点要注意的就是要保证AfterBuild Target必须出现在其他的Target import之后。
用AfterTargets属性,这个是msbuild 4以上的版本才支持的。比如 则定义了Optimize这个target依赖于Compile,必须等到Compile结束后才跑。 - 扩展BuildDependsOn列表,这个是最高级也是最灵活的用法。如果你需要跑一堆复杂的脚本,并且它们之间还有依赖关系,那用这个就最合适了。
扩展BuildDependsOn列表
可以在项目文件的末尾声明另一个名为 BuildDependsOn 的属性,从而对此属性值进行覆盖。 将以前的 BuildDependsOn 属性包括在新属性中,便可以将新目标添加到目标列表的开头和结尾。 例如:
<PropertyGroup>
<BuildDependsOn>
MyCustomTarget1;
$(BuildDependsOn);
MyCustomTarget2
</BuildDependsOn>
</PropertyGroup>
<Target Name="MyCustomTarget1">
<Message Text="Running MyCustomTarget1..."/>
</Target>
<Target Name="MyCustomTarget2">
<Message Text="Running MyCustomTarget2..."/>
</Target>
通常被覆盖的“DependsOn”属性
属性名 | 说明 |
---|---|
BuildDependsOn | 希望在整个生成过程之前或之后插入自定义目标时要覆盖的属性。 |
CleanDependsOn | 希望清理自定义生成过程的输出时要覆盖的属性。 |
CompileDependsOn | 希望在编译步骤之前或之后插入自定义过程时要覆盖的属性。 |