Historia de éxito de la transferencia de ScreenPlay de QMake a CMake

ScreenPlay es una aplicación de código abierto para Windows (y pronto también para Linux y macOS) diseñada para funcionar con fondos de pantalla y widgets. Fue creado utilizando herramientas modernas (C ++ / Qt / QML) y ha estado trabajando activamente en él desde la primera mitad de 2017. El código del proyecto se almacena en la plataforma GitLab . El autor del artículo, cuya traducción publicamos hoy, está desarrollando ScreenPlay. Enfrentó una serie de problemas, que fueron ayudados por la transición de QMake a CMake.











QMake y desarrollo de grandes proyectos



▍ Compartir códigos en QMake es muy inconveniente



Al desarrollar aplicaciones que son bastante complejas, generalmente es mejor dividirlas en partes pequeñas y manejables. Por ejemplo, si necesita presentar su aplicación como un archivo ejecutable principal al que están conectadas las bibliotecas, entonces usando QMake, esto se puede hacer solo usando un proyecto basado en una plantilla subdirs. Este es un proyecto, representado por un archivo, digamos con un nombre MyApp.pro, que contiene una entrada para la plantilla utilizada y una lista de carpetas del proyecto:



  TEMPLATE = subdirs
 
  SUBDIRS = \
            src/app \   #  
            src/lib \
            src/lib2


Con este enfoque, tenemos varios subproyectos a nuestra disposición en los que necesitamos organizar el intercambio de código. Para decirle al compilador dónde exactamente en otros proyectos necesita buscar archivos de encabezado y archivos con código fuente, necesita decirle al vinculador información sobre qué bibliotecas necesita incluir y dónde buscar los archivos compilados. QMake hace esto creando enormes archivos .pri que se utilizan únicamente para describir qué incluir en un proyecto. Esto es similar al uso de construcciones de vista normales de C ++ #include <xyz.h>. Como resultado, resulta que, por ejemplo, el archivo está MyProjectName.priincluido en la composición MyProjectName.pro. Y para solucionar el problema de la ruta relativa, agregue la ruta absoluta actual a cada línea.



▍Dependencias externas



Trabajar con dependencias externas destinadas a varios sistemas operativos se reduce principalmente a copiar las rutas a las dependencias correspondientes y pegarlas en un archivo .pro. Este es un trabajo aburrido y tedioso, ya que cada SO tiene sus propias peculiaridades al respecto. Por ejemplo, Linux no tiene subcarpetas separadas debugy release.



▍CONFIG + = Order es un asesino de rendimiento de compilación



Otro inconveniente de QMake es que tiene problemas de compilación intermitentes. Por tanto, si un proyecto tiene muchos subproyectos, que son bibliotecas que se utilizan en otros subproyectos, la compilación falla periódicamente. El motivo del error puede ser algo como esto: la biblioteca libAdepende de las bibliotecas libBy libC. Pero en el momento del montaje, la libAbiblioteca libCaún no está lista. Por lo general, el problema desaparece cuando se vuelve a compilar el proyecto. Pero el hecho de que esto esté sucediendo indica un problema grave con QMake. Y estos problemas no se pueden resolver con algo comolibA.depends = libB... Probablemente (y, quizás, sea así), esté haciendo algo mal, pero ni yo ni mis colegas logramos hacer frente al problema. La única forma de resolver el problema con el orden de construcción de las bibliotecas es usar una personalización CONFIG += ordered, pero debido a esto, al eliminar la construcción paralela, el rendimiento sufre mucho.



QBS y CMake



▍ ¿Por qué QBS pierde ante CMake?



El mensaje sobre el fin del soporte para QBS (Qt Build System, Qt build system) fue un verdadero shock para mí. Incluso fui uno de los iniciadores de un intento de cambiar esto. QBS usa una sintaxis agradable que es familiar para cualquiera que haya escrito código QML. No puedo decir lo mismo sobre CMake, pero después de haber trabajado con este sistema de compilación de proyectos durante varios meses, puedo afirmar con confianza que cambiar de QBS fue la decisión correcta y que continuaré usando CMake ...



CMake, aunque tiene algunas fallas sintácticas, funciona de manera confiable. Y los problemas de QBS son más políticos que técnicos.



Este es uno de los principales factores que obliga a los programadores que no están contentos con el tamaño de Qt (tanto en términos de número de líneas de código como en términos de tamaño de biblioteca) a buscar una alternativa. Además, a muchas personas les disgusta mucho MOC. Es un compilador de metaobjetos que convierte el código C ++ escrito con Qt en C ++ normal. Gracias a este compilador, puede, por ejemplo, utilizar construcciones convenientes, como las que le permiten trabajar con señales.



▍Alternativas a QBS



Además de QBS, tenemos a nuestra disposición sistemas de construcción de proyectos como build2, CMake, Meson, SCons. Fuera del ecosistema Qt, se utilizan en muchos proyectos.



▍ Pobre compatibilidad con QBS en IDE



Hasta donde yo sé, el único IDE que admite QBS es QtCreator.



▍ Brillante unión de vcpkg y CMake



¿Recuerda cómo me molestaban los problemas con las dependencias externas anteriores? Por lo tanto, no es sorprendente cuántas emociones positivas me causó el administrador de paquetes vcpkg. ¡Un comando es suficiente para instalar la dependencia! Creo que vcpkg puede ser útil para cualquier programador de C ++.



Sintaxis de CMake aparentemente poco atractiva



