Files
qt-creator/src/plugins/android/androidtoolchain.cpp
Alessandro Portale 5c65115271 Android: Convert to using Tr::tr
Change-Id: Ie9110093101b0f49808b4da7b13ac3f47c3bb994
Reviewed-by: hjk <hjk@qt.io>
2022-10-07 10:24:32 +00:00

248 lines
9.1 KiB
C++

// Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#include "androidconfigurations.h"
#include "androidconstants.h"
#include "androidtoolchain.h"
#include "androidtr.h"
#include <projectexplorer/kitmanager.h>
#include <projectexplorer/toolchainmanager.h>
#include <projectexplorer/projectexplorer.h>
#include <utils/environment.h>
#include <QLoggingCategory>
using namespace ProjectExplorer;
using namespace Utils;
namespace Android {
namespace Internal {
static Q_LOGGING_CATEGORY(androidTCLog, "qtc.android.toolchainmanagement", QtWarningMsg);
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)}}
));
static ToolChain *findToolChain(FilePath &compilerPath, Id lang, const QString &target,
const ToolChainList &alreadyKnown)
{
ToolChain *tc = Utils::findOrDefault(alreadyKnown, [target, compilerPath, lang](ToolChain *tc) {
return tc->typeId() == Constants::ANDROID_TOOLCHAIN_TYPEID
&& tc->language() == lang
&& tc->targetAbi() == ClangTargets->value(target)
&& tc->compilerCommand() == compilerPath;
});
return tc;
}
AndroidToolChain::AndroidToolChain()
: ClangToolChain(Constants::ANDROID_TOOLCHAIN_TYPEID)
{
setTypeDisplayName(Tr::tr("Android Clang"));
}
FilePath AndroidToolChain::ndkLocation() const
{
return m_ndkLocation;
}
void AndroidToolChain::setNdkLocation(const FilePath &ndkLocation)
{
m_ndkLocation = ndkLocation;
}
AndroidToolChain::~AndroidToolChain() = default;
bool AndroidToolChain::isValid() const
{
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);
}
}
const bool isChildofNdk = compilerCommand().isChildOf(m_ndkLocation);
const bool isChildofSdk = compilerCommand().isChildOf(
AndroidConfigurations::currentConfig().sdkLocation());
return ClangToolChain::isValid() && typeId() == Constants::ANDROID_TOOLCHAIN_TYPEID
&& targetAbi().isValid() && (isChildofNdk || isChildofSdk)
&& !originalTargetTriple().isEmpty();
}
void AndroidToolChain::addToEnvironment(Environment &env) const
{
const AndroidConfig &config = AndroidConfigurations::currentConfig();
env.set(QLatin1String("ANDROID_NDK_HOST"), config.toolchainHostFromNdk(m_ndkLocation));
const FilePath javaHome = config.openJDKLocation();
if (javaHome.exists()) {
env.set(Constants::JAVA_HOME_ENV_VAR, javaHome.toUserOutput());
const FilePath javaBin = javaHome.pathAppended("bin");
const FilePath currentJavaFilePath = env.searchInPath("java");
if (!currentJavaFilePath.isChildOf(javaBin))
env.prependOrSetPath(javaBin);
}
env.set(QLatin1String("ANDROID_HOME"), config.sdkLocation().toUserOutput());
env.set(QLatin1String("ANDROID_SDK_ROOT"), config.sdkLocation().toUserOutput());
}
bool AndroidToolChain::fromMap(const QVariantMap &data)
{
if (!ClangToolChain::fromMap(data))
return false;
return isValid();
}
QStringList AndroidToolChain::suggestedMkspecList() const
{
return {"android-g++", "android-clang"};
}
FilePath AndroidToolChain::makeCommand(const Environment &env) const
{
Q_UNUSED(env)
FilePath makePath = AndroidConfigurations::currentConfig().makePathFromNdk(m_ndkLocation);
return makePath.exists() ? makePath : FilePath("make");
}
GccToolChain::DetectedAbisResult AndroidToolChain::detectSupportedAbis() const
{
for (auto itr = ClangTargets->constBegin(); itr != ClangTargets->constEnd(); ++itr) {
if (itr.value() == targetAbi())
return GccToolChain::DetectedAbisResult({targetAbi()}, itr.key());
}
return GccToolChain::DetectedAbisResult({targetAbi()}, "");
}
// --------------------------------------------------------------------------
// ToolChainFactory
// --------------------------------------------------------------------------
AndroidToolChainFactory::AndroidToolChainFactory()
{
setDisplayName(Tr::tr("Android Clang"));
setSupportedToolChainType(Constants::ANDROID_TOOLCHAIN_TYPEID);
setSupportedLanguages({ProjectExplorer::Constants::CXX_LANGUAGE_ID});
setToolchainConstructor([] { return new AndroidToolChain; });
}
static FilePath clangPlusPlusPath(const FilePath &clangPath)
{
return clangPath.parentDir().pathAppended(clangPath.baseName() + "++").withExecutableSuffix();
}
static FilePaths uniqueNdksForCurrentQtVersions()
{
const AndroidConfig &config = AndroidConfigurations::currentConfig();
auto androidQtVersions = QtSupport::QtVersionManager::versions(
[](const QtSupport::QtVersion *v) {
return v->targetDeviceTypes().contains(Android::Constants::ANDROID_DEVICE_TYPE);
});
FilePaths uniqueNdks;
for (const QtSupport::QtVersion *version : androidQtVersions) {
FilePath ndk = config.ndkLocation(version);
if (!uniqueNdks.contains(ndk))
uniqueNdks.append(ndk);
}
return uniqueNdks;
}
ToolChainList AndroidToolChainFactory::autodetectToolChains(const ToolChainList &alreadyKnown)
{
const QList<FilePath> uniqueNdks = uniqueNdksForCurrentQtVersions();
return autodetectToolChainsFromNdks(alreadyKnown, uniqueNdks);
}
ToolChainList AndroidToolChainFactory::autodetectToolChainsFromNdks(
const ToolChainList &alreadyKnown,
const QList<FilePath> &ndkLocations,
const bool isCustom)
{
QList<ToolChain *> result;
const AndroidConfig config = AndroidConfigurations::currentConfig();
const Id LanguageIds[] {
ProjectExplorer::Constants::CXX_LANGUAGE_ID,
ProjectExplorer::Constants::C_LANGUAGE_ID
};
for (const FilePath &ndkLocation : ndkLocations) {
FilePath clangPath = config.clangPathFromNdk(ndkLocation);
if (!clangPath.exists()) {
qCDebug(androidTCLog) << "Clang toolchains detection fails. Can not find Clang"
<< clangPath;
continue;
}
for (const 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;
}
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);
QLatin1String customStr = isCustom ? QLatin1String("Custom ") : QLatin1String();
const QString displayName(customStr + QString("Android Clang (%1, %2, NDK %3)")
.arg(ToolChainManager::displayNameOfLanguageId(lang),
AndroidConfig::displayName(abi),
config.ndkVersion(ndkLocation).toString()));
if (tc) {
// make sure to update the toolchain with current name format
if (tc->displayName() != displayName)
tc->setDisplayName(displayName);
} else {
qCDebug(androidTCLog) << "New Clang toolchain found" << abi.toString() << lang
<< "for NDK" << ndkLocation;
auto atc = new AndroidToolChain();
atc->setNdkLocation(ndkLocation);
atc->setOriginalTargetTriple(target);
atc->setLanguage(lang);
atc->setTargetAbi(ClangTargets->value(target));
atc->setPlatformCodeGenFlags({"-target", target});
atc->setPlatformLinkerFlags({"-target", target});
atc->setDisplayName(displayName);
atc->resetToolChain(compilerCommand);
tc = atc;
}
tc->setDetection(ToolChain::AutoDetection);
result << tc;
++targetItr;
}
}
}
return result;
}
} // namespace Internal
} // namespace Android