Entendiendo CMakeLists
CMake
En nuestro tutorial de introducción hemos usado CMake como sistema de compilación para nuestra aplicación, aunque solo hemos prestado más atención a uno de nuestros archivos CMakeLists.txt
. Aquí vamos a profundizar un poco más sobre cómo funciona.
CMake es útil porque nos permite automatizar la mayoría de las cosas necesarias que hay que hacer antes de compilar.
El CMakeLists.txt raíz
Es posible que recuerde este archivo CMakeLists.txt
del primer tutorial:
|
|
La primera línea, cmake_minimum_required()
define la versión de CMake que se va a utilizar.
A continuación, project(kirigami-tutorial)
define el nombre del proyecto.
Luego llegamos a una sección donde incluimos una serie de preferencias necesarias de CMake y de KDE usando extra-cmake-modules. Estas proporcionan un conjunto de prácticas utilidades:
- KDEInstallDirs proporciona variables de conveniencia, como
${KDE_INSTALL_TARGETS_DEFAULT_ARGS}
,${KDE_INSTALL_QMLDIR}
,${KDE_INSTALL_BINDIR}
y${KDE_INSTALL_LIBDIR}
. - KDECMakeSettings proporciona cosas como
CMAKE_AUTORCC ON
, un objetivouninstall
que se puede usar concmake --build build/ --target uninstall
, yENABLE_CLAZY
. - KDECompilerSettings proporciona un estándar de C++ mínimo, indicadores del compilador (como
-pedantic
) y macros de buenas prácticas (como-DQT_NO_CAST_FROM_ASCII
para exigir conversiones explícitas, comoQStringLiteral()
). - ECMFindQmlModule proporciona un modo para asegurar que al compilar se encuentra una dependencia QML en tiempo de ejecución.
- ECMQmlModule proporciona órdenes de CMake como
ecm_add_qml_module()
yecm_target_qml_sources()
.
La siguiente sección es importante, ya que especifica las dependencias necesarias durante la compilación. Veamos la primera:
|
|
- find_package() encuentra y carga la biblioteca externa y sus componentes.
REQUIRED
indica a CMake que salga con un error si no se puede encontrar el paquete.COMPONENTS
es un parámetro que precede a los componentes específicos de la infraestructura que vamos a incluir.- Cada palabra tras
COMPONENTS
hace referencia a un determinado componente de la biblioteca.
Nota
Si desea añadir alguno de los componentes que se muestran en la documentación de la API de KDE a la aplicación, puede consultar en la barra lateral derecha cómo se añade el componente con CMake. Por ejemplo, para Kirigami, encontrará algo semejante a find_package(KF6Kirigami)
, que, con la adición de ECM, se convierte en:
find_package(KF6 COMPONENTS Kirigami)
Preste mucha atención a los componentes incluidos, ya que si omite alguno de ellos en el código se detendrá la compilación de la aplicación.
La línea de instalación indica a CMake que instale el archivo de escritorio en ${KDE_INSTALL_APPDIR}
, que en Linux se traduce a $XDG_DATA_DIRS/applications
, normalmente /usr/share/applications
, y en Windows se traduce a C:/Program Files/${PROJECT_NAME}/bin/data/applications
:
|
|
La última línea permite que CMake liste los paquetes que ha encontrado y que haga que la compilación falle inmediatamente si se produce un error:
|
|
Y sobre ella, add_subdirectory(src)
hace que CMake se dirija al directorio src/
, donde encontrará otro archivo CMakeLists.txt
.
src/CMakeLists.txt
|
|
Mientras el primer archivo se encargaba de los metadatos y de encontrar bibliotecas, este se encargará de las dependencias y de instalar la aplicación. Contiene las siguientes llamadas de CMake:
- add_executable() crea el ejecutable de destino que usaremos para ejecutar nuestro proyecto.
ecm_add_qml_module()
crea un módulo QML de destino que será accesible mediante la importación de «org.kde.tutorial».- target_sources() añade los archivos de código fuente C++ al ejecutable de destino.
ecm_target_qml_sources()
añade archivos QML al módulo.- target_link_libraries enlaza las bibliotecas de C++ usadas en el código fuente con nuestro ejecutable. Kirigami no está incluido aquí porque estamos usando solo su módulo QML.
- install() instala el ejecutable en el sistema.
La documentación de las dos órdenes ECM se puede encontrar en la API de extra-cmake-modules para ECMQmlModule.
La llamada a ecm_add_qml_module()
se ha usado aquí para modificar el destino ejecutable del código fuente C++ tradicional y convertirlo en algo que pueda aceptar archivos QML y código fuente C++ al que se pueda acceder desde QML en lo que se denomina uso del ejecutable como destino de respaldo para un módulo QML. Esto significa que los archivos QML se ejecutan directamente como parte de la aplicación, como suele ser el caso de las aplicaciones.
También puede crear un módulo QML independiente que no use el ejecutable como destino de respaldo mediante ecm_add_qml_module()
. En este caso, crearía un destino de biblioteca mediante add_library(), lo enlazaría a un destino ejecutable existente mediante target_link_libraries()
y, además de instalar la biblioteca con install()
, deberá finalizar el módulo QML con ecm_finalize_qml_module() para que pueda generar dos archivos: qmldir
y qmltypes
. Las aplicaciones QtQuick usan estos archivos para buscar módulos QML independientes.
El método para crear un módulo QML separado se ejemplifica mejor en Uso de archivos separados.
Son adiciones proporcionadas por extra-cmake-modules para hacer que el uso del registro declarativo de Qt (el reemplazo de los archivos de recursos de Qt) sea más fácil.
Nota
Estas bibliotecas deben coincidir con los componentes que incluimos en nuestro archivoCMakeLists.txt
anterior; de lo contrario, estos componentes no se incluirán y nuestra aplicación no se compilará.La documentación de las tres órdenes se puede encontrar en la API de extra-cmake-modules para ECMQmlModule.
src/components/CMakeLists.txt
En el tutorial sobre cómo dividir el código en archivos separados, se introdujo un nuevo archivo CMake para permitir módulos QML separados:
|
|
El requisito para que CMake lea este archivo es añadir una llamada a add_subdirectory()
en el src/CMakeLists.txt
que apunte a él.
Creamos un nuevo objetivo llamado kirigami-hello-components
y luego lo convertimos en un módulo QML usando ecm_add_qml_module() bajo el nombre de importación org.kde.tutorial.components
y añadimos los archivos QML relevantes.
La llamada a add_library() genera un nuevo objetivo llamado kirigami-hello-components
. Este objetivo tendrá su propio conjunto de archivos de código fuente, archivos QML, enlazará sus propias bibliotecas, etc., aunque necesita estar enlazado al ejecutable, pero una vez que se compila, necesita estar enlazado al ejecutable creado en src/CMakeLists.txt
. Esto se hace añadiendo el nombre del objetivo a la lista de bibliotecas que se enlazarán al ejecutable en target_link_libraries()
.
The call to ecm_add_qml_module()
changes the library to allow it to accept QML files as before, but this time we need to use GENERATE_PLUGIN_SOURCE. When the executable is used as a backing target (like with kirigami-hello
) it doesn't need to generate plugin code since it's built into the executable; with separate QML modules like kirigami-hello-components
the plugin code is necessary.
Upstream Qt's qt_add_qml_module() by default generates a plugin together with the QML module, but KDE's ecm_add_qml_module()
by default does not for backwards compatibility.
Another thing that is necessary for separate QML modules is to finalize the target. This mainly means CMake generates two files, qmldir and qmltypes, which describe the QML modules we have and exports their symbols for use in the library. They are important when installing your application so that the executable being run is able to find where the QML files for each module are, so they are automatically added to the target.
Después podrá instalar el objetivo como antes.
Next time you need to add more QML files, remember to include them in this file. C++ files that use the QML_ELEMENT keyword which we will see much later in the tutorial can also be added here using target_sources()
. You can logically separate your code by creating more QML modules with different imports as needed.
Esta configuración será útil para desarrollar la mayoría de las aplicaciones de Kirigami.