Cmake

Açıklama

Çoğu programlama dili ile yazılan kodun çalıştırılabilir olması için derlenmesi gerekir.Derleme işlemi sırasında derleyiciye uygun parametrelerin eklenmesi, gerekli kütüphanelerin dahil edilmesi, birim testlerin çalıştırılması gibi işlemler yapılır. Tüm bu işlemler için sadece IDE kullanılabildiği gibi IDE ile birlikte başka araçlarlar ile de yapılabilir. Ancak IDE programlarının ayarları birbirinden farklıdır (Eclipse, VS). Bir IDE tüm işletim sistemlerinde yer almayabilir (VS). Aynı IDE farklı işletim sistemlerinde farklı ayarlara sahip olabilir (Eclipse). Önceki bölümde görüldüğü üzere Makefile ile bu iş yapılaiblir ancak Makefile’ın gerektirdiği make sadece Linux/Unix tabanlı işletim sistemlerinde gayet iyi çalışmaktadır. Windows’da fazla bir kullanım söz konusu değildir (nmake aracı olsa da). Bu durumları görmezden gelsek bile proje büyüdüğünde Makefile ile uğraşmak zorlayıcı olabilmektedir. Öte yandan, bir makefile ile yönetilen projeyi bağımsız şekilde istenilen bir IDE ortamında açmak uğraştırıcı olmaktadır.

İşte bu gibi sorunlara Cmake yardımcı oluyor. CMake C/C++ program oluşturma sürecini işletim sisteminden ve derleyiciden bağımsız bir şekilde gerçekleştirmemize olanak sağlayan açık kaynak kodlu ve çapraz platformlu bir sistemdir. Sisteminizdeki derleyici ve IDE’ye göre projeyi kullanabilecek konfigürasyonları üretebilir. Ek olarak test etme ve paketleme yapmamızı da sağlar.

  • Cmake Kullanan Bazı Projeler
    • OpenCV Bilgisayar görüsü alanında en popüler açık kaynak bir kütüphane.
    • KDE KDE’nin masaüstü programı
    • MySQL Dünyanın en bilinen açık kaynaklı veri tabanı programı
    • Boost C++ için standart birçok kütüphane içeren oldukça popüler kütüphaneler kümesi.

Kullanım

Öncelikle, “https://cmake.org/download” sayfasından işletim sisteminize göre kurulum yapılabilir. Alternatif olarak, ilgili ortamlar için tercih edilebilecek linkler:

Linux ortamında ise aşağıdaki formatta kurabilirsiniz.

$ <package_manager dnf, apt-get> install cmake

Nasıl ki, make uygulaması için bir Makefile gerekliyse Cmake uygulaması içinde bir dosya gerekli, ismi de “CmakeLists.txt”. Bu dosyanın içine, proje adı, çalıştırılabilir dosyalar, kütüphanelerin yönetimi (nasıl ekleneceği) gibi ayarlar yaparak aslında proje ile alakalı daha soyutsal bilgiler veririz. Sonra cmake programı zaten hiyerarşiyi, proje ismini, bağımlı olunan kütüphaneleri vb. bilgileri içeren dosyanın yardımıyla istediğimiz IDE için varsa yine istediğimiz derleyici için konfügurasyonlar oluşturacağız hatta ve hatta Makefile’ın kendinisini de bu yolla oluşturabileceğiz.

Şimdi basit bir Cmake projesi yapalım. Öncelikle bir “app.cpp” oluşturalım içine “Merhaba Dünya” örneği kod yazalım.

#include <iostream>

int main()
{
  std::cout << "Hello world cmake" << '\n';
  return 0;
}

“CMakeLists.txt” dosyasının oluşturulalım ve içine aşağıdaki yazıları yazalım.

