Pokud máme aplikaci ve VS 2015, ve které používáme nové možnosti jazyka C# 6.0, tak potřebujeme projekt kompilovat novým Roslyn kompilátorem. Na vývojovém počítači to problém není, ale na build serveru to problém být může. V mém případě provozujeme na build serveru TFS 2013 Update 5 (protože TFS 2015 je zatím pouze RC 2, tak jsme ho ještě neinstalovali).
Jak tedy přinutit, aby TFS 2013 build server používal nový kompilátor, přesněji řečeno, aby Build Agent spustil kompilaci pomoci MSBuild v 14.0?
Instalace .targets souborů
Na build server musíme nainstalovat plné Visual Studio 2015 a to například i s komponentou Web Developer Tools, pokud buildujeme webovou aplikaci. Tím se nám teprve na build server nahrají potřebné .targets soubory, umístěné v cestě:
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0
(Instalací samotného mu_microsoft_build_tools_2015_x86_x64_6846132.exe se tam nedostanou.)
Nastavení MSBuild
Musíme přepnou MSBuild na verzi 14.0, aby se použil kompilátor C# 6.0 tj.:
C:\Program Files (x86)\MSBuild\14.0\bin\csc.exe
Na internetu nejspíše jako já najdete, že je nutné v Build definici v záložce Process nastavit ve vlastnosti MSBuild Arguments parametry "/tv:14.0 /p:VisualStudioVersion=14.0"
Můžete to zkusit. Tím se sice kompilace již bude provádět pomoci nového MSBuild, ale v mém případě tudy cesta nevedla, protože se mi objevila následující chyba:
error MSB4025: The project file could not be loaded. Could not find file 'C:\Builds\...Project.csproj.metaproj'.
O co se jedná? Já mám totiž v build definici jako zdroj kompilace Solution (.sln). V případě pouze projekt souboru (.csproj) by to asi prošlo.
V případě solution si ale MSBuild právě vytváří soubory .csproj.metaproj na udržování pořadí kompilace projektů,
no a z nějakého důvodu je při tomto spuštění přes build agenta tvoří pouze do paměti, a pak je na disku v uvedené cestě nenajde.
Zajímavé bylo, že když jsem na build serveru spustil MSBuild ručně z command line, tak se.csproj.metaproj na disk vytvořili a build prošel.
Řešení pro kompilaci Solution
Na parametry MSBuild Arguments v definici tedy zapomeňte. Skoro náhodou jsem ale objevil následující řešení.
Změníme MSBuild šablonu, kterou naše build definice používá (já již používal svojí vlastní upravenou).
Tato šablona představuje Workflow diagram (.xaml) celého build procesu. A jedna aktivita, která zde je, je právě volání MSBuild. Protože aktivit je tam opravdu hodně, je jednodušší soubor editovat přímo v textu než v designeru.
Najděte aktivitu mtbwa:MSBuild například:
<mtbwa:MSBuild CommandLineArguments="[String.Format("/p:SkipInvalidConfigurations=true {0}", MSBuildArguments)]" Configuration="[platformConfiguration.Configuration]" DisplayName="Run MSBuild for Project" GenerateVSPropsFile="[True]" MaxProcesses="[If (MSBuildMultiProc, 0, 1)]" OutDir="[BinariesDirectory]" Platform="[platformConfiguration.Platform]" Project="[localBuildProjectItem]" Targets="[New String() { "Clean" }]" TargetsNotLogged="[New String() {"GetNativeManifest", "GetCopyToOutputDirectoryItems", "GetTargetPath"}]" ToolPlatform="[MSBuildPlatform]" Verbosity="[Verbosity]" />
a přidejte nastavení vlastnosti ToolVersion="14.0":
<mtbwa:MSBuild CommandLineArguments="[String.Format("/p:SkipInvalidConfigurations=true {0}", MSBuildArguments)]" Configuration="[platformConfiguration.Configuration]" DisplayName="Run MSBuild for Project" GenerateVSPropsFile="[True]" MaxProcesses="[If (MSBuildMultiProc, 0, 1)]" OutDir="[BinariesDirectory]" Platform="[platformConfiguration.Platform]" Project="[localBuildProjectItem]" Targets="[New String() { "Clean" }]" TargetsNotLogged="[New String() {"GetNativeManifest", "GetCopyToOutputDirectoryItems", "GetTargetPath"}]" ToolPlatform="[MSBuildPlatform]" ToolVersion="14.0" Verbosity="[Verbosity]" />
Já tuto aktivitu v souboru měl 2x, přidání tedy proveďte na všech místech.
Pozor, jedná se o string hodnotu, hodnota musí být celé "14.0", nestačí "14" (jak se nejprve povedlo mě).
Šablonu uložte a proveďte checkin do TFS.
Nyní při spuštění build definice s touto šablonou již kompilace projde v pořádku.