CMake ile Çalışmak

C++DerlemeCMake | | Barış Çelik<bariscelikweb@gmail.com>

CMake, açık kaynak, çapraz platform bir derleme, test etme ve paketleme aracı ailesidir.

Derleme, Test, Paketleme

Çeşitli derleyicilerin, çeşitli kodlarını öğrenmek ve uygulamak oldukça zaman alan ciddi bir iştir. Ayrıca bu alanda yoğun bilgi birikimine sahip olanlarımız bile çok fazla hata yapmaktadır.

Modern bir yazılım oluşturmak için her zaman kod odaklı olmak vazgeçilmezimizdir. Verimlilik, ancak sadece kodlarla ilgilenmeye başladığınızda kendini gösterebilir. Bazen yazdığınız kodu derlemek için kendi Makefile‘ınızı yazmak oldukça kasvetli, can sıkıcı ve gerçekten bir o kadar da motivasyonu bozan bir işlem olabilir. CMake bu noktada devreye girip Makefile dosyalarınızı kendisi yazar.

CMake’in temel avantajlarıyla başlayalım:

  • Kolay öğrenilir
  • Çapraz platformdur
  • Evrenseldir
  • Açık kaynak projelerin birçoğu CMake kullanır
  • Organizasyonu sağlar
  • Odağınızın derleme, test etme, paketleme, linker, kütüphaneler vb. gibi onlarca konuya değil, doğrudan koda kaymasını sağlar

CMake adeta bir derleme otomasyonu sistemidir. Otomasyon kelimesi karmaşık gelmesin. CMake karmaşık işleri basite indirgemek, organizasyonu artırmak için geliştirilmiş bir araçtır.

Başlangıç

Proje dizininizin içinde bir CMakeLists.txt dosyası oluşturun.

# proje adı
project(MathSolver)

# minimum cmake sürümü
cmake_minimum_required(VERSION 2.8)

# çalıştırılabilir dosya (executable) oluşturun
add_executable(MathSolver mathsolver.cpp integral.cpp derivative.cpp)

Oluşturduğunuz dosyaya versiyon numarası da ekleyebilirsiniz.

set(MathSolver_VERSION_MAJOR 1)
set(MathSolver_VERSION_MINOR 0)

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

include_directories(include_dir)

Kütüphane eklemek için

# static library
add_library(MathSolver STATIC FxParser)

# shared library
add_library(MathSolver SHARED FxParser)

# module library
add_library(MathSolver MODULE FxParser)

STATIC Yalnızca derleme zamanında doğrudan gömülebilen kütüphane SHARED Derleme zamanında linklenebilen ve çalışma zamanında yüklenebilen kütüphane MODULE Derleme zamanında linkleme olmaksızın, çalışma zamanında ihtiyaç hâlinde yüklenebilen kütüphane

Örnek Proje

Aşağıdaki gibi örnek bir proje yapısı üzerinden gidelim. Bir matematik kütüphanesine ait proje yapısı:

  • bin
  • build
  • doc
    • CMakeLists.txt
  • include
    • math
      • integral.cpp
      • integral.h
  • lib
  • src
    • math.cpp
    • CMakeLists.txt
  • test
    • integral.h
    • CMakeLists.txt
  • CMakeLists.txt

Ana dizindeki CMakeLists.txt dosyamız ana proje dosyası; src/CMakeLists.txt ve test/CMakeLists.txt ise alt proje dosyalarımız.

Minimal CMake

Öncelikle temel CMakeLists.txt dosyamızı oluşturalım.

# proje adı
project(MathSolver)

# minimum CMake sürümü
cmake_minimum_required(VERSION 2.8)

Seçenekler

CMakeLists.txt dosyamıza çeşitli seçenekler ekleyip bunları kullanabiliriz. Örneğimizde doxygen ile dökümantasyon oluşturulması ve testlerin derlenmesi seçeneklerimiz olsun.

Seçenekler için syntax şu şekildedir: option(ayar_adı "ayarın açıklaması" varsayılan_durum[ON/OFF])

option(BUILD_DOXYGEN "Build documentation" OFF)
option(BUILD_TESTS "Build tests" OFF)

Alt Proje Dizini Oluşturma

Örnekte ana dizindeki CMakeLists.txt dosyasında, alt dizinlerdeki CMakeLists.txt dosyalarını bağımsız şekilde tanıtabiliriz.

add_subdirectory(src)

Mantıksal Operatörler

CMakeLists.txt dosyalarında mantıksal operatörler kullanılabilir. Örneğin yukarıda belirlediğimiz seçeneklere göre alt proje dizinlerini dahil edebiliriz.

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.

