Objaśnienie procesu kompilacji

Autor : Jason Lee

Ten temat zawiera przewodnik po procesie kompilacji i wdrażania w skali przedsiębiorstwa. Podejście opisane w tym temacie używa niestandardowych plików projektu Microsoft Build Engine (MSBuild) w celu zapewnienia szczegółowej kontroli nad każdym aspektem procesu. W plikach projektu niestandardowe obiekty docelowe programu MSBuild są używane do uruchamiania narzędzi wdrażania, takich jak narzędzie wdrażania sieci Web usług Internet Information Services (IIS) (MSDeploy.exe) i narzędzie wdrażania bazy danych VSDBCMD.exe.

Uwaga

W poprzednim temacie Opis pliku projektu opisano kluczowe składniki pliku projektu MSBuild i przedstawiono koncepcję podzielonych plików projektu w celu obsługi wdrożenia w wielu środowiskach docelowych. Jeśli nie znasz jeszcze tych pojęć, przed rozpoczęciem pracy z tym tematem zapoznaj się z tematem Omówienie pliku projektu .

Ten temat stanowi część serii samouczków opartych na wymaganiach dotyczących wdrażania w przedsiębiorstwie fikcyjnej firmy o nazwie Fabrikam, Inc. W tej serii samouczków użyto przykładowego rozwiązania — rozwiązania Contact Manager — do reprezentowania aplikacji internetowej o realistycznym poziomie złożoności, w tym aplikacji ASP.NET MVC 3, usługi Windows Communication Foundation (WCF) i projektu bazy danych.

Metoda wdrażania w centrum tych samouczków jest oparta na metodzie podzielonego pliku projektu opisanego w opisie pliku projektu, w którym proces kompilacji jest kontrolowany przez dwa pliki projektu — jeden zawierający instrukcje kompilacji dotyczące każdego środowiska docelowego i jeden zawierający ustawienia kompilacji i wdrażania specyficzne dla środowiska. W czasie kompilacji plik projektu specyficzny dla środowiska jest scalony z plikiem projektu niezależnego od środowiska w celu utworzenia pełnego zestawu instrukcji kompilacji.

Omówienie kompilacji i wdrażania

W rozwiązaniu Contact Manager trzy pliki kontrolują proces kompilacji i wdrażania:

  • Plik projektu uniwersalnego (Publish.proj). Zawiera instrukcje kompilacji i wdrażania, które nie zmieniają się między środowiskami docelowymi.
  • Plik projektu specyficzny dla środowiska (Env-Dev.proj). Zawiera ustawienia kompilacji i wdrażania specyficzne dla określonego środowiska docelowego. Na przykład można użyć pliku Env-Dev.proj , aby zapewnić ustawienia dla dewelopera lub środowiska testowego i utworzyć alternatywny plik o nazwie Env-Stage.proj , aby zapewnić ustawienia środowiska przejściowego.
  • Plik polecenia (Publish-Dev.cmd). Zawiera MSBuild.exe polecenie określające, które pliki projektu chcesz wykonać. Można utworzyć plik polecenia dla każdego środowiska docelowego, w którym każdy plik zawiera MSBuild.exe polecenie określające inny plik projektu specyficzny dla środowiska. Dzięki temu deweloper może wdrożyć je w różnych środowiskach, uruchamiając odpowiedni plik polecenia.

W przykładowym rozwiązaniu można znaleźć te trzy pliki w folderze Publikuj rozwiązanie.

W przykładowym rozwiązaniu można znaleźć trzy pliki w folderze Publikuj rozwiązanie.

Zanim przyjrzysz się tym plikom bardziej szczegółowo, przyjrzyjmy się temu, jak działa ogólny proces kompilacji podczas korzystania z tego podejścia. Na wysokim poziomie proces kompilowania i wdrażania wygląda następująco:

Jak wygląda proces kompilacji i wdrażania na wysokim poziomie.

