forked from qt-creator/qt-creator
Android: Allow adding custom NDKs and auto detect their toolchains
This adds the option for the user to add a custom NDK out of the predefined list installed from SDK manager. Once an NDK is added and settings saved, both the toolchains and debuggers will be detected automatically. The user then can create a custom kit with those added toolchains and debuggers. Task-number: QTCREATORBUG-23286 Change-Id: I46200accca6fc956b73f211213bfe2a495093934 Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
@@ -100,6 +100,7 @@ namespace {
|
|||||||
|
|
||||||
const QLatin1String SettingsGroup("AndroidConfigurations");
|
const QLatin1String SettingsGroup("AndroidConfigurations");
|
||||||
const QLatin1String SDKLocationKey("SDKLocation");
|
const QLatin1String SDKLocationKey("SDKLocation");
|
||||||
|
const QLatin1String CustomNdkLocationsKey("CustomNdkLocations");
|
||||||
const QLatin1String SdkFullyConfiguredKey("AllEssentialsInstalled");
|
const QLatin1String SdkFullyConfiguredKey("AllEssentialsInstalled");
|
||||||
const QLatin1String SDKManagerToolArgsKey("SDKManagerToolArgs");
|
const QLatin1String SDKManagerToolArgsKey("SDKManagerToolArgs");
|
||||||
const QLatin1String OpenJDKLocationKey("OpenJDKLocation");
|
const QLatin1String OpenJDKLocationKey("OpenJDKLocation");
|
||||||
@@ -235,6 +236,7 @@ void AndroidConfig::load(const QSettings &settings)
|
|||||||
// user settings
|
// user settings
|
||||||
m_partitionSize = settings.value(PartitionSizeKey, 1024).toInt();
|
m_partitionSize = settings.value(PartitionSizeKey, 1024).toInt();
|
||||||
m_sdkLocation = FilePath::fromString(settings.value(SDKLocationKey).toString());
|
m_sdkLocation = FilePath::fromString(settings.value(SDKLocationKey).toString());
|
||||||
|
m_customNdkList = settings.value(CustomNdkLocationsKey).toStringList();
|
||||||
m_sdkManagerToolArgs = settings.value(SDKManagerToolArgsKey).toStringList();
|
m_sdkManagerToolArgs = settings.value(SDKManagerToolArgsKey).toStringList();
|
||||||
m_openJDKLocation = FilePath::fromString(settings.value(OpenJDKLocationKey).toString());
|
m_openJDKLocation = FilePath::fromString(settings.value(OpenJDKLocationKey).toString());
|
||||||
m_keystoreLocation = FilePath::fromString(settings.value(KeystoreLocationKey).toString());
|
m_keystoreLocation = FilePath::fromString(settings.value(KeystoreLocationKey).toString());
|
||||||
@@ -246,12 +248,14 @@ void AndroidConfig::load(const QSettings &settings)
|
|||||||
&& settings.value(changeTimeStamp).toInt() != QFileInfo(sdkSettingsFileName()).lastModified().toMSecsSinceEpoch() / 1000) {
|
&& settings.value(changeTimeStamp).toInt() != QFileInfo(sdkSettingsFileName()).lastModified().toMSecsSinceEpoch() / 1000) {
|
||||||
// persisten settings
|
// persisten settings
|
||||||
m_sdkLocation = FilePath::fromString(reader.restoreValue(SDKLocationKey, m_sdkLocation.toString()).toString());
|
m_sdkLocation = FilePath::fromString(reader.restoreValue(SDKLocationKey, m_sdkLocation.toString()).toString());
|
||||||
|
m_customNdkList = reader.restoreValue(CustomNdkLocationsKey).toStringList();
|
||||||
m_sdkManagerToolArgs = reader.restoreValue(SDKManagerToolArgsKey, m_sdkManagerToolArgs).toStringList();
|
m_sdkManagerToolArgs = reader.restoreValue(SDKManagerToolArgsKey, m_sdkManagerToolArgs).toStringList();
|
||||||
m_openJDKLocation = FilePath::fromString(reader.restoreValue(OpenJDKLocationKey, m_openJDKLocation.toString()).toString());
|
m_openJDKLocation = FilePath::fromString(reader.restoreValue(OpenJDKLocationKey, m_openJDKLocation.toString()).toString());
|
||||||
m_automaticKitCreation = reader.restoreValue(AutomaticKitCreationKey, m_automaticKitCreation).toBool();
|
m_automaticKitCreation = reader.restoreValue(AutomaticKitCreationKey, m_automaticKitCreation).toBool();
|
||||||
m_sdkFullyConfigured = reader.restoreValue(SdkFullyConfiguredKey, m_sdkFullyConfigured).toBool();
|
m_sdkFullyConfigured = reader.restoreValue(SdkFullyConfiguredKey, m_sdkFullyConfigured).toBool();
|
||||||
// persistent settings
|
// persistent settings
|
||||||
}
|
}
|
||||||
|
m_customNdkList.removeAll("");
|
||||||
parseDependenciesJson();
|
parseDependenciesJson();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,6 +267,7 @@ void AndroidConfig::save(QSettings &settings) const
|
|||||||
|
|
||||||
// user settings
|
// user settings
|
||||||
settings.setValue(SDKLocationKey, m_sdkLocation.toString());
|
settings.setValue(SDKLocationKey, m_sdkLocation.toString());
|
||||||
|
settings.setValue(CustomNdkLocationsKey, m_customNdkList);
|
||||||
settings.setValue(SDKManagerToolArgsKey, m_sdkManagerToolArgs);
|
settings.setValue(SDKManagerToolArgsKey, m_sdkManagerToolArgs);
|
||||||
settings.setValue(OpenJDKLocationKey, m_openJDKLocation.toString());
|
settings.setValue(OpenJDKLocationKey, m_openJDKLocation.toString());
|
||||||
settings.setValue(KeystoreLocationKey, m_keystoreLocation.toString());
|
settings.setValue(KeystoreLocationKey, m_keystoreLocation.toString());
|
||||||
@@ -353,6 +358,22 @@ QVector<int> AndroidConfig::availableNdkPlatforms(const BaseQtVersion *qtVersion
|
|||||||
return availableNdkPlatforms;
|
return availableNdkPlatforms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList AndroidConfig::getCustomNdkList() const
|
||||||
|
{
|
||||||
|
return m_customNdkList;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidConfig::addCustomNdk(const QString &customNdk)
|
||||||
|
{
|
||||||
|
if (!m_customNdkList.contains(customNdk))
|
||||||
|
m_customNdkList.append(customNdk);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidConfig::removeCustomNdk(const QString &customNdk)
|
||||||
|
{
|
||||||
|
m_customNdkList.removeAll(customNdk);
|
||||||
|
}
|
||||||
|
|
||||||
QStringList AndroidConfig::apiLevelNamesFor(const SdkPlatformList &platforms)
|
QStringList AndroidConfig::apiLevelNamesFor(const SdkPlatformList &platforms)
|
||||||
{
|
{
|
||||||
return Utils::transform(platforms, AndroidConfig::apiLevelNameFor);
|
return Utils::transform(platforms, AndroidConfig::apiLevelNameFor);
|
||||||
@@ -415,9 +436,9 @@ FilePath AndroidConfig::aaptToolPath() const
|
|||||||
return aaptToolPath.pathAppended(toolPath);
|
return aaptToolPath.pathAppended(toolPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
FilePath AndroidConfig::toolchainPath(const BaseQtVersion *qtVersion) const
|
FilePath AndroidConfig::toolchainPathFromNdk(const Utils::FilePath &ndkLocation) const
|
||||||
{
|
{
|
||||||
const FilePath toolchainPath = ndkLocation(qtVersion).pathAppended("toolchains/llvm/prebuilt/");
|
const FilePath toolchainPath = ndkLocation.pathAppended("toolchains/llvm/prebuilt/");
|
||||||
|
|
||||||
// detect toolchain host
|
// detect toolchain host
|
||||||
QStringList hostPatterns;
|
QStringList hostPatterns;
|
||||||
@@ -443,23 +464,41 @@ FilePath AndroidConfig::toolchainPath(const BaseQtVersion *qtVersion) const
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
FilePath AndroidConfig::clangPath(const BaseQtVersion *qtVersion) const
|
FilePath AndroidConfig::toolchainPath(const BaseQtVersion *qtVersion) const
|
||||||
{
|
{
|
||||||
const FilePath path = toolchainPath(qtVersion);
|
return toolchainPathFromNdk(ndkLocation(qtVersion));
|
||||||
|
}
|
||||||
|
|
||||||
|
FilePath AndroidConfig::clangPathFromNdk(const Utils::FilePath &ndkLocation) const
|
||||||
|
{
|
||||||
|
const FilePath path = toolchainPathFromNdk(ndkLocation);
|
||||||
if (path.isEmpty())
|
if (path.isEmpty())
|
||||||
return {};
|
return {};
|
||||||
return path.pathAppended(HostOsInfo::withExecutableSuffix("bin/clang"));
|
return path.pathAppended(HostOsInfo::withExecutableSuffix("bin/clang"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FilePath AndroidConfig::clangPath(const BaseQtVersion *qtVersion) const
|
||||||
|
{
|
||||||
|
return clangPathFromNdk(ndkLocation(qtVersion));
|
||||||
|
}
|
||||||
|
|
||||||
FilePath AndroidConfig::gdbPath(const ProjectExplorer::Abi &abi, const BaseQtVersion *qtVersion) const
|
FilePath AndroidConfig::gdbPath(const ProjectExplorer::Abi &abi, const BaseQtVersion *qtVersion) const
|
||||||
{
|
{
|
||||||
const FilePath path = ndkLocation(qtVersion).pathAppended(
|
return gdbPathFromNdk(abi, ndkLocation(qtVersion));
|
||||||
QString("prebuilt/%1/bin/gdb%2").arg(toolchainHost(qtVersion), QTC_HOST_EXE_SUFFIX));
|
}
|
||||||
|
|
||||||
|
FilePath AndroidConfig::gdbPathFromNdk(const Abi &abi, const FilePath &ndkLocation) const
|
||||||
|
{
|
||||||
|
const FilePath path = ndkLocation.pathAppended(
|
||||||
|
QString("prebuilt/%1/bin/gdb%2").arg(toolchainHostFromNdk(ndkLocation), QTC_HOST_EXE_SUFFIX));
|
||||||
if (path.exists())
|
if (path.exists())
|
||||||
return path;
|
return path;
|
||||||
// fallback for old NDKs (e.g. 10e)
|
// fallback for old NDKs (e.g. 10e)
|
||||||
return ndkLocation(qtVersion).pathAppended(QString("toolchains/%1-4.9/prebuilt/%2/bin/%3-gdb%4")
|
return ndkLocation.pathAppended(QString("toolchains/%1-4.9/prebuilt/%2/bin/%3-gdb%4")
|
||||||
.arg(toolchainPrefix(abi), toolchainHost(qtVersion), toolsPrefix(abi), QTC_HOST_EXE_SUFFIX));
|
.arg(toolchainPrefix(abi),
|
||||||
|
toolchainHostFromNdk(ndkLocation),
|
||||||
|
toolsPrefix(abi),
|
||||||
|
QTC_HOST_EXE_SUFFIX));
|
||||||
}
|
}
|
||||||
|
|
||||||
FilePath AndroidConfig::makePath(const BaseQtVersion *qtVersion) const
|
FilePath AndroidConfig::makePath(const BaseQtVersion *qtVersion) const
|
||||||
@@ -733,6 +772,16 @@ bool AndroidConfig::useNativeUiTools() const
|
|||||||
return !version.isNull() && version <= QVersionNumber(25, 3 ,0);
|
return !version.isNull() && version <= QVersionNumber(25, 3 ,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AndroidConfig::isValidNdk(const QString &ndkLocation) const
|
||||||
|
{
|
||||||
|
auto ndkPath = Utils::FilePath::fromUserInput(ndkLocation);
|
||||||
|
const Utils::FilePath ndkPlatformsDir = ndkPath.pathAppended("platforms");
|
||||||
|
|
||||||
|
return ndkPath.exists() && ndkPath.pathAppended("toolchains").exists()
|
||||||
|
&& ndkPlatformsDir.exists() && !ndkPlatformsDir.toString().contains(' ')
|
||||||
|
&& !ndkVersion(ndkPath).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
QString AndroidConfig::bestNdkPlatformMatch(int target, const BaseQtVersion *qtVersion) const
|
QString AndroidConfig::bestNdkPlatformMatch(int target, const BaseQtVersion *qtVersion) const
|
||||||
{
|
{
|
||||||
target = std::max(AndroidManager::apiLevelRange().first, target);
|
target = std::max(AndroidManager::apiLevelRange().first, target);
|
||||||
@@ -1076,10 +1125,53 @@ void AndroidConfigurations::registerNewToolChains()
|
|||||||
const QList<ToolChain *> existingAndroidToolChains
|
const QList<ToolChain *> existingAndroidToolChains
|
||||||
= ToolChainManager::toolChains(Utils::equal(&ToolChain::typeId,
|
= ToolChainManager::toolChains(Utils::equal(&ToolChain::typeId,
|
||||||
Core::Id(Constants::ANDROID_TOOLCHAIN_TYPEID)));
|
Core::Id(Constants::ANDROID_TOOLCHAIN_TYPEID)));
|
||||||
const QList<ToolChain *> newToolchains
|
QList<ToolChain *> newToolchains = AndroidToolChainFactory::autodetectToolChains(
|
||||||
= AndroidToolChainFactory::autodetectToolChainsForNdk(existingAndroidToolChains);
|
existingAndroidToolChains);
|
||||||
|
|
||||||
foreach (ToolChain *tc, newToolchains)
|
foreach (ToolChain *tc, newToolchains)
|
||||||
ToolChainManager::registerToolChain(tc);
|
ToolChainManager::registerToolChain(tc);
|
||||||
|
|
||||||
|
registerCustomToolChainsAndDebuggers();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidConfigurations::registerCustomToolChainsAndDebuggers()
|
||||||
|
{
|
||||||
|
const QList<ToolChain *> existingAndroidToolChains = ToolChainManager::toolChains(
|
||||||
|
Utils::equal(&ToolChain::typeId, Core::Id(Constants::ANDROID_TOOLCHAIN_TYPEID)));
|
||||||
|
QList<FilePath> customNdks = Utils::transform(currentConfig().getCustomNdkList(),
|
||||||
|
FilePath::fromString);
|
||||||
|
QList<ToolChain *> customToolchains
|
||||||
|
= AndroidToolChainFactory::autodetectToolChainsFromNdks(existingAndroidToolChains,
|
||||||
|
customNdks,
|
||||||
|
true);
|
||||||
|
for (ToolChain *tc : customToolchains) {
|
||||||
|
ToolChainManager::registerToolChain(tc);
|
||||||
|
|
||||||
|
const FilePath ndk = static_cast<AndroidToolChain *>(tc)->ndkLocation();
|
||||||
|
const FilePath command = AndroidConfigurations::currentConfig()
|
||||||
|
.gdbPathFromNdk(tc->targetAbi(), ndk);
|
||||||
|
|
||||||
|
const Debugger::DebuggerItem *existing = Debugger::DebuggerItemManager::findByCommand(
|
||||||
|
command);
|
||||||
|
QString abiStr
|
||||||
|
= static_cast<AndroidToolChain *>(tc)->platformLinkerFlags().at(1).split('-').first();
|
||||||
|
Abi abi = Abi::abiFromTargetTriplet(abiStr);
|
||||||
|
if (existing && existing->abis().contains(abi))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Debugger::DebuggerItem debugger;
|
||||||
|
debugger.setCommand(command);
|
||||||
|
debugger.setEngineType(Debugger::GdbEngineType);
|
||||||
|
debugger.setUnexpandedDisplayName(
|
||||||
|
AndroidConfigurations::tr("Custom Android Debugger (%1, NDK %2)")
|
||||||
|
.arg(abiStr,
|
||||||
|
AndroidConfigurations::currentConfig().ndkVersion(ndk).toString()));
|
||||||
|
debugger.setAutoDetected(true);
|
||||||
|
debugger.setAbi(abi);
|
||||||
|
debugger.reinitializeFromFile();
|
||||||
|
|
||||||
|
Debugger::DebuggerItemManager::registerDebugger(debugger);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidConfigurations::removeOldToolChains()
|
void AndroidConfigurations::removeOldToolChains()
|
||||||
@@ -1104,6 +1196,8 @@ void AndroidConfigurations::removeUnusedDebuggers()
|
|||||||
uniqueNdks.append(ndkLocation);
|
uniqueNdks.append(ndkLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uniqueNdks.append(Utils::transform(currentConfig().getCustomNdkList(), FilePath::fromString));
|
||||||
|
|
||||||
const QList<Debugger::DebuggerItem> allDebuggers = Debugger::DebuggerItemManager::debuggers();
|
const QList<Debugger::DebuggerItem> allDebuggers = Debugger::DebuggerItemManager::debuggers();
|
||||||
for (const Debugger::DebuggerItem &debugger : allDebuggers) {
|
for (const Debugger::DebuggerItem &debugger : allDebuggers) {
|
||||||
if (!debugger.displayName().contains("Android"))
|
if (!debugger.displayName().contains("Android"))
|
||||||
|
@@ -160,9 +160,12 @@ public:
|
|||||||
Utils::FilePath aaptToolPath() const;
|
Utils::FilePath aaptToolPath() const;
|
||||||
|
|
||||||
Utils::FilePath toolchainPath(const QtSupport::BaseQtVersion *qtVersion) const;
|
Utils::FilePath toolchainPath(const QtSupport::BaseQtVersion *qtVersion) const;
|
||||||
|
Utils::FilePath toolchainPathFromNdk(const Utils::FilePath &ndkLocation) const;
|
||||||
Utils::FilePath clangPath(const QtSupport::BaseQtVersion *qtVersion) const;
|
Utils::FilePath clangPath(const QtSupport::BaseQtVersion *qtVersion) const;
|
||||||
|
Utils::FilePath clangPathFromNdk(const Utils::FilePath &ndkLocation) const;
|
||||||
|
|
||||||
Utils::FilePath gdbPath(const ProjectExplorer::Abi &abi, const QtSupport::BaseQtVersion *qtVersion) const;
|
Utils::FilePath gdbPath(const ProjectExplorer::Abi &abi, const QtSupport::BaseQtVersion *qtVersion) const;
|
||||||
|
Utils::FilePath gdbPathFromNdk(const ProjectExplorer::Abi &abi, const Utils::FilePath &ndkLocation) const;
|
||||||
Utils::FilePath makePath(const QtSupport::BaseQtVersion *qtVersion) const;
|
Utils::FilePath makePath(const QtSupport::BaseQtVersion *qtVersion) const;
|
||||||
Utils::FilePath makePathFromNdk(const Utils::FilePath &ndkLocation) const;
|
Utils::FilePath makePathFromNdk(const Utils::FilePath &ndkLocation) const;
|
||||||
|
|
||||||
@@ -188,6 +191,11 @@ public:
|
|||||||
bool sdkFullyConfigured() const { return m_sdkFullyConfigured; };
|
bool sdkFullyConfigured() const { return m_sdkFullyConfigured; };
|
||||||
void setSdkFullyConfigured(bool allEssentialsInstalled) { m_sdkFullyConfigured = allEssentialsInstalled; };
|
void setSdkFullyConfigured(bool allEssentialsInstalled) { m_sdkFullyConfigured = allEssentialsInstalled; };
|
||||||
|
|
||||||
|
bool isValidNdk(const QString &ndkLocation) const;
|
||||||
|
QStringList getCustomNdkList() const;
|
||||||
|
void addCustomNdk(const QString &customNdk);
|
||||||
|
void removeCustomNdk(const QString &customNdk);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static QString getDeviceProperty(const Utils::FilePath &adbToolPath,
|
static QString getDeviceProperty(const Utils::FilePath &adbToolPath,
|
||||||
const QString &device, const QString &property);
|
const QString &device, const QString &property);
|
||||||
@@ -216,6 +224,7 @@ private:
|
|||||||
QStringList m_commonEssentialPkgs;
|
QStringList m_commonEssentialPkgs;
|
||||||
SdkForQtVersions m_defaultSdkDepends;
|
SdkForQtVersions m_defaultSdkDepends;
|
||||||
QList<SdkForQtVersions> m_specificQtVersions;
|
QList<SdkForQtVersions> m_specificQtVersions;
|
||||||
|
QStringList m_customNdkList;
|
||||||
bool m_sdkFullyConfigured = false;
|
bool m_sdkFullyConfigured = false;
|
||||||
|
|
||||||
//caches
|
//caches
|
||||||
@@ -237,6 +246,7 @@ public:
|
|||||||
static QString defaultDevice(ProjectExplorer::Project *project, const QString &abi); // serial number or avd name
|
static QString defaultDevice(ProjectExplorer::Project *project, const QString &abi); // serial number or avd name
|
||||||
static void clearDefaultDevices(ProjectExplorer::Project *project);
|
static void clearDefaultDevices(ProjectExplorer::Project *project);
|
||||||
static void registerNewToolChains();
|
static void registerNewToolChains();
|
||||||
|
static void registerCustomToolChainsAndDebuggers();
|
||||||
static void removeUnusedDebuggers();
|
static void removeUnusedDebuggers();
|
||||||
static void removeOldToolChains();
|
static void removeOldToolChains();
|
||||||
static void updateAutomaticKitList();
|
static void updateAutomaticKitList();
|
||||||
|
@@ -133,6 +133,7 @@ private:
|
|||||||
bool sdkToolsOk() const;
|
bool sdkToolsOk() const;
|
||||||
Utils::FilePath getDefaultSdkPath();
|
Utils::FilePath getDefaultSdkPath();
|
||||||
void showEvent(QShowEvent *event) override;
|
void showEvent(QShowEvent *event) override;
|
||||||
|
void addCustomNdkItem();
|
||||||
|
|
||||||
Ui_AndroidSettingsWidget *m_ui;
|
Ui_AndroidSettingsWidget *m_ui;
|
||||||
AndroidSdkManagerWidget *m_sdkManagerWidget = nullptr;
|
AndroidSdkManagerWidget *m_sdkManagerWidget = nullptr;
|
||||||
@@ -352,6 +353,22 @@ void AndroidSettingsWidget::updateNdkList()
|
|||||||
m_ui->ndkListComboBox->clear();
|
m_ui->ndkListComboBox->clear();
|
||||||
for (const Ndk *ndk : m_sdkManager->installedNdkPackages())
|
for (const Ndk *ndk : m_sdkManager->installedNdkPackages())
|
||||||
m_ui->ndkListComboBox->addItem(ndk->installedLocation().toString());
|
m_ui->ndkListComboBox->addItem(ndk->installedLocation().toString());
|
||||||
|
|
||||||
|
for (const QString &ndk : m_androidConfig.getCustomNdkList()) {
|
||||||
|
if (m_androidConfig.isValidNdk(ndk))
|
||||||
|
m_ui->ndkListComboBox->addItem(ndk);
|
||||||
|
else
|
||||||
|
m_androidConfig.removeCustomNdk(ndk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidSettingsWidget::addCustomNdkItem()
|
||||||
|
{
|
||||||
|
const QString ndkPath = QDir::toNativeSeparators(m_ui->customNdkPathChooser->rawPath());
|
||||||
|
m_androidConfig.addCustomNdk(ndkPath);
|
||||||
|
if (m_ui->ndkListComboBox->findData(ndkPath) == -1)
|
||||||
|
m_ui->ndkListComboBox->addItem(ndkPath);
|
||||||
|
m_ui->ndkListComboBox->setCurrentText(ndkPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
AndroidSettingsWidget::AndroidSettingsWidget()
|
AndroidSettingsWidget::AndroidSettingsWidget()
|
||||||
@@ -435,8 +452,23 @@ AndroidSettingsWidget::AndroidSettingsWidget()
|
|||||||
|
|
||||||
connect(m_ui->SDKLocationPathChooser, &Utils::PathChooser::rawPathChanged,
|
connect(m_ui->SDKLocationPathChooser, &Utils::PathChooser::rawPathChanged,
|
||||||
this, &AndroidSettingsWidget::onSdkPathChanged);
|
this, &AndroidSettingsWidget::onSdkPathChanged);
|
||||||
connect(m_ui->ndkListComboBox, QOverload<const QString &>::of(&QComboBox::currentIndexChanged),
|
connect(m_ui->ndkListComboBox,
|
||||||
[this](const QString) { validateNdk(); });
|
QOverload<const QString &>::of(&QComboBox::currentIndexChanged),
|
||||||
|
[this](const QString &ndk) {
|
||||||
|
validateNdk();
|
||||||
|
m_ui->removeCustomNdkButton->setEnabled(m_androidConfig.getCustomNdkList().contains(ndk));
|
||||||
|
});
|
||||||
|
connect(m_ui->customNdkPathChooser, &Utils::PathChooser::rawPathChanged, this, [this]() {
|
||||||
|
const QString ndkPath = m_ui->customNdkPathChooser->rawPath();
|
||||||
|
m_ui->addCustomNdkButton->setEnabled(m_androidConfig.isValidNdk(ndkPath));
|
||||||
|
});
|
||||||
|
connect(m_ui->addCustomNdkButton, &QPushButton::clicked, this,
|
||||||
|
&AndroidSettingsWidget::addCustomNdkItem);
|
||||||
|
connect(m_ui->removeCustomNdkButton, &QPushButton::clicked, this, [this]() {
|
||||||
|
m_androidConfig.removeCustomNdk(m_ui->ndkListComboBox->currentText());
|
||||||
|
m_ui->ndkListComboBox->removeItem(m_ui->ndkListComboBox->currentIndex());
|
||||||
|
});
|
||||||
|
|
||||||
connect(&m_virtualDevicesWatcher, &QFutureWatcherBase::finished,
|
connect(&m_virtualDevicesWatcher, &QFutureWatcherBase::finished,
|
||||||
this, &AndroidSettingsWidget::updateAvds);
|
this, &AndroidSettingsWidget::updateAvds);
|
||||||
connect(m_ui->AVDRefreshPushButton, &QAbstractButton::clicked,
|
connect(m_ui->AVDRefreshPushButton, &QAbstractButton::clicked,
|
||||||
|
@@ -93,7 +93,7 @@
|
|||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="SDKLocationLabel">
|
<widget class="QLabel" name="SDKLocationLabel">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
@@ -106,21 +106,24 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="4">
|
|
||||||
<widget class="QToolButton" name="downloadSDKToolButton">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Download Android SDK</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="ndkComboBoxLabel">
|
<widget class="QLabel" name="customNdkLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Android NDK list:</string>
|
<string>Add custom NDK:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="3">
|
<item row="1" column="6">
|
||||||
|
<widget class="QToolButton" name="downloadNDKToolButton">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1" colspan="4">
|
||||||
|
<widget class="Utils::PathChooser" name="SDKLocationPathChooser" native="true"/>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="5">
|
||||||
<widget class="QToolButton" name="sdkToolsAutoDownloadButton">
|
<widget class="QToolButton" name="sdkToolsAutoDownloadButton">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Automatically download Android SDK Tools to selected location.</string>
|
<string>Automatically download Android SDK Tools to selected location.</string>
|
||||||
@@ -130,29 +133,74 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0" colspan="5">
|
<item row="3" column="0" colspan="7">
|
||||||
<widget class="Utils::DetailsWidget" name="androidDetailsWidget" native="true"/>
|
<widget class="Utils::DetailsWidget" name="androidDetailsWidget" native="true"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="4">
|
<item row="2" column="0">
|
||||||
<widget class="QToolButton" name="downloadNDKToolButton">
|
<widget class="QLabel" name="ndkComboBoxLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string>Android NDK list:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="2">
|
<item row="0" column="6">
|
||||||
<widget class="Utils::PathChooser" name="SDKLocationPathChooser" native="true">
|
<widget class="QToolButton" name="downloadSDKToolButton">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Download Android SDK</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1" colspan="3">
|
||||||
|
<widget class="Utils::PathChooser" name="customNdkPathChooser" native="true">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="4">
|
||||||
|
<widget class="QPushButton" name="addCustomNdkButton">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Add the selected custom NDK. The toolchains and debuggers will be created automatically.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Add</string>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="2">
|
<item row="2" column="1" colspan="3">
|
||||||
<widget class="QComboBox" name="ndkListComboBox"/>
|
<widget class="QComboBox" name="ndkListComboBox"/>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="2" column="4">
|
||||||
|
<widget class="QPushButton" name="removeCustomNdkButton">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Remove the selected custom NDK.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Remove</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -351,6 +399,10 @@
|
|||||||
<extends>QWidget</extends>
|
<extends>QWidget</extends>
|
||||||
<header location="global">utils/pathchooser.h</header>
|
<header location="global">utils/pathchooser.h</header>
|
||||||
<container>1</container>
|
<container>1</container>
|
||||||
|
<slots>
|
||||||
|
<signal>editingFinished()</signal>
|
||||||
|
<signal>browsingFinished()</signal>
|
||||||
|
</slots>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>Utils::DetailsWidget</class>
|
<class>Utils::DetailsWidget</class>
|
||||||
|
@@ -171,7 +171,7 @@ AndroidToolChainFactory::AndroidToolChainFactory()
|
|||||||
|
|
||||||
ToolChainList AndroidToolChainFactory::autoDetect(const ToolChainList &alreadyKnown)
|
ToolChainList AndroidToolChainFactory::autoDetect(const ToolChainList &alreadyKnown)
|
||||||
{
|
{
|
||||||
return autodetectToolChainsForNdk(alreadyKnown);
|
return autodetectToolChains(alreadyKnown);
|
||||||
}
|
}
|
||||||
|
|
||||||
static FilePath clangPlusPlusPath(const FilePath &clangPath)
|
static FilePath clangPlusPlusPath(const FilePath &clangPath)
|
||||||
@@ -181,7 +181,7 @@ static FilePath clangPlusPlusPath(const FilePath &clangPath)
|
|||||||
QFileInfo(clangPath.toString()).baseName() + "++"));
|
QFileInfo(clangPath.toString()).baseName() + "++"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static QList<QtSupport::BaseQtVersion *> androidQtVersionsWithUniqueNdk()
|
static QList<FilePath> uniqueNdksForCurrentQtVersions()
|
||||||
{
|
{
|
||||||
AndroidConfig config = AndroidConfigurations::currentConfig();
|
AndroidConfig config = AndroidConfigurations::currentConfig();
|
||||||
|
|
||||||
@@ -190,36 +190,40 @@ static QList<QtSupport::BaseQtVersion *> androidQtVersionsWithUniqueNdk()
|
|||||||
return v->targetDeviceTypes().contains(Android::Constants::ANDROID_DEVICE_TYPE);
|
return v->targetDeviceTypes().contains(Android::Constants::ANDROID_DEVICE_TYPE);
|
||||||
});
|
});
|
||||||
|
|
||||||
auto shouldRemove = [config](const QtSupport::BaseQtVersion *first,
|
QList<FilePath> uniqueNdks;
|
||||||
const QtSupport::BaseQtVersion *second) {
|
for (const QtSupport::BaseQtVersion *version : androidQtVersions) {
|
||||||
return config.ndkLocation(first) == config.ndkLocation(second);
|
FilePath ndk = config.ndkLocation(version);
|
||||||
};
|
if (!uniqueNdks.contains(ndk))
|
||||||
|
uniqueNdks.append(ndk);
|
||||||
|
}
|
||||||
|
|
||||||
QList<QtSupport::BaseQtVersion *>::iterator it = std::unique(androidQtVersions.begin(),
|
return uniqueNdks;
|
||||||
androidQtVersions.end(),
|
|
||||||
shouldRemove);
|
|
||||||
androidQtVersions.erase(it, androidQtVersions.end());
|
|
||||||
|
|
||||||
return androidQtVersions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ToolChainList AndroidToolChainFactory::autodetectToolChainsForNdk(const ToolChainList &alreadyKnown)
|
ToolChainList AndroidToolChainFactory::autodetectToolChains(const ToolChainList &alreadyKnown)
|
||||||
|
{
|
||||||
|
const QList<Utils::FilePath> uniqueNdks = uniqueNdksForCurrentQtVersions();
|
||||||
|
return autodetectToolChainsFromNdks(alreadyKnown, uniqueNdks);
|
||||||
|
}
|
||||||
|
|
||||||
|
ToolChainList AndroidToolChainFactory::autodetectToolChainsFromNdks(
|
||||||
|
const ToolChainList &alreadyKnown,
|
||||||
|
const QList<Utils::FilePath> &ndkLocations,
|
||||||
|
const bool isCustom)
|
||||||
{
|
{
|
||||||
QList<ToolChain *> result;
|
QList<ToolChain *> result;
|
||||||
const QList<QtSupport::BaseQtVersion *> androidQtVersions = androidQtVersionsWithUniqueNdk();
|
|
||||||
const AndroidConfig config = AndroidConfigurations::currentConfig();
|
const AndroidConfig config = AndroidConfigurations::currentConfig();
|
||||||
|
|
||||||
for (const QtSupport::BaseQtVersion *qtVersion : androidQtVersions) {
|
for (const Utils::FilePath &ndkLocation : ndkLocations) {
|
||||||
FilePath clangPath = config.clangPath(qtVersion);
|
qCDebug(androidTCLog) << "Detecting toolchains from Android NDK:" << ndkLocation;
|
||||||
|
|
||||||
|
FilePath clangPath = config.clangPathFromNdk(ndkLocation);
|
||||||
if (!clangPath.exists()) {
|
if (!clangPath.exists()) {
|
||||||
qCDebug(androidTCLog) << "Clang toolchains detection fails. Can not find Clang"
|
qCDebug(androidTCLog) << "Clang toolchains detection fails. Can not find Clang"
|
||||||
<< clangPath;
|
<< clangPath;
|
||||||
return result;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(androidTCLog) << "Detecting toolchains from Android NDK:"
|
|
||||||
<< config.ndkLocation(qtVersion);
|
|
||||||
|
|
||||||
for (const Core::Id &lang : LanguageIds) {
|
for (const Core::Id &lang : LanguageIds) {
|
||||||
FilePath compilerCommand = clangPath;
|
FilePath compilerCommand = clangPath;
|
||||||
if (lang == ProjectExplorer::Constants::CXX_LANGUAGE_ID)
|
if (lang == ProjectExplorer::Constants::CXX_LANGUAGE_ID)
|
||||||
@@ -237,10 +241,11 @@ ToolChainList AndroidToolChainFactory::autodetectToolChainsForNdk(const ToolChai
|
|||||||
const QString target = targetItr.key();
|
const QString target = targetItr.key();
|
||||||
ToolChain *tc = findToolChain(compilerCommand, lang, target, alreadyKnown);
|
ToolChain *tc = findToolChain(compilerCommand, lang, target, alreadyKnown);
|
||||||
|
|
||||||
const QString displayName(QString("Android Clang (%1, %2, NDK %3)")
|
QLatin1String customStr = isCustom ? QLatin1String("Custom ") : QLatin1String();
|
||||||
|
const QString displayName(customStr + QString("Android Clang (%1, %2, NDK %3)")
|
||||||
.arg(ToolChainManager::displayNameOfLanguageId(lang),
|
.arg(ToolChainManager::displayNameOfLanguageId(lang),
|
||||||
AndroidConfig::displayName(abi),
|
AndroidConfig::displayName(abi),
|
||||||
config.ndkVersion(qtVersion).toString()));
|
config.ndkVersion(ndkLocation).toString()));
|
||||||
if (tc) {
|
if (tc) {
|
||||||
qCDebug(androidTCLog) << "Tool chain already known" << abi.toString() << lang;
|
qCDebug(androidTCLog) << "Tool chain already known" << abi.toString() << lang;
|
||||||
// make sure to update the toolchain with current name format
|
// make sure to update the toolchain with current name format
|
||||||
@@ -249,7 +254,7 @@ ToolChainList AndroidToolChainFactory::autodetectToolChainsForNdk(const ToolChai
|
|||||||
} else {
|
} else {
|
||||||
qCDebug(androidTCLog) << "New Clang toolchain found" << abi.toString() << lang;
|
qCDebug(androidTCLog) << "New Clang toolchain found" << abi.toString() << lang;
|
||||||
auto atc = new AndroidToolChain();
|
auto atc = new AndroidToolChain();
|
||||||
atc->setNdkLocation(config.ndkLocation(qtVersion));
|
atc->setNdkLocation(ndkLocation);
|
||||||
atc->setOriginalTargetTriple(target);
|
atc->setOriginalTargetTriple(target);
|
||||||
atc->setLanguage(lang);
|
atc->setLanguage(lang);
|
||||||
atc->setTargetAbi(ClangTargets[target]);
|
atc->setTargetAbi(ClangTargets[target]);
|
||||||
|
@@ -78,7 +78,10 @@ public:
|
|||||||
QString version;
|
QString version;
|
||||||
};
|
};
|
||||||
|
|
||||||
static ToolChainList autodetectToolChainsForNdk(const ToolChainList &alreadyKnown);
|
static ToolChainList autodetectToolChains(const ToolChainList &alreadyKnown);
|
||||||
|
static ToolChainList autodetectToolChainsFromNdks(const ToolChainList &alreadyKnown,
|
||||||
|
const QList<Utils::FilePath> &ndkLocations,
|
||||||
|
const bool isCustom = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
Reference in New Issue
Block a user