Compreendendo o CMakeLists
CMake
Em nosso tutorial introdutório, usamos o CMake como sistema de compilação para nossa aplicação, mas só prestamos realmente atenção a um dos nossos arquivos CMakeLists.txt. Aqui, vamos explicar como ele funciona com mais detalhes.
O CMake é útil porque nos permite automatizar muitas das coisas que precisam ser feitas antes da compilação.
O CMakeLists.txt raiz
Você deve se lembrar deste arquivo CMakeLists.txt do primeiro tutorial:
| |
A primeira linha, cmake_minimum_required(), define a versão do CMake que chamaremos.
Depois disso, project(kirigami-tutorial) define o nome do projeto.
Em seguida, chegamos a uma seção onde incluímos uma série de configurações necessárias do CMake e do KDE usando extra-cmake-modules. Eles fornecem um conjunto de utilitários úteis:
- KDEInstallDirs fornece variáveis de conveniência como
${KDE_INSTALL_TARGETS_DEFAULT_ARGS},${KDE_INSTALL_QMLDIR},${KDE_INSTALL_BINDIR}e${KDE_INSTALL_LIBDIR}. - KDECMakeSettings fornece recursos como
CMAKE_AUTORCC ON, um destino deuninstallque pode ser usado comcmake --build build/ --target uninstalleENABLE_CLAZY. - KDECompilerSettings fornece um padrão C++ mínimo, sinalizadores de compilador como
-pedantice macros de melhores práticas como-DQT_NO_CAST_FROM_ASCIIpara exigir conversões explícitas comoQStringLiteral(). - ECMFindQmlModule fornece uma maneira de garantir que uma dependência QML de tempo de execução seja encontrada em tempo de compilação.
- ECMQmlModule fornece comandos do CMake como
ecm_add_qml_module()eecm_target_qml_sources().
A seção a seguir é importante porque especifica quais dependências serão incluídas em tempo de compilação. Vejamos a primeira:
| |
- find_package() encontra e carrega a biblioteca externa e seus componentes.
REQUIREDinforma ao CMake para sair com um erro se o pacote não puder ser encontrado.COMPONENTSé um parâmetro que precede os componentes específicos do framework que incluiremos.- Cada palavra depois de
COMPONENTSse refere a um componente específico da biblioteca.
Nota
Se você deseja adicionar algum componente listado na documentação da API do KDE ao seu aplicativo, consulte a barra lateral direita para saber como adicionar o componente com o CMake. Por exemplo, para o Kirigami, você encontrará algo como find_package(KF6Kirigami), que com a adição do ECM se torna:
find_package(KF6 COMPONENTS Kirigami)Preste muita atenção aos componentes incluídos, pois omitir aqueles usados em nosso código impedirá a compilação do nosso aplicativo.
A linha de instalação instrui o CMake a instalar o arquivo desktop em ${KDE_INSTALL_APPDIR}, que no Linux é traduzido para $XDG_DATA_DIRS/applications, geralmente /usr/share/applications, e no Windows é traduzido para C:/Arquivos de Programas/${NOME_PROJETO}/bin/data/applications:
| |
A linha final permite que o CMake exiba quais pacotes encontrou e faz com que a compilação falhe imediatamente se encontrar um erro:
| |
E acima disso, add_subdirectory(src) aponta o CMake para a pasta src/, onde ele encontra outro arquivo CMakeLists.txt.
src/CMakeLists.txt
| |
Enquanto o primeiro arquivo tratava de metadados e buscava bibliotecas, este consistirá em lidar com dependências e instalar o aplicativo. Ele contém as seguintes chamadas CMake:
- add_executable() cria o executável que usaremos para executar nosso projeto.
ecm_add_qml_module()cria um destino de módulo QML que será acessível por meio da importação "org.kde.tutorial".- target_sources() adiciona arquivos de origem C++ ao destino executável.
ecm_target_qml_sources()adiciona arquivos QML ao módulo.- target_link_libraries() vincula as bibliotecas C++ usadas em nosso código ao nosso executável. Kirigami não está incluído aqui porque estamos usando apenas seu módulo QML.
- install() instala o executável no sistema.
A documentação para os dois comandos ECM pode ser encontrada na API do extra-cmake-modules para ECMQmlModule.
A chamada para ecm_add_qml_module() foi usada aqui para modificar o executável de código-fonte C++ tradicional e transformá-lo em algo que possa aceitar arquivos QML e código-fonte C++ acessível a partir de QML, no que é chamado de usando o executável como destino de suporte para um módulo QML. Isso significa que os arquivos QML são executados diretamente como parte do aplicativo, o que geralmente acontece com aplicativos.
Você também pode criar um módulo QML separado que não use o executável como destino de apoio usando ecm_add_qml_module(). Nesse caso, você criaria um destino de biblioteca usando add_library(), vincularia-o a um destino executável existente usando target_link_libraries() e, além de instalar a biblioteca com install(), você precisará finalizar o módulo QML com ecm_finalize_qml_module() para que ele possa gerar dois arquivos: qmldir e qmltypes. Esses arquivos são usados por aplicativos QtQuick para encontrar módulos QML separados.
O método para criar um módulo QML separado é melhor exemplificado em Usando arquivos separados.
Estas são adições fornecidas por extra-cmake-modules para facilitar o uso do registro declarativo do Qt (a substituição dos arquivos de recursos do Qt).
Nota
Essas bibliotecas devem corresponder aos componentes que incluímos em nosso arquivo anteriorCMakeLists.txt, caso contrário, esses componentes não serão incluídos e nosso aplicativo não será compilado.A documentação para todos os três comandos pode ser encontrada na API do extra-cmake-modules para ECMQmlModule.
src/components/CMakeLists.txt
No tutorial sobre como dividir seu código em arquivos separados, um novo arquivo CMake foi introduzido para permitir módulos QML separados:
| |
O requisito para que este arquivo seja lido pelo CMake é adicionar uma chamada para add_subdirectory() no src/CMakeLists.txt apontando para ele.
Criamos um novo alvo chamado kirigami-hello-components e o transformamos em um módulo QML usando ecm_add_qml_module() com o nome de importação org.kde.tutorial.components e adicionamos os arquivos QML relevantes.
A chamada para add_library() gera um novo alvo chamado kirigami-hello-components. Este alvo terá seu próprio conjunto de arquivos de código-fonte, arquivos QML, vinculará suas próprias bibliotecas e assim por diante, mas precisa ser vinculado ao executável. Uma vez compilado, ele precisa ser vinculado ao executável criado em src/CMakeLists.txt. Isso é feito adicionando o nome do alvo à lista de bibliotecas que serão vinculadas ao executável em target_link_libraries().
A chamada para ecm_add_qml_module() altera a biblioteca para permitir que ela aceite arquivos QML como antes, mas desta vez precisamos usar GENERATE_PLUGIN_SOURCE. Quando o executável é usado como um alvo de apoio (como com kirigami-hello), ele não precisa gerar código de plugin, pois ele está embutido no executável; com módulos QML separados, como kirigami-hello-components, o código de plugin é necessário.
O qt_add_qml_module() do Qt upstream gera, por padrão, um plugin junto com o módulo QML, mas o ecm_add_qml_module() do KDE, por padrão, não o faz para compatibilidade com versões anteriores.
Outra coisa necessária para módulos QML separados é finalizar o alvo. Isso significa principalmente que o CMake gera dois arquivos, qmldir e qmltypes, que descrevem os módulos QML que temos e exportam seus símbolos para uso na biblioteca. Eles são importantes ao instalar seu aplicativo para que o executável em execução seja capaz de encontrar onde estão os arquivos QML de cada módulo, para que eles sejam adicionados automaticamente ao alvo.
Você pode então instalar o alvo como antes.
Da próxima vez que precisar adicionar mais arquivos QML, lembre-se de incluí-los neste arquivo. Arquivos C++ que usam a palavra-chave QML_ELEMENT, que veremos mais adiante neste tutorial, também podem ser adicionados aqui usando target_sources(). Você pode separar logicamente seu código criando mais módulos QML com importações diferentes, conforme necessário.
Esta configuração será útil ao desenvolver a maioria dos aplicativos Kirigami.