预编译头文件(PCH)是一些编译器支持的一种性能特性,用于编译稳定的代码体,并将代码的编译状态存储在二进制文件中。在后续编译期间,编译器将加载存储的状态,并继续编译指定的文件。因为稳定的代码体不需要重新编译,所以后续的每次编译都会更快。
qmake 支持在一些平台和构建环境中使用预编译头文件,包括:
- Windows
- nmake
- Visual Studio projects (VS 2008 and later)
- macOS, iOS, tvOS, and watchOS
- Makefile
- Xcode
- Unix
- GCC 3.4 and above
- clang
1. 向项目添加预编译头文件
预编译头必须包含在整个项目中稳定且静态的代码。一个典型的预编译头可能是这样的:
// Add C includes here
#if defined __cplusplus
// Add C++ includes here
#include <stdlib>
#include <iostream>
#include <vector>
#include <QApplication> // Qt includes
#include <QPushButton>
#include <QLabel>
#include "thirdparty/include/libmain.h"
#include "my_stable_class.h"
...
#endif
注意: 预编译头文件需要将 C 包含从 C++ 包含中分离出来,因为用于 C 文件的预编译头文件可能不包含 C++ 代码。
1.1 项目选项
要让我们的项目使用预编译头文件,我们只需要在我们的项目文件中定义 PRECOMPILED_HEADER 变量:
PRECOMPILED_HEADER = stable.h
qmake 将处理剩下的工作,以确保创建和使用预编译头文件。我们不需要在 HEADERS 中包含预编译头文件,因为如果配置支持预编译头文件,qmake 就会这样做。
默认情况下,MSVC 和 g++ 的设定目标窗口启用了 precompile_header
使用此选项,我们可以在使用预编译头文件时触发项目文件中的条件块来添加设置。例如:
precompile_header:!isEmpty(PRECOMPILED_HEADER) {
DEFINES += USING_PCH
}
要对 MSVC nmake 目标上的 C 文件也使用预编译头,请将 precompile_header_c 添加到 CONFIG 变量中。如果该 C 头文件也用于 C++,并且它包含 C++ 关键字/include,那么用 #ifdef __cplusplus
将它们括起来)。
2. 可能出现的问题
在某些平台上,预编译头文件的文件名后缀与其他目标文件的文件名后缀相同。例如,以下声明可能导致生成两个具有相同名称的不同对象文件:
PRECOMPILED_HEADER = window.h
SOURCES = window.cpp
为了避免类似的潜在冲突,最好为将要预编译的头文件提供独特的名称。
3. 示例项目
我们可以在 Qt 发行版的 examples/qmake/precompile 目录中找到以下源代码:
3.1 mydialog.ui
下图在 Qt Creator 设计模式中显示了 mydialog.ui 文件。我们可以在编辑模式下查看其代码。
qmake-precompile-ui3.2 stable.h
/* Add C includes here */
#if defined __cplusplus
/* Add C++ includes here */
# include <iostream>
# include <QApplication>
# include <QPushButton>
# include <QLabel>
#endif
3.3 myobject.h
#include <QObject>
class MyObject : public QObject
{
public:
MyObject();
~MyObject();
};
3.4 myobject.cpp
#include <iostream>
#include <QDebug>
#include <QObject>
#include "myobject.h"
MyObject::MyObject()
: QObject()
{
std::cout << "MyObject::MyObject()\n";
}
3.5 util.cpp
void util_function_does_nothing()
{
// Nothing here...
int x = 0;
++x;
}
3.6 main.cpp
#include <QApplication>
#include <QPushButton>
#include <QLabel>
#include "myobject.h"
#include "mydialog.h"
int main(int argc, char **argv)
{
QApplication app(argc, argv);
MyObject obj;
MyDialog dialog;
dialog.connect(dialog.aButton, SIGNAL(clicked()), SLOT(close()));
dialog.show();
return app.exec();
}
3.7 precompile.pro
TEMPLATE = app
LANGUAGE = C++
CONFIG += cmdline precompile_header
# Use Precompiled headers (PCH)
PRECOMPILED_HEADER = stable.h
HEADERS = stable.h \
mydialog.h \
myobject.h
SOURCES = main.cpp \
mydialog.cpp \
myobject.cpp \
util.cpp
FORMS = mydialog.ui
网友评论