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>
|
|
|
|
|
|
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
|
|
|
|
2021-05-28 18:22:44 +03:00
|
|
|
using ClangTargetsType = QHash<QString, Abi>;
|
|
|
|
|
Q_GLOBAL_STATIC_WITH_ARGS(ClangTargetsType, 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)}}
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
Q_GLOBAL_STATIC_WITH_ARGS(QList<Utils::Id>, LanguageIds, (
|
|
|
|
|
{ProjectExplorer::Constants::CXX_LANGUAGE_ID,
|
|
|
|
|
ProjectExplorer::Constants::C_LANGUAGE_ID}))
|
2018-10-25 18:12:43 +02:00
|
|
|
|
2020-06-26 13:59:38 +02:00
|
|
|
static ToolChain *findToolChain(Utils::FilePath &compilerPath, Utils::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
|
2021-05-28 18:22:44 +03:00
|
|
|
&& tc->targetAbi() == ClangTargets->value(target)
|
2018-10-25 18:12:43 +02:00
|
|
|
&& 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
|
|
|
{
|
2020-02-11 08:46:52 +01:00
|
|
|
setTypeDisplayName(AndroidToolChain::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
|
|
|
{
|
2021-10-25 15:58:02 +03:00
|
|
|
const AndroidConfig &config = AndroidConfigurations::currentConfig();
|
2020-02-16 20:46:23 +02:00
|
|
|
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))
|
2021-11-09 18:20:14 +01:00
|
|
|
env.prependOrSetPath(javaBin);
|
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);
|
2021-08-10 16:19:02 +02:00
|
|
|
return makePath.exists() ? makePath : FilePath("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
|
|
|
{
|
2021-05-28 18:22:44 +03:00
|
|
|
for (auto itr = ClangTargets->constBegin(); itr != ClangTargets->constEnd(); ++itr) {
|
2019-01-02 11:35:34 +01:00
|
|
|
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
|
|
|
{
|
2020-02-11 08:46:52 +01:00
|
|
|
setDisplayName(AndroidToolChain::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-05-28 13:49:26 +02:00
|
|
|
static FilePath clangPlusPlusPath(const FilePath &clangPath)
|
2018-11-14 16:54:47 +01:00
|
|
|
{
|
2021-08-16 09:22:54 +02:00
|
|
|
return clangPath.parentDir().pathAppended(clangPath.baseName() + "++").withExecutableSuffix();
|
2018-11-14 16:54:47 +01:00
|
|
|
}
|
|
|
|
|
|
2020-02-24 11:19:02 +02:00
|
|
|
static QList<FilePath> uniqueNdksForCurrentQtVersions()
|
2020-02-16 20:46:23 +02:00
|
|
|
{
|
2021-10-25 15:58:02 +03:00
|
|
|
const AndroidConfig &config = AndroidConfigurations::currentConfig();
|
2020-02-16 20:46:23 +02:00
|
|
|
|
|
|
|
|
auto androidQtVersions = QtSupport::QtVersionManager::versions(
|
|
|
|
|
[](const QtSupport::BaseQtVersion *v) {
|
|
|
|
|
return v->targetDeviceTypes().contains(Android::Constants::ANDROID_DEVICE_TYPE);
|
|
|
|
|
});
|
|
|
|
|
|
2020-02-24 11:19:02 +02:00
|
|
|
QList<FilePath> uniqueNdks;
|
|
|
|
|
for (const QtSupport::BaseQtVersion *version : androidQtVersions) {
|
|
|
|
|
FilePath ndk = config.ndkLocation(version);
|
|
|
|
|
if (!uniqueNdks.contains(ndk))
|
|
|
|
|
uniqueNdks.append(ndk);
|
|
|
|
|
}
|
2020-02-16 20:46:23 +02:00
|
|
|
|
2020-02-24 11:19:02 +02:00
|
|
|
return uniqueNdks;
|
|
|
|
|
}
|
2020-02-16 20:46:23 +02:00
|
|
|
|
2020-02-24 11:19:02 +02:00
|
|
|
ToolChainList AndroidToolChainFactory::autodetectToolChains(const ToolChainList &alreadyKnown)
|
|
|
|
|
{
|
|
|
|
|
const QList<Utils::FilePath> uniqueNdks = uniqueNdksForCurrentQtVersions();
|
|
|
|
|
return autodetectToolChainsFromNdks(alreadyKnown, uniqueNdks);
|
2020-02-16 20:46:23 +02:00
|
|
|
}
|
|
|
|
|
|
2020-02-24 11:19:02 +02:00
|
|
|
ToolChainList AndroidToolChainFactory::autodetectToolChainsFromNdks(
|
|
|
|
|
const ToolChainList &alreadyKnown,
|
|
|
|
|
const QList<Utils::FilePath> &ndkLocations,
|
|
|
|
|
const bool isCustom)
|
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 AndroidConfig config = AndroidConfigurations::currentConfig();
|
2013-08-28 13:34:24 +02:00
|
|
|
|
2020-02-24 11:19:02 +02:00
|
|
|
for (const Utils::FilePath &ndkLocation : ndkLocations) {
|
|
|
|
|
FilePath clangPath = config.clangPathFromNdk(ndkLocation);
|
2020-02-16 20:46:23 +02:00
|
|
|
if (!clangPath.exists()) {
|
|
|
|
|
qCDebug(androidTCLog) << "Clang toolchains detection fails. Can not find Clang"
|
|
|
|
|
<< clangPath;
|
2020-02-24 11:19:02 +02:00
|
|
|
continue;
|
2020-02-16 20:46:23 +02:00
|
|
|
}
|
2015-10-15 16:01:40 +02:00
|
|
|
|
2021-05-28 18:22:44 +03:00
|
|
|
for (const Utils::Id &lang : *LanguageIds) {
|
2020-02-16 20:46:23 +02:00
|
|
|
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
|
|
|
|
2021-05-28 18:22:44 +03:00
|
|
|
auto targetItr = ClangTargets->constBegin();
|
|
|
|
|
while (targetItr != ClangTargets->constEnd()) {
|
2020-02-16 20:46:23 +02:00
|
|
|
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
|
|
|
|
2020-02-24 11:19:02 +02:00
|
|
|
QLatin1String customStr = isCustom ? QLatin1String("Custom ") : QLatin1String();
|
|
|
|
|
const QString displayName(customStr + QString("Android Clang (%1, %2, NDK %3)")
|
2020-02-25 12:27:23 +02:00
|
|
|
.arg(ToolChainManager::displayNameOfLanguageId(lang),
|
|
|
|
|
AndroidConfig::displayName(abi),
|
2020-02-24 11:19:02 +02:00
|
|
|
config.ndkVersion(ndkLocation).toString()));
|
2020-02-16 20:46:23 +02:00
|
|
|
if (tc) {
|
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 {
|
2020-07-01 19:32:30 +03:00
|
|
|
qCDebug(androidTCLog) << "New Clang toolchain found" << abi.toString() << lang
|
|
|
|
|
<< "for NDK" << ndkLocation;
|
2020-02-16 20:46:23 +02:00
|
|
|
auto atc = new AndroidToolChain();
|
2020-02-24 11:19:02 +02:00
|
|
|
atc->setNdkLocation(ndkLocation);
|
2020-02-16 20:46:23 +02:00
|
|
|
atc->setOriginalTargetTriple(target);
|
|
|
|
|
atc->setLanguage(lang);
|
2021-05-28 18:22:44 +03:00
|
|
|
atc->setTargetAbi(ClangTargets->value(target));
|
2020-02-16 20:46:23 +02:00
|
|
|
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
|