2012-12-06 31 views
9

Tôi có tệp giải pháp VS2010 với hơn 20 dự án trong đó và một số dự án có phụ thuộc vào các dự án khác từ bên trong giải pháp.MSBuild 4.5 bỏ qua phụ thuộc của dự án

Tôi cũng có nhiều cấu hình xây dựng được thiết lập cho các mục đích khác nhau, nhưng tôi đã cắt bớt các dự án được xây dựng để chỉ bao gồm số lượng dự án tối thiểu.

Ví dụ: tôi có ba thư viện (A, B và C), một dự án trang web và một dự án triển khai trang web (VS2010). Trang web có tham chiếu đến các thư viện A và B, và B lần lượt có tham chiếu đến C. Cấu hình xây dựng của tôi chỉ có trang web và dự án triển khai đã được kiểm tra. Khi tôi kiểm tra các phụ thuộc của dự án từ các thuộc tính của giải pháp, trang web liệt kê chính xác các thư viện và B hiển thị C, như mong đợi.

Khi tôi chạy xây dựng dựa trên cấu hình xây dựng của tôi từ bên trong VS2010, nó hoạt động hoàn toàn tốt, nhưng khi tôi chạy MSBuild trên giải pháp xác định cấu hình của tôi (như sau), nó chỉ dẫn đến một loạt các lỗi.

msbuild.exe mysolution.sln /t:Build /p:configuration=MyConfig

Dưới đây là một ví dụ về các lỗi tôi nhận được:

Services\IService.cs(11,63): error CS0246: The type or namespace name 'Priority' could not be found (are you missing a using directive or an assembly reference?)

Tôi nhận thấy điều này xảy ra vào xây dựng máy chủ của tôi (TeamCity v7.1.2), nhưng tôi có thể tái tạo nó trên nhiều máy tính và tôi đã thu hẹp nó xuống một vấn đề với MSBuild.

Nó chỉ bắt đầu xảy ra sau khi tôi cài đặt .NET 4.5 (và 2 bản vá bảo mật), vì vậy tôi đã gỡ cài đặt nó, cài đặt lại .NET 4.0 (với các bản vá) vì nó cũng bị loại bỏ. khỏe.

Điều này dẫn tôi tin rằng một cái gì đó đã được thay đổi hoặc bị hỏng trong MSBuild với .NET 4.5, nhưng không có gì trong tài liệu của họ dường như nói về loại thay đổi này.

MSBuild 4,5 tài liệu: http://msdn.microsoft.com/en-us/library/hh162058.aspx

Tôi thậm chí đã cố gắng đi qua BuildProjectDependencies=true để MSBuild, và nó đi lên nói rằng nó đã bỏ qua các dự án khác bởi vì họ đã không được chọn trong bộ quản lý cấu hình, đó là chính xác và có chủ ý.

Cách duy nhất để làm việc với MSBuild 4.5 là quay lại và chọn các dự án bị bỏ qua, nhưng vì giải pháp thực tế phức tạp hơn một chút với chuỗi phụ thuộc, tôi không muốn có để cố gắng quản lý các cấu hình theo cách thủ công mỗi lần chúng tôi cập nhật giải pháp với các dự án hoặc phụ thuộc mới. Nó NÊN được tự động.

Bất kỳ ý tưởng nào về những gì tôi đang làm?

Trả lời

3

Nếu bạn vẫn không được giải quyết vấn đề này, cho phép thử một số bức ảnh mù:

  1. Msbuild đã xác nhận lỗi khi nó đôi khi tạo ra sai trật tự xây dựng dựa trên sự phụ thuộc theo sau. Cố gắng xây dựng không phải toàn bộ giải pháp mà là dự án chính xác bạn muốn xây dựng - như msbuild.exe YourWebsiteProject.csproj /t:Clean;Build /p:configuration=MyConfig. Vấn đề vẫn còn tồn tại?

  2. Đảm bảo rằng YourWebsiteProject và libs của bạn (B và C) có tham chiếu chính xác - trên dự án, chứ không phải trên dll trong thư mục dự án khác (cách đơn giản nhất để khắc phục điều đó - xóa khỏi tham chiếu B sang C và thêm lại nó, chỉ cần đảm bảo rằng bạn đang thêm tham chiếu dự án và không duyệt đến bin \ Debug cho rất C.dll). Vấn đề vẫn còn đó?

