Make moc obey the preprocessor environment variable for include paths
C preprocessors augment their standard list of include paths from the environment: Unix preprocessors use $C_INCLUDE_PATH (for C) and $CPLUS_INCLUDE_PATH (for C++), plus CPATH for both, whereas MSVC uses the an environment variable simply called "INCLUDE". Handling this for MSVC is particularly important because the VCVARSALL.BAT script sets the necessary #include paths in the environment for important things. Without that being parsed, moc won't find some #defines, like WINAPI_DESKTOP_FAMILY. [ChangeLog][moc] qmake and moc now cooperate to use the Visual Studio environment variables (set by the VCVARSALL.BAT script) to find system include files. A possible consequence is that moc parses application headers slightly differently, depending on #if conditions that depended on macros that previous versions had not seen #define'd. Implementers of other buildsystems are advised to pass the --compiler-flavor=msvc option to moc. Change-Id: I7e06274214d1939b0124e5b4bf169cceaef9ca46 Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>bb10
parent
36d524e6a3
commit
da04322b4c
|
|
@ -51,6 +51,7 @@ defineReplace(mocCmdBase) {
|
|||
}
|
||||
|
||||
RET = $$QMAKE_MOC $(DEFINES)
|
||||
msvc: RET += --compiler-flavor=msvc
|
||||
|
||||
isEmpty(MOC_PREDEF_FILE): RET += $$join(QMAKE_COMPILER_DEFINES, " -D", -D)
|
||||
else: RET += --include $$moc_predefs.output
|
||||
|
|
|
|||
|
|
@ -90,6 +90,9 @@ macro(QT5_GET_MOC_FLAGS _moc_flags)
|
|||
if(WIN32)
|
||||
set(${_moc_flags} ${${_moc_flags}} -DWIN32)
|
||||
endif()
|
||||
if (MSVC)
|
||||
set(${_moc_flags} --compiler-flavor=msvc)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,10 @@ unix: {
|
|||
unix:HEADERS += \
|
||||
socket/qnet_unix_p.h
|
||||
|
||||
# Suppress deprecation warnings with moc because MS headers have
|
||||
# invalid C/C++ code otherwise.
|
||||
msvc: QMAKE_MOC_OPTIONS += -D_WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
|
||||
win32:!winrt:SOURCES += socket/qnativesocketengine_win.cpp \
|
||||
socket/qlocalsocket_win.cpp \
|
||||
socket/qlocalserver_win.cpp
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2016 Intel Corporation.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the tools applications of the Qt Toolkit.
|
||||
|
|
@ -242,6 +243,11 @@ int runMoc(int argc, char **argv)
|
|||
metadataOption.setFlags(QCommandLineOption::ShortOptionStyle);
|
||||
parser.addOption(metadataOption);
|
||||
|
||||
QCommandLineOption compilerFlavorOption(QStringLiteral("compiler-flavor"));
|
||||
compilerFlavorOption.setDescription(QStringLiteral("Set the compiler flavor: either \"msvc\" or \"unix\"."));
|
||||
compilerFlavorOption.setValueName(QStringLiteral("flavor"));
|
||||
parser.addOption(compilerFlavorOption);
|
||||
|
||||
QCommandLineOption noIncludeOption(QStringLiteral("i"));
|
||||
noIncludeOption.setDescription(QStringLiteral("Do not generate an #include statement."));
|
||||
parser.addOption(noIncludeOption);
|
||||
|
|
@ -328,9 +334,32 @@ int runMoc(int argc, char **argv)
|
|||
if (parser.isSet(pathPrefixOption))
|
||||
moc.includePath = QFile::encodeName(parser.value(pathPrefixOption));
|
||||
}
|
||||
|
||||
const auto includePaths = parser.values(includePathOption);
|
||||
for (const QString &path : includePaths)
|
||||
pp.includes += Preprocessor::IncludePath(QFile::encodeName(path));
|
||||
QString compilerFlavor = parser.value(compilerFlavorOption);
|
||||
if (compilerFlavor.isEmpty() || compilerFlavor == QLatin1String("unix")) {
|
||||
// traditional Unix compilers use both CPATH and CPLUS_INCLUDE_PATH
|
||||
// $CPATH feeds to #include <...> and #include "...", whereas
|
||||
// CPLUS_INCLUDE_PATH is equivalent to GCC's -isystem, so we parse later
|
||||
const auto cpath = qgetenv("CPATH").split(QDir::listSeparator().toLatin1());
|
||||
for (const QByteArray &p : cpath)
|
||||
pp.includes += Preprocessor::IncludePath(p);
|
||||
const auto cplus_include_path = qgetenv("CPLUS_INCLUDE_PATH").split(QDir::listSeparator().toLatin1());
|
||||
for (const QByteArray &p : cplus_include_path)
|
||||
pp.includes += Preprocessor::IncludePath(p);
|
||||
} else if (compilerFlavor == QLatin1String("msvc")) {
|
||||
// MSVC uses one environment variable: INCLUDE
|
||||
const auto include = qgetenv("INCLUDE").split(QDir::listSeparator().toLatin1());
|
||||
for (const QByteArray &p : include)
|
||||
pp.includes += Preprocessor::IncludePath(p);
|
||||
} else {
|
||||
error(qPrintable(QLatin1String("Unknown compiler flavor '") + compilerFlavor +
|
||||
QLatin1String("'; valid values are: msvc, unix.")));
|
||||
parser.showHelp(1);
|
||||
}
|
||||
|
||||
const auto macFrameworks = parser.values(macFrameworkOption);
|
||||
for (const QString &path : macFrameworks) {
|
||||
// minimalistic framework support for the mac
|
||||
|
|
|
|||
|
|
@ -577,6 +577,8 @@ private slots:
|
|||
void defineMacroViaCmdline();
|
||||
void defineMacroViaForcedInclude();
|
||||
void defineMacroViaForcedIncludeRelative();
|
||||
void environmentIncludePaths_data();
|
||||
void environmentIncludePaths();
|
||||
void specifyMetaTagsFromCmdline();
|
||||
void invokable();
|
||||
void singleFunctionKeywordSignalAndSlot();
|
||||
|
|
@ -1295,6 +1297,52 @@ void tst_Moc::defineMacroViaForcedIncludeRelative()
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
void tst_Moc::environmentIncludePaths_data()
|
||||
{
|
||||
#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
|
||||
QTest::addColumn<QString>("cmdline");
|
||||
QTest::addColumn<QString>("varname");
|
||||
|
||||
QTest::newRow("INCLUDE") << "--compiler-flavor=msvc" << "INCLUDE";
|
||||
QTest::newRow("CPATH1") << QString() << "CPATH";
|
||||
QTest::newRow("CPATH2") << "--compiler-flavor=unix" << "CPATH";
|
||||
QTest::newRow("CPLUS_INCLUDE_PATH1") << QString() << "CPLUS_INCLUDE_PATH";
|
||||
QTest::newRow("CPLUS_INCLUDE_PATH2") << "--compiler-flavor=unix" << "CPLUS_INCLUDE_PATH";
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_Moc::environmentIncludePaths()
|
||||
{
|
||||
#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
|
||||
QFETCH(QString, cmdline);
|
||||
QFETCH(QString, varname);
|
||||
|
||||
QStringList args;
|
||||
if (!cmdline.isEmpty())
|
||||
args << cmdline;
|
||||
args << "--include" << QStringLiteral("extradefines.h")
|
||||
<< m_sourceDirectory + QStringLiteral("/macro-on-cmdline.h");
|
||||
|
||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||
env.remove("INCLUDE");
|
||||
env.remove("CPATH");
|
||||
env.remove("CPLUS_INCLUDE_PATH");
|
||||
env.insert(varname, m_sourceDirectory + "/subdir");
|
||||
|
||||
QProcess proc;
|
||||
proc.setProcessEnvironment(env);
|
||||
proc.start(m_moc, args);
|
||||
QVERIFY(proc.waitForFinished());
|
||||
QCOMPARE(proc.exitCode(), 0);
|
||||
QCOMPARE(proc.readAllStandardError(), QByteArray());
|
||||
QByteArray mocOut = proc.readAllStandardOutput();
|
||||
QVERIFY(!mocOut.isEmpty());
|
||||
#else
|
||||
QSKIP("Only tested on linux/gcc");
|
||||
#endif
|
||||
}
|
||||
|
||||
// tst_Moc::specifyMetaTagsFromCmdline()
|
||||
// plugin_metadata.h contains a plugin which we register here. Since we're not building this
|
||||
// application as a plugin, we need top copy some of the initializer code found in qplugin.h:
|
||||
|
|
|
|||
Loading…
Reference in New Issue