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
|
|
|
|
2020-02-16 20:46:23 +02:00
|
|
|
#include <projectexplorer/kitmanager.h>
|
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 {
|
2020-01-15 14:39:23 +01:00
|
|
|
static 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};
|
|
|
|
|
|
2019-05-28 13:49:26 +02:00
|
|
|
static ToolChain *findToolChain(Utils::FilePath &compilerPath, Core::Id lang, const QString &target,
|
2019-06-14 11:29:12 +02:00
|
|
|
const ToolChainList &alreadyKnown)
|
2018-10-25 18:12:43 +02:00
|
|
|
{
|
|
|
|
|
ToolChain * tc = Utils::findOrDefault(alreadyKnown, [target, compilerPath, lang](ToolChain *tc) {
|
2019-06-14 11:12:19 +02:00
|
|
|
return tc->typeId() == Constants::ANDROID_TOOLCHAIN_TYPEID
|
2018-10-25 18:12:43 +02:00
|
|
|
&& 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
|
|
|
|
2019-06-19 17:28:20 +02:00
|
|
|
AndroidToolChain::AndroidToolChain()
|
|
|
|
|
: ClangToolChain(Constants::ANDROID_TOOLCHAIN_TYPEID)
|
2012-04-18 20:30:57 +03:00
|
|
|
{
|
2019-06-19 17:28:20 +02:00
|
|
|
setTypeDisplayName(AndroidToolChainFactory::tr("Android Clang"));
|
2012-04-18 20:30:57 +03:00
|
|
|
}
|
|
|
|
|
|
2020-02-16 20:46:23 +02:00
|
|
|
Utils::FilePath AndroidToolChain::ndkLocation() const
|
|
|
|
|
{
|
|
|
|
|
return m_ndkLocation;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidToolChain::setNdkLocation(const Utils::FilePath &ndkLocation)
|
|
|
|
|
{
|
|
|
|
|
m_ndkLocation = ndkLocation;
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-19 17:28:20 +02:00
|
|
|
AndroidToolChain::~AndroidToolChain() = default;
|
|
|
|
|
|
2012-04-18 20:30:57 +03:00
|
|
|
bool AndroidToolChain::isValid() const
|
|
|
|
|
{
|
2020-02-25 12:31:25 +02:00
|
|
|
if (m_ndkLocation.isEmpty()) {
|
|
|
|
|
QStringList ndkParts(compilerCommand().toString().split("toolchains/llvm/prebuilt/"));
|
|
|
|
|
if (ndkParts.size() > 1) {
|
|
|
|
|
QString ndkLocation(ndkParts.first());
|
|
|
|
|
if (ndkLocation.endsWith('/'))
|
|
|
|
|
ndkLocation.chop(1);
|
|
|
|
|
m_ndkLocation = FilePath::fromString(ndkLocation);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-16 20:46:23 +02:00
|
|
|
const bool isChildofNdk = compilerCommand().isChildOf(m_ndkLocation);
|
|
|
|
|
const bool isChildofSdk = compilerCommand().isChildOf(
|
|
|
|
|
AndroidConfigurations::currentConfig().sdkLocation());
|
|
|
|
|
|
|
|
|
|
return ClangToolChain::isValid() && typeId() == Constants::ANDROID_TOOLCHAIN_TYPEID
|
2020-02-25 12:31:25 +02:00
|
|
|
&& targetAbi().isValid() && (isChildofNdk || isChildofSdk)
|
2020-02-16 20:46:23 +02:00
|
|
|
&& !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
|
|
|
{
|
2020-02-16 20:46:23 +02:00
|
|
|
AndroidConfig config = AndroidConfigurations::currentConfig();
|
|
|
|
|
env.set(QLatin1String("ANDROID_NDK_HOST"), config.toolchainHostFromNdk(m_ndkLocation));
|
|
|
|
|
const Utils::FilePath javaHome = config.openJDKLocation();
|
2019-08-12 16:04:31 +02:00
|
|
|
if (javaHome.exists()) {
|
2015-11-20 14:11:26 +01:00
|
|
|
env.set(QLatin1String("JAVA_HOME"), javaHome.toString());
|
2019-05-28 13:49:26 +02:00
|
|
|
const FilePath javaBin = javaHome.pathAppended("bin");
|
2019-08-13 10:53:30 +02:00
|
|
|
const FilePath currentJavaFilePath = env.searchInPath("java");
|
|
|
|
|
if (!currentJavaFilePath.isChildOf(javaBin))
|
2017-09-20 12:53:30 +02:00
|
|
|
env.prependOrSetPath(javaBin.toUserOutput());
|
2015-11-20 14:11:26 +01:00
|
|
|
}
|
2020-02-16 20:46:23 +02:00
|
|
|
env.set(QLatin1String("ANDROID_HOME"), config.sdkLocation().toString());
|
|
|
|
|
env.set(QLatin1String("ANDROID_SDK_ROOT"), config.sdkLocation().toString());
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-27 14:22:15 +02:00
|
|
|
QStringList AndroidToolChain::suggestedMkspecList() const
|
2012-04-18 20:30:57 +03:00
|
|
|
{
|
2019-05-27 14:22:15 +02:00
|
|
|
return {"android-g++", "android-clang"};
|
2012-04-18 20:30:57 +03:00
|
|
|
}
|
|
|
|
|
|
2019-05-28 13:49:26 +02:00
|
|
|
FilePath AndroidToolChain::makeCommand(const Environment &env) const
|
2012-04-18 20:30:57 +03:00
|
|
|
{
|
2019-07-23 10:58:00 +02:00
|
|
|
Q_UNUSED(env)
|
2020-02-16 20:46:23 +02:00
|
|
|
FilePath makePath = AndroidConfigurations::currentConfig().makePathFromNdk(m_ndkLocation);
|
2019-05-28 13:49:26 +02:00
|
|
|
return makePath.exists() ? makePath : FilePath::fromString("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-06-14 11:12:19 +02:00
|
|
|
setSupportedToolChainType(Constants::ANDROID_TOOLCHAIN_TYPEID);
|
2019-05-08 15:36:57 +02:00
|
|
|
setSupportedLanguages({ProjectExplorer::Constants::CXX_LANGUAGE_ID});
|
2019-05-10 17:35:04 +02:00
|
|
|
setToolchainConstructor([] { return new AndroidToolChain; });
|
2016-07-12 11:33:17 +02:00
|
|
|
}
|
|
|
|
|
|
2019-06-14 11:29:12 +02:00
|
|
|
ToolChainList AndroidToolChainFactory::autoDetect(const ToolChainList &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
|
|
|
}
|
|
|
|
|
|
2019-05-28 13:49:26 +02:00
|
|
|
static FilePath clangPlusPlusPath(const FilePath &clangPath)
|
2018-11-14 16:54:47 +01:00
|
|
|
{
|
2019-05-17 13:20:41 +02:00
|
|
|
return clangPath.parentDir().pathAppended(
|
2018-11-14 16:54:47 +01:00
|
|
|
HostOsInfo::withExecutableSuffix(
|
|
|
|
|
QFileInfo(clangPath.toString()).baseName() + "++"));
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-16 20:46:23 +02:00
|
|
|
static QList<QtSupport::BaseQtVersion *> androidQtVersionsWithUniqueNdk()
|
|
|
|
|
{
|
|
|
|
|
AndroidConfig config = AndroidConfigurations::currentConfig();
|
|
|
|
|
|
|
|
|
|
auto androidQtVersions = QtSupport::QtVersionManager::versions(
|
|
|
|
|
[](const QtSupport::BaseQtVersion *v) {
|
|
|
|
|
return v->targetDeviceTypes().contains(Android::Constants::ANDROID_DEVICE_TYPE);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
auto shouldRemove = [config](const QtSupport::BaseQtVersion *first,
|
|
|
|
|
const QtSupport::BaseQtVersion *second) {
|
|
|
|
|
return config.ndkLocation(first) == config.ndkLocation(second);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
QList<QtSupport::BaseQtVersion *>::iterator it = std::unique(androidQtVersions.begin(),
|
|
|
|
|
androidQtVersions.end(),
|
|
|
|
|
shouldRemove);
|
|
|
|
|
androidQtVersions.erase(it, androidQtVersions.end());
|
|
|
|
|
|
|
|
|
|
return androidQtVersions;
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-14 11:29:12 +02:00
|
|
|
ToolChainList AndroidToolChainFactory::autodetectToolChainsForNdk(const ToolChainList &alreadyKnown)
|
2013-02-14 15:51:59 +01:00
|
|
|
{
|
2018-10-25 18:12:43 +02:00
|
|
|
QList<ToolChain *> result;
|
2020-02-16 20:46:23 +02:00
|
|
|
const QList<QtSupport::BaseQtVersion *> androidQtVersions = androidQtVersionsWithUniqueNdk();
|
|
|
|
|
const AndroidConfig config = AndroidConfigurations::currentConfig();
|
2013-08-28 13:34:24 +02:00
|
|
|
|
2020-02-16 20:46:23 +02:00
|
|
|
for (const QtSupport::BaseQtVersion *qtVersion : androidQtVersions) {
|
|
|
|
|
FilePath clangPath = config.clangPath(qtVersion);
|
|
|
|
|
if (!clangPath.exists()) {
|
|
|
|
|
qCDebug(androidTCLog) << "Clang toolchains detection fails. Can not find Clang"
|
|
|
|
|
<< clangPath;
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2015-10-15 16:01:40 +02:00
|
|
|
|
2020-02-16 20:46:23 +02:00
|
|
|
qCDebug(androidTCLog) << "Detecting toolchains from Android NDK:"
|
|
|
|
|
<< config.ndkLocation(qtVersion);
|
2013-08-28 13:34:24 +02:00
|
|
|
|
2020-02-16 20:46:23 +02:00
|
|
|
for (const Core::Id &lang : LanguageIds) {
|
|
|
|
|
FilePath compilerCommand = clangPath;
|
|
|
|
|
if (lang == ProjectExplorer::Constants::CXX_LANGUAGE_ID)
|
|
|
|
|
compilerCommand = clangPlusPlusPath(clangPath);
|
|
|
|
|
|
|
|
|
|
if (!compilerCommand.exists()) {
|
|
|
|
|
qCDebug(androidTCLog)
|
|
|
|
|
<< "Skipping Clang toolchain. Can not find compiler" << compilerCommand;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2013-08-28 13:34:24 +02:00
|
|
|
|
2020-02-16 20:46:23 +02:00
|
|
|
auto targetItr = ClangTargets.constBegin();
|
|
|
|
|
while (targetItr != ClangTargets.constEnd()) {
|
|
|
|
|
const Abi &abi = targetItr.value();
|
|
|
|
|
const QString target = targetItr.key();
|
|
|
|
|
ToolChain *tc = findToolChain(compilerCommand, lang, target, alreadyKnown);
|
2020-02-25 12:27:23 +02:00
|
|
|
|
|
|
|
|
const QString displayName(QString("Android Clang (%1, %2, NDK %3)")
|
|
|
|
|
.arg(ToolChainManager::displayNameOfLanguageId(lang),
|
|
|
|
|
AndroidConfig::displayName(abi),
|
|
|
|
|
config.ndkVersion(qtVersion).toString()));
|
2020-02-16 20:46:23 +02:00
|
|
|
if (tc) {
|
|
|
|
|
qCDebug(androidTCLog) << "Tool chain already known" << abi.toString() << lang;
|
2020-02-25 12:27:23 +02:00
|
|
|
// make sure to update the toolchain with current name format
|
|
|
|
|
if (tc->displayName() != displayName)
|
|
|
|
|
tc->setDisplayName(displayName);
|
2020-02-16 20:46:23 +02:00
|
|
|
} else {
|
|
|
|
|
qCDebug(androidTCLog) << "New Clang toolchain found" << abi.toString() << lang;
|
|
|
|
|
auto atc = new AndroidToolChain();
|
|
|
|
|
atc->setNdkLocation(config.ndkLocation(qtVersion));
|
|
|
|
|
atc->setOriginalTargetTriple(target);
|
|
|
|
|
atc->setLanguage(lang);
|
|
|
|
|
atc->setTargetAbi(ClangTargets[target]);
|
|
|
|
|
atc->setPlatformCodeGenFlags({"-target", target});
|
|
|
|
|
atc->setPlatformLinkerFlags({"-target", target});
|
2020-02-25 12:27:23 +02:00
|
|
|
atc->setDisplayName(displayName);
|
2020-02-16 20:46:23 +02:00
|
|
|
atc->resetToolChain(compilerCommand);
|
|
|
|
|
tc = atc;
|
|
|
|
|
}
|
2020-02-25 12:27:23 +02:00
|
|
|
tc->setDetection(ToolChain::AutoDetection);
|
2020-02-16 20:46:23 +02:00
|
|
|
result << tc;
|
|
|
|
|
++targetItr;
|
2018-10-25 18:12:43 +02:00
|
|
|
}
|
|
|
|
|
}
|
2013-08-28 13:34:24 +02:00
|
|
|
}
|
|
|
|
|
|
2012-04-18 20:30:57 +03:00
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace Internal
|
|
|
|
|
} // namespace Android
|