用MSBuild替换.sln并将包含的项目包装到目标中

用MSBuild替换.sln并将包含的项目包装到目标中,msbuild,biztalk,Msbuild,Biztalk,我想创建一个MSBuild项目,该项目反映解决方案中的项目依赖关系,并将VS项目包装在可重用目标中 我喜欢解决的问题是svn在BizTalk应用程序中导出、构建和部署特定程序集(及其依赖项) 我的问题是:如何使svn导出、构建和部署的目标可重用,以及在为不同依赖项构建包装的项目时如何重用这些项目 我知道构建解决方案并只部署所需的程序集会更简单,但我希望尽可能多地重用目标 零件 我喜欢部署的项目 出口 它所依赖的项目看起来几乎与此一模一样(other.btproj和.csproj)。哇,这是一

我想创建一个MSBuild项目,该项目反映解决方案中的项目依赖关系,并将VS项目包装在可重用目标中

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

我的问题是:如何使svn导出、构建和部署的目标可重用,以及在为不同依赖项构建包装的项目时如何重用这些项目

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

零件

我喜欢部署的项目


出口

它所依赖的项目看起来几乎与此一模一样(other.btproj和.csproj)。

哇,这是一个论坛帖子的问题。我写了大约20页关于在我的中创建可重用的.targets文件的内容,但我将从这里的基础知识开始。我认为创建可重用构建脚本(即目标文件)的关键是三个要素:

  • 将行为(即目标)放在单独的文件中
  • 将数据(即属性和项目,称为.proj文件)放入它们自己的文件中
  • 扩展性
  • .targets文件应验证假设
其思想是,您希望将所有目标放在单独的文件中,然后这些文件将由驱动构建过程的文件导入。这些是包含数据的文件。自从导入.targets文件以来,您获得了所有目标,就好像它们是内联定义的一样。.proj和.targets文件之间将有一个静默契约。本合同在双方使用的财产和物品中定义。这是需要验证的

这里的想法并不新鲜。遵循此模式的是.csproj(以及VisualStudio生成的其他项目)。如果查看.csproj文件,您将不会找到单个目标,只会找到属性和项目。然后在文件底部导入Microsoft.csharp.targets(可能因项目类型而异)。此项目文件(及其导入的其他文件)包含实际执行生成的所有目标

所以它的布局是这样的:

  • SharedBuild.targets
  • MyProduct.proj
其中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>
<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>
在您的情况下,我将创建一个SvnExport.targets文件,该文件使用所需的属性:

  • SvnExportRoot
  • 斯文努尔
  • SVN工作目录 您将使用这些属性进行导出
然后为Biztalk构建和部署创建另一个。如有必要,您可以将其拆分为2

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

这仅仅是创建可重用构建元素的真正开始,但这应该会让你的大脑转动起来。我将把所有这些都发布到我的网站上,并下载所有文件的链接

更新:


发布到博客

感谢您提供关于可重用目标的全面入门!这将给我一个很好的起点。我认为我尝试的问题是,我试图混合使用驱动构建的.proj和可重用的.targets。有没有“简单”的方法来强制所有包含的.proj文件中的元素?我的意思是,若你们包括像这样的项目,你们可能会包括并没有和自定义目标连接的项目。哦,还有@filburt,你应该看看Sayed的书,它值每一分钱@约翰内斯我想说有一个简单的方法,但它有点太多的包装成一个评论。也许可以看看“项目”部分。基本上只需将全局导入包含在最外层的范围内并添加到此集合。@JohannesH。。。是的,岩石说!从我上面链接的答案中,你们会看到我拼凑了一个很好的解决方案,它推动了我的BizTalk构建部署过程。谢谢各位,我很高兴我的书对你们有所帮助。
<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>
<Project ...>
   ...
  <Import Project="SharedBuild.targets"/>
  <PropertyGroup>
    <BuildDependsOn>
      $(BuildDependsOn);
      CustomAfterBuild
    </BuildDependsOn>
  </PropertyGroup>
  <Target Name="CustomAfterBuild">
    <!-- Insert stuff here -->
  </Target>
</Project>