qmake: Introduce precompile_header_c for MSVC

MSVC requires that the C PCH file is compiled (as an object) and linked if
any C file is found, and the same for C++.

Most qmake projects are C++.

If a C++ project has a precompiled header, it is typically of C++ type, and
cannot be compiled as C (for example, it contains or includes classes).

Since there is no easy way to conditionally build the C PCH file only if C
files are found in the project (as done for g++), we need a setting that is
disabled by default.

This amends 30331afda118.

[ChangeLog][Tools][qmake] Introduced precompile_header_c CONFIG option for
MSVC to enable precompiled header for C sources.

Task-number: QTBUG-65103
Change-Id: Id9688a35ee7d9b5e4f5a846b81986cb674bc5f4e
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@qt.io>
This commit is contained in:
Orgad Shaneh 2018-01-02 19:07:03 +02:00 committed by Orgad Shaneh
parent 3e58f2b090
commit af1a179cc8
3 changed files with 25 additions and 13 deletions

View File

@ -939,6 +939,8 @@
order in which they are given. order in which they are given.
\row \li precompile_header \li Enables support for the use of \row \li precompile_header \li Enables support for the use of
\l{Using Precompiled Headers}{precompiled headers} in projects. \l{Using Precompiled Headers}{precompiled headers} in projects.
\row \li precompile_header_c (MSVC only) \li Enables support for the use of
\l{Using Precompiled Headers}{precompiled headers} for C files.
\row \li warn_on \li The compiler should output as many warnings as possible. \row \li warn_on \li The compiler should output as many warnings as possible.
If \c warn_off is also specified, the last one takes effect. If \c warn_off is also specified, the last one takes effect.
\row \li warn_off \li The compiler should output as few warnings as possible. \row \li warn_off \li The compiler should output as few warnings as possible.
@ -4623,6 +4625,11 @@
\snippet code/doc_src_qmake-manual.pro 106 \snippet code/doc_src_qmake-manual.pro 106
To use the precompiled header also for C files on MSVC nmake target, add
\c precompile_header_c to the \l{CONFIG} variable. If the header is
used also for C++ and it contains C++ keywords/includes, enclose them
with \c{#ifdef __cplusplus}).
\section1 Notes on Possible Issues \section1 Notes on Possible Issues
On some platforms, the file name suffix for precompiled header files is On some platforms, the file name suffix for precompiled header files is

View File

@ -51,7 +51,7 @@ static QString nmakePathList(const QStringList &list)
.replace('#', QLatin1String("^#")).replace('$', QLatin1String("$$")); .replace('#', QLatin1String("^#")).replace('$', QLatin1String("$$"));
} }
NmakeMakefileGenerator::NmakeMakefileGenerator() : Win32MakefileGenerator(), usePCH(false) NmakeMakefileGenerator::NmakeMakefileGenerator() : usePCH(false), usePCHC(false)
{ {
} }
@ -324,6 +324,8 @@ void NmakeMakefileGenerator::writeNmakeParts(QTextStream &t)
<< escapeDependencyPaths(findDependencies(precompH)).join(" \\\n\t\t") << escapeDependencyPaths(findDependencies(precompH)).join(" \\\n\t\t")
<< "\n\t$(CXX) " + precompRule +" $(CXXFLAGS) $(INCPATH) -TP " << "\n\t$(CXX) " + precompRule +" $(CXXFLAGS) $(INCPATH) -TP "
<< escapeFilePath(precompH) << endl << endl; << escapeFilePath(precompH) << endl << endl;
}
if (usePCHC) {
QString precompRuleC = QString("-c -Yc -Fp%1 -Fo%2") QString precompRuleC = QString("-c -Yc -Fp%1 -Fo%2")
.arg(escapeFilePath(precompPchC), escapeFilePath(precompObjC)); .arg(escapeFilePath(precompPchC), escapeFilePath(precompObjC));
t << escapeDependencyPath(precompObjC) << ": " << escapeDependencyPath(precompH) << ' ' t << escapeDependencyPath(precompObjC) << ": " << escapeDependencyPath(precompH) << ' '
@ -335,14 +337,14 @@ void NmakeMakefileGenerator::writeNmakeParts(QTextStream &t)
QString NmakeMakefileGenerator::var(const ProKey &value) const QString NmakeMakefileGenerator::var(const ProKey &value) const
{ {
if (usePCH) { if (usePCH || usePCHC) {
const bool isRunC = (value == "QMAKE_RUN_CC_IMP_BATCH" const bool isRunC = (value == "QMAKE_RUN_CC_IMP_BATCH"
|| value == "QMAKE_RUN_CC_IMP" || value == "QMAKE_RUN_CC_IMP"
|| value == "QMAKE_RUN_CC"); || value == "QMAKE_RUN_CC");
if (isRunC const bool isRunCpp = (value == "QMAKE_RUN_CXX_IMP_BATCH"
|| value == "QMAKE_RUN_CXX_IMP_BATCH" || value == "QMAKE_RUN_CXX_IMP"
|| value == "QMAKE_RUN_CXX_IMP" || value == "QMAKE_RUN_CXX");
|| value == "QMAKE_RUN_CXX") { if ((isRunCpp && usePCH) || (isRunC && usePCHC)) {
QFileInfo precompHInfo(fileInfo(precompH)); QFileInfo precompHInfo(fileInfo(precompH));
QString precompH_f = escapeFilePath(precompHInfo.fileName()); QString precompH_f = escapeFilePath(precompHInfo.fileName());
QString precompRule = QString("-c -FI%1 -Yu%2 -Fp%3") QString precompRule = QString("-c -FI%1 -Yu%2 -Fp%3")
@ -410,21 +412,24 @@ void NmakeMakefileGenerator::init()
// Setup PCH variables // Setup PCH variables
precompH = project->first("PRECOMPILED_HEADER").toQString(); precompH = project->first("PRECOMPILED_HEADER").toQString();
usePCH = !precompH.isEmpty() && project->isActiveConfig("precompile_header"); usePCH = !precompH.isEmpty() && project->isActiveConfig("precompile_header");
usePCHC = !precompH.isEmpty() && project->isActiveConfig("precompile_header_c");
if (usePCH) { if (usePCH) {
// Created files // Created files
precompObj = var("PRECOMPILED_DIR") + project->first("TARGET") + "_pch" + Option::obj_ext; precompObj = var("PRECOMPILED_DIR") + project->first("TARGET") + "_pch" + Option::obj_ext;
precompPch = var("PRECOMPILED_DIR") + project->first("TARGET") + "_pch.pch"; precompPch = var("PRECOMPILED_DIR") + project->first("TARGET") + "_pch.pch";
precompObjC = var("PRECOMPILED_DIR") + project->first("TARGET") + "_pch_c" + Option::obj_ext;
precompPchC = var("PRECOMPILED_DIR") + project->first("TARGET") + "_pch_c.pch";
// Add linking of precompObj (required for whole precompiled classes) // Add linking of precompObj (required for whole precompiled classes)
project->values("OBJECTS") += precompObj; project->values("OBJECTS") += precompObj;
project->values("OBJECTS") += precompObjC;
// Add pch file to cleanup // Add pch file to cleanup
project->values("QMAKE_CLEAN") += precompPch; project->values("QMAKE_CLEAN") += precompPch;
project->values("QMAKE_CLEAN") += precompPchC;
// Return to variable pool // Return to variable pool
project->values("PRECOMPILED_OBJECT") = ProStringList(precompObj); project->values("PRECOMPILED_OBJECT") = ProStringList(precompObj);
project->values("PRECOMPILED_PCH") = ProStringList(precompPch); project->values("PRECOMPILED_PCH") = ProStringList(precompPch);
}
if (usePCHC) {
precompObjC = var("PRECOMPILED_DIR") + project->first("TARGET") + "_pch_c" + Option::obj_ext;
precompPchC = var("PRECOMPILED_DIR") + project->first("TARGET") + "_pch_c.pch";
project->values("OBJECTS") += precompObjC;
project->values("QMAKE_CLEAN") += precompPchC;
project->values("PRECOMPILED_OBJECT_C") = ProStringList(precompObjC); project->values("PRECOMPILED_OBJECT_C") = ProStringList(precompObjC);
project->values("PRECOMPILED_PCH_C") = ProStringList(precompPchC); project->values("PRECOMPILED_PCH_C") = ProStringList(precompPchC);
} }

View File

@ -53,7 +53,7 @@ protected:
QString var(const ProKey &value) const; QString var(const ProKey &value) const;
QString precompH, precompObj, precompPch; QString precompH, precompObj, precompPch;
QString precompObjC, precompPchC; QString precompObjC, precompPchC;
bool usePCH; bool usePCH, usePCHC;
public: public:
NmakeMakefileGenerator(); NmakeMakefileGenerator();