Русский
Русский
English
Статистика
Реклама

Перевод История успешного перевода ScreenPlay с QMake на CMake

ScreenPlay это опенсорсное приложение для Windows (а скоро ещё и для Linux и macOS), предназначенное для работы с обоями и виджетами. Оно создано с использованием современных инструментов (C++/Qt/QML), активная работа над ним ведётся с первой половины 2017 года. Код проекта хранится на платформе GitLab.



Автор статьи, перевод которой мы сегодня публикуем, занимается разработкой ScreenPlay. Он столкнулся с рядом проблем, решить которые ему помог переход с QMake на CMake.

QMake и разработка больших проектов


Совместное использование кода в QMake это очень неудобно


При разработке достаточно сложных приложений обычно лучше всего разбивать их на небольшие фрагменты, которыми удобно управлять. Например, если нужно представить приложение в виде основного исполняемого файла, к которому подключаются библиотеки, то, пользуясь QMake, сделать это можно лишь с помощью проекта, основанного на шаблоне subdirs. Это проект, представленный файлом, скажем, с именем MyApp.pro, который содержит запись об используемом шаблоне и список папок проекта:

TEMPLATE = subdirsSUBDIRS = \src/app \  # относительные путиsrc/lib \src/lib2

При таком подходе в нашем распоряжении оказываются несколько подпроектов, в которых нужно организовать совместное использование кода. Для того чтобы сообщить компилятору о том, где именно в других проектах ему нужно искать заголовочные файлы и файлы с исходным кодом, нужно передать линковщику сведения о том, какие именно библиотеки ему требуется подключать, и о том, где искать скомпилированные файлы. В QMake это делается через создание огромных .pri-файлов, которые используются исключительно для описания того, что нужно включить в проект. Это напоминает использование обычных C++-конструкций вида #include <xyz.h>. В результате оказывается, что, например, файл MyProjectName.pri включается в состав MyProjectName.pro. А для исправления проблемы, связанной с относительными путями, нужно добавить текущий абсолютный путь в каждую строку.

Внешние зависимости


Работа с внешними зависимостями, предназначенными для различных операционных систем, сводится, в основном, к копированию путей к соответствующим зависимостям и к вставке их в .pro-файл. Это скучная и утомительная работа, так как у каждой ОС есть, в этом плане, свои особенности. Например, в Linux нет отдельных подпапок debug и release.

CONFIG += ordered убийца производительности компиляции


Ещё один недостаток QMake заключается в периодическом возникновении проблем с компиляцией. Так, если в проекте есть множество подпроектов, которые представляют собой библиотеки, используемые в других подпроектах, то компиляция периодически завершается с ошибкой. Причиной ошибки может быть примерно такая ситуация: библиотека libA зависит от библиотек libB и libC. Но к моменту сборки libA библиотека libC ещё не готова. Обычно проблема исчезает при перекомпиляции проекта. Но то, что такое вообще происходит, указывает на серьёзные проблемы QMake. И эти проблемы не удаётся решить, пользуясь чем-то вроде libA.depends = libB. Вероятно (и, пожалуй, так оно и есть), я что-то делаю не так, но справиться с проблемой не удалось ни мне, ни моим коллегам. Единственный способ решить проблему с порядком сборки библиотек заключается в использовании настройки CONFIG += ordered, но из-за этого, за счёт отказа от параллельной сборки, сильно страдает производительность.

QBS и CMake


Почему QBS проигрывает CMake?


Сообщение о прекращении поддержки QBS (Qt Build System, система сборки Qt) стало для меня настоящим шоком. Я даже был одним из инициаторов попытки это изменить. При использовании QBS применяются приятные синтаксические конструкции, знакомые каждому, кто когда-либо писал QML-код. Не могу сказать того же о CMake, но после того, как я несколько месяцев поработал с этой системой сборки проектов, я могу с уверенностью заявить о том, что переход на неё с QBS был правильным решением, и о том, что я продолжу пользоваться CMake.

CMake, хотя и имеет некоторые недостатки синтаксического плана, работает надёжно. А проблемы QBS больше относятся к сфере политики, чем к технической стороне вопроса.

Это один из основных факторов, заставляющих программистов, недовольных размером Qt (и в плане количества строк кода, и в плане размера библиотеки), искать альтернативу. Кроме того, многим крайне не нравится MOC. Это метаобъектный компилятор, который преобразует C++-код, написанный с использованием Qt, в обычный C++. Благодаря этому компилятору можно, например, пользоваться удобными конструкциями, вроде тех, которые позволяют работать с сигналами.

Альтернативы QBS


В нашем распоряжении, помимо QBS, имеются такие системы сборки проектов, как build2, CMake, Meson, SCons. Они, за пределами экосистемы Qt, используются во многих проектах.

Плохая поддержка QBS в IDE


Насколько мне известно, единственной IDE, поддерживающей QBS, является QtCreator.

Блестящий союз vcpkg и CMake


Помните, как выше я возмущался проблемами с внешними зависимостями? Поэтому неудивительно то, сколько положительных эмоций у меня вызвал диспетчер пакетов vcpkg. Для установки зависимости достаточно одной команды! Полагаю, vcpkg может пригодиться любому C++-программисту.

