Uygulama İzleme Yazılımı 4 – Qt Ayarlamaları

Evet dostlar, kısa bir ara verdikten sonra uygulama izleme yazılımı yazılarımıza devam ediyoruz. Bu yazımızda, CMake ile QT kütüphanelerimizi nasıl konfigüre edebilirize bakacağız. Bunu da yaparken uygulama izleme yazılımımızın parçalarını oluşturmaya devam edeceğiz. Önceki yazılarım ile birlikte aslında, uygulama için gerekli alt yapıyı ve anlatmak istediğimi diğer teknolojilere kısa da olsa değinmiş olduk. Bir süre, uygulamanın kendisine yakından bakacağız, fakat bu yazıda ağırlıklı olarak yeni eklediğimiz proje tipleri ve bunlara ilişkin CMake ile ilgili yapılması gereken ayarlara değiniyor olacağız.

Açıkçası, internette CMake’e, QT ve CMake kullanımına ilişkin, bir çok kaynak var ama genelde hep belirli bir noktaya değiniyorlar ve derli toplu bir kaynak bulmak gerçekten zor. Umut ediyorum ki, bu yazı ve proje yapısı QT ve CMake kullanıcıları için güzel bir başvuru ve başlangıç noktası olacak.

Öncelikle, uygulama izleme yazılımına ilişkin önceki yazılara aşağıdan ulaşabilirsiniz:

Uygulama İzleme Yazılımı

Uygulama İzleme Yazılımı 2 – Başlangıç

Uygulama İzleme Yazılımı Serisi 3 – Utility, Birim Testler, Sürekli Entegrasyon

Peki bu yazıda nelere bakıyor olacağız. Hemen kısaca bir özetleyeyim:

  • Daha önce de bir kaç yazımda bahsettiğim soket alt yapısının elden geçirilmesi ve  statik kütüphane olarak eklenmesi,
  • QT statik kütüphane (ağ kabiliyetleri), dinamik kütüphane (varsayılan protokol) ve uygulama örnekleri (istemci test uygulaması),
  • QT dinamik kütüphane oluşturma ve kullanımı,
  • QML uygulama örneği (uygulama izleme sunucu yazılımı),
  • QT için kullanılabilecek CMake ayarları,
  • QT için gerekli bağımlılıkların da CMake aracılığı ile oluşturulan dosyaların yanına kopyalanması.

Gördüğünüz üzere, bir çok konu var değineceğimiz, hemen başlayalım 😉

Genel Yapı ve Projeler

Bu yazı sonunda, VS 2019 içerisinde göreceğiniz proje yapısı aşağıdaki gibi olacaktır. Burada çalıştırılabilir uygulamalarımız “Apps” altında toplanacak, kütüphaneler “Libraries” altında toplanıyor olacak ve üçüncü parti kütüphaneler de “Ext” altında toplanıyor olacak. Test projelerini de “Test” dizini altında toplayacağız.

Yeni eklediğim projelere ve kaynak kodlara ilişkin olabildiğince sizleri yönlendirebilecek, yorumları ekledim. Kodları incelerken sizlere yardımcı olacaktır.