Nếu bạn có thể cung cấp đăng nhập msbuild chi tiết hoặc thậm chí chẩn đoán (thêm vào dòng lệnh msbuild của bạn sau switch/ds/v: diag và sau đó chia sẻ TeamCity đầy đủ build log ở đâu đó hoặc ống dòng lệnh log vào tập tin) hoặc một số các dự án mẫu thiết lập nơi tôi có thể tái tạo hành vi này - nó có thể giúp giải quyết rất nhiều vấn đề.

+0

+1 vì lý do thứ hai. –

+0

Bạn có ý gì khi nói MSBuild có lỗi xác nhận? Có một liên kết đến vấn đề này trong MSDN vì vậy tôi có thể theo dõi nó và xem nếu Microsoft có bất kỳ hướng dẫn? –

+0

Nó đã ở đây http://connect.microsoft.com/VisualStudio/feedback/details/586875/msbuild-4-0-incorrectly-processes-project-dependencies-specified-in-solution-file cố định trong 4.5 –

2

Tôi đã gặp sự cố tương tự. Hai công việc xung quanh tôi đã tìm được cả hai đều không thể chấp nhận được trong thời gian dài, nhưng họ đã khắc phục vấn đề ban đầu về việc xây dựng các quy trình xây dựng cũ của chúng tôi làm việc với ngăn xếp mới 4.5.

  1. Trao đổi các tài liệu tham khảo dự án với sự tham khảo tập tin
  2. Tạo hợp chất xây dựng cấu hình

tôi đã chọn cho # 2, như tài liệu tham khảo tập tin có nghĩa là các nhà phát triển sẽ mất đi theo thời gian thực IntelliSense, vv

Các cấu hình hợp chất đơn giản này:

  • phát hành Server -> Tất cả các máy chủ dự án
  • phát hành Consumer -> "Release Server" + Khách hàng dự án

Vấn đề có vẻ là, rằng nếu một dự án không được bao gồm trong hiện tại/hoạt động xây dựng cấu hình, rằng nó sẽ không bao gồm nó như là một phụ thuộc tham chiếu. Vì vậy, bằng cách thêm các phụ thuộc vào cấu hình, các dự án sẽ biên dịch ít nhất.

Cả hai đều xấu xí, nhưng ít nhất nó giúp tôi thoát khỏi một chỗ chật hẹp.

Matt

4

tôi nghĩ rằng tôi muốn cập nhật câu trả lời trước đây của tôi, như tôi đã dành rất nhiều thời gian và công sức tạo ra cách giải quyết của riêng tôi cho vấn đề này. Các công việc xung quanh là một chút toàn diện hơn chỉ đơn giản là sống với vấn đề, nhưng tôi đã cố gắng để loại bỏ cả hai vấn đề và cách nhiệt chính mình chống lại những cú sốc trong tương lai như thế này.

MSBuild đã bị giảm hạng khi làm việc với các giải pháp, cấu hình hoặc cách khác. MSBuild chỉ được yêu cầu biên dịch các dự án một cách riêng biệt. Thứ tự này xảy ra được tính toán bởi một kịch bản Powershell phân tích các giải pháp và dự án của chúng tôi để xây dựng kế hoạch thực hiện xây dựng Just-In-Time tốt nhất.

chính này (và tôi nghĩ rằng bạn có thể tìm thấy hữu ích) đều được các đoạn sau:

Xác định các giải pháp của tôi

tôi có một danh sách của tất cả các giải pháp trong nền tảng của tôi, và tôi về cơ bản lặp trên mỗi cái này.

$buildPlan = (
@{ 
    solutions = (
     @{ 
      name  = "DataStorage" 
      namespace = "Platform.Databases" 
     }, 
     @{ 
      name  = "CoreFramework" 
     }, 
     @{ 
      namespace = "Platform.Server" 
      name  = "Application1" 
     }, 
     @{ 
      namespace = "Platform.Server" 
      name  = "Application2" 
     }, 
     @{ 
      namespace = "Platform.Client" 
      name  = "Application1" 
     } 
    ) 
}) 

Tôi có một số logic giúp dịch thành con đường vật lý thực tế, nhưng nó rất riêng biệt với nhu cầu của chúng tôi, vì vậy tôi sẽ không liệt kê ở đây. Có thể nói, từ danh sách này, tôi có thể tìm thấy tệp .sln mà tôi cần phân tích cú pháp.

Phân tích các tập tin giải pháp cho các dự án

Với mỗi giải pháp, tôi đọc file sln và cố gắng trích xuất tất cả các dự án chứa bên trong mà tôi sẽ cần phải xây dựng sau này.

Vì vậy, trước hết, xác định tất cả các dự án trong tôi

$solutionContent = Get-Content $solutionFile 

