Первая попытка собрать из исходников libQtCore.a

Итак после долгого отсутствия в мире программирования Windows приложений пришлось вернуться и озадачится по взрослому - можно ли собрать Qt4 тот , что устанавливается в C:\QtSDK1.2.1 прямо из исходников...

На дворе 2021г. У нас Windows 10-64. Qt4.

Почему это показалось возможным? В мире программирования контроллеров был получен опыт сборки из исходников с помощью бесплатного инcтрументария GNU gсс и т.д.

Итак все начинается с головы : имеем исходники в каталоге C:\QtSDK1.2.1\QtSources\4.8.1\src.
В голове C:\QtSDK1.2.1\QtSources\4.8.1 лежит тот самый главный projects.pro , который предположительно билдит все исходники из \src .

Для того чтобы начать хоть что-то компилировать надо по идеалогии Qt воспользоваться утилитой qmake, которая по файлам .pro cоздает в соответствующих каталогах файлы makefiles , которые в свою очередь уже будут использоваться при компиляции и сборке.

Вот примерно такая иерархия каталогов (дерево) реализовано. То есть там все исходники Qt раскиданы по каталогам.


projects.pro   // лежит в C:\QtSDK1.2.1\QtSources\4.8.1
\src\src.pro
\src\gui\gui.pro
\src\gui\kernel\kernel.pri
   ......
\src\corelib\corelib.pro
\src\corelib\io\io.pri
   ......

Примечание : если projects.pro не совсем корявый, то при открытие его в qt Creator должно сразу правильно разворачиваться дерево зависимых проектов. Если этого не происходит значит надо искать проблему...

Итак пытаемся вызвать qmake из Qt creator - процесс начинается , но будет затыкается много раз , пока мы не настроим не достающие переменные для зависимых проектов.

Вызов у нас такой (в логе посмотрели) :

"c:\qtsdk1.2.1\desktop\qt\4.8.1\mingw\bin\qmake.exe" C:\QtSDK1.2.1\QtSources\4.8.1\projects.pro -r -spec win32-g++ "CONFIG+=release"

-r - это рекурсивно, то есть по всем внутренним каталогам проходим.

На самом деле тот путь , что ниже описывается, это от не знания как правильно настраивается среда сборки Qt. Но тем не менее оставим для истории...

Первый затык связан переменной $$QT_SOURCE_TREE

Очень часто в файлах .pro в дереве каталогов встречается переменная $$QT_SOURCE_TREE , которая должная содержать путь самого верхнего каталога, то есть где лежит projects.pro. Но почему-то она пустая?... Это видно если в файле .pro сделать massage ($$QT_SOURCE_TREE). Это именно не переменная из среды окружения , так как тогда она бы применялась в коде так : $$(QT_SOURCE_TREE).

Самый верхний каталог это тот где мы запускаем qmake , то есть если открыт projects.pro в Qt и для него мы вызываем qmake в qt , то получится верхний каталог C:\QtSDK1.2.1\QtSources\4.8.1 .

Выясняется что , $$QT_SOURCE_TREE можно определить в .qmake.cache, который должен быть расположен на один каталог выше нашего projects.pro .

Второй затык связан с QT_BUILD_TREE

Также выясняется , что переменная QT_BUILD_TREE тоже в pro файлах оказывается пустая. Ее также добавляем в файл .qmake.cache.

Третий затык QT_ARCH

Итак qmake двинулся дальше по проектам и заткнулся в районе corelib/arch.pri . Сразу скажу , что QT_ARCH тоже пустая в файлах pro. Добавляем ее к .qmake.cache.

Примечание : чтобы облегчить себе жизнь можно убрать из набора каталогов лишнее QT_BUILD_PARTS = libs tools examples demos docs translations, то есть можно оставить только QT_BUILD_PARTS = libs . libs - это и будут после сборки наши статические библиотеки типа QtCore4.a . То есть наша задача их попробовать получить из открытых исходников Qt .

Теперь небольшое отступление.

Как определить где затыкается qmake?

Проблемка оказалась та еще... Пришлось пробовать опции прямо из командной строки. Обязательно надо сразу изучить опции командной строки qmake , так как прояснится сразу много вопросов :


Usage: qmake [mode] [options] [files]

QMake has two modes, one mode for generating project files based on
some heuristics, and the other for generating makefiles. Normally you
shouldn't need to specify a mode, as makefile generation is the default
mode for qmake, but you may use this to test qmake on an existing project

Mode:
  -project       Put qmake into project file generation mode
                 In this mode qmake interprets files as files to
                 be built,
                 defaults to *.c; *.ui; *.y; *.l; *.ts; *.xlf; *.qrc; *.h; *.hpp; *.hh; *.hxx; *.cpp; *.cc; *.cxx
                 Note: The created .pro file probably will
                 need to be edited. For example add the QT variable to
                 specify what modules are required.
  -makefile      Put qmake into makefile generation mode (default)
                 In this mode qmake interprets files as project files to
                 be processed, if skipped qmake will try to find a project
                 file in your current working directory

Warnings Options:
  -Wnone         Turn off all warnings; specific ones may be re-enabled by
                 later -W options
  -Wall          Turn on all warnings
  -Wparser       Turn on parser warnings
  -Wlogic        Turn on logic warnings (on by default)
  -Wdeprecated   Turn on deprecation warnings (on by default)

