2010-03-18 33 views
11

Tôi muốn tạo một dự án MSBuild phản ánh các phụ thuộc dự án trong một giải pháp và kết thúc các dự án VS bên trong các mục tiêu tái sử dụng.Thay thế .sln bằng MSBuild và bọc các dự án thành các mục tiêu

Vấn đề tôi muốn giải quyết là thực hiện svn-export, xây dựng và triển khai một assembly cụ thể (và các phụ thuộc của nó) trong một ứng dụng BizTalk.

Câu hỏi của tôi là: Làm cách nào để có thể thực hiện mục tiêu xuất, xây dựng và triển khai tái sử dụng và cũng sử dụng lại các dự án được bao bọc khi chúng được xây dựng cho các phụ thuộc khác nhau?

Tôi biết sẽ đơn giản hơn khi chỉ xây dựng giải pháp và triển khai chỉ các hội đồng cần thiết nhưng tôi muốn sử dụng lại các mục tiêu càng nhiều càng tốt.

Các bộ phận

Dự án tôi muốn triển khai

<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> 

Các dự án nó phụ thuộc vào cái nhìn gần như chính xác như thế này (.btproj khác và csproj).

Trả lời

16

Ồ, đây là câu hỏi được tải cho bài đăng trên diễn đàn. Tôi đã viết khoảng 20 trang về cách tạo các tệp .targets có thể tái sử dụng trong số book của tôi, nhưng tôi sẽ giúp bạn bắt đầu ở đây với các khái niệm cơ bản tại đây. Tôi tin rằng chìa khóa để tạo tái sử dụng xây dựng các kịch bản (tức là .targets files) là ba yếu tố:

  • hành vi Place (tức là nhắm) thành các file riêng biệt
  • dữ liệu Place (tức là tài sản và các mặt hàng, các được gọi là .proj file) vào các tập tin riêng của họ
  • Khả năng mở rộng
  • .targets file nên xác nhận giả định

Ý tưởng là bạn muốn đặt tất cả các mục tiêu của mình vào các tệp riêng biệt và sau đó các tệp này sẽ được nhập bằng các tệp sẽ thúc đẩy quá trình xây dựng. Đây là những tập tin chứa dữ liệu. Vì bạn nhập các tệp .targets bạn nhận được tất cả các mục tiêu như thể chúng đã được định nghĩa nội tuyến. Sẽ có một hợp đồng im lặng giữa các tệp .proj và .targets. Hợp đồng này được xác định trong các thuộc tính và vật phẩm mà cả hai đều sử dụng. Đây là những gì cần phải được xác nhận.

Ý tưởng ở đây không phải là mới. Mẫu này được theo sau bởi .csproj (và các dự án khác được tạo ra bởi Visual Studio). Nếu bạn xem tệp .csproj của bạn, bạn sẽ không tìm thấy một mục tiêu duy nhất, chỉ là các thuộc tính và các mục. Sau đó, về phía dưới cùng của tập tin nó nhập khẩu Microsoft.csharp.targets (có thể khác nhau tùy thuộc vào loại dự án). Tệp dự án này (cùng với các tệp khác mà nó nhập) chứa tất cả các mục tiêu thực sự thực hiện việc xây dựng.

Vì vậy, nó được đặt ra như thế này:

  • SharedBuild.targets
  • MyProduct.Proj

đâu MyProdcut.proj có thể trông giống như:

<?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 có thể trông giống như:

<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> 

Đừng nhìn quá nhiều vào SharedBuild_Validate mục tiêu được nêu ra. Tôi đặt nó ở đó cho đầy đủ nhưng không tập trung vào nó. Bạn có thể tìm thêm thông tin về điều đó tại blog của tôi tại http://sedodream.com/2009/06/30/ElementsOfReusableMSBuildScriptsValidation.aspx.

Các phần quan trọng cần chú ý là các điểm mở rộng. Mặc dù đây là một tệp rất cơ bản, nó có tất cả các thành phần của tệp .target có thể tái sử dụng. Bạn có thể tùy chỉnh hành vi của nó bằng cách chuyển các thuộc tính và mục khác nhau để xây dựng. Bạn có thể mở rộng đó là hành vi bằng cách ghi đè một mục tiêu (BeforeBuild, AfterBuild hoặc thậm chí CoreBuild) và bạn có thể tiêm các mục tiêu của riêng bạn vào xây dựng với:

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

Trong trường hợp của bạn tôi sẽ tạo ra một file SvnExport.targets trong đó sử dụng tính chất yêu cầu:

  • SvnExportRoot
  • SvnUrl
  • SvnWorkingDirectory Bạn sẽ sử dụng các đặc tính này để làm xuất khẩu.

Sau đó tạo một số khác để Biztalk xây dựng và triển khai. Bạn có thể chia nó thành 2 nếu cần.

Sau đó, bên trong tệp .proj của bạn, bạn chỉ cần nhập cả hai và thiết lập các mục tiêu để xây dựng theo đúng thứ tự và tắt của bạn.

Điều này chỉ thực sự là khởi đầu của việc tạo ra các yếu tố xây dựng tái sử dụng, nhưng điều này sẽ giúp các bánh xe quay trong đầu bạn. Tôi sẽ đăng tất cả điều này lên số blog cũng như các liên kết tải xuống cho tất cả các tệp.

UPDATE:

đăng lên blog tại http://sedodream.com/2010/03/19/ReplacingSolutionFilesWithMSBuildFiles.aspx

+0

Cám ơn hướng dẫn hoàn chỉnh này trên mục tiêu tái sử dụng! Điều này sẽ cho tôi một điểm khởi đầu tốt. Tôi nghĩ rằng vấn đề với nỗ lực của tôi là tôi đã cố gắng để trộn .proj lái xe xây dựng và các mục tiêu tái sử dụng. – Filburt

+0

Có cách nào "dễ dàng" để buộc phần tử trong tất cả các tệp .proj được bao gồm không? Ý tôi là, nếu bạn bao gồm các dự án như bạn có thể bao gồm các dự án không được kết nối với các mục tiêu tùy chỉnh. OH và @filburt, bạn nên xem cuốn sách của Sayed, nó đáng giá từng xu! :) – JohannesH

+0

@ JohannesH Tôi muốn nói rằng có một cách dễ dàng nhưng hơi quá nhiều để đóng góp vào một nhận xét. Có thể kiểm tra [câu trả lời của tôi về Thực hành tốt: Cách sử dụng lại các tệp .csproj và .sln để tạo tập lệnh MSBuild cho CI?] (Http://stackoverflow.com/a/3071804/205233) - "Các dự án" phần. Về cơ bản chỉ bao gồm nhập toàn cầu của bạn ở phạm vi ngoài cùng và thêm vào bộ sưu tập này. – Filburt

Các vấn đề liên quan