project(TestApp)
cmake_minimum_required(VERSION 3.16.3) 
add_executable(TestApp app.cpp)
set(TestApp_VERSION_MAJOR 1)
set(TestApp_VERSION_MINOR 0)
  • Bu dosya içerisinde aşağıdaki temel ayarların anlamına değinelim.
    • project : Projenin adını belirttiğimiz yerdir. Eğer cmake kullanarak VS için proje dosyaları üretirsek “TestApp.sln” dosyası oluşacaktır.
    • cmake_minimum_required : Proje için gerekli olan en düşük Cmake sürümününü belirtir. Cmake sürümleri arasında farklılıklar vardır. Cmake geliştikçe yeni özellikler kazanmaktadır.
    • add_executable : Çalıştırılabilir dosyanın hangi dosyalarla oluşturulacağını ifade eder. Tabi büyük projelerde dosyaları el ile bu şekilde yazmıyoruz.
    • set : Bir değişkene (sol taraf) bir değer atar (sağ taraf). Buradaki değişkenler Cmake tarafından kullanılacak global değişkenler olabildiği gibi, kendinize özgü de olabilir.

Evet, bu kadar. Başka birşeye gerek yok. Şimdi elimizde Cmake ile desteklenmiş bir proje var. Nasıl kullanacağız?

Ayrıntılar

  • Dahil edilecek dosyaların aranacağı yolları eklemek için (include path):

    include_directories(include_dir)
  • Kütüphane eklemek için:

       add_library(Cfile STATIC FxParser) : statik kütüphane
       add_library(Cfile SHARED FxParser) : paylaşılan kütüphane
       add_library(Cfile MODULE FxParser) : modül kütüphane 
  • Static yalnızca derleme zamanında doğrudan gömülebilen kütüphanedir.

  • Shared derleme zamanında linklenebilen ve çalışma zamanında yüklenebilen kütüphanedir.

  • Module derleme zamanında linkleme olmaksızın, çalışma zamanında ihtiyaç hâlinde yüklenebilen kütüphanedir.

CMakeLists.txt dosyamıza çeşitli seçenekler ekleyip bunları kullanabiliriz. Örnek olarak doxygen ile dokümantasyon oluşturulması ve testlerin derlenmesi seçenekler olsun.

Seçenekler için syntax şu şekildedir:

option(ayar_adı "ayarın açıklaması" varsayılan_durum[ON/OFF])
   option(BUILD_DOXYGEN "Insa dokumentasyonu" OFF)
   option(BUILD_TESTS "Insa testleri" OFF)
  • Alt Proje Dizini Oluşturma

Oluşturulan kütüphaneyi kullanmak için add_subdirectory ile kütüphane için oluşturulan CMakeLists.txt projeye eklenir.

   add_subdirectory(kutuphaneAdı)
  • Mantıksal Operatörler

CMakeLists.txt dosyasına mantıksal operatörler gibi alt dizinler ekleyebiliriz.

  if(BUILD_TESTS)
    add_subdirectory(test)
  endif(BUILD_TESTS)

  if(BUILD_DOXYGEN)
    add_subdirectory(docs)
  endif(BUILD_DOXYGEN)
  • Değişken Atama

CMake ile değişken atamak için set komutunu kullanmamız yeterlidir. Bu komut ile hem CMake’in global değişkenlerini atayabiliriz hem de yeni değişkenler oluşturup değer atayabiliriz.

   set : versiyon atama
   set(Cfile_VERSION_MINOR 0) -> versiyon atama
   set(disable_derivative on) -> değişken oluşturma & değer atama
   set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) -> global değişkene değer atama -çalışma dizini yolu gösteriyor.

Tüm anlatılanları toplama açısından bir CMakeLists.txt örneği aşağıdadır.

 
 project(Cfile)
 
 cmake_minimum_required(VERSION 3.16.3)

 option(BUILD_DOXYGEN "Insa dokumentasyonu" OFF)
 option(BUILD_TESTS "Insa testleri" OFF)

 set(disable_derivative on)
 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)

 add_subdirectory(kutuphaneAdı)

 if(BUILD_TESTS)
    add_subdirectory(test)
endif(BUILD_TESTS)