Öncelikle ağ kabliyetlerine ilişkin projlere bakalım. Daha önce bu kabiliyetlere, BÇOM serisinde detaylı bir şekilde değinmiştim. Aslında kabiliyet anlamında yeni bir şey yok. Sadece, orada tek bir kütüphane olarak sunduğumuz soket kütüphanesini burada, rafine alt kütüphanelere ayıyoruz nelerdir bunlar:

  • TCPClient:
    • TCP/IP haberleşme protokolü kullanarak, istemci kabiliyetlerini gerçekleştirmek için ihtiyaç duyulan işlevleri sunar,
    • Gerekli ayarların yapılmasına olanak sağlayan konfigürasyon parametreleri sunulmaktadır,
    • QT C++ statik kütüphane projesidir.
  • TCPServer:
    • TCP/IP haberleşme protokolü kullanarak, sunucu kabiliyetleri gerçekleştirmek için ihtiyaç duyulan işlevleri sunar,
    • Gerekli ayarların yapılmasına olanak sağlayan konfigürasyon parametreleri sunulmaktadır,
    • Birden fazla istemcinin bağlanmasına olanak sağlar,
    • QT C++ statik kütüphane projesidir.
  • UDP:
    • UDP/IP haberleşme protokolü kullanarak, akranlar arası UDP haberleşmesi için ihtiyaç duyulan işlevleri sunar,
    • Gerekli ayarların yapılmasına olanak sağlayan konfigürasyon parametreleri sunulmaktadır,
    • QT C++ statik kütüphane projesidir.
  • NetworkUtility:
    • Ağ alt yapısı ile ilgili bir takım yardımcı servisler (haberleşme cihazları, IP adresleri, vb) sunan kütüphanedir,
    • QT C++ statik kütüphane projesidir.

Şimdi de hızlıca diğer eklediğimiz projelerin işlevlerine ve ne yapacaklarına hızlıca bakalım. Bunların bir kısmını tekrar kullansak da, bir kısmını da bu yazı dizileri boyunca geliştirmeye devam ediyor olacağız.

  • MessageCommon:
    • QT C++ statik kütüphane projesidir,
    • Bu kütüphane içerisinde, uygulama izleme yazılımı haberleşmelerinde kullanacağımız arayüz ve temel sınıflarını içerir. Nelerdir bunlar:
      • IMsgListener:
        • Haberleşme kanalları üzerinden gelen mesajların aktarılacağı sınıflar için arayüz sınıf.
      • IMsgProtocol:
        • Uygulama izleme yazılımı ve istemciler arasında kullanılacak farklı protokoller için kullanılacak arayüz sınıf,
        • Bu arayüz sayesinde farklı mesajlasma protokolleri desteklenecektir.
      • ConnectionBase:
        • Uygulama izleme yazılımı ile, istemciler arasında haberleşme protokolünden bağımsız bir mekanizma için kullanılacak temel sınıftır,
        • Bu arayüz sayesinde izleme için bağlanan sınıfın kullandığı haberleşme yönteminden kendimizi soyutlayacağız.
      • CommonMsgHdrData:
        • Haberleşme için kullanacağımız bütün mesajlara ilişkin ortak bilgileri tutacak veri yapısıdır.
  • MessageLibrary:
    • QT C++ statik kütüphane projesidir,
    • Uygulama izleme yazılımı ile istemciler arasında iletilen mesajlara ilişkin sınıf ve yardımcı veri yapılarını içeren kütüphanedir.
  • DefaultCommProtocol:
    • QT C++ dinamik kütüphane projesidir,
    • IMsgProtocol arayüzünden türetilen ve uygulama yazılımımız için kullanacağımız varsayılan haberleşme protokolünü gerçekler.
  • AMTHostQmlApp:
    • QML uygulama projesidir,
    • Uygulama izleme yazılımını, QML kullanarak geliştiriyor olacağız. Bunun için ağ alt yapısı kütüphanelerini QML ile birlikte kullanacağız ama bu yazıda çok detaya girmeyeceğiz.
  • ClientTestApp:
    • QT C++ uygulama projesidir,
    • Uygulama izleme yazılımını geliştirirken, ilgili kabiliyetleri denemek için kullanacağımız örnek QT C++ projesidir
  • QtDLLTestApp:
    • QT C++ uygulama projesidir,
    • DefaultCommProtocol dinamik kütüphanesinin nasıl kullanılacağına ilişkin örnek bir projedir.

Ayrıca build dizini altında bir batch dosyası (Build.bat) da ekledim. Vs2019 için gerekli dosyaları tıklayarak oluşturabilirsiniz.

