forked from qt-creator/qt-creator
Clang: Android: fix clang code model errors
Add missing gcc include directories in Android toolchain. This introduces the similar "magic" that we have in qmake (*qtsource*/qtbase/mkspecs/common/android-base-head.conf) but allows us to have those paths wherever we use android toolchain. Change-Id: I5740f1f2339fd30670567f24db2be2454f665f41 Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
@@ -40,6 +40,7 @@
|
|||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/environment.h>
|
#include <utils/environment.h>
|
||||||
#include <utils/hostosinfo.h>
|
#include <utils/hostosinfo.h>
|
||||||
|
#include <utils/synchronousprocess.h>
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QDirIterator>
|
#include <QDirIterator>
|
||||||
@@ -91,6 +92,56 @@ AndroidToolChain::AndroidToolChain(const AndroidToolChain &tc) :
|
|||||||
AndroidToolChain::~AndroidToolChain()
|
AndroidToolChain::~AndroidToolChain()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
static QString getArch(const QString &triple)
|
||||||
|
{
|
||||||
|
if (triple.indexOf("x86_64") == 0)
|
||||||
|
return "x86_64";
|
||||||
|
if (triple.indexOf("i686") == 0)
|
||||||
|
return "x86";
|
||||||
|
if (triple.indexOf("mips64") == 0)
|
||||||
|
return "mips64";
|
||||||
|
if (triple.indexOf("mips") == 0)
|
||||||
|
return "mips";
|
||||||
|
if (triple.indexOf("aarch64") == 0)
|
||||||
|
return "arm64-v8a";
|
||||||
|
return "armeabi-v7a";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Paths added here are those that were used by qmake. They were taken from
|
||||||
|
// *qtsource*/qtbase/mkspecs/common/android-base-head.conf
|
||||||
|
// Adding them here allows us to use them for all build systems.
|
||||||
|
static void addSystemHeaderPaths(QList<ProjectExplorer::HeaderPath> &paths,
|
||||||
|
const QString &triple, const QString &version)
|
||||||
|
{
|
||||||
|
const Utils::FileName ndkPath = AndroidConfigurations::currentConfig().ndkLocation();
|
||||||
|
|
||||||
|
// Get short version (for example 4.9)
|
||||||
|
const QString clangVersion = version.left(version.lastIndexOf('.'));
|
||||||
|
Utils::FileName stdcppPath = ndkPath;
|
||||||
|
stdcppPath.appendPath("sources/cxx-stl/gnu-libstdc++/" + clangVersion);
|
||||||
|
Utils::FileName includePath = stdcppPath;
|
||||||
|
Utils::FileName cppLibsPath = stdcppPath;
|
||||||
|
cppLibsPath.appendPath("libs/" + getArch(triple) + "/include/");
|
||||||
|
paths.prepend({cppLibsPath.toString(), ProjectExplorer::HeaderPath::GlobalHeaderPath});
|
||||||
|
includePath.appendPath("include/");
|
||||||
|
paths.prepend({includePath.toString(), ProjectExplorer::HeaderPath::GlobalHeaderPath});
|
||||||
|
|
||||||
|
paths.prepend({ndkPath.toString() + "/sysroot/usr/include/" + triple,
|
||||||
|
ProjectExplorer::HeaderPath::GlobalHeaderPath});
|
||||||
|
paths.prepend({ndkPath.toString() + "/sysroot/usr/include",
|
||||||
|
ProjectExplorer::HeaderPath::GlobalHeaderPath});
|
||||||
|
}
|
||||||
|
|
||||||
|
AndroidToolChain::SystemHeaderPathsRunner AndroidToolChain::createSystemHeaderPathsRunner() const
|
||||||
|
{
|
||||||
|
const QString triple = originalTargetTriple();
|
||||||
|
const QString version = this->version();
|
||||||
|
initExtraHeaderPathsFunction([triple, version] (QList<HeaderPath> &paths) {
|
||||||
|
addSystemHeaderPaths(paths, triple, version);
|
||||||
|
});
|
||||||
|
return GccToolChain::createSystemHeaderPathsRunner();
|
||||||
|
}
|
||||||
|
|
||||||
QString AndroidToolChain::typeDisplayName() const
|
QString AndroidToolChain::typeDisplayName() const
|
||||||
{
|
{
|
||||||
return AndroidToolChainFactory::tr("Android GCC");
|
return AndroidToolChainFactory::tr("Android GCC");
|
||||||
@@ -246,7 +297,9 @@ void AndroidToolChain::setSecondaryToolChain(bool b)
|
|||||||
|
|
||||||
GccToolChain::DetectedAbisResult AndroidToolChain::detectSupportedAbis() const
|
GccToolChain::DetectedAbisResult AndroidToolChain::detectSupportedAbis() const
|
||||||
{
|
{
|
||||||
return QList<Abi>() << targetAbi();
|
GccToolChain::DetectedAbisResult supportedAbis = GccToolChain::detectSupportedAbis();
|
||||||
|
supportedAbis.supportedAbis = {targetAbi()};
|
||||||
|
return supportedAbis;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
@@ -415,6 +468,7 @@ AndroidToolChainFactory::autodetectToolChainsForNdk(const FileName &ndkPath,
|
|||||||
ToolChain::AutoDetection);
|
ToolChain::AutoDetection);
|
||||||
tc->resetToolChain(compilerPath);
|
tc->resetToolChain(compilerPath);
|
||||||
}
|
}
|
||||||
|
QTC_ASSERT(!tc->originalTargetTriple().isEmpty(), continue);
|
||||||
result.append(tc);
|
result.append(tc);
|
||||||
toolChainBundle.append(tc);
|
toolChainBundle.append(tc);
|
||||||
}
|
}
|
||||||
|
@@ -45,7 +45,7 @@ public:
|
|||||||
bool operator ==(const ProjectExplorer::ToolChain &) const override;
|
bool operator ==(const ProjectExplorer::ToolChain &) const override;
|
||||||
|
|
||||||
ProjectExplorer::ToolChainConfigWidget *configurationWidget() override;
|
ProjectExplorer::ToolChainConfigWidget *configurationWidget() override;
|
||||||
virtual Utils::FileName suggestedDebugger() const override;
|
Utils::FileName suggestedDebugger() const override;
|
||||||
Utils::FileName suggestedGdbServer() const;
|
Utils::FileName suggestedGdbServer() const;
|
||||||
|
|
||||||
QVariantMap toMap() const override;
|
QVariantMap toMap() const override;
|
||||||
@@ -58,6 +58,8 @@ public:
|
|||||||
bool isSecondaryToolChain() const;
|
bool isSecondaryToolChain() const;
|
||||||
void setSecondaryToolChain(bool b);
|
void setSecondaryToolChain(bool b);
|
||||||
|
|
||||||
|
SystemHeaderPathsRunner createSystemHeaderPathsRunner() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
DetectedAbisResult detectSupportedAbis() const override;
|
DetectedAbisResult detectSupportedAbis() const override;
|
||||||
|
|
||||||
|
@@ -451,16 +451,10 @@ bool CompilerOptionsBuilder::excludeDefineDirective(const ProjectExplorer::Macro
|
|||||||
if (macro.key == "__cplusplus")
|
if (macro.key == "__cplusplus")
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// gcc 4.9 has:
|
// Ignore for all compiler toolchains since LLVM has it's own implementation for
|
||||||
// #define __has_include(STR) __has_include__(STR)
|
// __has_include(STR) and __has_include_next(STR)
|
||||||
// #define __has_include_next(STR) __has_include_next__(STR)
|
if (macro.key.startsWith("__has_include"))
|
||||||
// The right-hand sides are gcc built-ins that clang does not understand, and they'd
|
|
||||||
// override clang's own (non-macro, it seems) definitions of the symbols on the left-hand
|
|
||||||
// side.
|
|
||||||
if (isGccOrMinGwToolchain(m_projectPart.toolchainType)
|
|
||||||
&& macro.key.contains("has_include")) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
// If _FORTIFY_SOURCE is defined (typically in release mode), it will
|
// If _FORTIFY_SOURCE is defined (typically in release mode), it will
|
||||||
// enable the inclusion of extra headers to help catching buffer overflows
|
// enable the inclusion of extra headers to help catching buffer overflows
|
||||||
|
@@ -579,23 +579,12 @@ WarningFlags GccToolChain::warningFlags(const QStringList &cflags) const
|
|||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
ToolChain::SystemHeaderPathsRunner GccToolChain::createSystemHeaderPathsRunner() const
|
QStringList GccToolChain::gccPrepareArguments(const QStringList &flags,
|
||||||
|
const QString &sysRoot,
|
||||||
|
const QStringList &platformCodeGenFlags,
|
||||||
|
Core::Id languageId,
|
||||||
|
OptionsReinterpreter reinterpretOptions)
|
||||||
{
|
{
|
||||||
// Using a clean environment breaks ccache/distcc/etc.
|
|
||||||
Environment env = Environment::systemEnvironment();
|
|
||||||
addToEnvironment(env);
|
|
||||||
|
|
||||||
const Utils::FileName compilerCommand = m_compilerCommand;
|
|
||||||
const QStringList platformCodeGenFlags = m_platformCodeGenFlags;
|
|
||||||
OptionsReinterpreter reinterpretOptions = m_optionsReinterpreter;
|
|
||||||
QTC_CHECK(reinterpretOptions);
|
|
||||||
std::shared_ptr<Cache<QList<HeaderPath>>> headerCache = m_headerPathsCache;
|
|
||||||
Core::Id languageId = language();
|
|
||||||
|
|
||||||
// This runner must be thread-safe!
|
|
||||||
return [env, compilerCommand, platformCodeGenFlags, reinterpretOptions, headerCache, languageId]
|
|
||||||
(const QStringList &flags, const QString &sysRoot) {
|
|
||||||
// Prepare arguments
|
|
||||||
QStringList arguments;
|
QStringList arguments;
|
||||||
const bool hasKitSysroot = !sysRoot.isEmpty();
|
const bool hasKitSysroot = !sysRoot.isEmpty();
|
||||||
if (hasKitSysroot)
|
if (hasKitSysroot)
|
||||||
@@ -618,17 +607,47 @@ ToolChain::SystemHeaderPathsRunner GccToolChain::createSystemHeaderPathsRunner()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
arguments << languageOption(languageId) << "-E" << "-v" << "-";
|
arguments << languageOption(languageId) << "-E" << "-v" << "-";
|
||||||
arguments = reinterpretOptions(arguments);
|
arguments = reinterpretOptions(arguments);
|
||||||
|
|
||||||
|
return arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: extraHeaderPathsFunction must NOT capture this or it's members!!!
|
||||||
|
void GccToolChain::initExtraHeaderPathsFunction(ExtraHeaderPathsFunction &&extraHeaderPathsFunction) const
|
||||||
|
{
|
||||||
|
m_extraHeaderPathsFunction = std::move(extraHeaderPathsFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
ToolChain::SystemHeaderPathsRunner GccToolChain::createSystemHeaderPathsRunner() const
|
||||||
|
{
|
||||||
|
// Using a clean environment breaks ccache/distcc/etc.
|
||||||
|
Environment env = Environment::systemEnvironment();
|
||||||
|
addToEnvironment(env);
|
||||||
|
|
||||||
|
const Utils::FileName compilerCommand = m_compilerCommand;
|
||||||
|
const QStringList platformCodeGenFlags = m_platformCodeGenFlags;
|
||||||
|
OptionsReinterpreter reinterpretOptions = m_optionsReinterpreter;
|
||||||
|
QTC_CHECK(reinterpretOptions);
|
||||||
|
std::shared_ptr<Cache<QList<HeaderPath>>> headerCache = m_headerPathsCache;
|
||||||
|
Core::Id languageId = language();
|
||||||
|
|
||||||
|
// This runner must be thread-safe!
|
||||||
|
return [env, compilerCommand, platformCodeGenFlags, reinterpretOptions, headerCache, languageId,
|
||||||
|
extraHeaderPathsFunction = m_extraHeaderPathsFunction]
|
||||||
|
(const QStringList &flags, const QString &sysRoot) {
|
||||||
|
|
||||||
|
QStringList arguments = gccPrepareArguments(flags, sysRoot, platformCodeGenFlags,
|
||||||
|
languageId, reinterpretOptions);
|
||||||
|
|
||||||
const Utils::optional<QList<HeaderPath>> cachedPaths = headerCache->check(arguments);
|
const Utils::optional<QList<HeaderPath>> cachedPaths = headerCache->check(arguments);
|
||||||
if (cachedPaths)
|
if (cachedPaths)
|
||||||
return cachedPaths.value();
|
return cachedPaths.value();
|
||||||
|
|
||||||
const QList<HeaderPath> paths = gccHeaderPaths(findLocalCompiler(compilerCommand, env),
|
QList<HeaderPath> paths = gccHeaderPaths(findLocalCompiler(compilerCommand, env),
|
||||||
arguments,
|
arguments,
|
||||||
env.toStringList());
|
env.toStringList());
|
||||||
|
extraHeaderPathsFunction(paths);
|
||||||
headerCache->insert(arguments, paths);
|
headerCache->insert(arguments, paths);
|
||||||
|
|
||||||
qCDebug(gccLog) << "Reporting header paths to code model:";
|
qCDebug(gccLog) << "Reporting header paths to code model:";
|
||||||
|
@@ -208,6 +208,10 @@ protected:
|
|||||||
// that passes the initial options directly down to the gcc compiler
|
// that passes the initial options directly down to the gcc compiler
|
||||||
using OptionsReinterpreter = std::function<QStringList(const QStringList &options)>;
|
using OptionsReinterpreter = std::function<QStringList(const QStringList &options)>;
|
||||||
void setOptionsReinterpreter(const OptionsReinterpreter &optionsReinterpreter);
|
void setOptionsReinterpreter(const OptionsReinterpreter &optionsReinterpreter);
|
||||||
|
|
||||||
|
using ExtraHeaderPathsFunction = std::function<void(QList<HeaderPath> &)>;
|
||||||
|
void initExtraHeaderPathsFunction(ExtraHeaderPathsFunction &&extraHeaderPathsFunction) const;
|
||||||
|
|
||||||
static QList<HeaderPath> gccHeaderPaths(const Utils::FileName &gcc, const QStringList &args, const QStringList &env);
|
static QList<HeaderPath> gccHeaderPaths(const Utils::FileName &gcc, const QStringList &args, const QStringList &env);
|
||||||
|
|
||||||
class WarningFlagAdder
|
class WarningFlagAdder
|
||||||
@@ -229,6 +233,11 @@ private:
|
|||||||
explicit GccToolChain(Detection d);
|
explicit GccToolChain(Detection d);
|
||||||
|
|
||||||
void updateSupportedAbis() const;
|
void updateSupportedAbis() const;
|
||||||
|
static QStringList gccPrepareArguments(const QStringList &flags,
|
||||||
|
const QString &sysRoot,
|
||||||
|
const QStringList &platformCodeGenFlags,
|
||||||
|
Core::Id languageId,
|
||||||
|
OptionsReinterpreter reinterpretOptions);
|
||||||
|
|
||||||
Utils::FileName m_compilerCommand;
|
Utils::FileName m_compilerCommand;
|
||||||
QStringList m_platformCodeGenFlags;
|
QStringList m_platformCodeGenFlags;
|
||||||
@@ -244,6 +253,7 @@ private:
|
|||||||
|
|
||||||
mutable std::shared_ptr<Cache<QVector<Macro>, 64>> m_predefinedMacrosCache;
|
mutable std::shared_ptr<Cache<QVector<Macro>, 64>> m_predefinedMacrosCache;
|
||||||
mutable std::shared_ptr<Cache<QList<HeaderPath>>> m_headerPathsCache;
|
mutable std::shared_ptr<Cache<QList<HeaderPath>>> m_headerPathsCache;
|
||||||
|
mutable ExtraHeaderPathsFunction m_extraHeaderPathsFunction = [](QList<HeaderPath> &) {};
|
||||||
|
|
||||||
friend class Internal::GccToolChainConfigWidget;
|
friend class Internal::GccToolChainConfigWidget;
|
||||||
friend class Internal::GccToolChainFactory;
|
friend class Internal::GccToolChainFactory;
|
||||||
|
Reference in New Issue
Block a user