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/environment.h>
|
||||
#include <utils/hostosinfo.h>
|
||||
#include <utils/synchronousprocess.h>
|
||||
|
||||
#include <QDir>
|
||||
#include <QDirIterator>
|
||||
@@ -91,6 +92,56 @@ AndroidToolChain::AndroidToolChain(const AndroidToolChain &tc) :
|
||||
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
|
||||
{
|
||||
return AndroidToolChainFactory::tr("Android GCC");
|
||||
@@ -246,7 +297,9 @@ void AndroidToolChain::setSecondaryToolChain(bool b)
|
||||
|
||||
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);
|
||||
tc->resetToolChain(compilerPath);
|
||||
}
|
||||
QTC_ASSERT(!tc->originalTargetTriple().isEmpty(), continue);
|
||||
result.append(tc);
|
||||
toolChainBundle.append(tc);
|
||||
}
|
||||
|
@@ -45,7 +45,7 @@ public:
|
||||
bool operator ==(const ProjectExplorer::ToolChain &) const override;
|
||||
|
||||
ProjectExplorer::ToolChainConfigWidget *configurationWidget() override;
|
||||
virtual Utils::FileName suggestedDebugger() const override;
|
||||
Utils::FileName suggestedDebugger() const override;
|
||||
Utils::FileName suggestedGdbServer() const;
|
||||
|
||||
QVariantMap toMap() const override;
|
||||
@@ -58,6 +58,8 @@ public:
|
||||
bool isSecondaryToolChain() const;
|
||||
void setSecondaryToolChain(bool b);
|
||||
|
||||
SystemHeaderPathsRunner createSystemHeaderPathsRunner() const override;
|
||||
|
||||
protected:
|
||||
DetectedAbisResult detectSupportedAbis() const override;
|
||||
|
||||
|
@@ -451,16 +451,10 @@ bool CompilerOptionsBuilder::excludeDefineDirective(const ProjectExplorer::Macro
|
||||
if (macro.key == "__cplusplus")
|
||||
return true;
|
||||
|
||||
// gcc 4.9 has:
|
||||
// #define __has_include(STR) __has_include__(STR)
|
||||
// #define __has_include_next(STR) __has_include_next__(STR)
|
||||
// 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")) {
|
||||
// Ignore for all compiler toolchains since LLVM has it's own implementation for
|
||||
// __has_include(STR) and __has_include_next(STR)
|
||||
if (macro.key.startsWith("__has_include"))
|
||||
return true;
|
||||
}
|
||||
|
||||
// If _FORTIFY_SOURCE is defined (typically in release mode), it will
|
||||
// enable the inclusion of extra headers to help catching buffer overflows
|
||||
|
@@ -579,6 +579,46 @@ WarningFlags GccToolChain::warningFlags(const QStringList &cflags) const
|
||||
return flags;
|
||||
}
|
||||
|
||||
QStringList GccToolChain::gccPrepareArguments(const QStringList &flags,
|
||||
const QString &sysRoot,
|
||||
const QStringList &platformCodeGenFlags,
|
||||
Core::Id languageId,
|
||||
OptionsReinterpreter reinterpretOptions)
|
||||
{
|
||||
QStringList arguments;
|
||||
const bool hasKitSysroot = !sysRoot.isEmpty();
|
||||
if (hasKitSysroot)
|
||||
arguments.append(QString::fromLatin1("--sysroot=%1").arg(sysRoot));
|
||||
|
||||
QStringList allFlags;
|
||||
allFlags << platformCodeGenFlags << flags;
|
||||
for (int i = 0; i < allFlags.size(); ++i) {
|
||||
const QString &flag = allFlags.at(i);
|
||||
if (flag.startsWith("-stdlib=") || flag.startsWith("--gcctoolchain=")) {
|
||||
arguments << flag;
|
||||
} else if (!hasKitSysroot) {
|
||||
// pass build system's sysroot to compiler, if we didn't pass one from kit
|
||||
if (flag.startsWith("--sysroot=")) {
|
||||
arguments << flag;
|
||||
} else if ((flag.startsWith("-isysroot") || flag.startsWith("--sysroot"))
|
||||
&& i < flags.size() - 1) {
|
||||
arguments << flag << allFlags.at(i + 1);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
arguments << languageOption(languageId) << "-E" << "-v" << "-";
|
||||
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.
|
||||
@@ -593,42 +633,21 @@ ToolChain::SystemHeaderPathsRunner GccToolChain::createSystemHeaderPathsRunner()
|
||||
Core::Id languageId = language();
|
||||
|
||||
// This runner must be thread-safe!
|
||||
return [env, compilerCommand, platformCodeGenFlags, reinterpretOptions, headerCache, languageId]
|
||||
return [env, compilerCommand, platformCodeGenFlags, reinterpretOptions, headerCache, languageId,
|
||||
extraHeaderPathsFunction = m_extraHeaderPathsFunction]
|
||||
(const QStringList &flags, const QString &sysRoot) {
|
||||
// Prepare arguments
|
||||
QStringList arguments;
|
||||
const bool hasKitSysroot = !sysRoot.isEmpty();
|
||||
if (hasKitSysroot)
|
||||
arguments.append(QString::fromLatin1("--sysroot=%1").arg(sysRoot));
|
||||
|
||||
QStringList allFlags;
|
||||
allFlags << platformCodeGenFlags << flags;
|
||||
for (int i = 0; i < allFlags.size(); ++i) {
|
||||
const QString &flag = allFlags.at(i);
|
||||
if (flag.startsWith("-stdlib=") || flag.startsWith("--gcctoolchain=")) {
|
||||
arguments << flag;
|
||||
} else if (!hasKitSysroot) {
|
||||
// pass build system's sysroot to compiler, if we didn't pass one from kit
|
||||
if (flag.startsWith("--sysroot=")) {
|
||||
arguments << flag;
|
||||
} else if ((flag.startsWith("-isysroot") || flag.startsWith("--sysroot"))
|
||||
&& i < flags.size() - 1) {
|
||||
arguments << flag << allFlags.at(i + 1);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
arguments << languageOption(languageId) << "-E" << "-v" << "-";
|
||||
arguments = reinterpretOptions(arguments);
|
||||
QStringList arguments = gccPrepareArguments(flags, sysRoot, platformCodeGenFlags,
|
||||
languageId, reinterpretOptions);
|
||||
|
||||
const Utils::optional<QList<HeaderPath>> cachedPaths = headerCache->check(arguments);
|
||||
if (cachedPaths)
|
||||
return cachedPaths.value();
|
||||
|
||||
const QList<HeaderPath> paths = gccHeaderPaths(findLocalCompiler(compilerCommand, env),
|
||||
arguments,
|
||||
env.toStringList());
|
||||
QList<HeaderPath> paths = gccHeaderPaths(findLocalCompiler(compilerCommand, env),
|
||||
arguments,
|
||||
env.toStringList());
|
||||
extraHeaderPathsFunction(paths);
|
||||
headerCache->insert(arguments, paths);
|
||||
|
||||
qCDebug(gccLog) << "Reporting header paths to code model:";
|
||||
|
@@ -208,6 +208,10 @@ protected:
|
||||
// that passes the initial options directly down to the gcc compiler
|
||||
using OptionsReinterpreter = std::function<QStringList(const QStringList &options)>;
|
||||
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);
|
||||
|
||||
class WarningFlagAdder
|
||||
@@ -229,6 +233,11 @@ private:
|
||||
explicit GccToolChain(Detection d);
|
||||
|
||||
void updateSupportedAbis() const;
|
||||
static QStringList gccPrepareArguments(const QStringList &flags,
|
||||
const QString &sysRoot,
|
||||
const QStringList &platformCodeGenFlags,
|
||||
Core::Id languageId,
|
||||
OptionsReinterpreter reinterpretOptions);
|
||||
|
||||
Utils::FileName m_compilerCommand;
|
||||
QStringList m_platformCodeGenFlags;
|
||||
@@ -244,6 +253,7 @@ private:
|
||||
|
||||
mutable std::shared_ptr<Cache<QVector<Macro>, 64>> m_predefinedMacrosCache;
|
||||
mutable std::shared_ptr<Cache<QList<HeaderPath>>> m_headerPathsCache;
|
||||
mutable ExtraHeaderPathsFunction m_extraHeaderPathsFunction = [](QList<HeaderPath> &) {};
|
||||
|
||||
friend class Internal::GccToolChainConfigWidget;
|
||||
friend class Internal::GccToolChainFactory;
|
||||
|
Reference in New Issue
Block a user