Görev Tabanlı Derleme Sistemleri

Sorun bildirin Kaynağı göster

Bu sayfada, görev tabanlı derleme sistemleri, bunların işleyiş şekli ve göreve dayalı sistemlerde oluşabilecek bazı sorunlar ele alınmaktadır. Kabuk komut dosyalarından sonra, görev tabanlı derleme sistemleri, derlemenin bir sonraki mantıksal gelişimidir.

Görev tabanlı derleme sistemlerini anlama

Görev tabanlı bir derleme sisteminde temel çalışma birimi görevdir. Her görev her türlü mantığı yürütebilen bir komut dosyasıdır ve görevler, diğer görevleri, öncesinde yapmaları gereken bağımlılıklar olarak belirtir. Bugün kullanıma sunulan Ant, Maven, Gradle, Grunt ve Rake gibi başlıca derleme sistemleri görev tabanlıdır. Çoğu modern derleme sisteminde, kabuk komut dosyaları yerine mühendislerin derlemenin nasıl yapılacağını açıklayan derleme dosyaları oluşturması gerekir.

Metinden ilgili şu örneği inceleyin:

<project name="MyProject" default="dist" basedir=".">
   <description>
     simple example build file
   </description>
   <!-- set global properties for this build -->
   <property name="src" location="src"/>
   <property name="build" location="build"/>
   <property name="dist" location="dist"/>

   <target name="init">
     <!-- Create the time stamp -->
     <tstamp/>
     <!-- Create the build directory structure used by compile -->
     <mkdir dir="${build}"/>
   </target>
   <target name="compile" depends="init"
       description="compile the source">
     <!-- Compile the Java code from ${src} into ${build} -->
     <javac srcdir="${src}" destdir="${build}"/>
   </target>
   <target name="dist" depends="compile"
       description="generate the distribution">
     <!-- Create the distribution directory -->
     <mkdir dir="${dist}/lib"/>
     <!-- Put everything in ${build} into the MyProject-${DSTAMP}.jar file -->
     <jar jarfile="${dist}/lib/MyProject-${DSTAMP}.jar" basedir="${build}"/>
   </target>
   <target name="clean"
       description="clean up">
     <!-- Delete the ${build} and ${dist} directory trees -->
     <delete dir="${build}"/>
     <delete dir="${dist}"/>
   </target>
</project>