Si juzga a CMake por los diez enlaces principales encontrados por Google, puede parecer que el sistema utiliza una sintaxis muy poco atractiva. Pero el problema aquí es que Google es el primero en mostrar cosas antiguas de CMake de Stack Overflow, con fecha de 2008. También aparecen enlaces a la documentación anterior para la versión CMake 2.8. La sintaxis utilizada cuando se trabaja con CMake puede ser bastante bonita. El hecho es que el uso de CMake implica principalmente el uso de las construcciones que se muestran a continuación (esta es una versión abreviada del archivo CMakeList.txt del proyecto ScreenPlay).



#   
cmake_minimum_required(VERSION 3.16.0)

#   .       
#       ${PROJECT_NAME}
project(ScreenPlay)

#   Qt,    MOC
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOMOC ON)

#  -   .    src,
#   .       add_executable
set(src main.cpp
        app.cpp
        #  - 
        src/util.cpp
        src/create.cpp)

set(headers app.h
        src/globalvariables.h
        #   - 
        src/util.h
        src/create.h)

#  Qt     
qt5_add_big_resources(resources  resources.qrc)

#  CMake  qml  C++   release
#   !
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
    set(qml qml.qrc)
else()
    qtquick_compiler_add_resources(qml qml.qrc )
endif()

#  CMake   .  ,   ,  CMAKE_TOOLCHAIN_FILE
#         !
find_package(
  Qt5
  COMPONENTS Quick
             QuickCompiler
             Widgets
             Gui
             WebEngine
  REQUIRED)

#   vcpkg
find_package(ZLIB REQUIRED)
find_package(OpenSSL REQUIRED)
find_package(libzippp CONFIG REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)

#  CMake    : 
# add_executable    
# add_library   
add_executable(${PROJECT_NAME} ${src} ${headers} ${resources} ${qml})

#        Windows
# https://stackoverflow.com/questions/8249028/how-do-i-keep-my-qt-c-program-from-opening-a-console-in-windows
set_property(TARGET ${PROJECT_NAME} PROPERTY WIN32_EXECUTABLE true)

#     .    
#     vcpkg.      
# dll/lib/so/dynlib  vcpkg/installed
#      , 
#   project(MyLib)  target_link_libraries.
#        .
target_link_libraries(${PROJECT_NAME}
    PRIVATE
    Qt5::Quick
    Qt5::Gui
    Qt5::Widgets
    Qt5::Core
    Qt5::WebEngine
    nlohmann_json::nlohmann_json
    libzippp::libzippp
    ScreenPlaySDK
    QTBreakpadplugin)

#  CMake      build   ,   .
# ${CMAKE_BINARY_DIR} -   build!
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/bin/assets/fonts)
configure_file(assets/fonts/NotoSansCJKkr-Regular.otf ${CMAKE_BINARY_DIR}/bin/assets/fonts COPYONLY)


Ninja acelera CMake



El papel de CMake es solo generar instrucciones para el sistema de construcción del proyecto elegido por el desarrollador. Esto puede ser una gran ventaja cuando se trabaja con personas que usan Visual Studio en lugar de Qt Creator. Al usar CMake, puede (y debe) elegir Ninja como su sistema de compilación predeterminado. Compilar proyectos usando el paquete CMake + Ninja es muy bueno. Ambos se pueden encontrar en la caja de herramientas Qt Maintenance. Entre otras cosas, estas herramientas pueden manejar cambios muy rápidamente en un enfoque de desarrollo iterativo. De hecho, todo funciona tan rápido que cuando uso Godot con SCons, realmente quiero usar CMake aquí también.



Vcpkg permite que CMake brille



Administrar dependencias en proyectos C ++ no es una tarea fácil. Para solucionarlo, muchos proyectos incluso colocan las DLL necesarias en sus repositorios de Git. Y esto es malo, ya que aumenta innecesariamente el tamaño de los repositorios (aquí no tocamos Git LFS). El único inconveniente de vcpkg es que este administrador de paquetes solo admite una versión global de un paquete (es decir, debe instalar diferentes versiones de vcpkg usted mismo, pero esto es un truco y rara vez es necesario). Es cierto que en los planes de desarrollo del proyecto se puede ver que va en la dirección correcta.



Para instalar paquetes, use el siguiente comando:



vcpkg install crashpad


Mientras trabajábamos en ScreenPlay, simplemente creamos los scripts install_dependencies_windows.bat e install_dependencies_linux_mac.sh para clonar el repositorio vcpkg, construirlo e instalar todas nuestras dependencias. Cuando trabaje con Qt Creator, debe escribir en la CMAKE_TOOLCHAIN_FILEruta relativa a vcpkg. Además, es necesario indicar a vcpkg qué sistema operativo y qué arquitectura estamos usando.



    #  QtCreator. Extras -> Tools -> Kits ->  -> CMake Configuration.    :
    CMAKE_TOOLCHAIN_FILE:STRING=%{CurrentProject:Path}/Common/vcpkg/scripts/buildsystems/vcpkg.CMake
    VCPKG_TARGET_TRIPLET:STRING=x64-windows


¿Necesitas instalar alguna otra biblioteca? Para hacer esto, simplemente use el comando del formulario vcpkg install myLibToInstall.



Salir



El enfoque de utilizar los más nuevos y populares tiene sus ventajas. Pero, ¿qué hacer, por ejemplo, cuando los sistemas de construcción con gran potencial como QBS se encuentran repentinamente al margen? En última instancia, el propio desarrollador decide qué utilizar en sus proyectos. Por eso decidí transferir mi proyecto a CMake. Y debo decir que fue la decisión correcta. Hoy, en 2020, CMake se ve bastante bien.



¿Está utilizando CMake y vcpkg?










All Articles