Options:
   * You can place any variable assignment in options and it will be     *
   * processed as if it was in [files]. These assignments will be parsed *
   * before [files].                                                     *
  -o file        Write output to file
  -d             Increase debug level
  -t templ       Overrides TEMPLATE as templ
  -tp prefix     Overrides TEMPLATE so that prefix is prefixed into the value
  -help          This help
  -v             Version information
  -after         All variable assignments after this will be
                 parsed after [files]
  -norecursive   Don't do a recursive search
  -recursive     Do a recursive search
  -set   Set persistent property
  -unset   Unset persistent property
  -query   Query persistent property. Show all if  is empty.
  -cache file    Use file as cache           [makefile mode only]
  -spec spec     Use spec as QMAKESPEC       [makefile mode only]
  -nocache       Don't use a cache file      [makefile mode only]
  -nodepend      Don't generate dependencies [makefile mode only]
  -nomoc         Don't generate moc targets  [makefile mode only]
  -nopwd         Don't look for files in pwd [project mode only]

Батник для запуска с максимальным уровнем отладочной информации по ошибкам и т.д. примерно такой :


set QTDIR=C:\QtSDK1.2.1\Desktop\Qt\4.8.1\mingw
set PATH=%QTDIR%\bin;%PATH%
set PATH=C:\QtSDK1.2.1\mingw\bin;%PATH%

qmake -makefile -Wall -Wparser -Wlogic -Wdeprecated -d -recursive -r -spec win32-g++ "CONFIG+=release" -o log_qmake.txt >log_echo_qmake.txt

Промучавшись с qmake и правкой .pro файлов примерно 1-2 дня (на изучение команд и переменных qmake для .pro фалов) можно получить приятный результат :

The process "c:\qtsdk1.2.1\desktop\qt\4.8.1\mingw\bin\qmake.exe" exited normally.

Вот с таким .qmake.cache у нас прошел процесс qmake до конца:

QT_SOURCE_TREE = $$quote(C:\\QtSDK1.2.1\\QtSources\\4.8.1)
QT_BUILD_TREE = $$QT_SOURCE_TREE
QT_ARCH = i386

config.exe

А теперь мы , как чаcто бывает , узнаем , что в каталоге C:\QtSDK1.2.1\QtSources\4.8.1 есть файл config.exe , который как раз и создает нам .qmake.cache и .qmake.cache автоматически.

Config.exe создает файл .qmake.cache и .qmake.cache в этом же каталоге C:\QtSDK1.2.1\QtSources\4.8.1. А мы знаем уже ,что .qmake.cache должен быть на каталог выше чем наш файл с проектом .pro и на одном уровне каталогов с каталогом теневой сборки (это т тот куда вся сборка попадает). Поэтому догадались , что сonfig.exe готовит .qmake.cache для проектов на один уровень ниже себя, то есть например для src.pro или tools.pro.

Как окажется позднее сonfig.exe не совсем очевидно влияет на процесс сборки проекта исходников src.pro.

Поэтому открываем src.pro qt криатором , делаем qmake (нормально), и нормально проходит компиляция исходников . Но затыкаемся на этапе сборки :

G++ -Wl,-s -Wl,-subsystem,console -mthreads -o ..\..\..\bin\moc.exe release/moc.o release/preprocessor.o release/generator.o release/parser.o release/token.o release/main.o -L"c:\QtSDK1.2.1\QtSources\4.8.1\src\tools\bootstrap\release" -lbootstrap -luser32 .

Обращаю внимание на значение -L каталога , где надо искать libbootstrap.a : c:\QtSDK1.2.1\QtSources\4.8.1\src\tools\bootstrap\release - оно не корректно!.. Все это пока только наводит на мысли , что надо изучать язык qmake и makefile.


cannot find -lbootstrap

bootstrap - начальная загрузка. libbootstrap.a у нас (после компиляции) появился и лежит в каталоге :

C:\QtSDK1.2.1\QtSources\4.8.1\src\tools-build-desktop-Qt_4_8_1_for_Desktop_-_MinGW__Qt_SDK__Release\bootstrap\release\libbootstrap.a

src.pro

Теперь пытаемся собрать исходники из проекта scr.pro , который лежит у нас в C:\QtSDK1.2.1\QtSources\4.8.1\src .
Это и есть наши исходники Qt . Там же есть зависимости к другим каталогам (других проектов). Но все эти связи учитываются в .pro файлах.

Тут надо как-то уменьшить объем собираемых данных , иначе это затягивается на 20-30 минут. Оказывается , что для этого надо просто в проект src.pro уменьшить содержимое переменных SRC_SUBDIRS и QT_CONFIG. Откуда они берут начальные значения непонятно, но там изначально всего по максимуму.

Для того ,чтобы оставить только corelib делаем в начале src.pro так :


QT_CONFIG -= opengl openvg phonon multimedia webkit activeqt svg qt3support script declarative xmlpatterns gui
...
и в таком духе закоментим лишнее
# SRC_SUBDIRS += src_plugins

# то есть в результате SRC_SUBDIRS будет = src_corelib
# QT_CONFIG будет 

Останется только подсунуть из каталога C:\QtSDK1.2.1\QtSources\4.8.1\src-build-desktop-Qt_4_8_1_for_Desktop_-_MinGW__Qt_SDK__Release\tools\bootstrap\release файл libbootstrap.a в каталог c:\QtSDK1.2.1\QtSources\4.8.1\src\tools\bootstrap\release.