Nedir Bu MSBuild? - Makale - Yazılım Dilleri
Bu yazıdaki amacımız MSBuild platformunu kısaca tanımaya ve anlamaya çalışıp neler yapılabileceğinin yolunu göstermektir.
[Orjinal Yazım Tarihi – 25/02/2013]
Yıllar öncesinde bir kaç seneliğine de olsa saygın bir eğitim kurumunda eğitmen olarak görev alma şansını yakalamıştım. Özellikle C#’ ın öğretilmeye çalışıldığı başlangıç niteliğindeki seanslarda dilin temel özelliklerini anlatırken, tüm dış çevre ile olan bağlantıyı kesip, sadece anahtar kelime(keyword), ifade ve materyale odaklanmaya çalışırdık. Bu sebepten genellikle ilk örneklerimiz veHello World uygulamamız, Notepad gibi bir program ve komut satırındaki csc(C# Compiler) ile inşa edilirdi.
O zamanlar bu bizim için yeterli görünüyordu ama tabi .Net Framework 2.0 ile birlikte hayatımıza yeni bir inşa süreci de girdi. Aslında bu günkü konumuzda da, Notepad(tam olarak Notepad 2)ve komut satırı aracını kullanarak ilerlemeye çalışıyor olacağız. Amacımız MSBuild platformunu çok kısaca tanımaya ve anlamaya çalışmak.
Microsoft Build Engine aslında başlı başına bir platformdur. Kısaca MSBuild olarak anılmaktadır ve bir uygulamanın inşa edilmesi noktasında devreye giren XML(eXtensible Markup Language)tabanlı bir Script bütününü esas alır. Kısacası uygulamanın inşa edilmesi sırasındaki aşamalar XMLtabanlı bir akış olarak ifade edilebilmektedir. MSBuild platformunun en önemli özelliği ise, inşa sürecinde Visual Studio gibi bir araca ihtiyaç duymuyor oluşudur.
Evet Visual Studio’ nun kendisi, Build işlemlerinde bu platformu kullanmaktadır doğru ama, tam tersi durum geçerli değildir. Yani istersek MSBuild aracını kullanarak, bir uygulamanın veya uygulama ortamının üretilmesi sırasındaki aşamaları, basit bir Notepad aracı ile tasarlayabilir veMSBuild.exe’ den yararlanarak hayata geçirebiliriz(Ancak bu gün şanslısınız çünkü Notepad2isimli ürünü kullanacağız. Sourceforge adresinden indirebilirsiniz )
Bu fikir tabi ki otomatize edilmiş Build işlemlerinin de icra edilebileceği anlamına gelmektedir. KiTeam Foundation Server ürünü de MSBuild’ un etkin bir şekilde kullanılmasına olanak tanımaktadır. Özellikle Team Foundation Build olarak anılan platform içerisinde Build Server’ un kurulduğu ortam MSBuild Script’ lerini kullanarak üretim işlemlerini gerçekleştirmektedir. Söz gelimizi TFS tarafında eğer Continous Integration gibi bir strateji tercih edilmişse, kodlamacılarınCheck-In işlemleri sonrası Team Foundation Build devreye girecek ve MSBuild script’ leri otomatik olarak çalıştırılarak inşa işlemleri icra edilecektir. (Team Foundation Build ayrıca incelenmesi gereken bir konu olduğundan bu yazımızda detaylandırılmamıştır)
Visual Studio ortamında geliştirdiğimiz projeleri göz önüne aldığımızda, oluşturulan proje dosyaları içerisinde, MSBuild’ un kullanacağı ayarlar(Settings) ve bazı koşul bağlı işlevsellikler konuşlandırılmaktadır. Tabi geliştirici olarak bu kısımlar ile pek fazla uğraşmayız ve nihayetindeVisual Studio bizim için bu akışları otomatik olarak inşa eder. Ancak Release Manager gibi pozisyonlar özellikle bu proje dosya içeriklerini değerlendirerek genişletmeler yapabilir ve MSBuildsürecini farklılaştırabilirler.
Visual Studio ile geliştirilen proje dosyaları C# tarafı için csproj, Visual Basic tarafı için vbproj, Managed C++ tarafı içinse vcxproj uzantılı olanlardır.
Hangi Durumlarda MSBuild
Peki MSBuild ağırlık olarak hangi hallerde ele alınır.
En bilinen sebep elimizde Visual Studio olmayan bir ortamda inşa etme işlemlerinde değerlendirilebiliyor olmasıdır.
Compiler devreye girmeden önce bazı dosyaların Process edilmesi gereken durumlarda ele alınabilir.(Pre-Processing Steps)
Benzer şekilde Process sonrası yapılması istenen işlemler içinde kullanılabilir(Post-Processing Steps)
Build işlemi sonucu çıktıların farklı bir klasöre taşınması sağlanabilir. (Ki bu klasör pek çok projenin ortaktaşa kullandığı bir assembly için paylaşımdaki bir makine bile olabilir)
Çıktıların sıkıştırılması istendiği bir durumda ele alınabilir.
İnşa işleminin birden fazla Process’ e bölünerek daha hızlı tamamlanması istendiği durumlarda değerlendirilebilir. (Özellikle Enterprise çözümlerde, n sayıda Branch’ in ve dolayısıyla çıktının söz konusu olabileceği senaryolarda, uzun sürebilecek Build işlemleri için kritik bir özelliktir)
MSBuild 64bitlik bir sistem için inşa işlemini icra edebilir.
Build işleminin herhangibir noktasında harici bir aracın kullanılması istendiği hallerde göz önüne alınabilir.
ve benzeri pek çok durumda MSBuild’ u açık bir şekilde özelleştirerek kullanabiliriz.
Proje Dosyasının İçine Bakalım
Hızlı bir şekilde uygulama geliştirme işine giren pek çok yazılımcı çoğunlukla MSBuild gibi programların ürettiği çıktıları göz ardı etmektedir. Nasıl olsa binlerce dolar verilerek satın alınanVisual Studio bizim yerimize pek güzel bu işi halletmektedir. Ancak gerçek hayatta öyle vakalar ve senaryolara vuku bulmaktadır ki, bunların üstesinden gelebilmek için özelleştirmelere gidilmesi şart olmaktadır. Bu özelleştirme konsepti MSBuild tarafı için de geçerlidir. Bu sebepten proje dosyalarının içeriğinin az da olsa bilinmesi en azından şema yapısının anlaşılması yararlıdır. Tipik olarak bir Console uygulaması dahi açsak, üretilen proje dosyası içerisinde(ki örneğimiz csprojuzantılı olandır) aşağıdakine benzer bir içerik oluştuğu görülecektir.
Bu XML içeriğinin şema yapısına bakıldığında aşağıdaki grafikte görülen iskeletin söz konusu olduğu görülecektir.
Aslında içerik okunduğunda, Visual Studio Proje Özelliklerinden de ayarladığımız pek çok öğenin buraya yazıldığı görülebilir. Örneğin PropertyGroup elementlerinde Debug, Debug-Any CPU ve Release-Any CPU için bazı atamalar söz konusudur.
Debug ile alakalı PropertyGroup’ a bakıldığında uygulamanın vereceği çıktının exe olacağı, .NetFramework 4.5 platformunu hedef aldığı, Assembly adının ConsoleApplication33 olduğu ve buna bağlı olarak da Root Namespace’ in yine ConsoleApplication33 şeklinde set edildiği görülebilir. Condition niteliklerinde belirtilen kısımlar, MSBuild uygulamasına bazı kriterlere göre nasıl çıktı üretmesi gerektiğini de söylemektedir. Örneğin uygulama Release modda inşa edildiğinde, çıktının bin\Release klasörüne doğru yapılması gerektiği yine bir PropertyGroupiçerisinde ifade edilmiştir.
Condition niteliklerinde kullanılan $ notasyonu mutlaka dikkatinizi çekmiştir. Aslında burada $[PropertyName] şeklinde bir kullanım söz konusudur. Burada inanılmaz geniş bir esneklik vardır.
Örneğin $(registery:Hive\SomeKey\SomeSubKey@Value) gibi bir ifade ile Registery’ deki bir değeri okuyabilir ve Build içerisinde kullanabiliriz. Ya da $([System.DateTime]::Now.ToString("yyyy.MM.dd")) gibi bir kullanım ile o anki zamanı istediğimiz formatta elde edebiliriz vb…
[PropertyName] yerine gelecek MSBuild özelliklerinin neler olabileceğini MSDN adresinden öğrenebilirsiniz.
ItemGroup elementleri içerisine bakıldığında, uygulamanın referans ettiği diğer Assembly’ ların adları, Compile işlemi sırasında derlemeye tabi olacak C# dosyaları gibi bilgiler yer almaktadır.Visual Studio’ nun ürettiği XML içeriğine bakıldığında, son kısımda yorum satırları içerisine dahil edilmiş Target isimli bir element daha olduğu görülmektedir. Bu elementi kullanarak MSBuild için bazı Task’ lar tanımlanabilir ve inşa işlemi sırasında devreye girmeleri sağlanabilir.
Task olarak yapılan tanımlamalar paylaşılabilir ve farklı geliştirme Build’ larında da kullanılabilir. Bu yüzden bir yazılım evinin Build işlemlerinde standart olarak gerçekleştirdiği bazı yürütmeler, Taskolarak tanımlanıp ilgili Build paketlerine gömülebilir. Ayrıca Task’ lar Reusable özelliği taşımaktadır. (Target elementleri genellikle yazıldıkları sırada çalışmaktadır. Yani belirli bir sırada icra edilmesi istenen Task’ lar var ise, Target elementinin buna uygun olacak şekilde kullanılması gerekir)
Schema yapısı bu kadar basit değildir. Kullanılabilecek tüm elementler için MSDN üzerindeki şu adrese gitmenizi öneririm.
Yazımızın bu bölümünde basit bir örnek geliştirmeye çalışıyor olacağız. Amacımız temel seviyedeMSBuild aracını kullanmak ve konsepti anlamaya çalışmak olacaktır. İlk olarak basit bir C# koduna ihtiyacımız var. Bu amaçla örneğin C:\Samples\HowToMSBuild\ isimli klasör altında, aşağıdaki içeriğe sahip bir C# dosyası oluşturduğumuzu düşünelim.
Bu adımdan sonra yine Notepad2 aracını kullanarak aşağıdaki içeriğe sahip bir csproj dosyası üreterek devam edelim.
<Compile Include="MSBuildHowTo.cs" />
Project içerisinde bir adet ItemGroup ve Target elementi yer almaktadır. ItemGroup içerisinde yer alan Compile elementi, Include niteliğinde(attribute), derleme işlemine tabi olacak dosyayı belirtmektedir. Target altındaki Csc elementinin Sources niteliğinde ise Compile isimli bir komut yer almaktadır. Dolayısıyla bu Task, MSBuild aracına, Compile elementine dahil edilen dosyanın derlenmesi gerektiğini söylemektedir.
Bu içeriği Builder.csproj adı ile kaydettikten sonra ise sıradaki operasyon, MSBuild komut satırı aracını kullanarak inşa işlemini yürüttürmektir. Bunun için MSBuild’ u aşağıdaki gibi kullanabiliriz.
msbuild Builder.csproj /t: Build /verbosity: detailed
Görüldüğü gibi çalışma sonrasında MSBuildHowTo isimli bir exe dosyası oluşmuştur. Söz konusuexe dosyasını doğrudan çalıştırdığımızda ise, pre-precessor direktifi dışında kalan kod parçasının yürütüldüğü gözlemlenecektir.
MSBuild özellikle kurulu olan .Net Framework versiyonuna bağlı olaraktan Microsoft.Net\Framework\vX.X.XXXXX altında yer almaktadır. Örneğin ben kendi sistemimde aşağıdaki klasörde yer alan sürümü kullandım.
Bunu sistem’ de Path olarak belirtebiliriz ama dilerseniz doğrudan Visual Studio Command Prompt’ tan da yararlanabiliriz.
CSPROJ İçeriğini Genişletelim
Şimdi csproj dosyasının içeriğini biraz daha genişletelim ve aşağıdaki hale getirelim.
<Csc Sources="@(Compile)" OutputAssembly="$(OutputPath)$(AssemblyName).exe"/>
Bu sefer PropertyGroup içerisinde assembly adını(AssemblyName elementi) ve build işlemi sonrası ortaya çıkacak olan çıktının konuşlandırılacağı klasörü de belirttik(OutputPath). Diğer yandan bu örneğimizde yer alan en önemli kısım Build isimli Target elementinin içeriğidir. Dikkat edilecek olursa ilk sırada MakeDir isimli element yer almaktadır. Burada $(OutputPath) ile çıktının yapılacağı klasör işaretlenirken aslında PropertyGroup>OutputPath elementinin içeriği ifade edilmektedir. Önemli olan kısım ise Condition niteliğinde yazılan değerdir.!Exists(‘$(OutputPath)’) ifadesi ile şu söylenmektedir. “OutputPath yoksa…”. Buna göre eğerCondition sağlanırsa, MakeDir OutputPath’ in oluşturulması gerektiğini belirtecektir.
Csc elementinde ise derleme işlemi için kullanılacak olan kaynak Sources elementi ile ifade edilirken, aslında ItemGroup içerisindeki Compile elementinde yer alan Include niteliğinin değeri işaret edilmektedir. OutputAssembly niteliğine atanan değer ise, OutputhPath özelliğinin belirttiği klasörün altına AssemblyName’ in işaret ettiği isimle bir exe üretilmesi gerektiğini belirtmektedir. Buna göre komut satırından yapılan MSBuild çağrısı sonucu aşağıdaki gibi olacaktır.
Oldukça zevkli öyle değil mi?
Öyleyse gelin olayı biraz daha genişleterek devam edelim.
<Project DefaultTargets="Build" xmlns=" http://schemas.microsoft.com/developer/msbuild/2003">
Bu seferki çalışmada 3 adet Target elementi söz konusudur. Ancak her birinin Name niteliğinin değerleri farklıdır. Buna göre, Build, Clean ve Rebuild isimli Target’ lar olduğunu ve aslında bunların 3 ayrı Task’ ı ifade ettiğini düşünebiliriz. Yani MSBuild aracını kullanırken /t: [TargetNameValue] şeklinde bir yaklaşım ile, istediğimiz Target’ ın yürütülmesini sağlayabiliriz. Söz gelimi;
msbuild Builder.csproj /t: Clean /verbosity: detailed
şeklinde yapılan çağrı sonucunda, proje dosyasındaki Target elementlerinden Clean isimli olanı çalıştırılacaktır. Bu elementte ise Delete isimli bir alt element yer almakta olup Files niteliğinde belirtilen kritere göre, Bin klasöre altında assembly adı ile duran exe dosyasının silinmesi gerektiği ifade edilmektedir.
Eğer Rebuild takısını kullanırsak bu durumda Target->Name niteliği Rebuild olan bölüm devreye girecektir. Bu vakada dikkat edilmesi gereken ise DependsOnTargets niteliği içerisinde yazılanClean;Build ifadesidir. Yani şunu ifade etmiş oluruz;
Ey MSBuild!…Önce Clean isimli Target, sonrasında ise Build isimli Target içeriğini icra et
ki bu durumda Bin klasörü içeriği silinecek ve tekrardan bir derleme işlemi yapılarak, orada ilgili exeçıktısının üretilmesi sağlanacaktır.
msbuild Builder.csproj /t: Rebuild /verbosity: detailed
Örnekler daha da çoğaltılabilir. Yapılabilecek pek çok şey var Bunun için mutlaka MSDN orjinli bir kaynağa başvurmanızı veya yazımızın sonunda belirttiğimiz tarzdaki bir kitabı tedarik etmenizi öneririm. Ancak temel mantığı ifade edebildiğimizi varsayıyorum. Bundan sonrasında Condition’lara ve kullanılabilecek element/attribute tiplerine bakılması yeterli olur düşüncesindeyim.
.Net Framework 4.5 ile Gelen Yenilikler
MSBuild ürününe Framework 4.5 sürümü ile birlikte bazı geliştirmeler ve yeni özellikler de katılmıştır. Henüz inceleme fırsatı bulamadığım bu özellikleri aşağıdaki maddeler ile özetleyebiliriz.
ARM(Advanced RISC Machine) desteği gelmiştir. Yani Build çıktıları ARM işlemcilerini hedef alacak şekilde üretilebilir.
Bir Task (Target elementi ile belirtilen bir görev diyelim) süreç dışı(Out of Process) modda çalışmaya zorlanabilir.
Yeni bazı XML element ve nitelikleri(Attributes) gelmiştir.
Klasik bir cümle olacak ama, Performans(Performance) ve Ölçeklendirme(Scabilitiy) noktasında iyileştirmeler vardır
MSBuild’ un etkili kullanımı üzerine geliştirilmiş bazı araçlar da vardır. Görsel arabirimleri olan bu araçlar yardımıyla MSBuild akışlarını daha kolay yönetebiliriz. Attrice firmasının bu alanda ön plana çıkan Microsoft Build Sidekick isimli ürünü gibi.
Microsoft’ un Visual Studio ailesi ve geliştirme platformu oldukça geniş bir alana yayılmakta olup, pek çok notkasında uzmanlık gerektiren yapılar içermektedir. Bu sebepten söz konusu yapılara yönelik pek çok yayın da(kitap, official site, blog vb) mevcuttur.
Örneğin MSBuild tarafında daha önceden yayınlanmış olan Inside The Microsoft Build Engine isimli kitabın Nisan ayı içerisinde yayınlanan yeni bir tamamlayıcı baskısı mevcuttur. Yaklaşık olarak 120 sayfalık bir kitap olmasına rağmen odaklandığı konu özünde MSBuild ürünüdür. Kitaba Amazon üzerinden bu adres yardımıyla erişebilirsiniz.
Böylece geldik bir yazımızın daha sonuna. Bu yazımızda kısada olsa, MSBuild platformunu ve XMLtarafındaki betikleri(Scripts) anlamaya çalıştık. Ağırlıklı olarak bir inşa sürecine müdahale edebildiğimizi, bunun için platformun sunduğu bazı standart element ve niteliklerin olduğunu gördük. Devamı sizde artık Bir başka yazımızda görüşünceye dek hepinize mutlu günler dilerim.
[Güncel bilgi –> MS Build is now part of Visual Studio!]