使用 Qt Creator / qmake / MinGw 的预编译标头无法在调试版本中工作

Posted

技术标签:

【中文标题】使用 Qt Creator / qmake / MinGw 的预编译标头无法在调试版本中工作【英文标题】:PRECOMPILED HEADERS not working in debug build with Qt Creator / qmake / MinGw 【发布时间】:2014-01-08 22:52:15 【问题描述】:

在 Qt Creator 中,我有一个使用 PRECOMPILED HEADERS 的 pro 文件。

当我在发布模式下构建时,构建工作得非常完美。但是在调试模式下构建会出错,生成目标文件失败。示例:

17:12:40: Running steps for project Euclide...
17:12:40: Configuration unchanged, skipping qmake step.
17:12:40: Starting: "C:\Qt\Tools\mingw48_32\bin\mingw32-make.exe" 
C:\Qt\5.2.0\mingw48_32\bin\qmake.exe -spec win32-g++ CONFIG+=debug -o Makefile ..\euclide\Euclide.pro
C:/Qt/Tools/mingw48_32/bin/mingw32-make -f Makefile.Debug
mingw32-make[1]: Entering directory 'C:/UserPrograms/Euclide/build'
g++ -c -include debug\_pch.h -pipe -fno-keep-inline-dllexport -std=gnu++11 -g -frtti -Wall -Wextra -fexceptions -mthreads -DUNICODE -DQT_WEBKITWIDGETS_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_QUICK_LIB -DQT_POSITIONING_LIB -DQT_OPENGL_LIB -DQT_PRINTSUPPORT_LIB -DQT_WEBKIT_LIB -DQT_MULTIMEDIA_LIB -DQT_QML_LIB -DQT_WIDGETS_LIB -DQT_NETWORK_LIB -DQT_SENSORS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_NEEDS_QMAIN -I..\euclide -I"..\..\..\Program Files (x86)\boost\boost_1_53_0" -I"..\numlib\mathvec" -I"..\..\..\Qt\5.2.0\mingw48_32\include" -I"..\..\..\Qt\5.2.0\mingw48_32\include\QtWebKitWidgets" -I"..\..\..\Qt\5.2.0\mingw48_32\include\QtMultimediaWidgets" -I"..\..\..\Qt\5.2.0\mingw48_32\include\QtQuick" -I"..\..\..\Qt\5.2.0\mingw48_32\include\QtPositioning" -I"..\..\..\Qt\5.2.0\mingw48_32\include\QtOpenGL" -I"..\..\..\Qt\5.2.0\mingw48_32\include\QtPrintSupport" -I"..\..\..\Qt\5.2.0\mingw48_32\include\QtWebKit" -I"..\..\..\Qt\5.2.0\mingw48_32\include\QtMultimedia" -I"..\..\..\Qt\5.2.0\mingw48_32\include\QtQml" -I"..\..\..\Qt\5.2.0\mingw48_32\include\QtWidgets" -I"..\..\..\Qt\5.2.0\mingw48_32\include\QtNetwork" -I"..\..\..\Qt\5.2.0\mingw48_32\include\QtSensors" -I"..\..\..\Qt\5.2.0\mingw48_32\include\QtGui" -I"..\..\..\Qt\5.2.0\mingw48_32\include\QtCore" -I"debug" -I"." -I"." -I"..\..\..\Qt\5.2.0\mingw48_32\mkspecs\win32-g++" -o debug\main.o ..\euclide\main.cpp

Makefile.Debug:1543: recipe for target 'debug/main.o' failed
mingw32-make[1]: *** [debug/main.o] Error 1
mingw32-make[1]: Leaving directory 'C:/UserPrograms/Euclide/build'
makefile:34: recipe for target 'debug' failed
mingw32-make: *** [debug] Error 2
17:12:59: The process "C:\Qt\Tools\mingw48_32\bin\mingw32-make.exe" exited with code 2.
Error while building/deploying project Euclide (kit: Desktop Qt 5.2.0 MinGW 32bit)
When executing step 'Make'
17:12:59: Elapsed time: 00:19.

真正令人困惑的是它在 Release 中运行良好。我用一个小项目做了一些测试,它在发布或调试模式下运行良好,但出于任何原因,一个更大的项目失败了。在 Debug 中编译项目的单个文件甚至是不可能的。 pro文件如下:

QT += core gui \
    webkitwidgets \
    printsupport

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = Euclide
TEMPLATE = app

QMAKE_CXXFLAGS += -std=gnu++11

CONFIG += precompile_header

# Use Precompiled headers (PCH)
PRECOMPILED_HEADER  = _pch.h    

SOURCES +=  main.cpp\
    mainwindow.cpp \
    zero.cpp \
    ... lot of files here...
    debug_tool.cpp

