Záznam ze Vzdělávacího okénka HAVIT z 1. března 2018. Je publikován na našem HAVIT YouTube Channelu. Téma prezentoval Jiří Kanda.
Dotčená témata:
- MSBuild
- csproj
- MSBuild command line
- build tools
- parametrizace
- nástroje
- TFS Build
- Publish
Záznam ze Vzdělávacího okénka HAVIT z 1. března 2018. Je publikován na našem HAVIT YouTube Channelu. Téma prezentoval Jiří Kanda.
Dotčená témata:
Pokud máte stejně jako já rádi čisté okno Error List ve Visual Studiu, pak vás může otravovat warrning typu
There was a mismatch between the processor architecture of the project being built „MSIL“ and the processor architecture of the reference „XYZ, Version=XXX, Culture=neutral, processorArchitecture=x86“, „XXX“. This mismatch may cause runtime failures. Please consider changing the targeted processor architecture of your project through the Configuration Manager so as to align the processor architectures between your project and references, or take a dependency on references with a processor architecture that matches the targeted processor architecture of your project.
Nechci teď rozebírat, jak vyřešit příčinu hlášky, ale mám návod, jak se vypořádat se situací, kdy se příčiny zbavit nechcete/nemůžete, ale potřebujete hlášku potlačit (suppress).
Do .csproj
souboru příslušného projektu stačí do úvodní sekce PropertyGroup
přidat:
<PropertyGroup> <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch> </PropertyGroup>
Jenom pozor, že tím můžete zakrýt i další varování, která se objeví později a mohou vás zajímat.
Máte-li samostatný build-server na x64 platformě, na něm nainstalované Code Contracts a pouštíte 64-bitový MSBuild, potom rychle zjistíte, že takový build ignoruje Code Contracts.
Problém je v tom, že do msbuildu se nanaimportují targets pro Code Contracts (C:\Program Files (x86)\Microsoft\Contracts\MsBuild\v3.5\Microsoft.CodeContracts.targets), protože Code Contracts se nainstalují do „Program Files (x86)“ složky, kdežto 64-bitový MSBuild si nastaví property MSBuildExtensionsPath na „Program Files“ a tam Code Contracts nainstalované nejsou.
Microsoft.CodeContracts.targets se dostávají do MSBuildu přes Custom.After.Microsoft.Common.targets, které se linkují z Microsoft.Common.targets – tam je však cesta k nim sestavena přes property MSBuildExtensionsPath a ta má pro 64-bitový MSBuild hodnotu „C:\Program Files\MSBuild\“ a ne „C:\Program Files (x86)\MSBuild\“.
Problém se dá vyřešit buď používáním 32-bitového MSBuildu, nebo násilným přepsáním hodnoty MSBuildExtensionsPath na „C:\Program Files (x86)\MSBuild\“ v souboru c:\Windows\Microsoft.NET\Framework64\v3.5\Microsoft.CodeContracts.targets takto:
<PropertyGroup> <!-- HAVIT: Workaround oprava ConnectID 109232 --> <MSBuildExtensionsPath>C:\Program Files (x86)\MSBuild\</MSBuildExtensionsPath> <!-- HAVIT: end --> <CustomBeforeMicrosoftCommonTargets Condition="'$(CustomBeforeMicrosoftCommonTargets)'==''">$(MSBuildExtensionsPath)\v3.5\Custom.Before.Microsoft.Common.targets</CustomBeforeMicrosoftCommonTargets> <CustomAfterMicrosoftCommonTargets Condition="'$(CustomAfterMicrosoftCommonTargets)'==''">$(MSBuildExtensionsPath)\v3.5\Custom.After.Microsoft.Common.targets</CustomAfterMicrosoftCommonTargets> <ReportingServicesTargets Condition="'$(ReportingServicesTargets)'==''">$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v9.0\ReportingServices\Microsoft.ReportingServices.targets</ReportingServicesTargets> </PropertyGroup>
Problém samozřejmě může nastat, až jiné build-extense než Code Contracts použijí C:\Program Files\MSBuild\ a celé se to rozjede.
Dle hlášeného bugu na Connectu však stejný problém je i s WCF, takže si myslím, že soudruzi v Microsoftu někde přecijenom dělají chybu.
Prakticky identický problém jsem řešil s beta verzí Web Deployment Projectu pro VS2010, nakonec jsem se vykašlal na úpravy souborů a prostě jsem sesynchronizoval obsah C:\Program Files\MSBuild\ se složkou C:\Program Files (x86)\MSBuild (překopíroval jsem jedno přes druhé a vice versa).
Nyní s vydáním RTW verze Web Deployment Projectu jsem si všimnul, že je toto již řešeno použitím propert $(MSBuildExtensionsPath32), která vede do správného místa. V Code Contracts by tedy mělo stačit změnit „všechny“ $(MSBuildExtensionsPath) na $(MSBuildExtensionsPath32), ale nezkoušel jsem to zatím.
Uff, dalo mi hodně práce vymyslet titulek tohoto článku, aby alespoň trochu vyjadřoval, co článek popisuje – tedy jak pomocí nové techniky Visual Studia 2010 pro web.config transformace, tedy pomocí transformačních XDT souborů (XML Document Transformation Engine), transformovat libovolný jiný XML soubor jako součást běžného buildu.
Pokud nevíte, jak fungují ve Visual Studiu 2010 transformace web.config souborů při deploymentu, podívejte se na můj screencast na MSTV (12:48 minut) nebo na materiály z prezentací (vč. demokódu). Pokud Vás zajímá, jak tímto způsobem transformovat libovolný jiný XML soubor (ať už .config, .sitemap, nebo jakýkoliv jiný .xml), potom čtěte dále.
Celé kouzlo spočívá ve využití připraveného TransformXml MSBuild tasku, který je použit i v připraveném targetu TransformWebConfig používaném při deploymentu webových aplikací (vytváření Package). Task TransformXml je prostý, má tři parametry a vypadá takto:
<TransformXml Source="path/original.xml" Transform="path/transformation.xml" Destination="path/transformed.xml" />
Abyste však tento task mohli použít v libovolném projektovém (.csproj, .vbproj, …) souboru (nejenom tedy webu, ale i ConsoleApplication, ClassLibrary, či čehokoliv jiného mimo WebSite), musíte jej importovat instrukcí using z assembly webového deploymentu:
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll"/>
No použít task můžete samozřejmě v rámci libovolného targetu, celé to pak může v .csproj souboru vypadat takto:
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll"/> <Target Name="AfterBuild"> <TransformXml Source="Menu\default.xml" Transform="Menu\MyTransform.xml" Destination="Menu\MyMenu.xml" /> </Target>
Target AfterBuild je připravený a automaticky spouštěný po základním buildu projektu. Znáte-li fungování projektových souborů a MSBuildu, dále číst nemusíte.
Projektové soubory, jak je znáte z Visual Studia, nejsou ve skutečnosti nic jiného, než MSBuild instrukční soubory, které nejenom drží pohromadě konfiguraci Vašeho projektu, ale představují především zadání pro MSBuild, jak má Vás projekt v různých situacích buildovat.
Nebojte se tedy s těmito soubory pracovat a editovat je! Nejedná se o žádné hackování Visual Studia, ale o zamýšlený způsob ovládání Microsoftího build-procesu. Visual Studio pro Vás tyto soubory typicky založí, během práce s projektem je aktualizuje, nicméně je nepřegenerovává, ale pouze edituje a je opravdu na Vás, pokud chcete buildování Vašeho projektu nějak obohatit, abyste s těmito XML soubory pracovali.
Podrobnější popis fungování těchto souborů je mimo rozsah tohoto článku, pro začátek Vám však značí znát pojmy jako target a task.
MSBuild task je primitivní úkon, který má MSBuild během své práce vykonat. Např. něco zkompilovat, smazat, zkopírovat, založit složku, zkomprimovat do ZIP souboru, transformovat XML, atp. V projektovém souboru se zapisuje jako XML emelent a jeho nastavení se provádí pomocí atributů, viz např. výše uvedený TransformXml task. Základní sada tasků je v MSBuild integrována, další lze připojit jako doplňky (viz výše uvedený Using, který zavádí task TransformXml z .NET assembly).
MSBuild target je něco jako procedura, sada tasků nebo jiných targetů, které se mají vykonat. Pokud např. Visual Studio builduje Váš projekt, volá target „Build“, při publishingu webových aplikací se používají targety jako „CreatePackage“ nebo „TransformWebConfig“. Výchozí konfigurace zahrnuje speciální template-targety „BeforeBuild“, „AfterBuild“ a podobné, kam se snadno můžete zapojit se svými tasky při běžných buildech.
No a to co my ve skutečnosti při výše uvedených transformacích XML souborů děláme, je ve skutečnosti to, že do targetu AfterBuild přidáme task TransformXml (před tím zavedený pomocí Using), který v patřičné fází buildu transformaci provede.
Jak na editaci projektových souborů z Visual Studia:
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets. <Target Name="BeforeBuild"> </Target> <Target Name="AfterBuild"> </Target> -->
4. Po potřebných úpravách souboru a jeho uložení stačí opět dát pravým na projekt v Solution Exploreru a „Reload Project“.
5. Nyní můžete buildovat…
Pokud zapomenete udělat Reload Project, projekt se Vám bude při buildu ignorovat, což nemusí být hned zjevné.