# değişken oluşturma & değer atama
set(disable_derivative on)

# global değişkene değer atama (çalışma dizini yolu gösteriliyor)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)

Pratik

Görüldüğü gibi CMake derleme işlemlerini organize etmemize, kolaylaştırmamıza yarayan bir araçtır. Tüm bu anlattıklarımızın sonucunda aşağıdaki gibi bir CMakeLists.txt oluşturabiliriz.

# proje adı
project(MathSolver)

# minimum CMake sürümü
cmake_minimum_required(VERSION 2.8)

option(BUILD_DOXYGEN "Build documentation" OFF)
option(BUILD_TESTS "Build tests" OFF)

# değişken oluşturma & değer atama
set(disable_derivative on)

# global değişkene değer atama (çalışma dizini yolu gösteriliyor)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)

add_subdirectory(src)

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

if(BUILD_DOXYGEN)
    add_subdirectory(docs)
endif(BUILD_DOXYGEN)

Değişkenler

CMake ile kullanabileceğiniz değişkenlerin bir kısmı bilgi sağlar, bir kısmı da atama yapmak için uygundur. Ortam değişkenleri ise standart değişkenlerden, asla önbelleğe alınmaması ve global scope’ta çalışması gibi farklarla ayrılırlar. Bazı önemli CMake değişkenleri:

DEĞİŞKENAÇIKLAMA
CMAKE_SOURCE_DIRCMakeLists.txt dosyasının bulunduğu üst-seviye klasör
PROJECT_NAMEproje adı (PROJECT() komutuyla belirlenebilir)
PROJECT_SOURCE_DIRProje kaynak klasörünün tam yolu.
CMAKE_MAJOR_VERSIONMajör CMake sürüm numarası
CMAKE_MINOR_VERSIONMinör CMake sürüm numarası
CMAKE_C_COMPILERC dosyaları için kullanılan derleyici. Normalde CMake çalışırken sistem derleyicisini otomatik tespit eder, farklı bir derleyici kullanmak için bu değerin üzerine yazabilirsiniz. CMake ilk çalıştırıldıktan sonra bu değer değiştirilemez.

Mesaj Yazdırma

CMake ile mesaj yazdırmak için message([<mode>] "Hello World!") söz dizimini kullanılmaktadır. mode parametresi için:

MODAÇIKLAMA
STATUSBilgi metni
WARNINGCMake Uyarısı, işlem devam eder
AUTHOR_WARNINGCMake Uyarısı (kod), işleme devam eder
SEND_ERRORCMake Hatası, işleme devam eder fakat oluşturmayı atlar
FATAL_ERRORCMake Hatası, işlemi ve oluşturmayı durdurur
DEPRECATIONCMake Kullanımdan Kaldırılma Hatası, CMAKE_ERROR_DEPRECATED ya da CMAKE_WARN_DEPRECATED değişkeni aktif değilse hata vermez

İşletim Sistemini Algılama

Özellikle cross-platform yazılım üretirken, desteklenen işletim sistemlerine özgü prosedürler, kodlar ya da kütüphaneler olabilir. Örneğin; arayüz (GUI) kütüphanesi olarak her iki işletim sisteminin de native kütüphanelerini kullanmak gerekebilir. Bu durum işletim sistemini algılamayı gerektirir. Bazı işletim sistemleri için algılama aşağıdaki gibi yapılabilir.

# Windows işletim sistemleri
if (WIN32)

endif()

# Unix tabanlı işletim sistemleri (Apple OS X de dâhil)
if (UNIX)
    
endif()

# Apple Mac OS X işletim sistemi
if (APPLE)

endif()

# Linux işletim sistemleri
if(UNIX AND NOT APPLE)

endif()

Derleyiciye Parametre Eklemek

CMake ile derleyiciye manuel olarak parametre geçebilirsiniz. Bunu yaparken mevcut parametreleri de muhafaza edip, istediğiniz parametreyi eklemek için aşağıdaki kodu inceleyin.

# old-style-cast hatalarını görüntüler. Örn: (int) 2/3;

# derleyicinin tek parametresi aşağıdaki gibi olur
set(CMAKE_CXX_FLAGS "-Wold-style-cast")

# mevcut parametrelerin sonuna ekleme yapar
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wold-style-cast")

Include Klasörü Eklemek ve Kütüphaneleri Bağlamak

# include klasörü eklemek
include_directories("inc")

# kütüphaneyi bağlamak/linklemek
target_link_libraries(MathSolver ${Boost_LIBRARIES})