Pierwszą rzeczą jest to, że dwa pliki projektu — jeden zawierający uniwersalne instrukcje kompilacji i wdrażania, a drugi zawierający ustawienia specyficzne dla środowiska — są scalane w jeden plik projektu. Program MSBuild następnie wykonuje instrukcje w pliku projektu. Kompiluje każdy z projektów w rozwiązaniu przy użyciu pliku projektu dla każdego projektu. Następnie wywołuje ona inne narzędzia, takie jak Web Deploy (MSDeploy.exe) i narzędzie VSDBCMD w celu wdrożenia zawartości internetowej i baz danych w środowisku docelowym.

Od początku do końca proces kompilowania i wdrażania wykonuje następujące zadania:

  1. Usuwa zawartość katalogu wyjściowego w ramach przygotowań do nowej kompilacji.

  2. Kompiluje każdy projekt w rozwiązaniu:

    1. W przypadku projektów internetowych — w tym przypadku aplikacja internetowa ASP.NET MVC i usługa internetowa WCF — proces kompilacji tworzy pakiet wdrożeniowy sieci Web dla każdego projektu.
    2. W przypadku projektów baz danych proces kompilacji tworzy manifest wdrożenia (plik deploymanifest) dla każdego projektu.
  3. Używa on narzędzia VSDBCMD.exe do wdrażania każdego projektu bazy danych w rozwiązaniu przy użyciu różnych właściwości z plików projektu — docelowych parametrów połączenia i nazwy bazy danych — wraz z plikiem .deploymanifest.

  4. Używa on narzędzia MSDeploy.exe do wdrażania każdego projektu internetowego w rozwiązaniu przy użyciu różnych właściwości z plików projektu w celu kontrolowania procesu wdrażania.

Możesz użyć przykładowego rozwiązania do śledzenia tego procesu bardziej szczegółowo.

Uwaga

Aby uzyskać wskazówki dotyczące dostosowywania plików projektu specyficznych dla środowiska dla własnych środowisk serwerowych, zobacz Konfigurowanie właściwości wdrożenia dla środowiska docelowego.

Wywoływanie procesu kompilacji i wdrażania

Aby wdrożyć rozwiązanie Contact Manager w środowisku testowym dewelopera, deweloper uruchamia plik polecenia Publish-Dev.cmd . Spowoduje to wywołanie MSBuild.exe, określając plik Publish.proj jako plik projektu do wykonania i Env-Dev.proj jako wartość parametru.

msbuild.exe Publish.proj /fl /p:TargetEnvPropsFile=EnvConfig\Env-Dev.proj

Uwaga

Przełącznik /fl (skrót od /fileLogger) rejestruje dane wyjściowe kompilacji do pliku o nazwie msbuild.log w bieżącym katalogu. Aby uzyskać więcej informacji, zobacz dokumentację wiersza polecenia programu MSBuild.

W tym momencie program MSBuild uruchamia działanie, ładuje plik Publish.proj i rozpoczyna przetwarzanie zawartych w nim instrukcji. Pierwsza instrukcja nakazuje programowi MSBuild zaimportowanie pliku projektu, który określa parametr TargetEnvPropsFile .

<Import Project="$(TargetEnvPropsFile)" />

Parametr TargetEnvPropsFile określa plik Env-Dev.proj, więc MSBuild scala zawartość pliku Env-Dev.proj z plikiem Publish.proj.

Kolejnymi elementami napotkanymi w scalanych plikach projektu są grupy właściwości. Właściwości są przetwarzane w kolejności, w której są wyświetlane w pliku. Program MSBuild tworzy parę klucz-wartość dla każdej właściwości, zapewniając spełnienie określonych warunków. Właściwości zdefiniowane w dalszej części pliku zastąpią wszystkie właściwości o tej samej nazwie zdefiniowanej wcześniej w pliku. Rozważmy na przykład właściwości OutputRoot .

<OutputRoot Condition=" '$(OutputRoot)'=='' ">..\Publish\Out\</OutputRoot>
<OutputRoot Condition=" '$(BuildingInTeamBuild)'=='true' ">$(OutDir)</OutputRoot>

