forked from qt-creator/qt-creator
ProjectExplorer: Get predefined clang-cl macros in g++ and cl driver modes
By default clang-cl accepts only MSVC-style compile flags. However it's possible to run it with gcc-style flags when --driver-mode=g++ is set. With this change clang-cl is run in order to get proper predefined macros for both cases. Change-Id: I248d411561a503a60385b3a3106beecb38f3d063 Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
@@ -98,54 +98,6 @@ QString AbstractMsvcToolChain::originalTargetTriple() const
|
|||||||
: QLatin1String("i686-pc-windows-msvc");
|
: QLatin1String("i686-pc-windows-msvc");
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// We want to detect the language version based on the predefined macros.
|
|
||||||
// Unfortunately MSVC does not conform to standard when it comes to the predefined
|
|
||||||
// __cplusplus macro - it reports "199711L", even for newer language versions.
|
|
||||||
//
|
|
||||||
// However:
|
|
||||||
// * For >= Visual Studio 2015 Update 3 predefines _MSVC_LANG which has the proper value
|
|
||||||
// of __cplusplus.
|
|
||||||
// See https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=vs-2017
|
|
||||||
// * For >= Visual Studio 2017 Version 15.7 __cplusplus is correct once /Zc:__cplusplus
|
|
||||||
// is provided on the command line. Then __cplusplus == _MSVC_LANG.
|
|
||||||
// See https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus
|
|
||||||
//
|
|
||||||
// We rely on _MSVC_LANG if possible, otherwise on some hard coded language versions
|
|
||||||
// depending on _MSC_VER.
|
|
||||||
//
|
|
||||||
// For _MSV_VER values, see https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=vs-2017.
|
|
||||||
//
|
|
||||||
LanguageVersion static languageVersionForMsvc(const Core::Id &language, const Macros ¯os)
|
|
||||||
{
|
|
||||||
int mscVer = -1;
|
|
||||||
QByteArray msvcLang;
|
|
||||||
for (const ProjectExplorer::Macro ¯o : macros) {
|
|
||||||
if (macro.key == "_MSVC_LANG")
|
|
||||||
msvcLang = macro.value;
|
|
||||||
if (macro.key == "_MSC_VER")
|
|
||||||
mscVer = macro.value.toInt(nullptr);
|
|
||||||
}
|
|
||||||
QTC_CHECK(mscVer > 0);
|
|
||||||
|
|
||||||
if (language == Constants::CXX_LANGUAGE_ID) {
|
|
||||||
if (!msvcLang.isEmpty()) // >= Visual Studio 2015 Update 3
|
|
||||||
return ToolChain::cxxLanguageVersion(msvcLang);
|
|
||||||
if (mscVer >= 1800) // >= Visual Studio 2013 (12.0)
|
|
||||||
return LanguageVersion::CXX14;
|
|
||||||
if (mscVer >= 1600) // >= Visual Studio 2010 (10.0)
|
|
||||||
return LanguageVersion::CXX11;
|
|
||||||
return LanguageVersion::CXX98;
|
|
||||||
} else if (language == Constants::C_LANGUAGE_ID) {
|
|
||||||
if (mscVer >= 1910) // >= Visual Studio 2017 RTW (15.0)
|
|
||||||
return LanguageVersion::C11;
|
|
||||||
return LanguageVersion::C99;
|
|
||||||
} else {
|
|
||||||
QTC_CHECK(false && "Unexpected toolchain language, assuming latest C++ we support.");
|
|
||||||
return LanguageVersion::LatestCxx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool static hasFlagEffectOnMacros(const QString &flag)
|
bool static hasFlagEffectOnMacros(const QString &flag)
|
||||||
{
|
{
|
||||||
if (flag.startsWith("-") || flag.startsWith("/")) {
|
if (flag.startsWith("-") || flag.startsWith("/")) {
|
||||||
@@ -177,8 +129,7 @@ ToolChain::MacroInspectionRunner AbstractMsvcToolChain::createMacroInspectionRun
|
|||||||
|
|
||||||
const Macros macros = msvcPredefinedMacros(filteredFlags, env);
|
const Macros macros = msvcPredefinedMacros(filteredFlags, env);
|
||||||
|
|
||||||
const auto report = MacroInspectionReport{macros,
|
const auto report = MacroInspectionReport{macros, languageVersion(macros)};
|
||||||
languageVersionForMsvc(lang, macros)};
|
|
||||||
macroCache->insert(filteredFlags, report);
|
macroCache->insert(filteredFlags, report);
|
||||||
|
|
||||||
return report;
|
return report;
|
||||||
|
@@ -98,7 +98,7 @@ protected:
|
|||||||
// Function must be thread-safe!
|
// Function must be thread-safe!
|
||||||
virtual Macros msvcPredefinedMacros(const QStringList cxxflags,
|
virtual Macros msvcPredefinedMacros(const QStringList cxxflags,
|
||||||
const Utils::Environment& env) const = 0;
|
const Utils::Environment& env) const = 0;
|
||||||
|
virtual LanguageVersion languageVersion(const Macros ¯os) const = 0;
|
||||||
|
|
||||||
Utils::FileName m_debuggerCommand;
|
Utils::FileName m_debuggerCommand;
|
||||||
|
|
||||||
|
@@ -29,7 +29,6 @@
|
|||||||
#include "gccparser.h"
|
#include "gccparser.h"
|
||||||
#include "linuxiccparser.h"
|
#include "linuxiccparser.h"
|
||||||
#include "projectmacro.h"
|
#include "projectmacro.h"
|
||||||
#include "projectexplorerconstants.h"
|
|
||||||
#include "toolchainmanager.h"
|
#include "toolchainmanager.h"
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
@@ -98,18 +97,6 @@ static QByteArray runGcc(const FileName &gcc, const QStringList &arguments, cons
|
|||||||
return response.allOutput().toUtf8();
|
return response.allOutput().toUtf8();
|
||||||
}
|
}
|
||||||
|
|
||||||
static const QStringList languageOption(Core::Id languageId)
|
|
||||||
{
|
|
||||||
if (languageId == Constants::C_LANGUAGE_ID)
|
|
||||||
return {"-x", "c"};
|
|
||||||
return {"-x", "c++"};
|
|
||||||
}
|
|
||||||
|
|
||||||
static const QStringList gccPredefinedMacrosOptions(Core::Id languageId)
|
|
||||||
{
|
|
||||||
return languageOption(languageId) + QStringList({"-E", "-dM"});
|
|
||||||
}
|
|
||||||
|
|
||||||
static ProjectExplorer::Macros gccPredefinedMacros(const FileName &gcc,
|
static ProjectExplorer::Macros gccPredefinedMacros(const FileName &gcc,
|
||||||
const QStringList &args,
|
const QStringList &args,
|
||||||
const QStringList &env)
|
const QStringList &env)
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "projectexplorer_export.h"
|
#include "projectexplorer_export.h"
|
||||||
|
|
||||||
|
#include "projectexplorerconstants.h"
|
||||||
#include "toolchain.h"
|
#include "toolchain.h"
|
||||||
#include "toolchaincache.h"
|
#include "toolchaincache.h"
|
||||||
#include "abi.h"
|
#include "abi.h"
|
||||||
@@ -51,6 +52,18 @@ class LinuxIccToolChainFactory;
|
|||||||
// GccToolChain
|
// GccToolChain
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
inline const QStringList languageOption(Core::Id languageId)
|
||||||
|
{
|
||||||
|
if (languageId == Constants::C_LANGUAGE_ID)
|
||||||
|
return {"-x", "c"};
|
||||||
|
return {"-x", "c++"};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const QStringList gccPredefinedMacrosOptions(Core::Id languageId)
|
||||||
|
{
|
||||||
|
return languageOption(languageId) + QStringList({"-E", "-dM"});
|
||||||
|
}
|
||||||
|
|
||||||
class PROJECTEXPLORER_EXPORT GccToolChain : public ToolChain
|
class PROJECTEXPLORER_EXPORT GccToolChain : public ToolChain
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "msvctoolchain.h"
|
#include "msvctoolchain.h"
|
||||||
|
|
||||||
|
#include "gcctoolchain.h"
|
||||||
#include "msvcparser.h"
|
#include "msvcparser.h"
|
||||||
#include "projectexplorer.h"
|
#include "projectexplorer.h"
|
||||||
#include "projectexplorerconstants.h"
|
#include "projectexplorerconstants.h"
|
||||||
@@ -506,6 +507,55 @@ Macros MsvcToolChain::msvcPredefinedMacros(const QStringList cxxflags,
|
|||||||
return predefinedMacros;
|
return predefinedMacros;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// We want to detect the language version based on the predefined macros.
|
||||||
|
// Unfortunately MSVC does not conform to standard when it comes to the predefined
|
||||||
|
// __cplusplus macro - it reports "199711L", even for newer language versions.
|
||||||
|
//
|
||||||
|
// However:
|
||||||
|
// * For >= Visual Studio 2015 Update 3 predefines _MSVC_LANG which has the proper value
|
||||||
|
// of __cplusplus.
|
||||||
|
// See https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=vs-2017
|
||||||
|
// * For >= Visual Studio 2017 Version 15.7 __cplusplus is correct once /Zc:__cplusplus
|
||||||
|
// is provided on the command line. Then __cplusplus == _MSVC_LANG.
|
||||||
|
// See https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus
|
||||||
|
//
|
||||||
|
// We rely on _MSVC_LANG if possible, otherwise on some hard coded language versions
|
||||||
|
// depending on _MSC_VER.
|
||||||
|
//
|
||||||
|
// For _MSV_VER values, see https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=vs-2017.
|
||||||
|
//
|
||||||
|
LanguageVersion MsvcToolChain::languageVersion(const Macros ¯os) const
|
||||||
|
{
|
||||||
|
const Core::Id lang = language();
|
||||||
|
int mscVer = -1;
|
||||||
|
QByteArray msvcLang;
|
||||||
|
for (const ProjectExplorer::Macro ¯o : macros) {
|
||||||
|
if (macro.key == "_MSVC_LANG")
|
||||||
|
msvcLang = macro.value;
|
||||||
|
if (macro.key == "_MSC_VER")
|
||||||
|
mscVer = macro.value.toInt(nullptr);
|
||||||
|
}
|
||||||
|
QTC_CHECK(mscVer > 0);
|
||||||
|
|
||||||
|
if (lang == Constants::CXX_LANGUAGE_ID) {
|
||||||
|
if (!msvcLang.isEmpty()) // >= Visual Studio 2015 Update 3
|
||||||
|
return ToolChain::cxxLanguageVersion(msvcLang);
|
||||||
|
if (mscVer >= 1800) // >= Visual Studio 2013 (12.0)
|
||||||
|
return LanguageVersion::CXX14;
|
||||||
|
if (mscVer >= 1600) // >= Visual Studio 2010 (10.0)
|
||||||
|
return LanguageVersion::CXX11;
|
||||||
|
return LanguageVersion::CXX98;
|
||||||
|
} else if (lang == Constants::C_LANGUAGE_ID) {
|
||||||
|
if (mscVer >= 1910) // >= Visual Studio 2017 RTW (15.0)
|
||||||
|
return LanguageVersion::C11;
|
||||||
|
return LanguageVersion::C99;
|
||||||
|
} else {
|
||||||
|
QTC_CHECK(false && "Unexpected toolchain language, assuming latest C++ we support.");
|
||||||
|
return LanguageVersion::LatestCxx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Windows: Expand the delayed evaluation references returned by the
|
// Windows: Expand the delayed evaluation references returned by the
|
||||||
// SDK setup scripts: "PATH=!Path!;foo". Some values might expand
|
// SDK setup scripts: "PATH=!Path!;foo". Some values might expand
|
||||||
// to empty and should not be added
|
// to empty and should not be added
|
||||||
@@ -1063,6 +1113,31 @@ bool ClangClToolChain::operator ==(const ToolChain &other) const
|
|||||||
return m_clangPath == clangClTc->m_clangPath;
|
return m_clangPath == clangClTc->m_clangPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Macros ClangClToolChain::msvcPredefinedMacros(const QStringList cxxflags,
|
||||||
|
const Utils::Environment &env) const
|
||||||
|
{
|
||||||
|
Utils::SynchronousProcess cpp;
|
||||||
|
cpp.setEnvironment(env.toStringList());
|
||||||
|
cpp.setWorkingDirectory(Utils::TemporaryDirectory::masterDirectoryPath());
|
||||||
|
|
||||||
|
QStringList arguments = cxxflags;
|
||||||
|
arguments.append(gccPredefinedMacrosOptions(language()));
|
||||||
|
arguments.append("-");
|
||||||
|
Utils::SynchronousProcessResponse response = cpp.runBlocking(compilerCommand().toString(),
|
||||||
|
arguments);
|
||||||
|
if (response.result != Utils::SynchronousProcessResponse::Finished ||
|
||||||
|
response.exitCode != 0) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return Macro::toMacros(response.allRawOutput());
|
||||||
|
}
|
||||||
|
|
||||||
|
LanguageVersion ClangClToolChain::languageVersion(const Macros ¯os) const
|
||||||
|
{
|
||||||
|
return ToolChain::languageVersion(language(), macros);
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// MsvcToolChainFactory
|
// MsvcToolChainFactory
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
@@ -94,6 +94,7 @@ protected:
|
|||||||
// Function must be thread-safe!
|
// Function must be thread-safe!
|
||||||
Macros msvcPredefinedMacros(const QStringList cxxflags,
|
Macros msvcPredefinedMacros(const QStringList cxxflags,
|
||||||
const Utils::Environment &env) const override;
|
const Utils::Environment &env) const override;
|
||||||
|
LanguageVersion languageVersion(const Macros ¯os) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct GenerateEnvResult
|
struct GenerateEnvResult
|
||||||
@@ -136,6 +137,9 @@ public:
|
|||||||
void setClangPath(const QString &path) { m_clangPath = path; }
|
void setClangPath(const QString &path) { m_clangPath = path; }
|
||||||
|
|
||||||
void resetMsvcToolChain(const MsvcToolChain *base = nullptr);
|
void resetMsvcToolChain(const MsvcToolChain *base = nullptr);
|
||||||
|
Macros msvcPredefinedMacros(const QStringList cxxflags,
|
||||||
|
const Utils::Environment &env) const override;
|
||||||
|
LanguageVersion languageVersion(const Macros ¯os) const override;
|
||||||
|
|
||||||
bool operator ==(const ToolChain &) const override;
|
bool operator ==(const ToolChain &) const override;
|
||||||
private:
|
private:
|
||||||
|
Reference in New Issue
Block a user