2010-03-18 41 views
11

我想创建一个反映解决方案中项目依赖关系的MSBuild项目,并将VS项目封装在可重用目标中。将.sln替换为MSBuild并将包含的项目包装到目标中

我喜欢解决这个问题的方法是在一个BizTalk应用程序中svn导出,构建和部署特定程序集(及其依赖项)。

我的问题是:如何为svn-exporting,构建和部署可重用的目标做好准备,并且在为不同的依赖构建它们时重用包装的项目?

我知道只是构建解决方案并仅部署所需的程序集会更简单,但我希望尽可能重复使用目标。

零件

我喜欢的项目部署

<Project DefaultTargets="Deploy" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
    <PropertyGroup> 
     <ExportRoot Condition="'$(Export)'==''">Export</ExportRoot> 
    </PropertyGroup> 

    <Target Name="Clean_Export"> 
     <RemoveDir Directories="$(ExportRoot)\My.Project.Dir" /> 
    </Target> 

    <Target Name="Export_MyProject"> 
     <Exec Command="svn export svn://xxx/trunk/Biztalk2009/MyProject.btproj --force" WorkingDirectory="$(ExportRoot)" /> 
    </Target> 

    <Target Name="Build_MyProject" DependsOnTargets="Export_MyProject"> 
     <MSBuild Projects="$(ExportRoot)\My.Project.Dir\MyProject.btproj" Targets="Build" Properties="Configuration=Release"></MSBuild> 
    </Target> 

    <Target Name="Deploy_MyProject" DependsOnTargets="Build_MyProject"> 
     <Exec Command="BTSTask AddResource -ApplicationName:CORE -Source:MyProject.dll" /> 
    </Target> 
</Project> 

它几乎完全取决于这个样子的这些项目(其他.btproj和.csproj的)。

回答

16

哇,这是一个论坛帖子加载的问题。我在我的book中编写了大约20页关于创建可重用的.targets文件,但我会从这里开始介绍这里的基础知识。我认为,关键是制造可重复使用的构建脚本(即.targets文件)是三个要素:

  • 地方行为(即目标)为独立的文件
  • 将数据(IE属性和物品,这些被称为.proj文件)到自己的文件
  • 扩展
  • .targets文件应该验证假设

这个想法是,你想把所有的目标放在单独的文件中,然后这些文件将被导入构建过程的文件导入。这些是包含数据的文件。由于您导入.targets文件,因此您可以获得所有目标,就好像它们已经内联定义一样。 .proj和.targets文件之间会有一个无声的合同。该合同在两者都使用的属性和项目中定义。这是需要验证的。

这里的想法并不新鲜。该模式后面跟着.csproj(以及由Visual Studio生成的其他项目)。如果你看看你的.csproj文件,你不会找到一个目标,只是属性和项目。然后朝文件底部输入Microsoft.csharp.targets(可能因项目类型而异)。该项目文件(以及其他导入文件)包含实际执行构建的所有目标。

因此它奠定了这样的:

  • SharedBuild.targets
  • myProduct的。凸出

MyProdcut.proj可能看起来像:

<?xml version="1.0" encoding="utf-8"?> 
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
    <!-- This uses a .targets file to off load performing the build --> 
    <PropertyGroup> 
    <Configuration Condition=" '$(Configuration)'=='' ">Release</Configuration> 
    <OutputPath Condition=" '$(OutputPath)'=='' ">$(MSBuildProjectDirectory)\BuildArtifacts\bin\</OutputPath> 
    </PropertyGroup> 

    <ItemGroup> 
    <Projects Include="$(MSBuildProjectDirectory)\..\ClassLibrary1\ClassLibrary1.csproj"/> 
    <Projects Include="$(MSBuildProjectDirectory)\..\ClassLibrary2\ClassLibrary2.csproj"/> 
    <Projects Include="$(MSBuildProjectDirectory)\..\ClassLibrary3\ClassLibrary3.csproj"/> 
    <Projects Include="$(MSBuildProjectDirectory)\..\WindowsFormsApplication1\WindowsFormsApplication1.csproj"/> 
    </ItemGroup> 

    <Import Project="SharedBuild.targets"/> 
</Project> 