Gdy program MSBuild przetwarza pierwszy element OutputRoot , podając podobnie nazwany parametr nie został podany, ustawia wartość właściwości OutputRoot na wartość .. \Publish\Out. Gdy napotka drugi element OutputRoot , jeśli warunek zwróci wartość true, zastąpi wartość właściwości OutputRoot wartością parametru OutDir .

Następnym elementem napotkanym przez program MSBuild jest grupa pojedynczych elementów zawierająca element o nazwie ProjectsToBuild.

<ItemGroup>
   <ProjectsToBuild Include="$(SourceRoot)ContactManager-WCF.sln"/>
</ItemGroup>

Program MSBuild przetwarza tę instrukcję, tworząc listę elementów o nazwie ProjectsToBuild. W takim przypadku lista elementów zawiera jedną wartość — ścieżkę i nazwę pliku rozwiązania.

W tym momencie pozostałe elementy są elementami docelowymi. Obiekty docelowe są przetwarzane inaczej niż właściwości i elementy — zasadniczo obiekty docelowe nie są przetwarzane, chyba że są jawnie określone przez użytkownika lub wywoływane przez inną konstrukcję w pliku projektu. Pamiętaj, że otwierający tag Project zawiera atrybut DefaultTargets .

<Project ToolsVersion="4.0" 
         DefaultTargets="FullPublish" 
         xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

Spowoduje to, że program MSBuild wywoła obiekt docelowy FullPublish , jeśli obiekty docelowe nie zostaną określone podczas wywoływania MSBuild.exe. Element docelowy FullPublish nie zawiera żadnych zadań; zamiast tego po prostu określa listę zależności.

<PropertyGroup>   
  <FullPublishDependsOn>
     Clean;
     BuildProjects;      
     GatherPackagesForPublishing;
     PublishDbPackages;
     PublishWebPackages;
  </FullPublishDependsOn>
</PropertyGroup>
<Target Name="FullPublish" DependsOnTargets="$(FullPublishDependsOn)" />

Ta zależność informuje program MSBuild, że aby wykonać obiekt docelowy FullPublish , musi wywołać tę listę obiektów docelowych w podanej kolejności:

  1. Musi wywołać element docelowy Clean .
  2. Musi wywołać obiekt docelowy BuildProjects .
  3. Musi wywołać element docelowy GatherPackagesForPublishing .
  4. Musi wywołać element docelowy PublishDbPackages .
  5. Musi wywołać element docelowy PublishWebPackages .

Czysty element docelowy

Element docelowy Clean zasadniczo usuwa katalog wyjściowy i całą jego zawartość jako przygotowanie do nowej kompilacji.

<Target Name="Clean" Condition=" '$(BuildingInTeamBuild)'!='true' ">
  <Message Text="Cleaning up the output directory [$(OutputRoot)]"/>
  <ItemGroup>
     <_FilesToDelete Include="$(OutputRoot)**\*"/>
  </ItemGroup>
  <Delete Files="@(_FilesToDelete)"/>
  <RemoveDir Directories="$(OutputRoot)"/>
</Target>

Zwróć uwagę, że element docelowy zawiera element ItemGroup . Podczas definiowania właściwości lub elementów w elemecie Targettworzysz dynamiczne właściwości i elementy. Innymi słowy, właściwości lub elementy nie są przetwarzane, dopóki element docelowy nie zostanie wykonany. Katalog wyjściowy może nie istnieć lub zawierać żadnych plików do momentu rozpoczęcia procesu kompilacji, więc nie można skompilować listy _FilesToDelete jako elementu statycznego; musisz poczekać, aż trwa wykonywanie. W związku z tym lista jest kompilowana jako element dynamiczny w elemencie docelowym.

Uwaga

W tym przypadku, ponieważ element docelowy Clean jest pierwszym do wykonania, nie ma potrzeby używania dynamicznej grupy elementów. Jednak dobrym rozwiązaniem jest użycie właściwości dynamicznych i elementów w tym scenariuszu, ponieważ w pewnym momencie warto wykonywać obiekty docelowe w innej kolejności.
Należy również unikać deklarowania elementów, które nigdy nie będą używane. Jeśli masz elementy, które będą używane tylko przez określony element docelowy, rozważ umieszczenie ich wewnątrz elementu docelowego, aby usunąć wszelkie niepotrzebne obciążenie w procesie kompilacji.