$buildConfigurations += Get-Content $solutionFile | Select-String "{([a-fA-F0-9]{8}-([a-fA-F0-9]{4}-){3}[a-fA-F0-9]{12})}\.(Release.*)\|Any CPU\.Build" | % { 
     New-Object PSObject -Property @{ 
      Name = $_.matches[0].groups[3].value.replace("Release ",""); 
      Guid = $_.matches[0].groups[1].value 
      } 

    } | Sort-Object Name,Guid -unique 

Và sau đó dịch này vào một danh sách tốt đẹp của dự án mà tôi có thể lặp qua sau đó.

$projectDefinitions = $solutionContent | 
     Select-String 'Project\(' | 
     ForEach-Object { 
      $projectParts = $_ -Split '[,=]' | ForEach-Object { $_.Trim('[ "{}]') }; 
      $configs = ($buildConfigurations | where {$_.Guid -eq $projectParts[3]} | Select-Object Name) 

      foreach ($config in $configs) 
      { 
       $santisiedConfig = if ([string]::IsNullOrEmpty($config.Name)){"Release"}else{$config.Name} 
       if ($projectParts[1] -match "OurCompanyPrefix.") 
       { 
        New-Object PSObject -Property @{ 
        Name = $projectParts[1]; 
        File = $projectParts[2]; 
        Guid = $projectParts[3]; 
        Config = $santisiedConfig 
        } 
       } 
      } 
    } 

tải Visual Studio dự án

Từ phân tích của tôi về tập tin giải pháp, bây giờ tôi có một danh sách các dự án mỗi giải pháp, trong đó điều quan trọng chứa các File Path tương đối từ gốc giải pháp để tìm ra dự án.

$projectDefinition = [xml](Get-Content $csProjectFileName) 
$ns = @{ e = "http://schemas.microsoft.com/developer/msbuild/2003" } 
$references = @(); 

1) Xác định các dự án bên ngoài tham chiếu

$references += Select-Xml -Xml $projectDefinition -XPath "//e:Project/e:ItemGroup/e:Reference" -Namespace $ns | % {$_.Node} | where {$_.Include -match "OurCompanyPrefix" -and $_.HintPath -notmatch "packages"} | % {$_.Include} 

2) Xác định các dự án nội bộ tham chiếu

$references += Select-Xml -Xml $projectDefinition -XPath "//e:Project/e:ItemGroup/e:ProjectReference" -Namespace $ns | % { $_.Node.Name } 

3) Sau "Post-xây dựng" các sự kiện như tài liệu tham khảo bên ngoài

$references += Select-Xml -Xml $projectDefinition -XPath "//e:Project/e:PropertyGroup/e:PostBuildEvent" -Namespace $ns | where {(!([String]::IsNullOrEmpty($_.Node.InnerText)))} | % { 

      $postBuildEvents = $_.Node.InnerText.Split("`n") 
      $projectsReferencedInPostBuildEvents = $postBuildEvents | Select-String "\(SolutionDir\)((\w|\.)*)" | % {$_.Matches[0].Groups[1].Value} 
      if ($projectsReferencedInPostBuildEvents -ne $null) 
      { 
       Write-Output $projectsReferencedInPostBuildEvents | % { $matchedProject = $_; ($releaseConfiguation | ? {$_.File -match $matchedProject}).Name } 
      } 

     } 

Và, vì chúng ta đang ở đó, nhận được một số thông tin cơ bản đầu ra quá

Đây là tiện dụng khi nói đến lặp lại danh sách các dự án xây dựng, như bí quyết nơi để đẩy sản lượng hoặc nơi để tìm đầu ra của người phụ thuộc.

$assemblyName = (Select-Xml -Xml $projectDefinition -XPath "//e:Project/e:PropertyGroup/e:AssemblyName" -Namespace $ns).Node.InnerText 
$outputPath = (Select-Xml -Xml $projectDefinition -XPath "//e:Project/e:PropertyGroup[contains(@Condition,'Release|')]/e:OutputPath" -Namespace $ns).Node.InnerText 

Và ở phần cuối của nó tất cả

Chúng ta chỉ cần chắc chắn rằng chúng tôi không có bất kỳ bản sao, vì vậy tôi ghi lại chỉ là phụ thuộc khác biệt của dự án mã đặc biệt này:

$dependendents = @(); 
if ($references -ne $null) 
{ 
    $buildAction.project.dependencies += $references | where {(!([string]::IsNullOrEmpty($_))) -and ($_ -match "OurCompanyPrefix\.(.*)")} | % { $_.ToLower()} | Select -unique 
}  