HEADERS += mainwindow.h \
    zero.h \
    ... lot of files here...
    debug_tool.h \
    _pch.h

FORMS += mainwindow.ui \
    zero.ui \
    ... other files...
    apphelp.ui \
    message.ui

INCLUDEPATH = "C:/Program Files (x86)/boost/boost_1_53_0"

LIBS += \
    ../build/release/exprcompiler.dll

RESOURCES += \
    resources/euclide_resources.qrc

我在网上花了几天的时间广泛研究来解决这个问题,但没有找到任何解释,即使关于 qmake 的文档是完整的......

有谁知道如何解决这个问题?因为我现在考虑的唯一解决方案是拥有这个所有项目的特殊“调试”版本,没有预编译头文件...... 感谢您的帮助。

【问题讨论】:

您能否提供一个独立的示例来重现该问题?详情请参考 sscce.org。 在构建代码时,使用预编译头文件是否可以节省大量时间?我倾向于在超过 30KLOC 的项目或非常慢的开发平台上使用预编译头文件。使用它们时的头痛,就像您正在经历的那样,并不能证明浪费时间是正当的。或者使用它们获得的时间被浪费在这样的问题上。 @ThomasMatthews:有人不会在没有真正收益的​​情况下使用它们,对吧? :-) 人们在寻找慢速编译优化时通常会选择它。我无法想象任何其他情况。 @Laszlo:这个项目现在(相当)大,有几十个文件(不包括包含和 dll 源),所以很遗憾我无法发布代码。但实际上,除了我的帖子顶部的这个 debug/main.o 错误 1 ​​之外,编译输出没有给出任何解释。还有,小项目在两种模式下都能正常工作,不知道去哪里找。 @LaszloPapp 我个人认为这是一个可以接受的问题。问题不是“我的项目中的错误在哪里”,而是一般意义上的“PCH 可能导致什么问题”。如果它没有有意义的答案(即答案是“你的代码中有错误”),那很好,它不会得到一个好的答案,并且可能是自我封闭的候选者操作。另一方面,如果预编译的头文件确实有一个必须解决的特定问题,那么这可能对其未来的其他人有所帮助,并且是一个合理的问题。 【参考方案1】:

我(可能)遇到了同样的问题,并花了一些时间来找出发生了什么。

在创建 MWE 后,我发现 .pch 文件的大小似乎对这个问题至关重要。

使用大于 128 MB 的 PCH 会中止编译且不显示任何消息并返回代码 1(而不是成功编译的 0)。

我的发现类似于GCC mailing list entry 中所述的问题。

似乎让它工作的唯一方法是将 PCH 文件的大小减小到 128 MB 以下

仅作记录: 我正在使用 Qt 5.2.1 中的 QMake 项目以及 WinXP 32 位和 Win 8 64 位上包含的 MinGW (rev2) gcc 4.8.0 32 位。

另一方面,我在 linux 下的 GCC 4.8.2 64bit 毫无怨言地吃了一个 ~5GB PCH 文件(我会测试一个更大的文件,但编译这个文件几乎超出了我的 RAM)。

深入挖掘

我生成了一个头文件用作PCH,内容如下:

class _1 ;
class _2 ;
class _3 ;
class _4 ;
class _5 ;
class _6 ;
class _7 ;
class _8 ;
class _9 ;
class _10 ;
//...

使用二分查找(查找此文件中的类数)我发现 用 128273 个类填充这个文件会生成一个大小为 135266564 字节的 PCH 文件,可以在编译其他文件时使用。 使用 128274 个类生成的 PCH 文件大小为 135270660 字节,使用此 PCH 编译失败。

我不确定如何处理这些信息。不给出错误消息肯定是错误的,但我不知道该怪谁(GCC(版本?)、MinGW/Windows、32 位)。

也许手头有更多时间的人可以决定并通知合适的人?

【讨论】:

很好的答案!我在 Qt 5.3.0(使用 gcc 4.8.2)时遇到了同样的问题。包括 QtCore、QtGui 和 QtWidgets 到 pch(这大大减少了编译时间)产生了 136MB,并且在 pch 之外的第一个编译文件上构建失败。仅包括 QtCore 和 QtGui 产生了 119MB 并且构建成功。

以上是关于使用 Qt Creator / qmake / MinGw 的预编译标头无法在调试版本中工作的主要内容,如果未能解决你的问题,请参考以下文章

使用 Qt Creator / qmake / MinGw 的预编译标头无法在调试版本中工作

没有为 Qt Creator 3.2.0 找到 qmake.exe

fedora10系统里,安了qt creator,想用qt自带的qt库。在tools_>options里配置qmake的时候,为啥总是叉

qt creator配置qt version:从别处拷贝来的qt库时遇到的问题

如何更改 Qt Creator 构建工具?

使用类似环境的 Qt Creator 运行脚本