2012-12-06 144 views
9

我有一個VS2010解決方案文件,其中包含超過20個項目,並且一些項目對解決方案中的其他項目具有依賴性。MSBuild 4.5忽略項目依賴關係

我也有不同的目的設置了多個構建配置,但我已經減少了要構建的項目,只包含最少數量的項目。

例如,我有三個庫(A,B和C),一個網站項目和一個網站部署項目(VS2010)。該網站引用了庫A和B,而B又引用了C.我的構建配置僅檢查了網站和部署項目。按照預期,當我從解決方案的屬性中檢查項目依賴關係時,該網站正確列出了這些庫,而B顯示了C。

當我在VS2010中針對我的構建配置運行構建時,它工作得很好,但是當我在指定配置的解決方案上運行MSBuild時(如下所示),它只會導致一堆錯誤。

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

這裏是我得到的錯誤示例:

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

我發現我的構建服務器(TeamCity的V7.1.2)對這種情況的發生,但我可以重現它在多臺機器,並且我縮小了MSBuild本身的一個問題。

它只是在我安裝.NET 4.5(和2個安全補丁)之後纔開始發生的,所以我卸載了它,重新安裝了.NET 4.0(帶補丁),因爲它也被刪除了,然後嘗試了相同的命令,精細。

這使我相信在.NET 4.5中,MSBuild中的某些內容已經發生了變化或中斷,但是他們的文檔中沒有任何內容似乎討論了這種變化。

的MSBuild 4.5文檔:http://msdn.microsoft.com/en-us/library/hh162058.aspx

我甚至試過路過BuildProjectDependencies=true到的MSBuild,它出現,說明它跳過了其他項目,因爲他們沒有在配置管理器,這是正確的,故意的選擇。

我得到它與MSBuild 4.5一起工作的唯一方法是返回並選擇被跳過的項目,但由於實際的解決方案與依賴鏈有點複雜,我不想每次我們用新項目或依賴關係更新解決方案時,都要手動管理配置。它應該是自動的。

任何想法與我在做什麼?

回答

3

如果您還沒有解決這個問題,讓我們嘗試一些盲目出手:

  1. 的MSBuild已確認的錯誤時,有時會產生基於其次依賴錯誤的生成順序。嘗試構建不是完整的解決方案,而是要構建精確的項目 - 如msbuild.exe YourWebsiteProject.csproj /t:Clean;Build /p:configuration=MyConfig。問題仍然存在?

  2. 確保YourWebsiteProject和您的庫(B和C)具有適當的引用 - 在項目上,而不是在另一個項目文件夾中的DLL上(最簡單的方法來解決 - 從B引用移除並重新添加它,只要確保你正在添加項目引用,而不是瀏覽bin \ Debug就可以獲得C.dll)。問題仍然存在嗎?

如果你能提供詳細的,甚至診斷的MSBuild日誌(添加到您的MSBuild命令行下面的開關/ DS/V:診斷,然後份額的TeamCity全力打造地方日誌或管道命令行日誌文件)或一些示例項目設置了我可以重現此行爲的位置 - 它可以幫助解決問題。

+0

+1。 –

+0

當你說MSBuild有確認的錯誤時,你是什麼意思?有沒有在MSDN中的這個問題的鏈接,所以我可以跟蹤它,看看微軟是否有任何指導? –

+0

正是在這裏 http://connect.microsoft.com/VisualStudio/feedback/details/586875/msbuild-4-0-incorrectly-processes-project-dependencies-specified-in-solution-file 固定爲4.5 –

2

我遇到了完全相同的問題。我設法找到的兩個解決方案從長遠來看都是不可接受的,但他們確實克服了最初的問題,即讓我們的構建過程與新的4.5堆棧一起工作。

  1. 交換與文件引用的項目引用
  2. 創建複合構建配置

我選擇了#2,如文件引用意味着開發商將失去了實時智能感知等。

的化合物結構是簡單:

  • 發佈服務器 - >所有服務器項目
  • 發佈消費 - >「發佈服務器」 +客戶項目

這個問題似乎是,如果一個項目沒有包括在當前/活動的構建配置,它不會將其包含爲引用的依賴項。因此,通過在配置中添加依賴關係,項目至少可以編譯。

既醜陋,但至少它讓我走出一個狹窄的地方。

馬特

4

我想我會更新我以前的答案,因爲我已經花了很多時間和精力創造我自己的解決此問題的。解決問題的方法比簡單地解決問題要全面一些,但我試圖消除這個問題,並且避免像這樣的未來衝擊。