Tôi hy vọng điều này sẽ cung cấp cho bạn đủ thông tin để phân tích cú pháp tệp SLN và PROJ của bạn. Làm thế nào bạn sẽ chọn để nắm bắt và lưu trữ thông tin này tôi nghĩ rằng sẽ phụ thuộc hoàn toàn vào bạn.

Tôi đang ở giữa viết một bài đăng blog chuyên sâu về điều này, trong đó sẽ chứa tất cả các trang trí và khung mà tôi đã bỏ qua ở trên.Bài đăng chưa sẵn sàng, nhưng tôi sẽ liên kết đến bài đăng đó từ bài đăng trước đó: http://automagik.piximo.me/2013/02/just-in-time-compilation.html - Vì sự thay đổi này của Microsoft gần như làm trật bánh công việc này!

Chúc mừng.

3

Trong .NET 4.5, giá trị mặc định của thuộc tính OnlyReferenceAndBuildProjectsEnabledInSolutionConfiguration trong C: \ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ Microsoft.Common.targets đã được thay đổi từ false thành true. Như tên gọi của nó, thuộc tính này làm cho MSBuild bỏ qua các tham chiếu đến các dự án bị loại trừ khỏi cấu hình xây dựng.

(Có thể là Microsoft đã thực hiện thay đổi này để đáp ứng với một Connect bug I filed against MSBuild 4.0, mặc dù tôi đã cảnh báo họ rằng sự thay đổi phá vỡ xây dựng.)

Cách giải quyết rất đơn giản: Thiết lập thuộc tính phía sau để false trong lần đầu tiên <PropertyGroup> của mỗi dự án của bạn:

<PropertyGroup> 
    ... 
    <OnlyReferenceAndBuildProjectsEnabledInSolutionConfiguration>false</OnlyReferenceAndBuildProjectsEnabledInSolutionConfiguration> 
</PropertyGroup> 
+0

Cho một số lý do liên kết đến lỗi Kết nối của tôi bị hỏng ngay bây giờ. Bing vẫn có [phiên bản được lưu trong bộ nhớ cache] (http://cc.bingj.com/cache.aspx?q=OnlyReferenceAndBuildProjectsEnabledInSolutionConfiguration&d=4756437099940543&mkt=en-US&setlang=en-US&w=gy6I4RMi2T9y-j5M_jzlnbwuu4wnvbzd). –

0

Tôi hiểu được vấn đề này có nhiều nguyên nhân. Tôi đã thử hầu hết các giải pháp ở đây. Tôi không thể thay đổi máy chủ xây dựng của chúng tôi để sử dụng tập lệnh PS để giải pháp đã hết. Không có gì tôi có thể thử làm việc.

Cuối cùng, tôi đã xóa giải pháp của mình và bắt đầu giải pháp mới. Các giải pháp mới làm việc. Sau khi phân biệt giải pháp bị hỏng với dung dịch làm việc, tôi thấy giải pháp ban đầu là thiếu các dòng. Mỗi phụ thuộc không biên dịch bị thiếu dòng này:

{A93FB559-F0DB-4F4D-9569-E676F59D6168}.Release|Any CPU.Build.0 = Release|Any CPU 

Lưu ý 1: GUID sẽ thay đổi từ phụ thuộc vào phụ thuộc.

Lưu ý 2: Bạn có thể tìm các dòng như thế này trong phần "GlobalSection (ProjectConfigurationPlatforms) = postSolution" của tệp giải pháp.

Tệp build.proj của tôi cho biết xây dựng "Bản phát hành" bằng nền tảng "Bất kỳ CPU" nào. Bởi vì MSBuild không thể tìm thấy dòng này nên nó không xây dựng sự phụ thuộc này. Điều này dẫn đến lỗi "CS0246: Không thể tìm thấy loại hoặc không gian tên".

Nếu bạn tò mò, ai đó đã đặt giải pháp này cho nền tảng "x86" (điều này là sai đối với chúng tôi). Tôi đã thay đổi nó thành "CPU bất kỳ" (cùng với một số thay đổi khác). Visual Studio không thêm các dòng tương ứng vào tệp giải pháp. Tất cả mọi thứ được xây dựng tốt trong IDE, nhưng MSBuild bắt đầu ném lỗi.

0

Tôi thấy rằng MSBuild đang xây dựng các dự án từ một giải pháp theo thứ tự mà chúng được khai báo trong tệp .sln. Vì vậy, nếu bạn sắp xếp lại chúng với trình soạn thảo văn bản, bạn có thể sửa thứ tự cho MSBuild.

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