2016-01-15 14:57:40 +01:00
|
|
|
/****************************************************************************
|
2012-04-18 20:30:57 +03:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
|
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2012-04-18 20:30:57 +03:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2012-04-18 20:30:57 +03:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** Commercial License Usage
|
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
2016-01-15 14:57:40 +01:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
2012-04-18 20:30:57 +03:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** GNU General Public License Usage
|
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
|
** General Public License version 3 as published by the Free Software
|
|
|
|
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
|
|
|
** included in the packaging of this file. Please review the following
|
|
|
|
|
** information to ensure the GNU General Public License requirements will
|
|
|
|
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
2012-04-18 20:30:57 +03:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2012-04-18 20:30:57 +03:00
|
|
|
|
|
|
|
|
#include "androidtoolchain.h"
|
|
|
|
|
#include "androidconstants.h"
|
|
|
|
|
#include "androidconfigurations.h"
|
2012-12-07 19:52:56 +02:00
|
|
|
|
2012-04-18 20:30:57 +03:00
|
|
|
#include <projectexplorer/toolchainmanager.h>
|
|
|
|
|
#include <projectexplorer/projectexplorer.h>
|
|
|
|
|
|
|
|
|
|
#include <utils/environment.h>
|
|
|
|
|
|
2018-10-25 18:12:43 +02:00
|
|
|
#include <QFileInfo>
|
|
|
|
|
#include <QLoggingCategory>
|
2017-03-09 23:02:32 +01:00
|
|
|
#include <QRegExp>
|
2018-10-25 18:12:43 +02:00
|
|
|
|
2012-04-18 20:30:57 +03:00
|
|
|
|
2013-01-25 16:49:22 +01:00
|
|
|
namespace {
|
2018-11-06 09:37:19 +01:00
|
|
|
Q_LOGGING_CATEGORY(androidTCLog, "qtc.android.toolchainmanagement", QtWarningMsg);
|
2013-01-25 16:49:22 +01:00
|
|
|
}
|
|
|
|
|
|
2012-04-18 20:30:57 +03:00
|
|
|
namespace Android {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
2012-08-09 01:56:51 +02:00
|
|
|
using namespace ProjectExplorer;
|
2012-08-23 15:53:58 +02:00
|
|
|
using namespace Utils;
|
2012-04-18 20:30:57 +03:00
|
|
|
|
2018-10-25 18:12:43 +02:00
|
|
|
static const QHash<QString, Abi> ClangTargets = {
|
|
|
|
|
{"arm-linux-androideabi",
|
|
|
|
|
Abi(Abi::ArmArchitecture, Abi::LinuxOS, Abi::AndroidLinuxFlavor, Abi::ElfFormat, 32)},
|
|
|
|
|
{"i686-linux-android",
|
|
|
|
|
Abi(Abi::X86Architecture, Abi::LinuxOS, Abi::AndroidLinuxFlavor, Abi::ElfFormat, 32)},
|
|
|
|
|
{"x86_64-linux-android",
|
|
|
|
|
Abi(Abi::X86Architecture, Abi::LinuxOS, Abi::AndroidLinuxFlavor, Abi::ElfFormat, 64)},
|
|
|
|
|
{"aarch64-linux-android",
|
|
|
|
|
Abi(Abi::ArmArchitecture, Abi::LinuxOS, Abi::AndroidLinuxFlavor, Abi::ElfFormat, 64)}};
|
|
|
|
|
|
|
|
|
|
static const QList<Core::Id> LanguageIds = {ProjectExplorer::Constants::CXX_LANGUAGE_ID,
|
|
|
|
|
ProjectExplorer::Constants::C_LANGUAGE_ID};
|
|
|
|
|
|
|
|
|
|
static ToolChain *findToolChain(Utils::FileName &compilerPath, Core::Id lang, const QString &target,
|
|
|
|
|
CToolChainList &alreadyKnown)
|
|
|
|
|
{
|
|
|
|
|
ToolChain * tc = Utils::findOrDefault(alreadyKnown, [target, compilerPath, lang](ToolChain *tc) {
|
|
|
|
|
return tc->typeId() == Constants::ANDROID_TOOLCHAIN_ID
|
|
|
|
|
&& tc->language() == lang
|
|
|
|
|
&& tc->targetAbi() == ClangTargets[target]
|
|
|
|
|
&& tc->compilerCommand() == compilerPath;
|
|
|
|
|
});
|
|
|
|
|
return tc;
|
2013-01-25 16:49:22 +01:00
|
|
|
}
|
2012-04-18 20:30:57 +03:00
|
|
|
|
2018-07-25 12:19:15 +02:00
|
|
|
AndroidToolChain::~AndroidToolChain() = default;
|
2012-04-18 20:30:57 +03:00
|
|
|
|
|
|
|
|
QString AndroidToolChain::typeDisplayName() const
|
|
|
|
|
{
|
2018-10-25 18:12:43 +02:00
|
|
|
return AndroidToolChainFactory::tr("Android Clang");
|
2012-04-18 20:30:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool AndroidToolChain::isValid() const
|
|
|
|
|
{
|
2018-10-25 18:12:43 +02:00
|
|
|
return ClangToolChain::isValid()
|
|
|
|
|
&& typeId() == Constants::ANDROID_TOOLCHAIN_ID
|
|
|
|
|
&& targetAbi().isValid()
|
2018-04-09 13:55:12 +02:00
|
|
|
&& compilerCommand().isChildOf(AndroidConfigurations::currentConfig().ndkLocation())
|
|
|
|
|
&& !originalTargetTriple().isEmpty();
|
2012-04-18 20:30:57 +03:00
|
|
|
}
|
|
|
|
|
|
2012-08-23 15:53:58 +02:00
|
|
|
void AndroidToolChain::addToEnvironment(Environment &env) const
|
2012-04-18 20:30:57 +03:00
|
|
|
{
|
2018-10-25 18:12:43 +02:00
|
|
|
env.set(QLatin1String("ANDROID_NDK_HOST"),
|
|
|
|
|
AndroidConfigurations::currentConfig().toolchainHost());
|
2015-11-20 14:11:26 +01:00
|
|
|
const Utils::FileName javaHome = AndroidConfigurations::currentConfig().openJDKLocation();
|
|
|
|
|
if (!javaHome.isEmpty() && javaHome.toFileInfo().exists()) {
|
|
|
|
|
env.set(QLatin1String("JAVA_HOME"), javaHome.toString());
|
|
|
|
|
Utils::FileName javaBin = javaHome;
|
|
|
|
|
javaBin.appendPath(QLatin1String("bin"));
|
2017-09-20 12:53:30 +02:00
|
|
|
if (!Utils::contains(env.path(), [&javaBin](const Utils::FileName &p) { return p == javaBin; }))
|
|
|
|
|
env.prependOrSetPath(javaBin.toUserOutput());
|
2015-11-20 14:11:26 +01:00
|
|
|
}
|
2018-10-25 18:12:43 +02:00
|
|
|
env.set(QLatin1String("ANDROID_HOME"),
|
|
|
|
|
AndroidConfigurations::currentConfig().sdkLocation().toString());
|
|
|
|
|
env.set(QLatin1String("ANDROID_SDK_ROOT"),
|
|
|
|
|
AndroidConfigurations::currentConfig().sdkLocation().toString());
|
2012-04-18 20:30:57 +03:00
|
|
|
}
|
|
|
|
|
|
2013-01-25 16:49:22 +01:00
|
|
|
FileName AndroidToolChain::suggestedDebugger() const
|
|
|
|
|
{
|
2018-10-25 18:12:43 +02:00
|
|
|
// TODO: Make use of LLDB if available.
|
2018-11-28 14:30:42 +01:00
|
|
|
return AndroidConfigurations::currentConfig().gdbPath(targetAbi());
|
2013-01-25 16:49:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FileName AndroidToolChain::suggestedGdbServer() const
|
|
|
|
|
{
|
2018-10-01 14:22:49 +03:00
|
|
|
return AndroidConfigurations::currentConfig().gdbServer(targetAbi());
|
2013-01-25 16:49:22 +01:00
|
|
|
}
|
|
|
|
|
|
2012-04-18 20:30:57 +03:00
|
|
|
bool AndroidToolChain::fromMap(const QVariantMap &data)
|
|
|
|
|
{
|
2018-10-25 18:12:43 +02:00
|
|
|
if (!ClangToolChain::fromMap(data))
|
2012-04-18 20:30:57 +03:00
|
|
|
return false;
|
|
|
|
|
return isValid();
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-03 14:01:25 +01:00
|
|
|
FileNameList AndroidToolChain::suggestedMkspecList() const
|
2012-04-18 20:30:57 +03:00
|
|
|
{
|
2017-08-16 16:40:55 +03:00
|
|
|
return FileNameList() << FileName::fromLatin1("android-g++")
|
|
|
|
|
<< FileName::fromLatin1("android-clang");
|
2012-04-18 20:30:57 +03:00
|
|
|
}
|
|
|
|
|
|
2015-02-03 23:50:37 +02:00
|
|
|
QString AndroidToolChain::makeCommand(const Environment &env) const
|
2012-04-18 20:30:57 +03:00
|
|
|
{
|
2018-10-25 18:12:43 +02:00
|
|
|
Q_UNUSED(env);
|
2017-11-06 15:59:11 +01:00
|
|
|
FileName makePath = AndroidConfigurations::currentConfig().makePath();
|
2018-10-25 18:12:43 +02:00
|
|
|
return makePath.exists() ? makePath.toString() : "make";
|
2013-08-28 13:34:24 +02:00
|
|
|
}
|
|
|
|
|
|
2016-03-04 15:33:16 +01:00
|
|
|
GccToolChain::DetectedAbisResult AndroidToolChain::detectSupportedAbis() const
|
2012-04-18 20:30:57 +03:00
|
|
|
{
|
2019-01-02 11:35:34 +01:00
|
|
|
for (auto itr = ClangTargets.constBegin();itr != ClangTargets.constEnd(); ++itr) {
|
|
|
|
|
if (itr.value() == targetAbi())
|
|
|
|
|
return GccToolChain::DetectedAbisResult({targetAbi()}, itr.key());
|
|
|
|
|
}
|
|
|
|
|
return GccToolChain::DetectedAbisResult({targetAbi()}, "");
|
2012-04-18 20:30:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
// ToolChainFactory
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
|
2013-08-09 17:49:30 +02:00
|
|
|
AndroidToolChainFactory::AndroidToolChainFactory()
|
2012-04-18 20:30:57 +03:00
|
|
|
{
|
2018-10-25 18:12:43 +02:00
|
|
|
setDisplayName(tr("Android Clang"));
|
2019-05-08 14:56:26 +02:00
|
|
|
setSupportedToolChainType(Constants::ANDROID_TOOLCHAIN_ID);
|
2019-05-08 15:36:57 +02:00
|
|
|
setSupportedLanguages({ProjectExplorer::Constants::CXX_LANGUAGE_ID});
|
2016-07-12 11:33:17 +02:00
|
|
|
}
|
|
|
|
|
|
2018-10-25 18:12:43 +02:00
|
|
|
ToolChainList AndroidToolChainFactory::autoDetect(CToolChainList &alreadyKnown)
|
2012-04-18 20:30:57 +03:00
|
|
|
{
|
2018-10-25 18:12:43 +02:00
|
|
|
return autodetectToolChainsForNdk(alreadyKnown);
|
2012-04-18 20:30:57 +03:00
|
|
|
}
|
|
|
|
|
|
2012-08-09 01:56:51 +02:00
|
|
|
ToolChain *AndroidToolChainFactory::restore(const QVariantMap &data)
|
2012-04-18 20:30:57 +03:00
|
|
|
{
|
2018-07-25 12:19:15 +02:00
|
|
|
auto tc = new AndroidToolChain();
|
2012-04-18 20:30:57 +03:00
|
|
|
if (tc->fromMap(data))
|
|
|
|
|
return tc;
|
|
|
|
|
|
|
|
|
|
delete tc;
|
2018-07-25 12:19:15 +02:00
|
|
|
return nullptr;
|
2012-04-18 20:30:57 +03:00
|
|
|
}
|
|
|
|
|
|
2018-11-14 16:54:47 +01:00
|
|
|
static FileName clangPlusPlusPath(const FileName &clangPath)
|
|
|
|
|
{
|
|
|
|
|
return clangPath.parentDir().appendPath(
|
|
|
|
|
HostOsInfo::withExecutableSuffix(
|
|
|
|
|
QFileInfo(clangPath.toString()).baseName() + "++"));
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-25 18:12:43 +02:00
|
|
|
ToolChainList AndroidToolChainFactory::autodetectToolChainsForNdk(CToolChainList &alreadyKnown)
|
2013-02-14 15:51:59 +01:00
|
|
|
{
|
2018-10-25 18:12:43 +02:00
|
|
|
QList<ToolChain *> result;
|
|
|
|
|
FileName clangPath = AndroidConfigurations::currentConfig().clangPath();
|
|
|
|
|
if (!clangPath.exists()) {
|
|
|
|
|
qCDebug(androidTCLog) << "Clang toolchains detection fails. Can not find Clang"<< clangPath;
|
2013-02-14 15:51:59 +01:00
|
|
|
return result;
|
2013-08-28 13:34:24 +02:00
|
|
|
}
|
|
|
|
|
|
2018-10-25 18:12:43 +02:00
|
|
|
qCDebug(androidTCLog) << "Detecting toolchains from Android NDK:"
|
|
|
|
|
<< AndroidConfigurations::currentConfig().ndkLocation();
|
2015-10-15 16:01:40 +02:00
|
|
|
|
2018-10-25 18:12:43 +02:00
|
|
|
for (const Core::Id &lang : LanguageIds) {
|
|
|
|
|
FileName compilerCommand = clangPath;
|
|
|
|
|
if (lang == ProjectExplorer::Constants::CXX_LANGUAGE_ID)
|
2018-11-14 16:54:47 +01:00
|
|
|
compilerCommand = clangPlusPlusPath(clangPath);
|
2013-08-28 13:34:24 +02:00
|
|
|
|
2018-10-25 18:12:43 +02:00
|
|
|
if (!compilerCommand.exists()) {
|
|
|
|
|
qCDebug(androidTCLog) << "Skipping Clang toolchain. Can not find compiler"
|
|
|
|
|
<< compilerCommand;
|
2013-01-25 16:49:22 +01:00
|
|
|
continue;
|
2015-10-15 16:01:40 +02:00
|
|
|
}
|
2013-08-28 13:34:24 +02:00
|
|
|
|
2018-10-25 18:12:43 +02:00
|
|
|
auto targetItr = ClangTargets.constBegin();
|
|
|
|
|
while (targetItr != ClangTargets.constEnd()) {
|
|
|
|
|
const Abi &abi = targetItr.value();
|
|
|
|
|
ToolChain *tc = findToolChain(compilerCommand, lang, targetItr.key(), alreadyKnown);
|
|
|
|
|
if (tc) {
|
|
|
|
|
qCDebug(androidTCLog) << "Tool chain already known" << abi.toString() << lang;
|
|
|
|
|
} else {
|
|
|
|
|
qCDebug(androidTCLog) << "New Clang toolchain found" << abi.toString() << lang;
|
|
|
|
|
auto atc = new AndroidToolChain(targetItr.key(), lang);
|
|
|
|
|
atc->resetToolChain(compilerCommand);
|
|
|
|
|
tc = atc;
|
|
|
|
|
}
|
|
|
|
|
result << tc;
|
|
|
|
|
++targetItr;
|
|
|
|
|
}
|
2013-08-28 13:34:24 +02:00
|
|
|
}
|
|
|
|
|
|
2012-04-18 20:30:57 +03:00
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-25 18:12:43 +02:00
|
|
|
// for fromMap
|
|
|
|
|
AndroidToolChain::AndroidToolChain()
|
2019-05-08 19:03:15 +02:00
|
|
|
: ClangToolChain(Constants::ANDROID_TOOLCHAIN_ID)
|
2018-10-25 18:12:43 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AndroidToolChain::AndroidToolChain(const QString& target, Core::Id languageId)
|
2019-05-08 19:03:15 +02:00
|
|
|
: ClangToolChain(Constants::ANDROID_TOOLCHAIN_ID)
|
2013-08-28 13:34:24 +02:00
|
|
|
{
|
2018-10-25 18:12:43 +02:00
|
|
|
setOriginalTargetTriple(target);
|
|
|
|
|
setLanguage(languageId);
|
|
|
|
|
setTargetAbi(ClangTargets[target]);
|
|
|
|
|
setPlatformCodeGenFlags({"-target", target});
|
|
|
|
|
setPlatformLinkerFlags({"-target", target});
|
2019-05-08 19:03:15 +02:00
|
|
|
setDetection(AutoDetection);
|
2018-10-25 18:12:43 +02:00
|
|
|
setDisplayName(QString::fromLatin1("Android Clang (%1, %2)")
|
|
|
|
|
.arg(ToolChainManager::displayNameOfLanguageId(languageId),
|
|
|
|
|
AndroidConfig::displayName(targetAbi())));
|
2013-08-28 13:34:24 +02:00
|
|
|
}
|
|
|
|
|
|
2012-04-18 20:30:57 +03:00
|
|
|
} // namespace Internal
|
|
|
|
|
} // namespace Android
|