MSBuild已從解決方案,配置或其他方面降級。只要求MSBuild獨立編譯項目。這種情況發生的順序是通過Powershell腳本來計算的,該腳本解析我們的解決方案和項目以制定出最佳的即時生成執行計劃。

關鍵就在這(我想你可能會發現有用)如下片段:

識別我的解決方案

我在我的平臺上的所有解決方案的列表,我基本上是重複在每個這些。

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

我有一些邏輯,幫助轉化爲實際的物理路徑,這一點,但它很定製我們的需求,所以我不會在這裏列出來。足以說,從這個列表中,我可以找到需要解析的.sln文件。

解析爲項目

隨着每個解決方案解決方案文件,我看了.sln文件,並嘗試提取我以後需要建立包含內的所有項目。

所以,首先,找出所有的項目在我

$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 

然後翻譯成的,我以後可以遍歷項目一個不錯的榜單。

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

加載Visual Studio項目

從我的解決方案文件的解析,我現在的每解決方案項目,其中關鍵的是含有從解決方案根的相對文件路徑,找到名單項目。

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

1)確定外部項目引用

$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)確定內部項目引用

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

3)繼 「生成後」 事件作爲外部引用

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

     } 

而且,由於我們是在它,瞭解一些基本的輸出信息太

這是非常方便,當涉及到迭代我的項目,以建立清單,知道在哪裏推輸出,或在哪裏查找依賴項的輸出。

$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 

而在這一切

我們只需要確保我們沒有任何重複,所以我只記錄這個特殊的代碼項目的不同依賴結束:

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

我希望這可以爲您提供足夠的信息來解析您的SLN和PROJ文件。如何選擇捕獲和存儲這些信息我認爲完全取決於您。

我正在編寫一篇相當深入的博客文章,其中將包含我上面未提及的所有修剪和框架。這篇文章還沒有準備好,但我會從早期的文章鏈接到它:http://automagik.piximo.me/2013/02/just-in-time-compilation.html - 由於微軟的這一改變幾乎使這項工作脫軌!

乾杯。

3

在.NET 4.5,在C OnlyReferenceAndBuildProjectsEnabledInSolutionConfiguration屬性的默認值:\ WINDOWS \ Microsoft.NET \框架\ v4.0.30319 \ Microsoft.Common.targets從false改爲true。顧名思義,該屬性使MSBuild忽略對構建配置中排除的項目的引用。

(這有可能是微軟在響應做出這種改變的Connect bug I filed against MSBuild 4.0,即使我警告他們的變化打破了編譯。)

解決方法很簡單:在第一<PropertyGroup>的屬性設置回false您的每個項目的部分:

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

For某些原因導致我的Connect錯誤現在已經被破壞。 Bing仍然有一個[緩存版本](http://cc.bingj.com/cache.aspx?q=OnlyReferenceAndBuildProjectsEnabledInSolutionConfiguration&d=4756437099940543&mkt=en-US&setlang=en-US&w=gy6I4RMi2T9y-j5M_jzlnbwuu4wnvbzd)。 –

0

我明白這個問題有多種原因。我在這裏嘗試了大部分解決方案。我無法將我們的構建服務器更改爲使用PS腳本,因此解決方案無法使用。沒有什麼我可以嘗試工作。

最後,我刪除了我的解決方案並開始了一個新的解決方案。新解決方案奏效。在用工作溶液分解破碎的溶液後,我發現原來的解決方案是缺少線。不能編譯的每個依賴關係都缺少這一行:

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

注1:GUID將從依賴關係更改爲依賴關係。注意2:您可以在解決方案文件的「GlobalSection(ProjectConfigurationPlatforms)= postSolution」部分下找到類似此行的行。

我的build.proj文件說使用「任何CPU」平臺構建「Release」。因爲MSBuild無法找到這條線,所以沒有建立這個依賴關係。這會導致「錯誤CS0246:無法找到類型或名稱空間」消息。

如果您好奇,有人已將此解決方案設置爲「x86」平臺(這對我們來說是錯誤的)。我將其更改爲「任何CPU」(以及其他一些更改)。 Visual Studio沒有將相應的行添加到解決方案文件中。在IDE中一切都很好,但MSBuild開始拋出錯誤。

0

我發現MSBuild正在從解決方案中建立項目,以便在.sln文件中聲明它們。所以如果你使用文本編輯器對它們進行重新排序,你可以修復MSBuild的順序。第二個原因爲