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 30331afda1.

[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.
\row \li precompile_header \li Enables support for the use of
\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.
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.
@ -4623,6 +4625,11 @@
\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
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("$$"));
}
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")
<< "\n\t$(CXX) " + precompRule +" $(CXXFLAGS) $(INCPATH) -TP "
<< escapeFilePath(precompH) << endl << endl;
}
if (usePCHC) {
QString precompRuleC = QString("-c -Yc -Fp%1 -Fo%2")
.arg(escapeFilePath(precompPchC), escapeFilePath(precompObjC));
t << escapeDependencyPath(precompObjC) << ": " << escapeDependencyPath(precompH) << ' '
@ -335,14 +337,14 @@ void NmakeMakefileGenerator::writeNmakeParts(QTextStream &t)
QString NmakeMakefileGenerator::var(const ProKey &value) const
{
if (usePCH) {
if (usePCH || usePCHC) {
const bool isRunC = (value == "QMAKE_RUN_CC_IMP_BATCH"
|| value == "QMAKE_RUN_CC_IMP"
|| value == "QMAKE_RUN_CC");
if (isRunC
|| value == "QMAKE_RUN_CXX_IMP_BATCH"
|| value == "QMAKE_RUN_CXX_IMP"
|| value == "QMAKE_RUN_CXX") {
const bool isRunCpp = (value == "QMAKE_RUN_CXX_IMP_BATCH"
|| value == "QMAKE_RUN_CXX_IMP"
|| value == "QMAKE_RUN_CXX");
if ((isRunCpp && usePCH) || (isRunC && usePCHC)) {
QFileInfo precompHInfo(fileInfo(precompH));
QString precompH_f = escapeFilePath(precompHInfo.fileName());
QString precompRule = QString("-c -FI%1 -Yu%2 -Fp%3")
@ -410,21 +412,24 @@ void NmakeMakefileGenerator::init()
// Setup PCH variables
precompH = project->first("PRECOMPILED_HEADER").toQString();
usePCH = !precompH.isEmpty() && project->isActiveConfig("precompile_header");
usePCHC = !precompH.isEmpty() && project->isActiveConfig("precompile_header_c");
if (usePCH) {
// Created files
precompObj = var("PRECOMPILED_DIR") + project->first("TARGET") + "_pch" + Option::obj_ext;
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)
project->values("OBJECTS") += precompObj;
project->values("OBJECTS") += precompObjC;
project->values("OBJECTS") += precompObj;
// Add pch file to cleanup
project->values("QMAKE_CLEAN") += precompPch;
project->values("QMAKE_CLEAN") += precompPchC;
project->values("QMAKE_CLEAN") += precompPch;
// Return to variable pool
project->values("PRECOMPILED_OBJECT") = ProStringList(precompObj);
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_PCH_C") = ProStringList(precompPchC);
}

View File

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