Derleme dosyası XML olarak yazılır ve görev listesiyle (XML'deki <target> etiketleri) birlikte derleme hakkında bazı basit meta verileri tanımlar. (Ant, bir görevi temsil etmek için hedef kelimesini ve komutları ifade etmek için ise görev kelimesini kullanır. Her görev, Ant tarafından tanımlanan olası komutların listesini yürütür. Bu listede, dizin oluşturma ve silme, javac çalıştırma ve JAR dosyası oluşturma yer alır. Bu komut grubu, kullanıcı tarafından sağlanan eklentiler tarafından herhangi bir mantık mantığını kapsayacak şekilde genişletilebilir. Her görev, bağımlı özelliğini kullanarak bağımlı olduğu görevleri de tanımlayabilir. Bu bağımlılıklar şekil 1'de görüldüğü gibi bir döngüsel grafik oluşturur.

Bağımlıları gösteren akrilik grafik

Şekil 1. Bağımlıları gösteren döngüsel grafik

Kullanıcılar, Ant'in komut satırı aracına görevler sağlayarak derlemeler gerçekleştirir. Örneğin, kullanıcı ant dist yazarken Ant aşağıdaki adımları uygular:

  1. Geçerli dizinde build.xml adlı dosyayı yükler ve Şekil 1'de gösterilen grafik yapısını oluşturmak için ayrıştırır.
  2. Komut satırında sağlanan dist adlı görevi arar ve görevin compile adlı göreve bağımlı olduğunu keşfeder.
  3. compile adlı görevi arar ve init adlı göreve bağımlı olduğunu fark eder.
  4. init adlı görevi arar ve görevin herhangi bir bağımlılığı olmadığını fark eder.
  5. init görevinde tanımlanan komutları yürütür.
  6. Bu görevin tüm bağımlılıklarının çalıştırılmış olması şartıyla, compile görevinde tanımlanan komutları yürütür.
  7. Bu görevin tüm bağımlılıklarının çalıştırılmış olması şartıyla, dist görevinde tanımlanan komutları yürütür.

Sonuç olarak, Ant tarafından dist görevi çalıştırılırken yürütülen kod, aşağıdaki kabuk komut dosyasına eşdeğerdir:

./createTimestamp.sh
mkdir build/
javac src/* -d build/
mkdir -p dist/lib/
jar cf dist/lib/MyProject-$(date --iso-8601).jar build/*

Söz dizimi çıkarıldığında derleme dosyası ve derleme komut dosyası aslında çok farklı olmaz. Fakat bu sayede büyük kazanç elde ettik. Diğer dizinlerde yeni derleme dosyaları oluşturup bunları birbirine bağlayabiliriz. Mevcut görevlere bağımlı olan yeni görevleri rastgele ve karmaşık şekillerde kolayca ekleyebiliriz. Tek bir görevin adını yalnızca ant komut satırı aracına iletmemiz gerekir ve çalıştırılması gereken her şey belirlenir.

Ant, ilk olarak 2000 yılında yayınlanan eski bir yazılımdır. Maven ve Gradle gibi diğer araçlar, aradan yıllarda Ant'te ilerleme kaydetti. Ayrıca şirket, dış bağımlılıkları otomatik olarak yönetme ve XML olmadan daha temiz söz dizimi gibi özellikler ekleyerek bu özelliği geliştirdi. Ancak bu daha yeni sistemlerin doğası aynı kalır: Mühendislerin ilke ve modüler bir şekilde görev komut dosyaları yazmasına ve bu görevlerin yürütülmesi ile bunların arasındaki bağımlıları yönetmelerine olanak tanıyan araçlar sağlar.

Görev tabanlı derleme sistemlerinin karanlık tarafı

Bu araçlar esasen mühendislerin herhangi bir alfabeyi görev olarak tanımlamasına olanak tanıdığından, son derece etkilidirler ve hayal edebileceğiniz hemen her şeyi yapabilirsiniz. Ancak bu güçlerin dezavantajları var. Derleme komut dosyaları daha karmaşık bir hal aldıkça göreve dayalı derleme sistemleriyle çalışmak zorlaşabilir. Bu tür sistemlerdeki sorun, mühendislere çok fazla güç ve sisteme yeterli güç vermemeleridir. Sistemin, komut dosyalarının ne yaptığı konusunda bir fikri olmadığından performans, oluşturma adımlarını planlarken ve yürüttüğünde son derece ölçülü olmalıdır. Sistemin her komut dosyasının olması gereken şekilde çalıştığını doğrulamanın bir yolu olmadığından komut dosyaları karmaşıklık gösterir ve hata ayıklama gerektiren başka bir öğe haline gelir.

Yapı adımlarını paralelleştirmenin zorluğu

Birkaç geliştirme adımını paralel olarak çalıştırabilen birden çok çekirdeğe sahip modern geliştirme iş istasyonları oldukça güçlüdür. Ancak görev tabanlı sistemler, çoğu zaman yapılabilse bile görev yürütme işlemini paralel hale getiremez. A görevinin B ve C görevlerine bağlı olduğunu varsayalım. B ve C görevlerinin birbirine bağımlı olmaması, sistemin A görevine daha hızlı ulaşabilmesi için bunları aynı anda çalıştırmak güvenli midir? Belki de aynı kaynaklardan herhangi birine dokunmadıklarında. Belki değil, iki durum da durumlarını izlemek için aynı dosyayı kullanıyor ve aynı anda çalıştırırken çakışmaya neden oluyor olabilir. Sistemin bunu bilmesinin genel bir yolu yoktur. Bu nedenle, bu çakışmaları riske atabilir (nadir ama hata ayıklaması çok zor olan derleme sorunlarına yol açar) veya tüm derlemeyi tek bir işlemde tek bir ileti dizisinde çalışacak şekilde kısıtlamalıdır. Bu durum, güçlü bir geliştirici makinesinin boşa harcanmasına neden olabilir ve derlemenin birden fazla makineye dağıtılma olasılığını tamamen ortadan kaldırır.

Artımlı derleme gerçekleştirmede zorluk

İyi bir derleme sistemi, mühendislerin güvenilir bir şekilde artan derlemeler gerçekleştirmesine olanak tanır. Böylece küçük bir değişiklik, tüm kod tabanının yeniden derlemeden yeniden oluşturulmasını gerektirmez. Bu, özellikle derleme sistemi yukarıda sözü edilen nedenlerle yavaşsa ve derleme adımlarını paralel hale getirmiyorsa önemlidir. Ancak ne yazık ki göreve dayalı derleme sistemleri de burada zorlanıyor. Görevler her şeyi yapabileceğinden, zaten tamamlanıp tamamlanmadıklarını kontrol etmenin bir yolu yoktur. Çoğu görev bir dizi kaynak dosya alıp bir derleyici çalıştırarak bir dizi ikili program oluşturur. Böylece temel kaynak dosyaları değişmediyse bunların yeniden çalıştırılması gerekmez. Ancak ek bilgiler olmadan sistem bunu kesin olarak söylemeyebilir. Belki de görev, değişmiş olabilecek bir dosya indirir veya her çalıştırmada farklı olabilecek bir zaman damgası yazar. Doğruluğu garantilemek için sistemin genellikle her derleme sırasında her görevi tekrar çalıştırması gerekir. Bazı derleme sistemleri, mühendislerin bir görevin yeniden çalıştırılması gereken koşulları belirtmesine izin vererek artımlı derlemeleri etkinleştirmeye çalışır. Bu bazen mümkün olsa da genellikle göründüğünden daha karmaşık bir sorundur. Örneğin, dosyaların doğrudan başka dosyalar tarafından dahil edilmesine izin veren C++ gibi dillerde, giriş kaynaklarını ayrıştırmadan değişiklikler için izlenmesi gereken dosya grubunun tamamını tanımlamak mümkün değildir. Mühendisler genellikle kısayol kullanırlar ve bu kısayollar, görevin kullanılmaması gereken bir durumda yeniden kullanıldığı nadir ve can sıkıcı sorunlara yol açabilir. Bu durumla sık sık karşılaşıldığında mühendisler, yeni bir yapıya sahip olmak için her derlemeden önce temiz çalışma alışkanlığı edinir ve sürecin başında artımlı bir yapıya sahip olma amacını tümüyle ortadan kaldırır. Bir görevin ne zaman yeniden çalıştırılması gerektiğini anlamak, şaşırtıcı derecede zor ve insan tarafından yapılan bir görevdir.

Komut dosyalarını yönetme ve hata ayıklamada zorluk

Son olarak, görev tabanlı derleme sistemleri tarafından uygulanan derleme komut dosyalarıyla çalışmak genellikle zordur. Derleme komut dosyaları genellikle daha az inceleme gerektirmesine rağmen, oluşturulan sistem gibi bir koddur ve hataların kolayca saklanabileceği yerlerdir. Görev tabanlı bir derleme sistemiyle çalışırken çok yaygın görülen bazı hata örneklerini aşağıda bulabilirsiniz:

  • A Görevi, belirli bir dosyayı çıktı olarak üretmek için B görevine bağlıdır. B görevinin sahibi, diğer görevlerin buna bağlı olduğunu fark etmez ve bu yüzden görevi farklı bir konumda çıktı üretecek şekilde değiştirir. Bu işlem, bir kullanıcı A görevini çalıştırmayı deneyip başarısız olduğunu tespit edene kadar algılanamaz.
  • A Görevi, A görevi için gereken çıkış olarak belirli bir dosya üreten C görevine bağlıdır. B görevinin sahibi, artık C görevine bağımlı olmasına gerek olmadığına karar veriyor. Bu da B görevi C'yi hiç önemsemiyor olsa da A görevinin başarısız olmasına neden oluyor.
  • Yeni bir görevin geliştiricisi, bir görevin konumu veya belirli ortam değişkenlerinin değeri gibi, görevi çalıştıran makine hakkında yanlışlıkla varsayımda bulunur. Görev, makinesinde çalışır ancak başka bir geliştirici her denediğinde başarısız olur.
  • Görevler, internetten dosya indirme veya bir derlemeye zaman damgası ekleme gibi belirleyici olmayan bir bileşen içerir. Artık kullanıcılar derlemeyi her çalıştırışlarında farklı sonuçlar alabilirler. Yani mühendisler, otomatik derleme sisteminde oluşan hataları veya hataları her zaman yeniden oluşturup düzeltemez.
  • Birden fazla bağımlılığı olan görevler yarış koşulları oluşturabilir. A görevi hem B görevine hem de C görevine bağlıdır, B ve C görevi aynı dosyayı değiştirirse A görevi, önce B ve C görevlerinden hangisinin tamamlanacağına bağlı olarak farklı bir sonuç elde eder.

Burada açıklanan göreve dayalı çerçeve içinde bu performans, doğruluk veya bakım sorunlarını çözmenin genel amaçlı bir yolu yoktur. Mühendisler derleme sırasında çalıştırılan rastgele kodlar yazabildiği sürece sistem, derlemeleri her zaman hızlı ve doğru bir şekilde çalıştırabilmek için yeterli bilgiye sahip olamaz. Bu sorunu çözmek için mühendislerin gücünden bir miktar enerjiyi geri alıp sistemin kontrolüne vermeli ve görevleri işlerken değil, yapı oluşturarak sisteme ait rolü yeniden kavramlandırmalıyız.

Bu yaklaşım sayesinde Blaze ve Bazel gibi yapı tabanlı derleme sistemleri geliştirildi.