if(BUILD_DOXYGEN)
    add_subdirectory(docs)
 endif(BUILD_DOXYGEN)
  • Bazı Önemli Cmake Değişkenleri

    • CMAKE_SOURCE_DIR -> CMakeLists.txt dosyasının bulunduğu üst seviye klasör.
    • PROJECT_NAME -> Proje adı. project() komutuyla belirlenebilir.
    • PROJECT_SOURCE_DIR -> Proje kaynak klasörünün tam yolu.
    • CMAKE_MAJOR_VERSION -> Majör Cmake sürüm numarası
    • CMAKE_MINOR_VERSION -> Minör Cmake sürüm numarası
  • Derleyiciye Parametre Eklemek

  set(CMAKE_CXX_FLAGS "Hello World" -> derleyicinin tek parametresi
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} Hello World") -> mevcut parametrelerin sonuna ekleme yapar.
  • Include Klasörü Eklemek

     include_directories("inc")

    Kütüphane proje eklendikten sonra target_link_libraries ile kütüphane projeye bağlanır.

  • Kütüphaneleri Bağlamak

 target_link_libraries(Cfile ${Boost_LIBRARIES})
  • Örnek olması açısından Ubuntu terminal üzerinden Cmake kullanarak “Hello World” yazdıralım.
     ~/Desktop                                                            ✔ ─╮
╰─ mkdir helloworld   -> helloworld klasörü oluşturduk.                     ─╯
╭─ ~/Desktop                                                              ✔ ─╮
╰─ cd helloworld                                                            ─╯
╭─ ~/Desktop/helloworld                                                   ✔ ─╮
╰─ vim main.cpp                                                             ─╯
  • main.cpp şu şekildedir.
   #include <iostream>
   using namespace std;
   int main() {
        cout << "Hello World!" << endl;
        return 0;
   }
╭─ ~/Desktop/helloworld                                                   ✔ ─╮
╰─ vim CMakeLists.txt                                                       ─╯
   #CMakeLists.txt şu şekildedir.
   cmake_minimum_required(VERSION 3.16.3)
   project(helloworld)
   add_executable(
       helloworld
        main.cpp
   )
╭─ ~/Desktop/helloworld                                                   ✔ ─╮
╰─ cmake .  -> cmake derliyoruz.                                            ─╯
-- The C compiler identification is GNU 9.3.0
-- The CXX compiler identification is GNU 9.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/saturn/Desktop/helloworld
╭─ ~/Desktop/helloworld                                                   ✔ ─╮
╰─ make                                                                     ─╯
Scanning dependencies of target helloworld
[ 50%] Building CXX object CMakeFiles/helloworld.dir/main.cpp.o
[100%] Linking CXX executable helloworld
[100%] Built target helloworld
╭─ ~/Desktop/helloworld                                                   ✔ ─╮
╰─ ./helloworld -> dosyamızı derleyip çalıştırıyoruz.                       ─╯
Hello World!

Avantajlar

  • Verimlidir.
    • Uzun süreli kod yazma, düşük süreli inşa sistemi çözme.
    • Her proje için açık kaynaklı ve ücretsizdir.
  • Güçlü bir yapısı vardır.
    • Cmake çoklu geliştirme ortamlarını destekler ve aynı projede derler.
    • C/C++/CUDA/Fortran/Python gibi birçok programlama dilini destekler.
    • Cmake ile üçüncü parti kütüphaneleri projelerinize entegre edebilirsiniz.
  • Karmaşık işleri basite indirger.
  • Kolay öğrenilir.
  • Çapraz platformdur.
  • Evrenseldir.
  • Makefile dosyalarını Cmake yazar.
  • Organizasyonu sağlar.

Dezavantajlar

  • Dili/Söz dizimi
    • Cmake dili önceden kullandığınız dillerle karşılaştırılmamalıdır. Çünkü sınıf(class), eşleme(map) ve sanal bir fonksiyon ya da lambda ifadeleri içermez. Yeni başlayanlar için giriş argümanlarını çözümlemek ve bir fonksiyonun sonuç döndürmesini anlamak karmaşıktır.
  • İş akışına etkisi
    • Cmake kullanırken projenin inşa konfigürasyonunu doğrudan IDE üzerinden güncelleştirilemez. CMakeLists.txt dosyasına eklenen ya da değiştirilen her target dosyası yazılmalı. Aksi halde IDE üzerinden yapılan güncellemeler ve değişiklikler Cmake çalıştırıldığında kaybolacaktır.
    • Cmake’de inşa betik dilini(script) çalıştırmak için en az bir araç gereklidir.
    • Sınırlı dokümantasyonu vardır.