Günümüzde oldukça fazla programlama dili ortaya çıkmıştır. Bu dillerde yazılan programlardan bazıları derleme (compiling) ile bazıları ise yorumlama (interpreting) ile kullanıma uygun hale getirilmektedirler. Bildiğiniz gibi bir dosyaya bir programlama dili ile bir şeyler yazmak ile işler bitmez. Bu kodları ya derleyerek çalıştırılabilir dosya (executable file) veya kütüphane (library) haline getirmeli ya da direk yorumlayarak onları çalıştırmalısınız. Elbette burada derleme kavramını biraz açmakta fayda var; normalde derlemeye dayalı bir programlama dilinde, kaynak dosyaya yazılan kodlar temsili olarak iki aşamadan geçerek çalıştırılabilir dosya veya kütüphane haline getirilirler: Derleme (Compiling) ve Bağlama (Linking).
Ancak derleme kavramı bu ikisinin birleşimini ifade etmek için de kullanılmaktadır. Bu iki kavramı karşılayacak daha genel bir terim ise Build terimidir. Bu terim de aslında Türkçe’ye "derleme" olarak çevrilse de aslında bundan fazlasını ifade eder. Ben de şimdilik bu terimi değiştirmeden, yani Türkçe’ye çevirmeden kullanacağım. Build, yazılan kaynak kodların çalıştırılabilir dosyaya, veya statik/dinamik kütüphane dosyasına çevrilme sürecini ifade eden bir kavramdır. Bunun içerisinde temelde derleme (compiling) ve bağlama (linking) aşamaları yer alsa da pek çok farklı aşama da yer alabilir. Yine derleme sonucunda daha farklı çıktılar elde edilmek istenebilir veya çeşitli Script dosyaları çalıştırılmak istenebilir.
Build Otomasyonu Nedir
Gördüğünüz gibi Build oldukça geniş bir kavramdır. Onun bu kadar geniş olması, özellikle büyük çaplı projelerde doğrudan komut satırından derleyici program ile derleme işlemini zorlaştıracaktır. Örneğin bir C++ projesini baz alalım. Bildiğiniz gibi C++’ın GCC, Clang, MSVC, Apple Clang, Intel C++ gibi pek çok farklı derleyicisi (compiler) bulunmaktadır. Elbette bu derleyicilerin C++ kodunu derleyebilmesi için çeşitli komut satırı programları; bu programların her birinin de alabileceği birçok argümanı bulunmaktadır. Örneğin "hello.cpp" isimli bir dosyayı GCC derleyicisinde derleyebilmek için komut satırına şunu yazmamız gerekir (herhangi bir Linux dağıtımında olduğunuzu varsayıyorum):
g++ hello.cpp -o hello
Burada "-o" seçeneği ile, derleme sonucunda ortaya çıkacak olan çalıştırılabilir dosyanın ismini belirtiyoruz. Bu size oldukça basit görünüyor değil mi? Ancak bir de şöyle düşünün: Birden fazla alt dizinden oluşan ve bu alt dizinlerin her birinde belli başlı kaynak kodlar bulunan, bu kaynak kodların da sistemdeki veya sistem dışındaki bazı kütüphanelere bağımlılıkları olan bir projeniz olsun. Bu projeyi yukarıdaki gibi derlemek bu kadar kolay olmayacaktır. Öncelikle belli gruplarda amaç kod (object code) adı verilen dosyaları oluşturup daha sonra bu dosyaları beğımlılıklar ile birlikte bağlayarak en son çalıştırılabilir dosyayı oluşturmanız gerekir. Bu işi el ile yapmak hiç de kolay olmayabilir.
İkinci sorunumuz ise şöyle bir senaryoda karşımıza çıkmaktadır: Yazdığınız bir kodu hem bir Linux dağıtımında, hem Windows’ta hem de MacOS’ta derleyerek, bu sistemlere özel çalıştırılabilir dosyalar oluşturmak istediğinizi düşünün. Bildiğiniz gibi her derleyici her işletim sisteminde kullanılmaya uygun değildir (bazı yolları olsa da gereksiz zaman kaybına neden olur). Bu yüzden her bir platform için ayrı ayrı derleyici kullanmanız gerekebilir. Bunun yanında her bir deleyicinin komut satırı araçlarının ismini ve bu araçların aldığı belli başlı argümanları de bilmeniz gerekir. İşte bu da çapraz platform (cross-platform) bir uygulamanın çektiği en büyük sıkıntılardan biridir.
Yazılımcılar bu gibi problemler için Build Otomasyonu (Build Automation) adı verilen bir kavram ortaya atmışlardır. Build otomasyonu, bir yazılımın Build sürecini ve bu süreç sonunda yapılacak olan işlemleri (test etme, paketleme vb.) otomatikleştirmeye verilen isimdir. Bunu da belli başlı araçlar kullanarak gerçekleştirebiliriz. Bu araçlara ise Build Otomasyon Yazılımları (Build Automation Software) adı verilmektedir. Aslında IDE (Integrated Development Environment) adı verilen yazılımlar arkaplanda bu araçlara güvenerek işlerini yürütmektedirler. Bu şekilde IDE yazılımları ile derleme (compiling), bağlama (linking), test etme (testing), paketleme (packaging) gibi pek çok aşamayı yönetebilirsiniz.
Build Otomasyon Yazılımlarının Kategorilendirilmesi
Build otomasyon araçlarından en bilineni Make olarak bilinen ve Makefile adı verilen dosyaları okuyarak, kaynak kodlardan çeşitli çalıştırılabilir dosyalar ve kütüphaneler oluşturmaya yarayan programdır. Make, Unix ve Unix-benzeri işletim sistemlerinde oldukça popüler bir araçtır. Onun bu popülerliği aslında Makefile adı verilen dosyaya dayanır. Bu dosya ile Build işleminin çeşitli aşamalarında ne yapılacağını belli bir söz dizimi ile belirleyebilirsiniz. Ayrıca kullanacağınız bağımlılıkları da basit bir şekilde belirtebilirsiniz. Aşağıda basit bir Makefile dosyasının içeriği verilmiştir[1]:
# Since the blah target is first, it is the default target and will be run when we run "make"
blah: blah.o
cc blah.o -o blah
blah.o: blah.c
cc -c blah.c -o blah.o
blah.c:
echo "int main() { return 0; }" > blah.c
clean:
rm -f blah.o blah.c blah
Bu dosyanın bulunduğu dizinde make komutunu çalıştırarak Build işlemini gerçekleştirebilirsiniz. Bu araç ve sağladığı özel söz dizimi o kadar popüler hale gelmiştir ki Build otomasyon yazılımları Make bazlı (Make-based) ve Make ile uyumsuz (Make-incompatible) olmak üzere ikiye ayrıldılar. Make bazlı olan otomasyon araçları Makefile dosyasını ve onun söz dizimini desteklerler. Diğer araçlar ise kendi dosya yapılarına ve söz dizimlerine sahiptirler. Make bazlı olan otomasyon araçlarından bazılarını ve kullanılabilecekleri platformları şöyle sıralayabiliriz:
- GNU Make (Unix bazlı sistemler, Inferno)
- MPW Make (Classic Mac OS)
- Nmake (Windows)
Make ile uyumsuz olan bazı popüler otomasyon araçları ve onların destekledikleri platformları ise şu şekilde verebiliriz:
- Apache Ant (Java SE)
- Bazel (GNU/Linux, Windows, MacOS)
- Gradle (GNU/Linux, Windows, MacOS)
- IncrediBuild (GNU/Linux, Windows)
- Ninja (GNU/Linux, Windows, MacOS)
Elbette bu araçlar Build otomasyonunun sadece küçük bir kısmını oluşturmaktadırlar. Bunlara ek olarak Build Script’i Oluşturma Araçları (Build Script Generation Tools) olarak adlandırılan birtakım yazılımlar vardır. Bu yazılımlar kendi söz dizimi ve dosya yapıları ile yukarıda bahsettiğim otomasyon araçlarına özel Script’leri oluşturmaya yararlar. Yani bu programların kendileri doğrudan Build işlemini gerçekleştirmezler (elbette bunu gerçekleştiren komut satırı yazılımları da bulunur), sadece Build işlemini gerçekleştirecek araçla ilgili kodları oluştururlar. Böylelikle yaptığımız programı çapraz platform olarak, farklı araçlar ile rahatlıkla Build edebilme imkanı sunarlar. Bu araçlardan en bilinenlerini şu şekilde verebiliriz:
- CMake
- GNU Build System (autotools)
- Meson
- qmake
- xmake
Günümüzde artık yüzlerce kişiye ulaşan yazılım takımlarını görmeye şaşırmamak gerek. Takımdaki kişi sayısının çoğalması projelerin her zaman hızlı yürüyeceğini göstermez. Bazen 5 kişilik iyi yönetilen bir takım, 15 kişilik kötü yönetilen veya doğru araçları kullanmayan bir takımdan daha iyi iş çıkarabilir. Yazılım mühendisliğinde bu tip takımlarda çalışan geliştiricilerin, kaynak kodlarında yaptığı değişiklikleri sürekli olarak entegre etme ve çalışılabilirliğinden emin olma pratiğine Continuous Integration (Sürekli Entegrasyon, CI) adı verilmektedir. Bu yöntemi kullanan çeşitli araçlardan en bilinenlerini şu şekilde sıralayabiliriz:
- Bamboo
- Bitbucket
- GitLab Runner
- GitHub Actions
- Hudson
- Jenkins
- TeamCity
- Travis CI
Bu yazılımların bazıları yerel makinelerde de iş yapabilirken, bazıları ise çevrimiçi olarak çalışmaktadır. Bu yazılımların örnek bir listesini burada göstermemdeki amaç ise, onların genelde Build araçlarını ve Build Script’i oluşturma araçlarını kullanmalarıdır. Bunun yanında Configuration Management Tools (Konfigürasyon Yönetim Araçları) olarak adlandırılan ve yine Build otomasyon araçlarını sıklıkla kullanan daha gelişmiş araçlar bulunmaktadır. Bu araçlar büyük yazılım projesinde kullanılan depolama alanlarını, sunucuları ve ağları belli Script’ler ile otomatikleştirirler. Bu araçlardan en popülerleri ise şöyledir:
- Ansible
- CFEngine
- Chef
- Puppet
- Salt
Bunun dışında pek çok farklı amaca hizmet eden Build otomasyon aracı bulunsa da bunlar konuyu dağıtacağından burada bahsetmek istemiyorum. Aslında genel olarak Build otomasyon araçlarını iki kategoride toplayabiliriz. Bu kategoriler, anlamları ve örnekleri şöyledir[2]:
- Build Otomasyonuna Yardımcı Araçlar (Build Automation Utilities): Temel amaçları kaynak kodlarını çeşitli hedef dosyalara Build etmek olan bu araçlar ile, kaynak kodun derlenmesi ve bağlanması gibi aşamaları gerçekleştirmek mümkündür. Make, CMake, Apache Ant ve Gradle gibi araçlar bu kategoriye girer.
- Build Otomasyon Sunucuları (Build Automation Servers): Bu araçlar Build otomasyon işlemini web tarafında çözmeye çalışırlar. En tipik örnekleri ise Continuos Integration kategorisine giren ve çevrimiçi olarak kullanılabilen araçlardır.
Build otomasyon araçlarının projelere çok büyük faydaları vardır. Bunlardan en önemlisi derleme ve bağlama başta olmak üzere, pek çok Build aşamasını kolay bir şekilde yöneterek bu aşamaların hızlı bir şekilde gerçekleştirilmesini sağlarlar. Böylelikle yazılımların yanlış derlenmesinden ortaya çıkabilecek sorunları azaltır ve kaliteli bir yazılım oluşturmayı amaçlarlar.
Bu araçların yardımcı olduğu bir başka önemli konu ise proje bağımlılıklarıdır. Projedeki bağımlılıklar belki de geliştiricilerin en fazla sıkıntı çektiği yerlerdir. Çünkü bağımlılıkları el ile yönetmek hem kullanılan platform ile ilgili bilgi birikimi ister hem de bu bağımlılıkların bir kaos yaratmaması için düzgün bir formda düzenlenmesini gerektirir. Build otomasyon araçları ile bu bağımlılıklar daha kolay bir şekilde ele alınabilmektedir.
CMake Nedir
Şimdi de esas konumuz olan CMake’e geçelim. CMake çapraz platform, ücretsiz ve açık kaynak kodlu bir Build Script’i oluşturma ve Build süreci yönetme aracıdır. Bu araç ile bulunduğunuz sistemdeki Make, Qt Creator, Ninja, Android Studio, Xcode ve Microsoft Visual Studio gibi Build ortamları için proje ve Script dosyaları oluşturabilirsiniz. Eğer sisteminizde bir C++ derleyicisi bulunuyorsa, CMake bunu genellikle otomatik olarak algılayacak ve ona göre işlem yapacaktır.
CMake aslında sadece Build etme sürecini değil, bir kaynak kodun Build edilmesinden testine ve oradan da paketlemesine kadar pek çok süreci yönetebilen aracı içerisinde barındırır. CMake’in bu süreçte kullandığı araçları şu şekilde görselleştirmemiz mümkündür:
CMake 1999 yılında ITK (Insight Segmentation and Registration Toolkit) isimli bir çatının geliştirme ihtiyaçlarına yanıt olarak doğmuş bir Build aracıdır. İlk implementasyonu ise 2000 yılında gerçekleşmiştir. Bu yıllardan beri CMake üzerinde pek çok geliştirmeler yapılmış ve pek çok projede onun kullanımı benimsenmiştir. 2014 yılında yayımlanan 3.0 sürümü ile "Modern CMake" doğmuştur. Ben bu yazıyı yazarkenki en stabil sürümü ise 3.30.1 sürümüydü. CMake ile içerisinde yer alan (ve yukarıdaki figürde belirtilen) CTest ve CPack isimli araçlar ile, Build sonrası test etme ve paketleme işlemlerini de gerçekleştirebilirsiniz. CPack şu paket türlerini desteklemektedir:
- Çeşitli arşiv dosyaları (7Z, TGZ, TXZ, TZ, ZIP vb.)
- Bundle (macOS)
- DEB paketi (UNIX)
- FreeBSD paketi
- Inno Setup yükleme paketi (Windows)
- NSIS dosyaları (Windows)
- RPM paketi (UNIX)
- WIX
CMake ile ilk başta proje ile ilgili genel tanımlar alınır ve kullanılan Build aracına ve platforma göre proje dosyaları oluşturulur. CMake hem Visual Studio, Xcode ve Eclipse CDT gibi IDE’ler için proje dosyaları oluşturmayı desteklerken hem de MSBuild, NMake, Unix Make ve Ninja gibi Build otomasyon yazılımları için Script oluşturmayı destekler. Onun hem platformlara hem de diğer derleme araçlarına olan bu büyük desteği, günümüz projelerinde onun kullanımını vazgeçilmez kılmıştır. CMake aracı C, C++, C#, CUDA, Objective-C, Objective-C++, Fortran, Swift, Assembly (NASM, MASM) gibi dilleri doğal olarak desteklemektedir. Sanılanın aksine baş harfindeki "C" programlama dilini değil "Cross-platform" kelimesini belirtmektedir.
Görsel CMake Araçları
CMake’in hem bir komut satırı programı hem de GUI yazılımları vardır. CMake’in komut satırı yazılımı cmake ismi ile kullanılır. CMake’in resmi GUI aracı ise cmake-gui olarak bilinir. Bu araç genellikle CMake yüklemeleri ile beraber gelmektedir ve eğer sisteminiz grafiksel arayüzü destekliyorsa, bu aracı rahatlıkla kullanabilirsiniz. Bu aracı kullanarak CMake projesi ile ilgili çeşitli değişkenleri görsel olarak düzenleyebilirsiniz. Bunun yanında derleme ortamlarını seçme, Log girdilerini görüntüleme ve Build ile ilgili nelerin yanlış gittiğini görsel olarak takip etme gibi pek çok işi bu araç ile yapabilirsiniz.
CMake’in bir de tam olarak grafiksel olmasa da komut satırı üzerinden etkileşimli olan bir aracı daha bulunmaktadır. ccmake isimli bu araç ile CMake’in GUI aracının benzer özelliklerini komut satırı üzerinde kullanabilirsiniz. Bu aracı, kullandığınız işletim sisteminde grafiksel arayüz olmadığı zamanlarda cmake-gui yerine alternatif olarak tercih edebilirsiniz.
Bu yazıda Build otomasyonu ile ilgili araçlara ve bunarın ne tür kategoriler ile incelendiğine değindim. Bu araçların yazılım projelerinde nasıl bir hayati öneme sahip olduğunu açıklamaya çalıştım. Ayrıca bu araçlardan belki de en sık karşımıza çıkan ve hemen hemen günümüzdeki bütün C ve C++ yazılım projelerinde kullanılan CMake otomasyon aracına ve onun özelliklerine kısaca değindim. En son ise bu aracın grafiksel arayüz sağlayan türevlerini çok kısa anlattım. Bundan sonraki yazılarda artık CMake aracının ayrıntılarına gireceğim.






CMake üzerine anlatım ve eğitimler çok kısıtlı iken Türkçe kaynak bulmak çok güzel. diğer mevcut kaynakların çoğu çok kafa karıştırıcı ve konunun en temel özelliklerini atlayarak anlatıyor. Güzel ve sade anlatımınız için teşekkürler hocam 🙂
C++ derslerinizi inceleme fırsatım daha olmadı ama referans olarak dilerseniz learncpp sayfasını kullanabilirsiniz hem detaylara inen anlatımı hem büyük bir yorum topluluğu var ayrıca sürekli güncel kalıyor.
Öncelikle güzel düşünceleriniz için teşekkür ederim 🙂 C++ eğitimini planladım ve birkaç makaleyi yayınladım. Ancak sonra bir öz eleştiri yapıp düşündüm ki biraz çağ dışı ve konuya çok ortadan giren bi plan olduğunu farkettim. Bildiğiniz gibi C++ her geçen gün güncelleniyor ve pek çok yeni özellik dile ekleniyor. Onunla ilgili planımı sıfırlayıp sıfırdan daha güncel bir C++ eğitimi planlıyorum. Ancak iş yoğunluğundan dolayı biraz vakit alacak. Takipte kalmaya devam edin 🙂