QMake وتطوير المشاريع الكبيرة
▍مشاركة الرمز في QMake أمر غير مريح للغاية
عند تطوير تطبيقات معقدة إلى حد ما ، فمن الأفضل عادةً تقسيمها إلى أجزاء صغيرة يمكن التحكم فيها. على سبيل المثال ، إذا كنت بحاجة إلى تقديم تطبيقك كملف تنفيذي رئيسي تتصل به المكتبات ، فعندئذٍ باستخدام QMake ، يمكن القيام بذلك فقط باستخدام مشروع يعتمد على قالب
subdirs. هذا مشروع ، يتم تمثيله بملف ، على سبيل المثال MyApp.pro، يحتوي على إدخال للقالب المستخدم وقائمة مجلدات المشروع:
TEMPLATE = subdirs
SUBDIRS = \
src/app \ #
src/lib \
src/lib2
باستخدام هذا النهج ، لدينا العديد من المشاريع الفرعية تحت تصرفنا والتي نحتاج فيها إلى تنظيم مشاركة الكود. من أجل إخبار المترجم بالمكان الذي يحتاج إليه بالضبط في المشاريع الأخرى للبحث عن ملفات الرأس والملفات ذات التعليمات البرمجية المصدر ، تحتاج إلى إعطاء معلومات الرابط حول المكتبات التي يحتاج إلى تضمينها ومكان العثور على الملفات المترجمة. يقوم QMake بذلك عن طريق إنشاء ملفات .pri ضخمة تُستخدم فقط لوصف ما يجب تضمينه في المشروع. هذا مشابه لاستخدام بنيات عرض C ++ العادية
#include <xyz.h>. نتيجة لذلك ، اتضح ، على سبيل المثال ، أن الملف MyProjectName.priمدرج في التكوين MyProjectName.pro. ولإصلاح مشكلة المسار النسبي ، أضف المسار المطلق الحالي لكل سطر.
▍ التبعيات الخارجية
يتم تقليل العمل مع التبعيات الخارجية المخصصة لأنظمة التشغيل المختلفة بشكل أساسي إلى نسخ المسارات إلى التبعيات المقابلة ولصقها في ملف .pro. هذه وظيفة مملة ومملة ، لأن كل نظام تشغيل له خصائصه الخاصة في هذا الصدد. على سبيل المثال، لينكس لايوجد المجلدات الفرعية منفصلة
debugو release.
▍CONFIG + = Order هو قاتل لأداء الترجمة
عيب آخر في QMake هو أنه يحتوي على مشاكل ترجمة متقطعة. لذلك ، إذا كان المشروع يحتوي على العديد من المشاريع الفرعية ، وهي مكتبات مستخدمة في مشاريع فرعية أخرى ، فسيخفق التجميع بشكل دوري. قد يكون سبب الخطأ شيء من هذا القبيل:
libAتعتمد المكتبة على المكتبات libBو libC. ولكن بحلول وقت التجميع ، لم تكن libAالمكتبة libCجاهزة بعد. عادة ما تنتهي المشكلة عند إعادة تجميع المشروع. لكن حقيقة حدوث ذلك على الإطلاق تشير إلى وجود مشكلة خطيرة في QMake. وهذه المشاكل لا يمكن حلها باستخدام شيء مثلlibA.depends = libB... ربما (وربما يكون الأمر كذلك) ، أنا أفعل شيئًا خاطئًا ، لكن لم أتمكن أنا ولا زملائي من التعامل مع المشكلة. الطريقة الوحيدة لحل مشكلة ترتيب إنشاء المكتبات هي استخدام التخصيص CONFIG += ordered، ولكن بسبب هذا ، من خلال التخلص من البناء المتوازي ، يعاني الأداء بشكل كبير.
QBS و CMake
▍لماذا تخسر QBS أمام CMake؟
كانت الرسالة المتعلقة بانتهاء دعم QBS (Qt Build System ، Qt build system) بمثابة صدمة حقيقية لي. كنت حتى من المبادرين لمحاولة تغيير هذا. يستخدم QBS صيغة لطيفة مألوفة لأي شخص سبق أن كتب كود QML. لا يمكنني قول الشيء نفسه عن CMake ، ولكن بعد العمل مع نظام بناء المشروع هذا لعدة أشهر ، يمكنني القول بثقة أن التحول إليه من QBS كان القرار الصحيح ، وأنني سأستمر في استخدام CMake ...
CMake ، على الرغم من أنه يحتوي على بعض العيوب النحوية ، يعمل بشكل موثوق. ومشاكل QBS سياسية أكثر منها فنية.
هذا هو أحد العوامل الرئيسية التي تجبر المبرمجين غير الراضين عن حجم Qt (سواء من حيث عدد أسطر الكود وحجم المكتبة) للبحث عن بديل. بالإضافة إلى ذلك ، يكره الكثير من الناس بشدة MOC. وهو عبارة عن مترجم كائن meta يقوم بتحويل كود 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, 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)
النينجا يسرع CMake
دور CMake هو فقط إنشاء تعليمات لنظام بناء المشروع الذي اختاره المطور. يمكن أن تكون هذه إضافة كبيرة عند العمل مع الأشخاص الذين يستخدمون Visual Studio بدلاً من Qt Creator. عند استخدام CMake ، يمكنك (ويجب عليك) اختيار Ninja كنظام بناء افتراضي. يعد تجميع المشاريع باستخدام حزمة CMake + Ninja أمرًا رائعًا للغاية. يمكن العثور على كلاهما في مربع أدوات Qt Maintenance. من بين أشياء أخرى ، يمكن لهذه الأدوات التعامل مع التغييرات بسرعة كبيرة في نهج التطوير التكراري. في الواقع ، كل شيء يعمل بسرعة كبيرة لدرجة أنني عند استخدام Godot مع SCons ، أريد حقًا استخدام CMake هنا أيضًا.
يسمح Vcpkg لـ CMake بالتألق
إدارة التبعيات في مشاريع C ++ ليست مهمة سهلة. لحل هذه المشكلة ، تضع العديد من المشاريع ملفات DLL الضرورية في مستودعات Git الخاصة بهم. وهذا أمر سيء ، لأن هذا يزيد بلا داع من حجم المستودعات (لا نتطرق إلى Git LFS هنا). العيب الوحيد في vcpkg هو أن مدير الحزم هذا يدعم إصدارًا عالميًا واحدًا فقط من الحزمة (أي ، عليك تثبيت إصدارات مختلفة من vcpkg بنفسك ، ولكن هذا نوع من الاختراق ، ونادرًا ما تكون هناك حاجة لذلك). صحيح ، في خطط تطوير المشروع ، يمكنك أن ترى أنه يسير في الاتجاه الصحيح.
لتثبيت الحزم ، استخدم الأمر التالي:
vcpkg install crashpad
بينما كان يعمل على سيناريو، ونحن ببساطة خلق 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.CMake
VCPKG_TARGET_TRIPLET:STRING=x64-windows
هل تحتاج إلى تثبيت أي مكتبة أخرى؟ للقيام بذلك ، ما عليك سوى استخدام أمر النموذج
vcpkg install myLibToInstall.
النتيجة
نهج استخدام الأحدث والأكثر شعبية له مزاياه. ولكن ماذا تفعل ، على سبيل المثال ، عند بناء أنظمة ذات إمكانات كبيرة مثل QBS تجد نفسها فجأة على الهامش؟ في النهاية ، يتخذ المطور نفسه قرارات بشأن ما يجب استخدامه في مشاريعه. لهذا السبب قررت نقل مشروعي إلى CMake. ويجب أن أقول إنه كان القرار الصحيح. اليوم ، في عام 2020 ، تبدو CMake جيدة جدًا.
هل تستخدم CMake و vcpkg؟
