一、前言
MSBuild是一个既熟悉又陌生的名字,Visual Studio的项目加载和构建均通过MSBuild来实现。VS中右键打开项目菜单,对应MSBuild的Build目标,
对应MSBuild的Rebuild目标,
对应MSBuild的Clean目标,
对应MSBuild的PublishOnly目标。到这里我想大家都明白MSBuild就和Ant一样就是一个用于项目构建的任务执行引擎,只不过它被融入到VS中,降低了入门难度。但融入VS中只是方便我们使用而已,并不代表不用了解学习,尤其项目规模愈发庞大时,编写结构良好的MSBuild Script来作为项目构建和管理的基石是必不可少。
本文是近日的学习记录,学习目标是看懂*.csproj项目文件的信息。若有纰漏请大家指正,谢谢。
附件知识 :
*.sln : 项目、解决方案在磁盘上的引用,VS通过该类文件加载整个项目、解决方案;
*.suo : 保存VS用户界面的自定义配置(包括布局、断电和项目最后编译后而又没有关闭的文件标签等),下一次打开VS时会恢复这些配置;
*.csproj.user: 保存VS的个人配置;
*.csproj : XML格式,保存项目的依赖项和项目构建步骤、任务等。(需要上传到版本库的)
注意:以下内容均以.NET Framework 4.0为环境。
目录一大坨:
MSBuild由两部分组成:脚本 和 执行引擎。
脚本:就是带变量、函数、流程控制的可编程语言。MSBuild Script是基于XML schema的,和Ant、Maven等差不多。
执行引擎:以脚本、变量、环境变量作为输入,对脚本进行解析执行。
直接到MSDN学习是一个不错的选择,但为了降低学习难度我们以**.csproj项目文件作为切入点。
在VS2013下新建名为LearnMSBuild的MVC4项目,然后在项目目录下有LearnMSBuild.csproj和LearnMSBuild.csproj.user两个项目文件,而里面就是MSBuild Script了。
在VS中查看LearnMSBuild.csproj的方法:右键点击项目->卸载项目->右键点击项目->编辑LearnMSBuild.csproj。
<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <ProductVersion> </ProductVersion> <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{13508D65-AC7D-4462-9106-2E8EC81F677D}</ProjectGuid> <ProjectTypeGuids>{E3E379DF-F4C6-4180-9B81-6769533ABE47};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids> <OutputType>Library</OutputType> <AppDesignerFolder>Properties</AppDesignerFolder> <RootNamespace>MvcApplication1</RootNamespace> <AssemblyName>MvcApplication1</AssemblyName> <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <MvcBuildViews>false</MvcBuildViews> <UseIISExpress>true</UseIISExpress> <IISExpressSSLPort /> <IISExpressAnonymousAuthentication /> <IISExpressWindowsAuthentication /> <IISExpressUseClassicPipelineMode /> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>true</DebugSymbols> <DebugType>full</DebugType> <Optimize>false</Optimize> <OutputPath>bin\</OutputPath> <DefineConstants>DEBUG;TRACE</DefineConstants> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <DebugType>pdbonly</DebugType> <Optimize>true</Optimize> <OutputPath>bin\</OutputPath> <DefineConstants>TRACE</DefineConstants> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> </PropertyGroup> <ItemGroup> <Reference Include="Microsoft.CSharp" /> <Reference Include="System" /> <Reference Include="System.Data" /> <Reference Include="System.Data.Entity" /> <Reference Include="System.Drawing" /> <Reference Include="System.Web.DynamicData" /> <Reference Include="System.Web.Entity" /> <Reference Include="System.Web.ApplicationServices" /> <Reference Include="System.ComponentModel.DataAnnotations" /> <Reference Include="System.Core" /> <Reference Include="System.Data.DataSetExtensions" /> <Reference Include="System.Xml.Linq" /> <Reference Include="System.Web" /> <Reference Include="System.Web.Extensions" /> <Reference Include="System.Web.Abstractions" /> <Reference Include="System.Web.Routing" /> <Reference Include="System.Xml" /> <Reference Include="System.Configuration" /> <Reference Include="System.Web.Services" /> <Reference Include="System.EnterpriseServices" /> <Reference Include="EntityFramework"> <HintPath>..\packages\EntityFramework.5.0.0\lib\net40\EntityFramework.dll</HintPath> </Reference> <Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Private>True</Private> <HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath> </Reference> <Reference Include="Microsoft.Web.Mvc.FixedDisplayModes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Private>True</Private> <HintPath>..\packages\Microsoft.AspNet.Mvc.FixedDisplayModes.1.0.0\lib\net40\Microsoft.Web.Mvc.FixedDisplayModes.dll</HintPath> </Reference> <Reference Include="Newtonsoft.Json"> <HintPath>..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll</HintPath> </Reference> <Reference Include="System.Net.Http"> <Private>True</Private> <HintPath>..\packages\Microsoft.Net.Http.2.0.30506.0\lib\net40\System.Net.Http.dll</HintPath> </Reference> <Reference Include="System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <HintPath>..\packages\Microsoft.AspNet.WebApi.Client.4.0.30506.0\lib\net40\System.Net.Http.Formatting.dll</HintPath> </Reference> <Reference Include="System.Net.Http.WebRequest"> <Private>True</Private> <HintPath>..\packages\Microsoft.Net.Http.2.0.30506.0\lib\net40\System.Net.Http.WebRequest.dll</HintPath> </Reference> <Reference Include="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <HintPath>..\packages\Microsoft.AspNet.WebApi.Core.4.0.30506.0\lib\net40\System.Web.Http.dll</HintPath> </Reference> <Reference Include="System.Web.Http.WebHost, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <HintPath>..\packages\Microsoft.AspNet.WebApi.WebHost.4.0.30506.0\lib\net40\System.Web.Http.WebHost.dll</HintPath> </Reference> <Reference Include="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Private>True</Private> <HintPath>..\packages\Microsoft.AspNet.Mvc.4.0.30506.0\lib\net40\System.Web.Mvc.dll</HintPath> </Reference> <Reference Include="System.Web.Optimization"> <HintPath>..\packages\Microsoft.AspNet.Web.Optimization.1.0.0\lib\net40\System.Web.Optimization.dll</HintPath> </Reference> <Reference Include="System.Web.Providers"> <HintPath>..\packages\Microsoft.AspNet.Providers.Core.1.2\lib\net40\System.Web.Providers.dll</HintPath> </Reference> <Reference Include="System.Web.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Private>True</Private> <HintPath>..\packages\Microsoft.AspNet.Razor.2.0.30506.0\lib\net40\System.Web.Razor.dll</HintPath> </Reference> <Reference Include="System.Web.WebPages, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Private>True</Private> <HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.30506.0\lib\net40\System.Web.WebPages.dll</HintPath> </Reference> <Reference Include="System.Web.WebPages.Deployment, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Private>True</Private> <HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.30506.0\lib\net40\System.Web.WebPages.Deployment.dll</HintPath> </Reference> <Reference Include="System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Private>True</Private> <HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.30506.0\lib\net40\System.Web.WebPages.Razor.dll</HintPath> </Reference> <Reference Include="WebGrease"> <Private>True</Private> <HintPath>..\packages\WebGrease.1.3.0\lib\WebGrease.dll</HintPath> </Reference> <Reference Include="Antlr3.Runtime"> <Private>True</Private> <HintPath>..\packages\WebGrease.1.3.0\lib\Antlr3.Runtime.dll</HintPath> </Reference> </ItemGroup> <ItemGroup> <Compile Include="App_Start\BundleConfig.cs" /> <Compile Include="App_Start\FilterConfig.cs" /> <Compile Include="App_Start\RouteConfig.cs" /> <Compile Include="App_Start\WebApiConfig.cs" /> <Compile Include="Global.asax.cs"> <DependentUpon>Global.asax</DependentUpon> </Compile> <Compile Include="Properties\AssemblyInfo.cs" /> </ItemGroup> <ItemGroup> <Content Include="Content\themes\base\images\ui-bg_flat_0_aaaaaa_40x100.png" /> <Content Include="Content\themes\base\images\ui-bg_flat_75_ffffff_40x100.png" /> <Content Include="Content\themes\base\images\ui-bg_glass_55_fbf9ee_1x400.png" /> <Content Include="Content\themes\base\images\ui-bg_glass_65_ffffff_1x400.png" /> <Content Include="Content\themes\base\images\ui-bg_glass_75_dadada_1x400.png" /> <Content Include="Content\themes\base\images\ui-bg_glass_75_e6e6e6_1x400.png" /> <Content Include="Content\themes\base\images\ui-bg_glass_95_fef1ec_1x400.png" /> <Content Include="Content\themes\base\images\ui-bg_highlight-soft_75_cccccc_1x100.png" /> <Content Include="Content\themes\base\images\ui-icons_222222_256x240.png" /> <Content Include="Content\themes\base\images\ui-icons_2e83ff_256x240.png" /> <Content Include="Content\themes\base\images\ui-icons_454545_256x240.png" /> <Content Include="Content\themes\base\images\ui-icons_888888_256x240.png" /> <Content Include="Content\themes\base\images\ui-icons_cd0a0a_256x240.png" /> <Content Include="Content\themes\base\jquery-ui.css" /> <Content Include="Content\themes\base\jquery.ui.accordion.css" /> <Content Include="Content\themes\base\jquery.ui.all.css" /> <Content Include="Content\themes\base\jquery.ui.autocomplete.css" /> <Content Include="Content\themes\base\jquery.ui.base.css" /> <Content Include="Content\themes\base\jquery.ui.button.css" /> <Content Include="Content\themes\base\jquery.ui.core.css" /> <Content Include="Content\themes\base\jquery.ui.datepicker.css" /> <Content Include="Content\themes\base\jquery.ui.dialog.css" /> <Content Include="Content\themes\base\jquery.ui.progressbar.css" /> <Content Include="Content\themes\base\jquery.ui.resizable.css" /> <Content Include="Content\themes\base\jquery.ui.selectable.css" /> <Content Include="Content\themes\base\jquery.ui.slider.css" /> <Content Include="Content\themes\base\jquery.ui.tabs.css" /> <Content Include="Content\themes\base\jquery.ui.theme.css" /> <Content Include="Content\themes\base\minified\images\ui-bg_flat_0_aaaaaa_40x100.png" /> <Content Include="Content\themes\base\minified\images\ui-bg_flat_75_ffffff_40x100.png" /> <Content Include="Content\themes\base\minified\images\ui-bg_glass_55_fbf9ee_1x400.png" /> <Content Include="Content\themes\base\minified\images\ui-bg_glass_65_ffffff_1x400.png" /> <Content Include="Content\themes\base\minified\images\ui-bg_glass_75_dadada_1x400.png" /> <Content Include="Content\themes\base\minified\images\ui-bg_glass_75_e6e6e6_1x400.png" /> <Content Include="Content\themes\base\minified\images\ui-bg_glass_95_fef1ec_1x400.png" /> <Content Include="Content\themes\base\minified\images\ui-bg_highlight-soft_75_cccccc_1x100.png" /> <Content Include="Content\themes\base\minified\images\ui-icons_222222_256x240.png" /> <Content Include="Content\themes\base\minified\images\ui-icons_2e83ff_256x240.png" /> <Content Include="Content\themes\base\minified\images\ui-icons_454545_256x240.png" /> <Content Include="Content\themes\base\minified\images\ui-icons_888888_256x240.png" /> <Content Include="Content\themes\base\minified\images\ui-icons_cd0a0a_256x240.png" /> <Content Include="Content\themes\base\minified\jquery-ui.min.css" /> <Content Include="Content\themes\base\minified\jquery.ui.accordion.min.css" /> <Content Include="Content\themes\base\minified\jquery.ui.autocomplete.min.css" /> <Content Include="Content\themes\base\minified\jquery.ui.button.min.css" /> <Content Include="Content\themes\base\minified\jquery.ui.core.min.css" /> <Content Include="Content\themes\base\minified\jquery.ui.datepicker.min.css" /> <Content Include="Content\themes\base\minified\jquery.ui.dialog.min.css" /> <Content Include="Content\themes\base\minified\jquery.ui.progressbar.min.css" /> <Content Include="Content\themes\base\minified\jquery.ui.resizable.min.css" /> <Content Include="Content\themes\base\minified\jquery.ui.selectable.min.css" /> <Content Include="Content\themes\base\minified\jquery.ui.slider.min.css" /> <Content Include="Content\themes\base\minified\jquery.ui.tabs.min.css" /> <Content Include="Content\themes\base\minified\jquery.ui.theme.min.css" /> <Content Include="Global.asax" /> <Content Include="Content\Site.css" /> <None Include="Scripts\jquery-1.8.2.intellisense.js" /> <Content Include="Scripts\jquery-1.8.2.js" /> <Content Include="Scripts\jquery-1.8.2.min.js" /> <None Include="Scripts\jquery.validate-vsdoc.js" /> <Content Include="Scripts\jquery-ui-1.8.24.js" /> <Content Include="Scripts\jquery-ui-1.8.24.min.js" /> <Content Include="Scripts\jquery.unobtrusive-ajax.js" /> <Content Include="Scripts\jquery.unobtrusive-ajax.min.js" /> <Content Include="Scripts\jquery.validate.js" /> <Content Include="Scripts\jquery.validate.min.js" /> <Content Include="Scripts\jquery.validate.unobtrusive.js" /> <Content Include="Scripts\jquery.validate.unobtrusive.min.js" /> <Content Include="Scripts\knockout-2.2.0.debug.js" /> <Content Include="Scripts\knockout-2.2.0.js" /> <Content Include="Scripts\modernizr-2.6.2.js" /> <Content Include="Scripts\_references.js" /> <Content Include="Web.config" /> <Content Include="Web.Debug.config"> <DependentUpon>Web.config</DependentUpon> </Content> <Content Include="Web.Release.config"> <DependentUpon>Web.config</DependentUpon> </Content> <Content Include="Views\Web.config" /> <Content Include="Views\_ViewStart.cshtml" /> <Content Include="Views\Shared\Error.cshtml" /> <Content Include="Views\Shared\_Layout.cshtml" /> </ItemGroup> <ItemGroup> <Folder Include="App_Data\" /> <Folder Include="Controllers\" /> <Folder Include="Models\" /> </ItemGroup> <ItemGroup> <Content Include="packages.config" /> </ItemGroup> <PropertyGroup> <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion> <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> </PropertyGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" /> <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" /> <Target Name="MvcBuildViews" AfterTargets="AfterBuild" Condition="'$(MvcBuildViews)'=='true'"> <AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" /> </Target> <ProjectExtensions> <VisualStudio> <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}"> <WebProjectProperties> <UseIIS>True</UseIIS> <AutoAssignPort>True</AutoAssignPort> <DevelopmentServerPort>40646</DevelopmentServerPort> <DevelopmentServerVPath>/</DevelopmentServerVPath> <IISUrl>http://localhost:40646/</IISUrl> <NTLMAuthentication>False</NTLMAuthentication> <UseCustomServer>False</UseCustomServer> <CustomServerUrl> </CustomServerUrl> <SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile> </WebProjectProperties> </FlavorProperties> </VisualStudio> </ProjectExtensions> <!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets. <Target Name="BeforeBuild"> </Target> <Target Name="AfterBuild"> </Target> --> <ItemGroup> <F Include="test.txt"> <OP>tst/</OP> </F> <F Include="test1.txt"> <OP>tst/</OP> </F> </ItemGroup> <Target Name="HW" Inputs="@(F)" Outputs="@(F->'%(OP)%(Filename)%(Extension)')"> <Message Text="%(F.OP)"/> <Copy SourceFiles="@(F)" DestinationFolder="%(F.OP)" /> </Target> </Project>