Repo’nun son halini her zamanki gibi https://gitlab.com/yazilimperver/applicationmonitoringtool adresinden indirebilirsiniz.

Şimdi artık CMake ile ilgili konulara dalabiliriz.

CMake’e Dair Hususlar

Bu başlık altında yukarıdaki projelerde CMake’e ilişkin kullanılan mekanizmalara değineceğiz. Bunu yaparken de, proje tiplerini referans alıyor olacağız ve olabildiğince aynı tip projeler için aynı yaklaşımı kullanıyor olacağım. Bütünlüğü korumak ve kopmama adına, önceki uygulama izleme yazılımı yazılarıma bakmanızda fayda var.

Öncelikle genel bir kaç konudan bahsedeyim:

  • CMake betikleri içerisinde aynı ismi dolaştırmamak adına, CMakeLists.txt içerisinde proje tipine göre LIB_NAME ve APP_NAME değişkenleri tanımlayarak kullandım (${LIB_NAME}, ${APP_NAME}),
  • IDE içerisinde gösterilecek olan dosyalar SOURCE_FILES, HEADER_FILES ve duruma göre RESOURCE_FILES ve QML_FILES olarak gruplandırdık,
  • Ayrıca cmake komutunu çalıştırırken “-DCMAKE_PREFIX_PATH=”C:\Qt5_14\5.15.0\msvc2019_64\lib\cmake” kısmını da ekliyoruz. Ör. Vs2019 için şöyle bir komut oluyor:
    • cmake .. -G “Visual Studio 16 2019″ -A x64 -DCMAKE_PREFIX_PATH=”C:\Qt5_14\5.15.0\msvc2019_64\lib\cmake”

Statik QT C++ Kütüphaneleri

Öncelikle, statik QT C++ kütüphaneleri için kullandığımız CMake betiklerine bakalım. Bu projelerin çıktısı, windows sistemler için .lib, unix ve benzeri sistemler için .a uzantılı olacaktır. Şimdi, CMake içerisinde bu tarz kütüphaneler için neler yaptığımıza madde madde bakalım:

  • QT Moc (Meta Object Compiler), Rcc (Resource Compiler) ve Uic (User Interface Compiler) araçlarına ilişkin ayarlamalar için aşağıdaki satırları ekliyoruz:
    • set(CMAKE_AUTOMOC ON)
      set(CMAKE_AUTORCC ON)
      set(CMAKE_AUTOUIC ON)
  • Mevcut kod ve oluşturma dizinlerini otomatik olarak eklemek için aşağıdaki komutu ekliyoruz:
    • set(CMAKE_INCLUDE_CURRENT_DIR ON)
  • Qt ile ilgili ihtiyaç duyulan paketleri belirtiyoruz. Burada örneğin “Core, Network” Qt kütüphaneleri ekleniyor. Bunları da projeye göre belirlemelisiniz. Ör:
    • find_package(Qt5 REQUIRED COMPONENTS Core Network)
  • Ayrıca, kullandığınız QT kütüphanelerine ilişkin başlık dosya dizinlerini de eklemelisiniz. Ör:
    • target_include_directories(${LIB_NAME} PUBLIC ${Qt5Core_INCLUDE_DIRS})
      target_include_directories(${LIB_NAME} PUBLIC ${Qt5Network_INCLUDE_DIRS})
  • Son olarak statik kütüphane olması sebebi ile “STATIC” anahtar kelimesini ekliyoruz:
    • add_library(${LIB_NAME} STATIC ${HEADER_FILES} ${SOURCE_FILES})

Temel olarak CMake üzerinde QT statik kütüphanelerine ilişkin öne çıkan ve minimum ayarlar bunlardır. Elbette bunların yanında bir çok ayar daha mevcut. Fakat, bir başlangıç için bunların yeterli olacağını düşünüyorum. Şimdi de, tam bir QT statik kütüphane CMake betik örneğine bakalım:

Dinamik QT C++ Kütüphaneleri

QT için hazırlayacağımız dinamik kütüphaneler de statik kütüphanelere oldukça benziyorlar. Yanlız statik kütüphanelerden farklı olarak dikkat etmemiz gereken bir kaç nokta da var elbette. Nedir bunlar hemen bakalım:

  • Öncelikle statik kütüphane için yazdığım maddelerden sonuncu hariç hepsi, dinamik QT kütüphaneleri için de geçerli. add_library komutunu bu sefer “SHARED” anahtar kelimesi ile kullanıyoruz:
    • add_library(${LIB_NAME} SHARED ${HEADER_FILES} ${SOURCE_FILES})
  • Ayrıca, statik kütüphaneden farklı olarak, QT kütüphanelerini bağlamak için target_link_libraries komutunu da, ilgili QT kütüphaneleri için eklememiz gerekiyor:
    • target_link_libraries(${LIB_NAME} MessageCommon Qt5::Core)
  • Windows için .DLL’e dair tanımlama dosyasını, bütün global semboller ile oluşturmak için aşağıdaki ifadeyi de ekliyoruz:
    • set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS 1)
  • Yukarıdaki kalemin yanında, dinamik kütüphane tarafından sembollerin doğru bir şekilde dışarı sunulması için de, bir tanımlama ekliyoruz. Benzer şekilde bu makroyu, kod içerisinde de ilgili sınıf ve fonksiyonların önünde kullanmamız gerekiyor (bakınız DefaultCommProtocol.h dosyasına):
    • add_definitions(-DDEFAULT_COMM_PROTOCOL_LIB_LIBRARY)
  • Son olarak dinamik kütüphaneler için gerekli “export” makrolarını oluşturmak için aşağıdaki satırları ekliyoruz. Bu fonksiyon için kaynaklara koyduğum adrese bakabilirsiniz. Bir çok parametre içeriyor.
    • generate_export_header(${LIB_NAME}
      BASE_NAME ${LIB_NAME}
      EXPORT_MACRO_NAME DEFAULT_COMM_PROTOCOL_LIB_EXPORT
      EXPORT_FILE_NAME ${LIB_NAME}_Export.h
      STATIC_DEFINE DEFAULT_COMM_PROTOCOL_BUILT_AS_STATIC)

Şimdi de, tam bir QT dinamik kütüphane CMake betik örneğine bakalım:

QT C++ Uygulamaları

QT için hazırlayacağımız uygulamalara bakalım şimdi de. Öncelikle, QT C++  uygulamasına bakalım. Burada da kütüphane projeleri ile ortak kodlar mevcut nedir. Bunların yanında çalıştırılabilir uygulama olması sebebi ile de bir kaç ek fonksyion çağırmamız gerekiyor:

  • find_package, fonksiyonunu yine kullanıyoruz,
  • .ui dosyaları için ayrı bir gruplandırma yapıp, bunları da, nihai çalıştırılabilir dosya fonksiyonuna dahil ediyoruz,
  • .ui dosyalarını bulması için aşağıdaki komutu ekliyoruz:
    • set(CMAKE_AUTOUIC_SEARCH_PATHS .)
  • Kullandığımız statik kütüphaneler ile QT kütüphanelerini ekliyoruz:
    • target_link_libraries(${APP_NAME} Utility MessageCommon UDP Qt5::Widgets Qt5::Core Qt5::Network)
  • Çalıştırılabilir dosya çıktısının debug/release ayrı isimlendirmesi için aşağıdaki komutu kullanabilirsiniz (ya da en tepedeki cmake betiğindeki komutu da kullanabilirsiniz):
    • set_target_properties(${APP_NAME} PROPERTIES OUTPUT_NAME_DEBUG ${APP_NAME}D )
      set_target_properties(${APP_NAME} PROPERTIES OUTPUT_NAME_RELEASE ${APP_NAME} )
  • Son olarak da, yazımda en çok hoşunuza gideceğin düşündüğüm bir kod parçasından bahsedeceğim. QT .dll ve diğer bağımlılıkların oluşturulan çalıştırılabilir dosyanın yanına alınması. Bu kod temelde, QT’nin kurulum dizinine ve kullanılan QT’ye göre, ilgili dizine gidip, windeployqt aracını cağırıyor ve bağımlılıkları, çıktının yanına kopyalıyor (bu araca da, daha önce değinmiştim). Biraz uzun olduğu için buraya eklemiyorum. Aşağıda çalıştırılabilir QT uygulamasına ilişkin CMake betiğini görebilirsiniz. Son kısmında yer alan kod parçası, bu amaçla kullanılmaktadır:

QtDLLTestApp uygulamasına ilişkin de CMake betiği, yukarıdaki betiğe çok benzemektedir.

QT QML Uygulamaları

Son olarak gelelim, QML uygulamalarına ilişkin CMake betiğine ve önemli noktalara. Aslında, QT uygulamaları için geçerli komutların çoğu QML uygulamaları için de geçerlidir ama bir kaç ek husus var:

  • QML uygulamaları için CMAKE_AUTOMOC ve benzeri ayarlara ihtiyaç duymayacağız (.ui dosyası olmadığı müddetçe),
  • QML dosyasını da içerisinde barındıran .qrc dosyasını aşağıdaki komut ile ekliyoruz
    • qt5_add_resources(QT_RESOURCES qml.qrc)
  • Başlık, kaynak ve QML dosyaları ile qrc dosyasını da çalıştırılabilir dosya komutuna ekliyoruz
    • add_executable(AMTHostQmlApp ${HEADER_FILES} ${SOURCE_FILES} ${QML_FILES} ${QT_RESOURCES})
  • Son olarak, windeployqt komutunu, qml dosyaları için biraz uyarlamamız gerekiyor. Bu da çok ince bir nokta dikkat:
    • COMMAND Qt5::windeployqt –qmldir “${CMAKE_CURRENT_SOURCE_DIR}” “$<TARGET_FILE_DIR:${APP_NAME}>/$<TARGET_FILE_NAME:${APP_NAME}>”

Sonuç

Evet, uygulama izleme yazılımımız ve QT uygulamaları için sanırım gerekli çoğu CMake komutunun üzerinden geçmiş olduk. CMake için de çok iyi bir referans olacağı kanısındayım, umarım sizler için de faydalı olur.

Burada, dikkatli okuyucularım özellikle, MessageCommon, MessageLibrary, DefaultCommProtocol ve QT’de dinamik kütüphane kullanım konularına çok girmediğimi fark etmişssinizdir. Açıkçası, CMake ile olan konu dağılmasın ve yazı da daha fazla uzamasın diye girmedim ama kodları gitlaba ekliyorum. Merak edenler, inceleyebilirler.

Ayrıca kaynaklar kısmına da, güzel siteler bırakıyorum onlara da bakmayı unutmayın lütfen.

Bir sonraki yazıma kadar kendinize çok iyi bakın ve sağlıkla kalın sevgili yazılımperver dostlarım.

Not: Kodları yükledikten sonra gitlabda bir kiç kere pipeline patladı. Ufak tefek bir kaç hata dışında (.ui arama dizini yanlış olmuş, proje isimlerinde büyük/küçük farkı olmuş, vs.), uint64_t’leri qint64’e çevirmem gerekti (windows’ta ihtiyaç olmamıştı, gitlab ubuntu üzerinde derliyor), bilginiz olsun. En son durumda pipeline da da bir sıkıntı kalmadı 😉 Repo için:

https://gitlab.com/yazilimperver/applicationmonitoringtool

Kaynaklar

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

This site uses Akismet to reduce spam. Learn how your comment data is processed.