Capire CMakeLists
CMake
Nel nostro tutorial introduttivo, abbiamo utilizzato CMake come sistema di compilazione per la nostra applicazione, ma abbiamo prestato molta attenzione solo a uno dei nostri file "CMakeLists.txt". Qui, esamineremo come funziona in modo un po' più dettagliato.
CMake è utile perché ci permette di automatizzare molte delle cose che bisogna fare prima della compilazione.
La radice CMakeLists.txt
Potresti ricordare questo file CMakeLists.txt dalla prima esercitazione:
| |
La prima riga, cmake_minimum_required() imposta la versione di CMake che chiameremo.
Successivamente, project(kirigami-tutorial) definisce il nome del progetto.
Quindi arriviamo a una sezione in cui includiamo una serie di impostazioni necessarie di CMake e KDE utilizzando extra-cmake-modules. Forniscono una serie di utili utilità:
- KDEInstallDirs fornisce variabili utili come
${KDE_INSTALL_TARGETS_DEFAULT_ARGS},${KDE_INSTALL_QMLDIR},${KDE_INSTALL_BINDIR}e${KDE_INSTALL_LIBDIR}. - KDECMakeSettings fornisce cose come
CMAKE_AUTORCC ON, un targetuninstallche può essere utilizzato concmake --build build/ --target uninstalleENABLE_CLAZY. - KDECompilerSettings fornisce uno standard C++ minimo, flag del compilatore come
-pedantice macro di best practice come-DQT_NO_CAST_FROM_ASCIIper richiedere conversioni esplicite comeQStringLiteral(). - ECMFindQmlModule fornisce un modo per garantire che venga trovata una dipendenza QML di runtime in fase di compilazione.
- ECMQmlModule fornisce comandi CMake come
ecm_add_qml_module()eecm_target_qml_sources().
La sezione seguente è importante perché specifica quali dipendenze introdurremo in fase di compilazione. Diamo un'occhiata al primo:
| |
- find_package() trova e carica la libreria esterna e i suoi componenti.
- «REQUIRED» indica a CMake di uscire con un errore se non è possibile trovare il pacchetto.
- `COMPONENTS`` è un parametro che precede i componenti specifici del framework che includeremo.
- Ogni parola dopo "COMPONENTI" si riferisce a un componente specifico della libreria.
Nota
Se stai cercando di aggiungere qualsiasi componente elencato nella documentazione dell'API KDE alla tua applicazione, puoi controllare la barra laterale destra per sapere come aggiungere il componente con CMake. Ad esempio, per Kirigami, troverai qualcosa come find_package(KF6Kirigami), che con l'aggiunta di ECM diventa:
find_package(KF6 COMPONENTS Kirigami)Presta molta attenzione ai componenti inclusi, poiché omettere quelli utilizzati nel nostro codice impedirà la compilazione della nostra applicazione.
La riga di installazione indica a CMake di installare il file desktop in ${KDE_INSTALL_APPDIR}, che su Linux si traduce in $XDG_DATA_DIRS/applications, solitamente /usr/share/applications, e su Windows si traduce in C:/Program Files/${PROJECT_NAME}/bin/data/applications:
| |
L'ultima riga consente a CMake di stampare quali pacchetti ha trovato e fa sì che la compilazione fallisca immediatamente se incontra un errore:
| |
E soprattutto, "add_subdirectory(src)" punta CMake nella directory "src/", dove trova un altro file "CMakeLists.txt".
src/CMakeLists.txt
| |
Mentre il primo file gestiva i metadati e la ricerca delle librerie, questo consisterà nella gestione delle dipendenze e nell'installazione dell'applicazione. Ha le seguenti chiamate CMake:
- add_executable() crea la destinazione eseguibile che utilizzeremo per eseguire il nostro progetto.
ecm_add_qml_module()crea un modulo QML di destinazione che sarà accessibile tramite l'importazione "org.kde.tutorial".- target_sources() aggiunge i file sorgente C++ alla destinazione eseguibile.
ecm_target_qml_sources()aggiunge i file QML al modulo.- target_link_libraries() collega le librerie C++ utilizzate nel nostro codice al nostro eseguibile. Kirigami non è incluso qui perché stiamo utilizzando solo il suo modulo QML.
- install() installa l'eseguibile nel sistema.
La documentazione per i due comandi ECM può essere trovata nell'API extra-cmake-modules per ECMQmlModule.
La chiamata a ecm_add_qml_module() è stata utilizzata qui per modificare la tradizionale destinazione eseguibile del codice sorgente C++ e trasformarla in qualcosa che può accettare file QML e codice sorgente C++ accessibile da QML in quello che viene chiamato usando l'eseguibile come destinazione di supporto per un QML modulo. Ciò significa che i file QML vengono eseguiti direttamente come parte dell'applicazione, come spesso accade per le applicazioni.
Puoi anche creare un modulo QML separato che non utilizzi l'eseguibile come destinazione di supporto utilizzando ecm_add_qml_module(). In questo caso, creerai una libreria di destinazione utilizzando add_library(), la collegheresti a una destinazione eseguibile esistente utilizzando target_link_libraries() e oltre a installare la libreria con install() dovrai finalizzare il modulo QML con ecm_finalize_qml_module() in modo che possa generare due file: qmldir e qmltypes. Questi file vengono utilizzati dalle applicazioni QtQuick per trovare moduli QML separati.
Il metodo per creare un modulo QML separato è meglio esemplificato in Utilizzo di file separati.
Queste sono aggiunte fornite da extra-cmake-modules per rendere più semplice l'uso della registrazione dichiarativa Qt (la sostituzione ai file di risorse Qt).
Nota
Queste librerie dovrebbero corrispondere ai componenti che abbiamo incluso nel nostro precedente fileCMakeLists.txt, altrimenti questi componenti non verranno inclusi e la nostra applicazione non verrà compilata.La documentazione per tutti e tre i comandi può essere trovata nell'API extra-cmake-modules per ECMQmlModule.
src/components/CMakeLists.txt
Nel tutorial su come dividere il codice in file separati, è stato introdotto un nuovo file CMake per consentire moduli QML separati:
| |
Il requisito affinché questo file venga letto da CMake è l'aggiunta di una chiamata a "add_subdirectory()" nel file "src/CMakeLists.txt" che punta ad esso.
Creiamo un nuovo target chiamato kirigami-hello-components e poi lo trasformiamo in un modulo QML utilizzando ecm_add_qml_module() con il nome di importazione org.kde.tutorial.components e aggiungiamo i file QML rilevanti.
La chiamata a add_library() genera un nuovo target chiamato "kirigami-hello-components". Questo target avrà il proprio set di file di codice sorgente, file QML, collegherà le proprie librerie e così via, ma deve essere collegato all'eseguibile, ma una volta compilato deve essere collegato all'eseguibile creato in "src/CMakeLists.txt". Questo viene fatto aggiungendo il nome di destinazione all'elenco delle librerie che verranno collegate all'eseguibile in target_link_libraries().
La chiamata a ecm_add_qml_module() modifica la libreria per consentirle di accettare file QML come prima, ma questa volta dobbiamo usare GENERATE_PLUGIN_SOURCE. Quando l'eseguibile viene utilizzato come destinazione di supporto (come con kirigami-hello) non è necessario generare codice plugin poiché è integrato nell'eseguibile; con moduli QML separati come kirigami-hello-components è necessario il codice del plugin.
Upstream qt_add_qml_module() di Qt genera per impostazione predefinita un plugin insieme al modulo QML, ma ecm_add_qml_module() di KDE per impostazione predefinita non lo fa per la compatibilità con le versioni precedenti.
Un'altra cosa necessaria per i moduli QML separati è finalizzare l'obiettivo. Ciò significa principalmente che CMake genera due file, qmldir e qmltypes, che descrivono i moduli QML di cui disponiamo ed esporta i loro simboli da utilizzare nella libreria. Sono importanti durante l'installazione dell'applicazione in modo che l'eseguibile in esecuzione sia in grado di trovare dove si trovano i file QML per ciascun modulo, in modo che vengano aggiunti automaticamente alla destinazione.
È quindi possibile installare semplicemente la destinazione come prima.
La prossima volta che dovrai aggiungere altri file QML, ricordati di includerli in questo file. I file C++ che utilizzano la parola chiave QML_ELEMENT che vedremo molto più avanti nel tutorial possono anche essere aggiunti qui utilizzando target_sources(). Puoi separare logicamente il tuo codice creando più moduli QML con importazioni diverse secondo necessità.
Questa impostazione sarà utile quando svilupperemo la maggior parte dei programmi con Kirigami.