Elementy dynamiczne — obiekt docelowy Clean jest dość prosty i korzysta z wbudowanych zadań Komunikat, Usuń i RemoveDir :

  1. Wyślij wiadomość do rejestratora.
  2. Utwórz listę plików do usunięcia.
  3. Usuń pliki.
  4. Usuń katalog wyjściowy.

Cel BuildProjects

Obiekt docelowy BuildProjects zasadniczo kompiluje wszystkie projekty w przykładowym rozwiązaniu.

<Target Name="BuildProjects" Condition=" '$(BuildingInTeamBuild)'!='true' ">
   <MSBuild Projects="@(ProjectsToBuild)"
            Properties="OutDir=$(OutputRoot);
                        Configuration=$(Configuration);
                        DeployOnBuild=true;
                        DeployTarget=Package"
            Targets="Build" />
  </Target>

Ten element docelowy został opisany szczegółowo w poprzednim temacie Opis pliku projektu, aby zilustrować, jak zadania i obiekty docelowe odwołują się do właściwości i elementów. W tym momencie interesuje Cię głównie zadanie MSBuild . To zadanie służy do kompilowania wielu projektów. Zadanie nie tworzy nowego wystąpienia MSBuild.exe; używa bieżącego uruchomionego wystąpienia do kompilowania każdego projektu. Kluczowymi punktami zainteresowania w tym przykładzie są właściwości wdrożenia:

  • Właściwość DeployOnBuild instruuje program MSBuild, aby uruchamiał instrukcje wdrażania w ustawieniach projektu po zakończeniu kompilacji każdego projektu.
  • Właściwość DeployTarget identyfikuje obiekt docelowy, który chcesz wywołać po skompilowania projektu. W takim przypadku docelowy pakiet kompiluje dane wyjściowe projektu do wdrażalnego pakietu internetowego.

Uwaga

Element docelowy pakietu wywołuje potok publikowania sieci Web (WPP), który zapewnia integrację między programem MSBuild i narzędziem Web Deploy. Jeśli chcesz przyjrzeć się wbudowanym obiektom docelowym zapewnianym przez program WPP, przejrzyj plik Microsoft.Web.Publishing.targets w folderze %PROGRAMFILES(x86)%\MSBuild\Microsoft\VisualStudio\v10.0\Web.

Obiekt docelowy GatherPackagesForPublishing

Jeśli zbadasz miejsce docelowe GatherPackagesForPublishing , zauważysz, że w rzeczywistości nie zawiera żadnych zadań. Zamiast tego zawiera grupę pojedynczych elementów, która definiuje trzy elementy dynamiczne.

<Target Name="GatherPackagesForPublishing">
   <ItemGroup>
      <PublishPackages 
         Include="$(_ContactManagerDest)ContactManager.Mvc.deploy.cmd">
         <WebPackage>true</WebPackage>
         <!-- More item metadata -->  
      </PublishPackages>
      <PublishPackages 
         Include="$(_ContactManagerSvcDest)ContactManager.Service.deploy.cmd">
         <WebPackage>true</WebPackage>
         <!-- More item metadata -->
      </PublishPackages>
      <DbPublishPackages Include="$(_DbDeployManifestPath)">
         <DbPackage>true</DbPackage>
         <!-- More item metadata -->
      </DbPublishPackages>
   </ItemGroup>
</Target>

Te elementy odwołują się do pakietów wdrożeniowych utworzonych podczas wykonywania obiektu docelowego BuildProjects . Nie można zdefiniować tych elementów statycznie w pliku projektu, ponieważ pliki, do których odwołują się elementy, nie istnieją, dopóki cel BuildProjects nie zostanie wykonany. Zamiast tego elementy muszą być definiowane dynamicznie w obiekcie docelowym, który nie jest wywoływany do momentu wykonania obiektu docelowego BuildProjects .