而且SharedBuild.targets可能看起来像:

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
    <!-- This represents a re-usable build file --> 
    <Target Name="SharedBuild_Validate"> 
    <!-- See http://sedodream.com/2009/06/30/ElementsOfReusableMSBuildScriptsValidation.aspx for more info 
     about this validation pattern 
    --> 
    <ItemGroup> 
     <_RequiredProperties Include ="Configuration"> 
      <Value>$(Configuration)</Value> 
     </_RequiredProperties>  
     <_RequiredProperties Include ="OutputPath"> 
      <Value>$(OutputPath)</Value> 
     </_RequiredProperties> 

     <_RequiredItems Include="Projects"> 
     <RequiredValue>%(Projects.Identity)</RequiredValue> 
     <RequiredFilePath>%(Projects.Identity)</RequiredFilePath> 
     </_RequiredItems> 
    </ItemGroup> 

    <!-- Raise an error if any value in _RequiredProperties is missing --> 
    <Error Condition="'%(_RequiredProperties.Value)'==''" 
      Text="Missing required property [%(_RequiredProperties.Identity)]"/> 

    <!-- Raise an error if any value in _RequiredItems is empty --> 
    <Error Condition="'%(_RequiredItems.RequiredValue)'==''" 
      Text="Missing required item value [%(_RequiredItems.Identity)]" /> 

    <!-- Validate any file/directory that should exist --> 
    <Error Condition="'%(_RequiredItems.RequiredFilePath)' != '' and !Exists('%(_RequiredItems.RequiredFilePath)')" 
      Text="Unable to find expeceted path [%(_RequiredItems.RequiredFilePath)] on item [%(_RequiredItems.Identity)]" /> 
    </Target> 

    <PropertyGroup> 
    <BuildDependsOn> 
     SharedBuild_Validate; 
     BeforeBuild; 
     CoreBuild; 
     AfterBuild; 
    </BuildDependsOn> 
    </PropertyGroup> 
    <Target Name="Build" DependsOnTargets="$(BuildDependsOn)"/> 
    <Target Name="BeforeBuild"/> 
    <Target Name="AfterBuild"/> 
    <Target Name="CoreBuild"> 
    <!-- Make sure output folder exists --> 
    <PropertyGroup> 
     <_FullOutputPath>$(OutputPath)$(Configuration)\</_FullOutputPath> 
    </PropertyGroup> 
    <MakeDir Directories="$(_FullOutputPath)"/> 
    <MSBuild Projects="@(Projects)" 
      BuildInParallel="true" 
      Properties="OutputPath=$(_FullOutputPath)"/> 
    </Target> 
</Project> 

不要看SharedBuild_Validate太多目标呢。我在那里提供完整性,但不关注它。你可以在我的博客http://sedodream.com/2009/06/30/ElementsOfReusableMSBuildScriptsValidation.aspx找到更多信息。

要注意的重要部分是可扩展性点。尽管这是一个非常基本的文件,但它具有可重复使用的.targets文件的所有组件。您可以通过传递不同的属性和项目来构建它的行为。你可以扩展它的行为通过覆盖目标(BeforeBuildAfterBuild甚至CoreBuild),你可以注入自己的目标,为构建具有:

<Project ...> 
    ... 
    <Import Project="SharedBuild.targets"/> 
    <PropertyGroup> 
    <BuildDependsOn> 
     $(BuildDependsOn); 
     CustomAfterBuild 
    </BuildDependsOn> 
    </PropertyGroup> 
    <Target Name="CustomAfterBuild"> 
    <!-- Insert stuff here --> 
    </Target> 
</Project> 

在你的情况我想创建它使用一个SvnExport.targets文件所需的属性:

  • SvnExportRoot
  • SvnUrl
  • SvnWorkingDirectory 您将使用这些属性做出口。

然后为Biztalk构建和部署创建另一个。如有必要,你可以将它分成2个。

然后在您的.proj文件中,您只需导入并设置目标以按正确顺序构建,然后关闭。

这仅仅是创造可重复使用的构建元素的开始,但这应该让轮子在你头上转动。我将把所有这些发布到我的blog以及下载所有文件的链接。

UPDATE:

发表于http://sedodream.com/2010/03/19/ReplacingSolutionFilesWithMSBuildFiles.aspx

+0

由于博客上的可重复使用的目标这篇全面的入门!这会给我一个很好的起点。我认为我尝试的问题是我试图混合驱动构建和可重用的.targets的.proj。 – Filburt

+0

是否有任何“简单”的方法来强制所有包含的.proj文件中的元素?我的意思是,如果包含像这样的项目,您可能会包含未与自定义目标连接的项目。 OH和@filburt,你应该看看Sayed的书,这是值得的每一分钱! :) – JohannesH

+0

@JohannesH我会说有一个简单的方法,但它有点太多,打包成评论。也许签出[我的回答良好实践:如何重用.csproj和.sln文件来创建您的MSBuild脚本的CI?](http://stackoverflow.com/a/3071804/205233) - “项目”部分。基本上只包括你的全球进口在最外面的范围,并添加到这个集合。 – Filburt

相关问题