Пример поиска одной ошибки в системе qmake/pro/makefile

Наконец-то первый минимальный вариант исходников (из проекта src.pro) компилируется и собирается нормально :
Creating library file: c:\QtSDK1.2.1\QtSources\4.8.1\lib\libQtCore4.a.

Но есть нюанс : почему-то компоновщик ищет libbootstrap.a в другом каталоге. Ошибка выглядит так :

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 .

cannot find -lbootstrap

Внимание на значение -L каталога , где надо искать libbootstrap.a : c:\QtSDK1.2.1\QtSources\4.8.1\src\tools\bootstrap\release - оно не корректно!..

Теперь вникаем в тонкости qmake "по-взрослому" и почему компоновщик ищет libbootstrap.a в другом каталоге (c:\QtSDK1.2.1\QtSources\4.8.1\src\tools\bootstrap\release). А наша сборка помещает 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 .

Пытаемся разобраться ...

Лог qmake из Qt криатора выглядит так :


11:18:42: Starting: "c:\qtsdk1.2.1\desktop\qt\4.8.1\mingw\bin\qmake.exe" C:\QtSDK1.2.1\QtSources\4.8.1\src\src.pro -r -spec win32-g++ "CONFIG+=release"
Qt: Untested Windows version 6.2 detected!
Reading C:/QtSDK1.2.1/QtSources/4.8.1/src/tools/bootstrap/bootstrap.pro [C:/QtSDK1.2.1/QtSources/4.8.1/src-build-desktop-Qt_4_8_1_for_Desktop_-_MinGW__Qt_SDK__Release/tools/bootstrap]
Reading C:/QtSDK1.2.1/QtSources/4.8.1/src/tools/moc/moc.pro [C:/QtSDK1.2.1/QtSources/4.8.1/src-build-desktop-Qt_4_8_1_for_Desktop_-_MinGW__Qt_SDK__Release/tools/moc]
Reading C:/QtSDK1.2.1/QtSources/4.8.1/src/tools/rcc/rcc.pro [C:/QtSDK1.2.1/QtSources/4.8.1/src-build-desktop-Qt_4_8_1_for_Desktop_-_MinGW__Qt_SDK__Release/tools/rcc]
Reading C:/QtSDK1.2.1/QtSources/4.8.1/src/tools/uic/uic.pro [C:/QtSDK1.2.1/QtSources/4.8.1/src-build-desktop-Qt_4_8_1_for_Desktop_-_MinGW__Qt_SDK__Release/tools/uic]
Reading C:/QtSDK1.2.1/QtSources/4.8.1/src/corelib/corelib.pro [C:/QtSDK1.2.1/QtSources/4.8.1/src-build-desktop-Qt_4_8_1_for_Desktop_-_MinGW__Qt_SDK__Release/corelib]

То есть , чтобы собрать минимально только corelib собираются зависимости bootstrap moc rcc uic . Это понятно , что созданы таким образом одноименные каталоги и там создан свой makefile для каждого из каталогов.


Теперь лог компиляции и сборки :