Elementy nie są używane w tym elemencie docelowym — ten element docelowy po prostu kompiluje elementy i metadane skojarzone z każdą wartością elementu. Po przetworzeniu tych elementów element PublishPackages będzie zawierać dwie wartości, ścieżkę do pliku ContactManager.Mvc.deploy.cmd i ścieżkę do pliku ContactManager.Service.deploy.cmd . Narzędzie Web Deploy tworzy te pliki jako część pakietu internetowego dla każdego projektu, a są to pliki, które należy wywołać na serwerze docelowym w celu wdrożenia pakietów. Jeśli otworzysz jeden z tych plików, w zasadzie zobaczysz polecenie MSDeploy.exe z różnymi wartościami parametrów specyficznych dla kompilacji.

Element DbPublishPackages będzie zawierać jedną wartość, ścieżkę do pliku ContactManager.Database.deploymanifest .

Uwaga

Plik .deploymanifest jest generowany podczas tworzenia projektu bazy danych i używa tego samego schematu co plik projektu MSBuild. Zawiera wszystkie informacje wymagane do wdrożenia bazy danych, w tym lokalizację schematu bazy danych (dbschema) oraz szczegóły wszystkich skryptów przed wdrożeniem i po wdrożeniu. Aby uzyskać więcej informacji, zobacz Omówienie kompilacji i wdrażania bazy danych.

Dowiesz się więcej na temat sposobu tworzenia pakietów wdrożeniowych i manifestów wdrażania bazy danych oraz ich użycia w temacie Kompilowanie i pakowanie projektów aplikacji internetowych oraz Wdrażanie projektów baz danych.

Obiekt docelowy PublishDbPackages

Krótko mówiąc, obiekt docelowy PublishDbPackages wywołuje narzędzie VSDBCMD w celu wdrożenia bazy danych ContactManager w środowisku docelowym. Konfigurowanie wdrażania bazy danych obejmuje wiele decyzji i niuansów. Więcej informacji na ten temat znajdziesz w temacie Wdrażanie projektów baz danych i Dostosowywanie wdrożeń bazy danych dla wielu środowisk. W tym temacie skoncentrujemy się na tym, jak ten element docelowy faktycznie działa.

Najpierw zwróć uwagę, że tag otwierający zawiera atrybut Outputs .

<Target Name="PublishDbPackages" Outputs="%(DbPublishPackages.Identity)">

Jest to przykład przetwarzania wsadowego docelowego. W plikach projektu MSBuild przetwarzanie wsadowe jest techniką iteracji nad kolekcjami. Wartość atrybutu Outputs"%(DbPublishPackages.Identity)" odnosi się do właściwości Metadane tożsamości listy elementów DbPublishPackages . Ta notacja , Outputs=%(ItemList.ItemMetadataName), jest tłumaczona jako:

  • Podziel elementy w dbPublishPackages na partie elementów, które zawierają tę samą wartość metadanych tożsamości .
  • Wykonaj element docelowy raz na partię.

Uwaga

Tożsamość jest jedną z wbudowanych wartości metadanych przypisanych do każdego elementu podczas tworzenia. Odwołuje się on do wartości atrybutu Include w elemencie Item — innymi słowy, ścieżki i nazwy pliku elementu.

W tym przypadku, ponieważ nigdy nie powinno istnieć więcej niż jeden element o tej samej ścieżce i nazwie pliku, zasadniczo pracujemy z rozmiarami partii jednego. Obiekt docelowy jest wykonywany raz dla każdego pakietu bazy danych.

Podobną notację można zobaczyć we właściwości _Cmd , która kompiluje polecenie VSDBCMD z odpowiednimi przełącznikami.

<_Cmd>"$(VsdbCmdExe)" 
   /a:Deploy 
   /cs:"%(DbPublishPackages.DatabaseConnectionString)" 
   /p:TargetDatabase=%(DbPublishPackages.TargetDatabase)             
   /manifest:"%(DbPublishPackages.FullPath)" 
   /script:"$(_CmDbScriptPath)" 
   $(_DbDeployOrScript)
</_Cmd>

