From 6a6f3d2a53c1adb78b9f424f3998721d5b070349 Mon Sep 17 00:00:00 2001 From: "Guillermo A. Amaral" Date: Thu, 4 Apr 2013 01:29:47 -0700 Subject: [PATCH] Add support for 64-bit NDKs to Android Plugin. Currently the Android plugin only checks for the linux-x86 prebuilds in the 64-bit Android NDK (and mingw-and-ndk), this means Qt Creator goes bonkers because it can't find the toolchain and debugger for the kits it auto-detects/creates. A work around is to symlink linux-x86_64 to linux-x86 in every toolchain. Change-Id: I04522b65ef48b6090a9f6925e8e3420ad1d333ee Reviewed-by: Paul Olav Tvete Reviewed-by: Daniel Teske --- src/plugins/android/androidconfigurations.cpp | 39 ++++++++++++++++++- src/plugins/android/androidconfigurations.h | 18 ++------- src/plugins/android/androidqtversion.cpp | 7 +--- src/plugins/android/androidsettingswidget.cpp | 1 + src/plugins/android/androidtoolchain.cpp | 30 ++------------ 5 files changed, 46 insertions(+), 49 deletions(-) diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp index e1164e93bfe..9d17c5b7f61 100644 --- a/src/plugins/android/androidconfigurations.cpp +++ b/src/plugins/android/androidconfigurations.cpp @@ -81,6 +81,7 @@ namespace { const QLatin1String KeystoreLocationKey("KeystoreLocation"); const QLatin1String AutomaticKitCreationKey("AutomatiKitCreation"); const QLatin1String PartitionSizeKey("PartitionSize"); + const QLatin1String ToolchainHostKey("ToolchainHost"); const QLatin1String ArmToolchainPrefix("arm-linux-androideabi"); const QLatin1String X86ToolchainPrefix("x86"); const QLatin1String MipsToolchainPrefix("mipsel-linux-android"); @@ -152,6 +153,7 @@ AndroidConfig::AndroidConfig(const QSettings &settings) antLocation = FileName::fromString(settings.value(AntLocationKey).toString()); openJDKLocation = FileName::fromString(settings.value(OpenJDKLocationKey).toString()); keystoreLocation = FileName::fromString(settings.value(KeystoreLocationKey).toString()); + toolchainHost = settings.value(ToolchainHostKey).toString(); automaticKitCreation = settings.value(AutomaticKitCreationKey, true).toBool(); PersistentSettingsReader reader; @@ -163,6 +165,7 @@ AndroidConfig::AndroidConfig(const QSettings &settings) antLocation = FileName::fromString(reader.restoreValue(AntLocationKey).toString()); openJDKLocation = FileName::fromString(reader.restoreValue(OpenJDKLocationKey).toString()); keystoreLocation = FileName::fromString(reader.restoreValue(KeystoreLocationKey).toString()); + toolchainHost = reader.restoreValue(ToolchainHostKey).toString(); QVariant v = reader.restoreValue(AutomaticKitCreationKey); if (v.isValid()) automaticKitCreation = v.toBool(); @@ -190,11 +193,16 @@ void AndroidConfig::save(QSettings &settings) const settings.setValue(KeystoreLocationKey, keystoreLocation.toString()); settings.setValue(PartitionSizeKey, partitionSize); settings.setValue(AutomaticKitCreationKey, automaticKitCreation); + settings.setValue(ToolchainHostKey, toolchainHost); } void AndroidConfigurations::setConfig(const AndroidConfig &devConfigs) { m_config = devConfigs; + + if (m_config.toolchainHost.isEmpty()) + detectToolchainHost(); + save(); updateAvailablePlatforms(); updateAutomaticKitList(); @@ -277,7 +285,7 @@ FileName AndroidConfigurations::toolPath(Abi::Architecture architecture, const Q return path.appendPath(QString::fromLatin1("toolchains/%1-%2/prebuilt/%3/bin/%4") .arg(toolchainPrefix(architecture)) .arg(ndkToolChainVersion) - .arg(ToolchainHost) + .arg(m_config.toolchainHost) .arg(toolsPrefix(architecture))); } @@ -291,6 +299,11 @@ FileName AndroidConfigurations::readelfPath(Abi::Architecture architecture, cons return toolPath(architecture, ndkToolChainVersion).append(QLatin1String("-readelf" QTC_HOST_EXE_SUFFIX)); } +FileName AndroidConfigurations::gccPath(Abi::Architecture architecture, const QString &ndkToolChainVersion) const +{ + return toolPath(architecture, ndkToolChainVersion).append(QLatin1String("-gcc" QTC_HOST_EXE_SUFFIX)); +} + FileName AndroidConfigurations::gdbPath(Abi::Architecture architecture, const QString &ndkToolChainVersion) const { return toolPath(architecture, ndkToolChainVersion).append(QLatin1String("-gdb" QTC_HOST_EXE_SUFFIX)); @@ -301,6 +314,30 @@ FileName AndroidConfigurations::openJDKPath() const return m_config.openJDKLocation; } +void AndroidConfigurations::detectToolchainHost() +{ + QStringList hostPatterns; + switch (HostOsInfo::hostOs()) { + case HostOsInfo::HostOsLinux: + hostPatterns << QLatin1String("linux*"); + break; + case HostOsInfo::HostOsWindows: + hostPatterns << QLatin1String("windows*"); + break; + case HostOsInfo::HostOsMac: + hostPatterns << QLatin1String("darwin*"); + break; + default: /* unknown host */ return; + } + + FileName path = m_config.ndkLocation; + QDirIterator it(path.appendPath(QLatin1String("prebuilt")).toString(), hostPatterns, QDir::Dirs); + if (it.hasNext()) { + it.next(); + m_config.toolchainHost = it.fileName(); + } +} + FileName AndroidConfigurations::openJDKBinPath() const { FileName path = m_config.openJDKLocation; diff --git a/src/plugins/android/androidconfigurations.h b/src/plugins/android/androidconfigurations.h index 50dce7a3edf..edd607fba14 100644 --- a/src/plugins/android/androidconfigurations.h +++ b/src/plugins/android/androidconfigurations.h @@ -42,21 +42,6 @@ QT_END_NAMESPACE namespace Android { namespace Internal { -#ifdef Q_OS_LINUX - const QLatin1String ToolchainHost("linux-x86"); -#else -# ifdef Q_OS_DARWIN - const QLatin1String ToolchainHost("darwin-x86"); -# else -# ifdef Q_OS_WIN32 - const QLatin1String ToolchainHost("windows"); -# else -# warning No Android supported OSs found - const QLatin1String ToolchainHost("linux-x86"); -# endif -# endif -#endif - class AndroidConfig { public: @@ -69,6 +54,7 @@ public: Utils::FileName antLocation; Utils::FileName openJDKLocation; Utils::FileName keystoreLocation; + QString toolchainHost; unsigned partitionSize; bool automaticKitCreation; }; @@ -95,6 +81,7 @@ public: Utils::FileName androidToolPath() const; Utils::FileName antToolPath() const; Utils::FileName emulatorToolPath() const; + Utils::FileName gccPath(ProjectExplorer::Abi::Architecture architecture, const QString &ndkToolChainVersion) const; Utils::FileName gdbPath(ProjectExplorer::Abi::Architecture architecture, const QString &ndkToolChainVersion) const; Utils::FileName openJDKPath() const; Utils::FileName keytoolPath() const; @@ -124,6 +111,7 @@ public slots: private: Utils::FileName toolPath(ProjectExplorer::Abi::Architecture architecture, const QString &ndkToolChainVersion) const; Utils::FileName openJDKBinPath() const; + void detectToolchainHost(); AndroidConfigurations(QObject *parent); void load(); diff --git a/src/plugins/android/androidqtversion.cpp b/src/plugins/android/androidqtversion.cpp index 91f9e30c86a..e92bc0240f0 100644 --- a/src/plugins/android/androidqtversion.cpp +++ b/src/plugins/android/androidqtversion.cpp @@ -103,13 +103,8 @@ QList AndroidQtVersion::detectQtAbis() const void AndroidQtVersion::addToEnvironment(const ProjectExplorer::Kit *k, Utils::Environment &env) const { - QString ndk_host = QLatin1String( - Utils::HostOsInfo::isLinuxHost() ? "linux-x86" : - Utils::HostOsInfo::isWindowsHost() ? "windows" : - Utils::HostOsInfo::isMacHost() ? "darwin-x86" : ""); - // this env vars are used by qmake mkspecs to generate makefiles (check QTDIR/mkspecs/android-g++/qmake.conf for more info) - env.set(QLatin1String("ANDROID_NDK_HOST"), ndk_host); + env.set(QLatin1String("ANDROID_NDK_HOST"), AndroidConfigurations::instance().config().toolchainHost); env.set(QLatin1String("ANDROID_NDK_ROOT"), AndroidConfigurations::instance().config().ndkLocation.toUserOutput()); Qt4Project *qt4pro = qobject_cast(ProjectExplorerPlugin::instance()->currentProject()); diff --git a/src/plugins/android/androidsettingswidget.cpp b/src/plugins/android/androidsettingswidget.cpp index b41ad3225a1..8a0163df7d8 100644 --- a/src/plugins/android/androidsettingswidget.cpp +++ b/src/plugins/android/androidsettingswidget.cpp @@ -286,6 +286,7 @@ void AndroidSettingsWidget::sdkLocationEditingFinished() void AndroidSettingsWidget::ndkLocationEditingFinished() { Utils::FileName location = Utils::FileName::fromUserInput(m_ui->NDKLocationLineEdit->text()); + m_androidConfig.toolchainHost.clear(); // force toolchain host detection if (!checkNDK(location)) return; saveSettings(true); diff --git a/src/plugins/android/androidtoolchain.cpp b/src/plugins/android/androidtoolchain.cpp index 3b00796d19d..04ee7586409 100644 --- a/src/plugins/android/androidtoolchain.cpp +++ b/src/plugins/android/androidtoolchain.cpp @@ -111,21 +111,7 @@ void AndroidToolChain::addToEnvironment(Environment &env) const // TODO this vars should be configurable in projects -> build tab // TODO invalidate all .pro files !!! - QString ndkHost; - switch (HostOsInfo::hostOs()) { - case HostOsInfo::HostOsLinux: - ndkHost = QLatin1String("linux-x86"); - break; - case HostOsInfo::HostOsWindows: - ndkHost = QLatin1String("windows"); - break; - case HostOsInfo::HostOsMac: - ndkHost = QLatin1String("darwin-x86"); - break; - default: - break; - } - env.set(QLatin1String("ANDROID_NDK_HOST"), ndkHost); + env.set(QLatin1String("ANDROID_NDK_HOST"), AndroidConfigurations::instance().config().toolchainHost); env.set(QLatin1String("ANDROID_NDK_TOOLCHAIN_PREFIX"), AndroidConfigurations::toolchainPrefix(targetAbi().architecture())); env.set(QLatin1String("ANDROID_NDK_TOOLS_PREFIX"), AndroidConfigurations::toolsPrefix(targetAbi().architecture())); env.set(QLatin1String("ANDROID_NDK_TOOLCHAIN_VERSION"), m_ndkToolChainVersion); @@ -302,12 +288,7 @@ QList AndroidToolChainFact if (ati.architecture == Abi::UnknownArchitecture) // e.g. mipsel which is not yet supported continue; // AndroidToolChain *tc = new AndroidToolChain(arch, version, true); - ati.compilerCommand = ndkPath; - ati.compilerCommand.appendPath(QString::fromLatin1("toolchains/%1/prebuilt/%3/bin/%4") - .arg(fileName) - .arg(ToolchainHost) - .arg(AndroidConfigurations::toolsPrefix(ati.architecture))); - ati.compilerCommand.append(QLatin1String("-gcc" QTC_HOST_EXE_SUFFIX)); + ati.compilerCommand = AndroidConfigurations::instance().gccPath(ati.architecture, ati.version); // tc->setCompilerCommand(compilerPath); result.append(ati); } @@ -334,12 +315,7 @@ QList AndroidToolChainFactory::createToolChainsForNdk(const Utils:: if (arch == Abi::UnknownArchitecture) // e.g. mipsel which is not yet supported continue; AndroidToolChain *tc = new AndroidToolChain(arch, version, true); - FileName compilerPath = ndkPath; - compilerPath.appendPath(QString::fromLatin1("toolchains/%1/prebuilt/%3/bin/%4") - .arg(fileName) - .arg(ToolchainHost) - .arg(AndroidConfigurations::toolsPrefix(arch))); - compilerPath.append(QLatin1String("-gcc" QTC_HOST_EXE_SUFFIX)); + FileName compilerPath = AndroidConfigurations::instance().gccPath(arch, version); tc->setCompilerCommand(compilerPath); result.append(tc); }