cd tools\bootstrap\ && C:/QtSDK1.2.1/mingw/bin/mingw32-make.exe -f Makefile 
mingw32-make.exe[1]: Entering directory `C:/QtSDK1.2.1/QtSources/4.8.1/src-build-desktop-Qt_4_8_1_for_Desktop_-_MinGW__Qt_SDK__Release/tools/bootstrap'
C:/QtSDK1.2.1/mingw/bin/mingw32-make.exe -f Makefile.Release
mingw32-make.exe[2]: Entering directory `C:/QtSDK1.2.1/QtSources/4.8.1/src-build-desktop-Qt_4_8_1_for_Desktop_-_MinGW__Qt_SDK__Release/tools/bootstrap'
mingw32-make.exe[2]: Nothing to be done for `first'.
mingw32-make.exe[2]: Leaving directory `C:/QtSDK1.2.1/QtSources/4.8.1/src-build-desktop-Qt_4_8_1_for_Desktop_-_MinGW__Qt_SDK__Release/tools/bootstrap'
mingw32-make.exe[1]: Leaving directory `C:/QtSDK1.2.1/QtSources/4.8.1/src-build-desktop-Qt_4_8_1_for_Desktop_-_MinGW__Qt_SDK__Release/tools/bootstrap'
cd tools\moc\ && C:/QtSDK1.2.1/mingw/bin/mingw32-make.exe -f Makefile 
mingw32-make.exe[1]: Entering directory `C:/QtSDK1.2.1/QtSources/4.8.1/src-build-desktop-Qt_4_8_1_for_Desktop_-_MinGW__Qt_SDK__Release/tools/moc'
C:/QtSDK1.2.1/mingw/bin/mingw32-make.exe -f Makefile.Release
mingw32-make.exe[2]: Entering directory `C:/QtSDK1.2.1/QtSources/4.8.1/src-build-desktop-Qt_4_8_1_for_Desktop_-_MinGW__Qt_SDK__Release/tools/moc'
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 
mingw32-make.exe[2]: Leaving directory `C:/QtSDK1.2.1/QtSources/4.8.1/src-build-desktop-Qt_4_8_1_for_Desktop_-_MinGW__Qt_SDK__Release/tools/moc'
mingw32-make.exe[1]: Leaving directory `C:/QtSDK1.2.1/QtSources/4.8.1/src-build-desktop-Qt_4_8_1_for_Desktop_-_MinGW__Qt_SDK__Release/tools/moc'
c:/qtsdk1.2.1/mingw/bin/../lib/gcc/mingw32/4.4.0/../../../../mingw32/bin/ld.exe: cannot find -lbootstrap
collect2: ld returned 1 exit status
mingw32-make.exe[2]: *** [..\..\..\bin\moc.exe] Error 1
mingw32-make.exe[1]: *** [release] Error 2
mingw32-make.exe: *** [sub-moc-make_default] Error 2
11:51:33: The process "C:\QtSDK1.2.1\mingw\bin\mingw32-make.exe" exited with code 2.
Error while building project src (target: Desktop)
When executing build step 'Make'

Вопрос первый - в каком makefile это происходит? По-видимому ответ : в ../tools/moc (смотрите последний Entering directory).

Теперь понятно - идет в /tools/moc , открываем там Makefile.Release и видим внутри :


LIBS = -L"c:\QtSDK1.2.1\QtSources\4.8.1\src\tools\bootstrap\release" -lbootstrap -luser32

То есть понятно , что qmake при генерации makefile для проекта /tools/moc утсанвливает неправильно переменную LIBS ....

Теперь открываем файл moc.pro :


TEMPLATE	= app
TARGET		= moc

DEFINES	       += QT_MOC
DESTDIR         = ../../../bin
INCLUDEPATH	+= . 
DEPENDPATH	+= .
LIBS	        =
# LIBS сначала просто очищается
OBJECTS_DIR	= .

include(moc.pri)
HEADERS += qdatetime_p.h
SOURCES += main.cpp
include(../bootstrap/bootstrap.pri)
# вот тут LIBS изменится из кода в bootstrap.pri 
# и станет :
#---------------------------------------------------
# LIBS = -lbootstrap -luser32
#---------------------------------------------------

target.path=$$[QT_INSTALL_BINS]
INSTALLS += target
include(../../qt_targets.pri)

!exists($$OUT_PW/tools/bootstrap/release){
    message(not exists $$OUT_PWD/tools/bootstrap/release )
}

INCLUDEPATH += $$OUT_PWD/tools/bootstrap/release

message(LIBS = $$LIBS)  # выводит в итоге LIBS = -lbootstrap -luser32

Вопрос откуда в makefile все-таки появляется -L"c:\QtSDK1.2.1\QtSources\4.8.1\src\tools\bootstrap\release" ?....

Этот путь напоминает путь не теневой сборки а прямой сборки.

Если установить изначально LIBS как ниже , то ошибка уйдет (и это логично) :
LIBS = -L../../tools/bootstrap/release

В makefile мы теперь увидим следующее :

LIBS = -L"c:\QtSDK1.2.1\QtSources\4.8.1\src\tools\bootstrap\release" -L../../tools/bootstrap/release -lbootstrap -luser32

То есть кто-то невидимой рукой все-равно добавляет -L"c:\QtSDK1.2.1\QtSources\4.8.1\src\tools\bootstrap\release" .

Примечательно , что $$QT_BUILD_TREE = c:\QtSDK1.2.1\QtSources\4.8.1\src\tools\bootstrap\release.

Поиск решения пришлось отложить , так как процесс сборки завершился удачно по причине отмены теневой сборки. Похоже , что сами исходники Qt не надо собирать в каталоге теневой сборке.

Так же примечательно , что сам qmake тоже представляется в виде исходников и его код можно смотреть...

Примечания:

цели главного makefile (самого верхнего):
clean очищает объектные файлы *.o
distclean очищает библиотеки *.a и кстати сам makefile удаляет