W tym przypadku %(DbPublishPackages.DatabaseConnectionString), %(DbPublishPackages.TargetDatabase) i %(DbPublishPackages.FullPath) odwołują się do wartości metadanych kolekcji elementów DbPublishPackages . Właściwość _Cmd jest używana przez zadanie Exec , które wywołuje polecenie .

<Exec Command="$(_Cmd)"/>

W wyniku tej notacji zadanie Exec utworzy partie na podstawie unikatowych kombinacji wartości metadanych DatabaseConnectionString, TargetDatabase i FullPath , a zadanie zostanie wykonane raz dla każdej partii. Jest to przykład dzielenia zadań na partie. Jednak ponieważ dzielenie kolekcji elementów na partie na poziomie docelowym zostało już podzielone na partie pojedynczego elementu, zadanie Exec zostanie uruchomione raz i tylko raz dla każdej iteracji obiektu docelowego. Innymi słowy to zadanie wywołuje narzędzie VSDBCMD raz dla każdego pakietu bazy danych w rozwiązaniu.

Uwaga

Aby uzyskać więcej informacji na temat dzielenia elementów docelowych i zadań na partie, zobacz MSBuild Batching, Item Metadata in Target Batching and Item Metadata in Task Batching (Przetwarzanie wsadowe w programie MSBuild), Item Metadata in Target Batching (Metadane elementów w partiach docelowych) i Item Metadata in Task Batching (Metadane elementów w partiach zadań podrzędnych).

Obiekt docelowy PublishWebPackages

W tym momencie wywołano element docelowy BuildProjects , który generuje pakiet wdrożeniowy sieci Web dla każdego projektu w przykładowym rozwiązaniu. Towarzyszący każdemu pakietowi jest plik deploy.cmd zawierający polecenia MSDeploy.exe wymagane do wdrożenia pakietu w środowisku docelowym oraz plik SetParameters.xml , który określa niezbędne szczegóły środowiska docelowego. Wywołano również element docelowy GatherPackagesForPublishing , który generuje kolekcję elementów zawierającą interesujące Cię pliki deploy.cmd . Zasadniczo obiekt docelowy PublishWebPackages wykonuje następujące funkcje:

  • Manipuluje on plikiemSetParameters.xml dla każdego pakietu, aby uwzględnić poprawne szczegóły środowiska docelowego przy użyciu zadania XmlPoke .
  • Wywołuje on plik deploy.cmd dla każdego pakietu przy użyciu odpowiednich przełączników.

Podobnie jak obiekt docelowy PublishDbPackages , obiekt docelowy PublishWebPackages używa przetwarzania wsadowego docelowego, aby upewnić się, że obiekt docelowy jest wykonywany raz dla każdego pakietu internetowego.

<Target Name="PublishWebPackages" Outputs="%(PublishPackages.Identity)">

W ramach elementu docelowego zadanie Exec służy do uruchamiania pliku deploy.cmd dla każdego pakietu internetowego.

<PropertyGroup>
   <_Cmd>
      %(PublishPackages.FullPath) 
      $(_WhatifSwitch) 
      /M:$(MSDeployComputerName) 
      %(PublishPackages.AdditionalMSDeployParameters)
   </_Cmd>
</PropertyGroup>
<Exec Command="$(_Cmd)"/>

Aby uzyskać więcej informacji na temat konfigurowania wdrażania pakietów internetowych, zobacz Tworzenie i pakowanie projektów aplikacji internetowych.

Podsumowanie

W tym temacie przedstawiono przewodnik dotyczący sposobu, w jaki podzielone pliki projektu są używane do kontrolowania procesu kompilacji i wdrażania od początku do końca dla przykładowego rozwiązania Contact Manager. Dzięki temu podejściu można uruchamiać złożone wdrożenia w skali przedsiębiorstwa w jednym powtarzalnym kroku, po prostu uruchamiając plik poleceń specyficzny dla środowiska.

Dalsze informacje

Aby uzyskać bardziej szczegółowe wprowadzenie do plików projektu i programu WPP, zobacz Inside the Microsoft Build Engine: Using MSBuild and Team Foundation Build by Sayed Ibrahim Hashimi and William Bartholomew, ISBN: 978-0-7356-4524-0.