О кажущейся непривлекательности синтаксиса CMake


Если судить о CMake по первой десятке ссылок найденных Google, то может показаться, что в этой системе используются весьма непривлекательные синтаксические конструкции. Но проблема тут в том, что Google выводит первыми старые материалы о CMake со Stack Overflow, датированные 2008 годом. Тут же попадаются и ссылки на старую документацию к версии CMake 2.8. Синтаксические конструкции, используемые при работе с CMake, могут быть очень даже симпатичными. Дело в том, что применение CMake предусматривает, в основном, использование конструкций, показанных ниже (это сокращённый вариант файла CMakeList.txt из проекта ScreenPlay).

# Проверка минимальных требованийcmake_minimum_required(VERSION 3.16.0)# Указание имени проекта. Оно потом будет использовано для именования# исполняемых файлов и для весьма полезного ${PROJECT_NAME}project(ScreenPlay)# Некоторые настройки Qt, касающиеся ресурсов и MOCset(CMAKE_AUTORCC ON)set(CMAKE_AUTOMOC ON)# Это - лишь синтаксический сахар. Тут создаётся переменная src,# содержащая список строк. Всё это потом будет использоваться в add_executableset(src main.cppapp.cpp# Тут кое-что пропустимsrc/util.cppsrc/create.cpp)set(headers app.hsrc/globalvariables.h# И тут кое-что пропустимsrc/util.hsrc/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(Qt5COMPONENTS QuickQuickCompilerWidgetsGuiWebEngineREQUIRED)# Внешние библиотеки vcpkgfind_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-windowsset_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}PRIVATEQt5::QuickQt5::GuiQt5::WidgetsQt5::CoreQt5::WebEnginenlohmann_json::nlohmann_jsonlibzippp::libzipppScreenPlaySDKQTBreakpadplugin)# Предлагаем 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 ускоряет CMake


Роль CMake заключается лишь в том, чтобы генерировать инструкции для выбранной разработчиком системы сборки проектов. Это может оказаться огромным плюсом при работе с людьми, которые пользуются не Qt Creator, а Visual Studio. При использовании CMake можно (и нужно) выбрать Ninja в качестве системы сборки, используемой по умолчанию. Компиляция проектов с применением связки CMake+Ninja это очень приятно. И то и другое можно найти в наборе инструментов Qt Maintenance. Кроме прочего, эти инструменты очень быстро обрабатывают изменения при итеративном подходе к разработке. На самом деле, всё работает так быстро, что при использовании Godot со SCons мне очень хочется и тут пользоваться CMake.

Vcpkg позволяет CMake проявить себя во всей красе


Управление зависимостями в C++-проектах это непростая задача. Для её решения многие проекты даже размещают в своих Git-репозиториях необходимые DLL. А это плохо, так как из-за этого неоправданно увеличиваются размеры репозиториев (Git LFS мы тут не касаемся). Недостаток vcpkg заключается лишь в том, что этот диспетчер пакетов поддерживает лишь одну глобальную версию некоего пакета (то есть, приходится самостоятельно устанавливать разные версии vcpkg, но это нечто вроде хака, да и нужно это редко). Правда, в планах развития проекта можно увидеть то, что он идёт в правильном направлении.

Для установки пакетов используется такая команда:

vcpkg install crashpad

Мы, при работе над ScreenPlay, просто создали скрипты install_dependencies_windows.bat и install_dependencies_linux_mac.sh для клонирования репозитория vcpkg, для его сборки и установки всех наших зависимостей. При работе с Qt Creator необходимо записывать в CMAKE_TOOLCHAIN_FILE относительный путь к vcpkg. Кроме того, vcpkg нужно сообщить о том, какую ОС и какую архитектуру мы используем.

# Настройка QtCreator. Extras -> Tools -> Kits -> -> CMake Configuration. Туда надо добавить следующее:CMAKE_TOOLCHAIN_FILE:STRING=%{CurrentProject:Path}/Common/vcpkg/scripts/buildsystems/vcpkg.CMakeVCPKG_TARGET_TRIPLET:STRING=x64-windows

Нужно установить ещё какую-нибудь библиотеку? Для этого достаточно воспользоваться командой вида vcpkg install myLibToInstall.

Итоги


У подхода, когда пользуются всем самым новым и популярным, есть свои плюсы. Но что делать, например, когда системы сборки с большим потенциалом, вроде QBS, вдруг оказываются на обочине? В конечном счёте, разработчик сам принимает решения о том, чем ему пользоваться в его проектах. Именно поэтому я решил перевести свой проект на CMake. И, надо сказать, это было правильное решение. Сегодня, в 2020 году, CMake смотрится очень даже хорошо.

Пользуетесь ли вы CMake и vcpkg?



Источник: habr.com
К списку статей
Опубликовано: 27.09.2020 16:05:45
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Блог компании ruvds.com

Open source

Разработка веб-сайтов

Qmake

Cmake

Разработка

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru