diff options
| author | Jake Petroules <jake.petroules@petroules.com> | 2015-07-14 22:10:33 -0700 |
|---|---|---|
| committer | Jake Petroules <jake.petroules@petroules.com> | 2015-07-22 13:23:36 +0000 |
| commit | a3cb59b277698ba92cdfde0ccc215e93b96ae92f (patch) | |
| tree | a58afa3f52ade66657afeab4092d11d2011c7a15 | |
| parent | 47f9b7c85a3e8033d618af73d18317fa68fcbc55 (diff) | |
| download | qbs-a3cb59b277698ba92cdfde0ccc215e93b96ae92f.tar.gz | |
Move more Android NDK logic out of the profiles.
Change-Id: Ie7c61fde802921b48d588b2760f798431fab81bf
Reviewed-by: Christian Kandeler <christian.kandeler@theqtcompany.com>
| -rw-r--r-- | doc/reference/modules/android-ndk-module.qdoc | 9 | ||||
| -rw-r--r-- | share/qbs/imports/qbs/Probes/AndroidNdkProbe.qbs | 65 | ||||
| -rw-r--r-- | share/qbs/imports/qbs/Probes/AndroidSdkProbe.qbs | 54 | ||||
| -rw-r--r-- | share/qbs/imports/qbs/base/Application.qbs | 2 | ||||
| -rw-r--r-- | share/qbs/imports/qbs/base/Library.qbs | 2 | ||||
| -rw-r--r-- | share/qbs/modules/Android/ndk/ndk.qbs | 79 | ||||
| -rw-r--r-- | share/qbs/modules/Android/ndk/utils.js | 106 | ||||
| -rw-r--r-- | share/qbs/modules/Android/sdk/sdk.qbs | 18 | ||||
| -rw-r--r-- | src/app/qbs-setup-android/android-setup.cpp | 338 | ||||
| -rw-r--r-- | tests/auto/blackbox/testdata/android/multiple-apks-per-project/product1/product1.qbs | 2 | ||||
| -rw-r--r-- | tests/auto/blackbox/testdata/android/teapot/teapot.qbs | 2 |
11 files changed, 321 insertions, 356 deletions
diff --git a/doc/reference/modules/android-ndk-module.qdoc b/doc/reference/modules/android-ndk-module.qdoc index 54187f86a..4d34c9ed9 100644 --- a/doc/reference/modules/android-ndk-module.qdoc +++ b/doc/reference/modules/android-ndk-module.qdoc @@ -81,6 +81,7 @@ \li 1.4 \li undefined \li The ABI name as it appears under "lib/" in the application package. + Corresponds to APP_ABI in Android.mk. \row \li appStl \li string @@ -90,11 +91,11 @@ "gabi++_shared", "stlport_static", "stlport_shared", "gnustl_static", "gnustl_shared", "c++_static", "c++_shared". \row - \li buildProfile - \li string - \li 1.4 + \li hardFloat + \li bool + \li 1.4.2 \li undefined - \li The name of the build profile, e.g. "armeabi-v7a-hard". + \li Whether to use the hard floating point variant of the armeabi-v7a ABI. \row \li enableExceptions \li bool diff --git a/share/qbs/imports/qbs/Probes/AndroidNdkProbe.qbs b/share/qbs/imports/qbs/Probes/AndroidNdkProbe.qbs new file mode 100644 index 000000000..29e954891 --- /dev/null +++ b/share/qbs/imports/qbs/Probes/AndroidNdkProbe.qbs @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Jake Petroules. +** Contact: http://www.qt.io/licensing +** +** This file is part of the Qt Build Suite. +** +** 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 +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +import qbs +import qbs.File +import qbs.FileInfo + +PathProbe { + // Inputs + property stringList hostOS: qbs.hostOS + + environmentPaths: qbs.getEnv("ANDROID_NDK_ROOT") + + // Outputs + property var hostArch + + configure: { + var i, j; + for (i in environmentPaths) { + var platforms = []; + if (hostOS.contains("windows")) + platforms.push("windows-x86_64", "windows"); + if (hostOS.contains("darwin")) + platforms.push("darwin-x86_64", "darwin-x86"); + if (hostOS.contains("linux")) + platforms.push("linux-x86_64", "linux-x86"); + for (j in platforms) { + if (File.exists(FileInfo.joinPaths(environmentPaths[i], "prebuilt", + platforms[j]))) { + path = environmentPaths[i]; + hostArch = platforms[j]; + found = true; + return; + } + } + } + } +} diff --git a/share/qbs/imports/qbs/Probes/AndroidSdkProbe.qbs b/share/qbs/imports/qbs/Probes/AndroidSdkProbe.qbs new file mode 100644 index 000000000..cd796a6f8 --- /dev/null +++ b/share/qbs/imports/qbs/Probes/AndroidSdkProbe.qbs @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Jake Petroules. +** Contact: http://www.qt.io/licensing +** +** This file is part of the Qt Build Suite. +** +** 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 +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +import qbs +import qbs.File +import qbs.FileInfo + +PathProbe { + environmentPaths: qbs.getEnv("ANDROID_HOME") + + // Outputs + property string buildToolsVersion + property string platform + + configure: { + var i; + for (i in environmentPaths) { + if (File.exists(FileInfo.joinPaths(environmentPaths[i], "tools", "android"))) { + path = environmentPaths[i]; + buildToolsVersion = undefined; // not yet implemented + platform = undefined; // not yet implemented + found = true; + return; + } + } + } +} diff --git a/share/qbs/imports/qbs/base/Application.qbs b/share/qbs/imports/qbs/base/Application.qbs index 92023b8ed..d998b1305 100644 --- a/share/qbs/imports/qbs/base/Application.qbs +++ b/share/qbs/imports/qbs/base/Application.qbs @@ -36,7 +36,7 @@ Product { } property bool isForAndroid: qbs.targetOS.contains("android") - property stringList architectures: isForAndroid ? ["armeabi"] : undefined + property stringList architectures: isForAndroid ? ["armv5"] : undefined Depends { name: "Android.ndk"; condition: isForAndroid } Depends { name: "bundle" } diff --git a/share/qbs/imports/qbs/base/Library.qbs b/share/qbs/imports/qbs/base/Library.qbs index fef974530..fb392a4e1 100644 --- a/share/qbs/imports/qbs/base/Library.qbs +++ b/share/qbs/imports/qbs/base/Library.qbs @@ -36,7 +36,7 @@ Product { } property bool isForAndroid: qbs.targetOS.contains("android") - property stringList architectures: isForAndroid ? ["armeabi"] : undefined + property stringList architectures: isForAndroid ? ["armv5"] : undefined Depends { name: "Android.ndk"; condition: isForAndroid } Depends { name: "bundle" } diff --git a/share/qbs/modules/Android/ndk/ndk.qbs b/share/qbs/modules/Android/ndk/ndk.qbs index 78c13e0b5..e8cf26ae3 100644 --- a/share/qbs/modules/Android/ndk/ndk.qbs +++ b/share/qbs/modules/Android/ndk/ndk.qbs @@ -32,6 +32,7 @@ import qbs import qbs.File import qbs.FileInfo import qbs.ModUtils +import qbs.Probes import qbs.TextFile import "utils.js" as NdkUtils @@ -39,7 +40,17 @@ import "utils.js" as NdkUtils Module { Depends { name: "cpp" } - property string abi // Corresponds to the subdir under "lib/" in the apk file. + Probes.AndroidNdkProbe { + id: ndkProbe + environmentPaths: [ndkDir].concat(base) + } + + readonly property string abi: NdkUtils.androidAbi(qbs.architecture) + PropertyOptions { + name: "abi" + description: "Corresponds to the 'APP_ABI' variable in an Android.mk file." + allowedValues: ["arm64-v8a", "armeabi", "armeabi-v7a", "mips", "mips64", "x86", "x86_64"] + } property string appStl: "system" PropertyOptions { @@ -57,19 +68,35 @@ Module { description: "Corresponds to the 'NDK_TOOLCHAIN_VERSION' variable in an Android.mk file." } - property string hostArch // E.g. darwin-x86_64 - property string toolchainDirPrefix // E.g. arm-linux-androideabi- - property string buildProfile // E.g. "armeabi-v7a-hard" + property string hostArch: ndkProbe.hostArch + property string toolchainDirPrefix: NdkUtils.toolchainDirPrefix(qbs.toolchain, abi) property bool enableExceptions: appStl !== "system" property bool enableRtti: appStl !== "system" - property string ndkDir + property bool hardFloat + property string ndkDir: ndkProbe.path property string platform: "android-9" // Internal properties. - property stringList compilerFlagsDebug: [] - property stringList compilerFlagsRelease: [] + property int platformVersion: { + if (platform) { + var match = platform.match(/^android-([0-9]+)$/); + if (match !== null) { + return parseInt(match[1], 10); + } + } + } + + property stringList abis: { + var list = ["armeabi", "armeabi-v7a"]; + if (platformVersion >= 9) + list.push("mips", "x86"); + if (platformVersion >= 21) + list.push("arm64-v8a", "mips64", "x86_64"); + return list; + } + property stringList defines: ["ANDROID"] - property bool hardFp + property string buildProfile: (abi === "armeabi-v7a" && hardFloat) ? (abi + "-hard") : abi property string cxxStlBaseDir: FileInfo.joinPaths(ndkDir, "sources/cxx-stl") property string gabiBaseDir: FileInfo.joinPaths(cxxStlBaseDir, "gabi++") property string stlPortBaseDir: FileInfo.joinPaths(cxxStlBaseDir, "stlport") @@ -116,17 +143,28 @@ Module { } cpp.toolchainInstallPath: FileInfo.joinPaths(ndkDir, "toolchains", - toolchainDirPrefix + toolchainVersion, + toolchainDirPrefix + + NdkUtils.toolchainVersionNumber(toolchainVersion), "prebuilt", hostArch, "bin") - cpp.commonCompilerFlags: { - var flags = qbs.buildVariant === "debug" - ? compilerFlagsDebug : compilerFlagsRelease; - if (armMode) - flags.push("-m" + armMode); - return flags; + cpp.toolchainPrefix: NdkUtils.toolchainPrefix(qbs.toolchain, abi) + + qbs.toolchain: { + var tc = []; + if (toolchainVersion && toolchainVersion.startsWith("clang")) + tc.push("clang"); + return tc.concat(["gcc"]); } + qbs.optimization: ["armeabi", "armeabi-v7a"].contains(abi) ? "small" : base + + cpp.compilerName: qbs.toolchain.contains("clang") ? "clang++" : "g++" + cpp.linkerName: qbs.toolchain.contains("clang") ? "clang++" : "g++" + + cpp.commonCompilerFlags: NdkUtils.commonCompilerFlags(qbs.buildVariant, abi, hardFloat, armMode) + + cpp.linkerFlags: NdkUtils.commonLinkerFlags(abi, hardFloat) + cpp.cxxFlags: { var flags = []; if (enableExceptions) @@ -143,7 +181,7 @@ Module { cpp.libraryPaths: { var prefix = FileInfo.joinPaths(cpp.sysroot, "usr"); var paths = []; - if (buildProfile === "mips64" || buildProfile === "x86_64") // no lib64 for arm64-v8a + if (abi === "mips64" || abi === "x86_64") // no lib64 for arm64-v8a paths.push(FileInfo.joinPaths(prefix, "lib64")); paths.push(FileInfo.joinPaths(prefix, "lib")); return paths; @@ -151,7 +189,7 @@ Module { cpp.dynamicLibraries: { var libs = ["c"]; - if (!hardFp) + if (!hardFloat) libs.push("m"); if (sharedStlFilePath) libs.push(sharedStlFilePath); @@ -159,7 +197,7 @@ Module { } cpp.staticLibraries: { var libs = ["gcc"]; - if (hardFp) + if (hardFloat) libs.push("m_hard"); if (staticStlFilePath) libs.push(staticStlFilePath); @@ -185,7 +223,7 @@ Module { } cpp.defines: { var list = defines; - if (hardFp) + if (hardFloat) list.push("_NDK_MATH_NO_SOFTFP=1"); return list; } @@ -245,11 +283,10 @@ Module { infoFile.close(); } } - var stripBinary = product.moduleProperty("cpp", "toolchainPathPrefix") + "strip"; var stripArgs = ["--strip-unneeded", outputs["android.nativelibrary"][0].filePath]; if (stlFilePath) stripArgs.push(stlFilePath); - var stripCmd = new Command(stripBinary, stripArgs); + var stripCmd = new Command(product.moduleProperty("cpp", "stripPath"), stripArgs); stripCmd.description = "Stripping unneeded symbols from " + outputs["android.nativelibrary"][0].fileName; return [copyCmd, stripCmd]; diff --git a/share/qbs/modules/Android/ndk/utils.js b/share/qbs/modules/Android/ndk/utils.js index 9e81b82ff..a293b1ae0 100644 --- a/share/qbs/modules/Android/ndk/utils.js +++ b/share/qbs/modules/Android/ndk/utils.js @@ -28,11 +28,113 @@ ** ****************************************************************************/ -function abiNameToDirName(abiName) -{ +function abiNameToDirName(abiName) { if (abiName.startsWith("armeabi")) return "arm"; if (abiName.startsWith("arm64")) return "arm64"; return abiName; } + +function androidAbi(arch) { + if (arch === "x86" || arch === "x86_64") + return arch; + return { + "arm64": "arm64-v8a", + "armv5": "armeabi", + "armv7": "armeabi-v7a", + "mipsel": "mips", + "mips64el": "mips64" + }[arch]; +} + +function toolchainVersionNumber(version) { + var prefix = "clang"; + if (version && version.startsWith(prefix)) + return version.substr(prefix.length); + return version; +} + +function toolchainDirPrefix(toolchain, abi) { + if (toolchain && toolchain.contains("clang")) + return "llvm-"; + if (["x86", "x86_64"].contains(abi)) + return abi + "-"; + return toolchainPrefix(toolchain, abi); +} + +function toolchainPrefix(toolchain, abi) { + if (toolchain && toolchain.contains("clang")) + return undefined; + return { + "arm64-v8a": "aarch64-linux-android-", + "armeabi": "arm-linux-androideabi-", + "armeabi-v7a": "arm-linux-androideabi-", // same prefix as above + "mips": "mipsel-linux-android-", + "mips64": "mips64el-linux-android-", + "x86": "i686-linux-android-", + "x86_64": "x86_64-linux-android-" + }[abi]; +} + +function commonCompilerFlags(buildVariant, abi, hardFloat, armMode) { + var flags = ["-ffunction-sections", "-funwind-tables", "-no-canonical-prefixes", + "-Wa,--noexecstack", "-Werror=format-security"]; + + if (buildVariant === "debug") + flags.push("-fno-omit-frame-pointer", "-fno-strict-aliasing"); + if (buildVariant === "release") + flags.push("-fomit-frame-pointer"); + + if (abi === "arm64-v8a") { + flags.push("-fpic", "-fstack-protector", "-funswitch-loops", "-finline-limit=300"); + if (buildVariant === "release") + flags.push("-fstrict-aliasing"); + } + + if (abi === "armeabi" || abi === "armeabi-v7a") { + flags.push("-fpic", "-fstack-protector", "-finline-limit=64"); + + if (abi === "armeabi") + flags.push("-march=armv5te", "-mtune=xscale", "-msoft-float"); + + if (abi === "armeabi-v7a") { + flags.push("-march=armv7-a", "-mfpu=vfpv3-d16"); + flags.push(hardFloat ? "-mhard-float" : "-mfloat-abi=softfp"); + } + + if (buildVariant === "release") + flags.push("-fno-strict-aliasing"); + } + + if (abi === "mips" || abi === "mips64") { + flags.push("-fpic", "-finline-functions", "-fmessage-length=0", + "-fno-inline-functions-called-once", "-fgcse-after-reload", + "-frerun-cse-after-loop", "-frename-registers"); + if (buildVariant === "release") + flags.push("-funswitch-loops", "-finline-limit=300", "-fno-strict-aliasing"); + } + + if (abi === "x86" || abi === "x86_64") { + flags.push("-fstack-protector", "-funswitch-loops", "-finline-limit=300"); + if (buildVariant === "release") + flags.push("-fstrict-aliasing"); + } + + if (armMode) + flags.push("-m" + armMode); + + return flags; +} + +function commonLinkerFlags(abi, hardFloat) { + var flags = ["-no-canonical-prefixes", "-Wl,-z,noexecstack", "-Wl,-z,relro", "-Wl,-z,now"]; + + if (abi === "armeabi-v7a") { + flags.push("-march=armv7-a", "-Wl,--fix-cortex-a8"); + if (hardFloat) + flags.push("-Wl,-no-warn-mismatch"); + } + + return flags; +} diff --git a/share/qbs/modules/Android/sdk/sdk.qbs b/share/qbs/modules/Android/sdk/sdk.qbs index 4c1c4fd64..863e566f6 100644 --- a/share/qbs/modules/Android/sdk/sdk.qbs +++ b/share/qbs/modules/Android/sdk/sdk.qbs @@ -37,14 +37,24 @@ import qbs.TextFile import "utils.js" as SdkUtils Module { - property path sdkDir - property path ndkDir - property string buildToolsVersion + Probes.AndroidSdkProbe { + id: sdkProbe + environmentPaths: [sdkDir].concat(base) + } + + Probes.AndroidNdkProbe { + id: ndkProbe + environmentPaths: [ndkDir].concat(base) + } + + property path sdkDir: sdkProbe.path + property path ndkDir: ndkProbe.path + property string buildToolsVersion: sdkProbe.buildToolsVersion property var buildToolsVersionParts: buildToolsVersion ? buildToolsVersion.split('.').map(function(item) { return parseInt(item, 10); }) : [] property int buildToolsVersionMajor: buildToolsVersionParts[0] property int buildToolsVersionMinor: buildToolsVersionParts[1] property int buildToolsVersionPatch: buildToolsVersionParts[2] - property string platform + property string platform: sdkProbe.platform // Internal properties. property int platformVersion: { diff --git a/src/app/qbs-setup-android/android-setup.cpp b/src/app/qbs-setup-android/android-setup.cpp index 9eb7927bb..60b6d4aaa 100644 --- a/src/app/qbs-setup-android/android-setup.cpp +++ b/src/app/qbs-setup-android/android-setup.cpp @@ -111,288 +111,22 @@ static QString detectPlatform(const QString &sdkDir) return newestPlatform; } -// Independent of architecture, build variant and language. -static QStringList commonCompilerFlags() +static QStringList expectedArchs() { - return QStringList() << qls("-ffunction-sections") << qls("-funwind-tables") - << qls("-no-canonical-prefixes") << qls("-Wa,--noexecstack") - << qls("-Werror=format-security"); + return QStringList({ + QStringLiteral("arm64"), + QStringLiteral("armv5"), + QStringLiteral("armv7"), + QStringLiteral("mipsel"), + QStringLiteral("mips64el"), + QStringLiteral("x86"), + QStringLiteral("x86_64")}); } -// Independent of architecture and language -static QStringList commonCompilerFlagsDebug() -{ - return commonCompilerFlags() << qls("-fno-omit-frame-pointer") << qls("-fno-strict-aliasing") - << qls("-O0"); -} - -// Independent of architecture and language -static QStringList commonCompilerFlagsRelease() -{ - return commonCompilerFlags() << qls("-fomit-frame-pointer"); -} - -static QStringList arm64FlagsDebug() -{ - return commonCompilerFlagsDebug() << qls("-fpic") << qls("-fstack-protector") - << qls("-funswitch-loops") << qls("-finline-limit=300"); -} - -static QStringList arm64FlagsRelease() -{ - return commonCompilerFlagsRelease() << qls("-fpic") << qls("-fstack-protector") << qls("-O2") - << qls("-fstrict-aliasing") << qls("-funswitch-loops") << qls("-finline-limit=300"); -} - -static QStringList armeabiFlagsDebug() -{ - return commonCompilerFlagsDebug() << qls("-fpic") << qls("-fstack-protector") - << qls("-march=armv5te") << qls("-mtune=xscale") << qls("-msoft-float") - << qls("-finline-limit=64"); -} - -static QStringList armeabiFlagsRelease() -{ - return commonCompilerFlagsRelease() << qls("-fpic") << qls("-fstack-protector") - << qls("-march=armv5te") << qls("-mtune=xscale") << qls("-msoft-float") << qls("-Os") - << qls("-fno-strict-aliasing") << qls("-finline-limit=64"); -} - -static QStringList armeabiV7aFlagsDebug() -{ - return commonCompilerFlagsDebug() << qls("-fpic") << qls("-fstack-protector") - << qls("-march=armv7-a") << qls("-mfpu=vfpv3-d16") << qls("-mfloat-abi=softfp") - << qls("-finline-limit=64"); -} - -static QStringList armeabiV7aFlagsRelease() -{ - return commonCompilerFlagsRelease() << qls("-fpic") << qls("-fstack-protector") - << qls("-march=armv7-a") << qls("-mfpu=vfpv3-d16") << qls("-mfloat-abi=softfp") - << qls("-Os") << qls("-fno-strict-aliasing") << qls("-finline-limit=64"); -} -static QStringList armeabiV7aHardFlagsDebug() +static QString subProfileName(const QString &mainProfileName, const QString &arch) { - return commonCompilerFlagsDebug() << qls("-fpic") << qls("-fstack-protector") - << qls("-march=armv7-a") << qls("-mfpu=vfpv3-d16") << qls("-mhard-float") - << qls("-finline-limit=64"); -} - -static QStringList armeabiV7aHardFlagsRelease() -{ - return commonCompilerFlagsRelease() << qls("-fpic") << qls("-fstack-protector") - << qls("-march=armv7-a") << qls("-mfpu=vfpv3-d16") << qls("-mhard-float") << qls("-Os") - << qls("-fno-strict-aliasing") << qls("-finline-limit=64"); -} - -static QStringList mipsFlagsDebug() -{ - return commonCompilerFlagsDebug() << qls("-fpic") << qls("-finline-functions") - << qls("-fmessage-length=0") << qls("-fno-inline-functions-called-once") - << qls("-fgcse-after-reload") << qls("-frerun-cse-after-loop") - << qls("-frename-registers"); -} - -static QStringList mipsFlagsRelease() -{ - return commonCompilerFlagsRelease() << qls("-fpic") << qls("-fno-strict-aliasing") - << qls("-finline-functions") << qls("-fmessage-length=0") - << qls("-fno-inline-functions-called-once") << qls("-fgcse-after-reload") - << qls("-frerun-cse-after-loop") << qls("-frename-registers") << qls("-O2") - << qls("-funswitch-loops") << qls("-finline-limit=300"); -} - -static QStringList x86FlagsDebug() -{ - return commonCompilerFlagsDebug() << qls("-fstack-protector") << qls("-funswitch-loops") - << qls("-finline-limit=300"); -} - -static QStringList x86FlagsRelease() -{ - return commonCompilerFlagsRelease() << qls("-fstack-protector") << qls("-O2") - << qls("-fstrict-aliasing") << qls("-funswitch-loops") << qls("-finline-limit=300"); -} - -static QStringList commonLinkerFlags() -{ - return QStringList() << qls("-no-canonical-prefixes") << qls("-Wl,-z,noexecstack") - << qls("-Wl,-z,relro") << qls("-Wl,-z,now"); -} - -static QStringList armeabiV7aLinkerFlags() -{ - return commonLinkerFlags() << qls("-march=armv7-a") << qls("-Wl,--fix-cortex-a8"); -} - -static QStringList armeabiV7aHardLinkerFlags() -{ - return armeabiV7aLinkerFlags() << qls("-Wl,-no-warn-mismatch"); -} - -class BuildProfile { -public: - BuildProfile() : linkerFlags(commonLinkerFlags()), hardFp(false) {} - - QString profileSuffix; - QString abi; - QString qbsArchName; - QString toolchainDirPrefix; - QString toolchainPrefix; - QStringList compilerFlagsDebug; - QStringList compilerFlagsRelease; - QStringList linkerFlags; - bool hardFp; -}; - -uint qHash(const BuildProfile &arch) { return qHash(arch.profileSuffix); } -bool operator==(const BuildProfile &a1, const BuildProfile &a2) { - return a1.profileSuffix == a2.profileSuffix; -} -typedef QHash<QString, BuildProfile> BuildProfileMap; - -// As of r10c. Let's hope they don't change it gratuitously. -static BuildProfileMap createArchMap() -{ - BuildProfileMap map; - - BuildProfile aarch64; - aarch64.abi = qls("arm64-v8a"); - aarch64.profileSuffix = aarch64.abi; - aarch64.qbsArchName = qls("arm64"); - aarch64.toolchainDirPrefix = qls("aarch64-linux-android-"); - aarch64.toolchainPrefix = qls("aarch64-linux-android-"); - aarch64.compilerFlagsDebug = arm64FlagsDebug(); - aarch64.compilerFlagsRelease = arm64FlagsRelease(); - map.insert(aarch64.profileSuffix, aarch64); - - BuildProfile armeabi; - armeabi.abi = qls("armeabi"); - armeabi.profileSuffix = armeabi.abi; - armeabi.qbsArchName = qls("arm"); - armeabi.toolchainDirPrefix = qls("arm-linux-androideabi-"); - armeabi.toolchainPrefix = qls("arm-linux-androideabi-"); - armeabi.compilerFlagsDebug = armeabiFlagsDebug(); - armeabi.compilerFlagsRelease = armeabiFlagsRelease(); - map.insert(armeabi.profileSuffix, armeabi); - - BuildProfile armeabiV7a = armeabi; - armeabiV7a.abi = qls("armeabi-v7a"); - armeabiV7a.profileSuffix = armeabiV7a.abi; - armeabiV7a.compilerFlagsDebug = armeabiV7aFlagsDebug(); - armeabiV7a.compilerFlagsRelease = armeabiV7aFlagsRelease(); - armeabiV7a.linkerFlags = armeabiV7aLinkerFlags(); - map.insert(armeabiV7a.profileSuffix, armeabiV7a); - - BuildProfile armeabiV7aHard = armeabiV7a; - armeabiV7aHard.profileSuffix = qls("armeabi-v7a-hard"); // Same abi as above. - armeabiV7aHard.compilerFlagsDebug = armeabiV7aHardFlagsDebug(); - armeabiV7aHard.compilerFlagsRelease = armeabiV7aHardFlagsRelease(); - armeabiV7aHard.linkerFlags = armeabiV7aHardLinkerFlags(); - armeabiV7aHard.hardFp = true; - map.insert(armeabiV7aHard.profileSuffix, armeabiV7aHard); - - BuildProfile mips; - mips.abi = qls("mips"); - mips.profileSuffix = mips.abi; - mips.qbsArchName = qls("mipsel"); - mips.toolchainDirPrefix = qls("mipsel-linux-android-"); - mips.toolchainPrefix = qls("mipsel-linux-android-"); - mips.compilerFlagsDebug = mipsFlagsDebug(); - mips.compilerFlagsRelease = mipsFlagsRelease(); - map.insert(mips.profileSuffix, mips); - - BuildProfile mips64; - mips64.abi = qls("mips64"); - mips64.profileSuffix = mips64.abi; - mips64.qbsArchName = qls("mips64el"); - mips64.toolchainDirPrefix = qls("mips64el-linux-android-"); - mips64.toolchainPrefix = qls("mips64el-linux-android-"); - mips64.compilerFlagsDebug = mipsFlagsDebug(); - mips64.compilerFlagsRelease = mipsFlagsRelease(); - map.insert(mips64.profileSuffix, mips64); - - BuildProfile x86; - x86.abi = qls("x86"); - x86.profileSuffix = x86.abi; - x86.qbsArchName = x86.abi; - x86.toolchainDirPrefix = qls("x86-"); - x86.toolchainPrefix = qls("i686-linux-android-"); - x86.compilerFlagsDebug = x86FlagsDebug(); - x86.compilerFlagsRelease = x86FlagsRelease(); - map.insert(x86.profileSuffix, x86); - - BuildProfile x86_64; - x86_64.abi = qls("x86_64"); - x86_64.profileSuffix = x86_64.abi; - x86_64.qbsArchName = x86_64.abi; - x86_64.toolchainDirPrefix = qls("x86_64-"); - x86_64.toolchainPrefix = qls("x86_64-linux-android-"); - x86_64.compilerFlagsDebug = x86FlagsDebug(); - x86_64.compilerFlagsRelease = x86FlagsRelease(); - map.insert(x86_64.profileSuffix, x86_64); - - return map; -} - - -static QString subProfileName(const QString &mainProfileName, const BuildProfile &arch) -{ - return mainProfileName + QLatin1Char('_') + arch.profileSuffix; -} - -static QString detectToolchainHostArch(const QString &ndkDirPath) -{ - QStringList candidates; - if (Internal::HostOsInfo::isWindowsHost()) { -#ifdef Q_PROCESSOR_X86_64 - candidates << qls("windows-x86_64"); -#endif -#ifdef Q_PROCESSOR_X86 - candidates << qls("windows"); // no -x86 suffix for Windows 32-bit -#endif - } - if (Internal::HostOsInfo::isOsxHost()) { -#ifdef Q_PROCESSOR_X86_64 - candidates << qls("darwin-x86_64"); -#endif -#ifdef Q_PROCESSOR_X86 - candidates << qls("darwin-x86"); -#endif - } - if (Internal::HostOsInfo::isLinuxHost()) { -#ifdef Q_PROCESSOR_X86_64 - candidates << qls("linux-x86_64"); -#endif -#ifdef Q_PROCESSOR_X86 - candidates << qls("linux-x86"); -#endif - } - - if (candidates.isEmpty()) { - throw ErrorInfo(Tr::tr("Unsupported host platform for Android NDK.")); - } - - QStringList checkedPaths; - QString hostArch; - Q_FOREACH (const QString &candidate, candidates) { - const QDir tcDir(ndkDirPath + qls("/prebuilt/") + candidate); - if (QDir(tcDir).exists() && hostArch.isEmpty()) { - hostArch = candidate; - } - - checkedPaths << qls("'") - + QDir::toNativeSeparators(QDir::cleanPath(tcDir.absolutePath())) - + qls("'"); - } - - if (hostArch.isEmpty()) { - throw ErrorInfo(Tr::tr("None of the following paths are present:\n%1") - .arg(checkedPaths.join(qls("\n")))); - } - - return hostArch; + return mainProfileName + QLatin1Char('_') + arch; } void setupSdk(qbs::Settings *settings, const QString &profileName, const QString &sdkDirPath) @@ -403,6 +137,7 @@ void setupSdk(qbs::Settings *settings, const QString &profileName, const QString } Profile profile(profileName, settings); + profile.removeProfile(); profile.setValue(qls("Android.sdk.sdkDir"), QDir::cleanPath(sdkDirPath)); profile.setValue(qls("Android.sdk.buildToolsVersion"), detectBuildToolsVersion(sdkDirPath)); @@ -420,54 +155,15 @@ void setupNdk(qbs::Settings *settings, const QString &profileName, const QString throw ErrorInfo(Tr::tr("NDK directory '%1' does not exist.") .arg(QDir::toNativeSeparators(ndkDirPath))); } - QDir stlLibsDir(ndkDirPath + qls("/sources/cxx-stl/stlport/libs")); - if (!stlLibsDir.exists()) { - throw ErrorInfo(Tr::tr("Expected directory '%1' to be present, but it is not.") - .arg(QDir::toNativeSeparators(stlLibsDir.path()))); - } - const QStringList archList = stlLibsDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); - if (archList.isEmpty()) { - throw ErrorInfo(Tr::tr("Failed to detect the architectures supported by the NDK, because " - "directory '%1' is empty.").arg(QDir::toNativeSeparators(stlLibsDir.path()))); - } - - const BuildProfileMap archMap = createArchMap(); - QList<BuildProfile> architectures; - foreach (const QString &archName, archList) { - const BuildProfileMap::ConstIterator it = archMap.find(archName); - if (it == archMap.constEnd()) { - qDebug("Ignoring unknown architecture '%s'.", qPrintable(archName)); - continue; - } - architectures << it.value(); - } - - for (BuildProfileMap::ConstIterator it = archMap.constBegin(); - it != archMap.constEnd(); ++it) { - Profile(subProfileName(profileName, it.value()), settings).removeProfile(); - } Profile mainProfile(profileName, settings); + mainProfile.setValue(qls("Android.ndk.ndkDir"), QDir::cleanPath(ndkDirPath)); mainProfile.setValue(qls("Android.sdk.ndkDir"), QDir::cleanPath(ndkDirPath)); - foreach (const BuildProfile &arch, architectures) { + foreach (const QString &arch, expectedArchs()) { Profile p(subProfileName(profileName, arch), settings); - p.setValue(qls("Android.ndk.abi"), arch.abi); - p.setValue(qls("Android.ndk.buildProfile"), arch.profileSuffix); - p.setValue(qls("Android.ndk.compilerFlagsDebug"), arch.compilerFlagsDebug); - p.setValue(qls("Android.ndk.compilerFlagsRelease"), arch.compilerFlagsRelease); - p.setValue(qls("Android.ndk.hardFp"), arch.hardFp); - p.setValue(qls("Android.ndk.hostArch"), detectToolchainHostArch(ndkDirPath)); - p.setValue(qls("Android.ndk.ndkDir"), QDir::cleanPath(ndkDirPath)); - p.setValue(qls("Android.ndk.toolchainDirPrefix"), arch.toolchainDirPrefix); - p.setValue(qls("cpp.compilerName"), qls("gcc")); - p.setValue(qls("cpp.debugInformation"), true); - p.setValue(qls("cpp.linkerFlags"), arch.linkerFlags); - p.setValue(qls("cpp.linkerName"), qls("g++")); - p.setValue(qls("cpp.toolchainPrefix"), arch.toolchainPrefix); - p.setValue(qls("qbs.architecture"), arch.qbsArchName); - p.setValue(qls("qbs.targetOS"), QStringList() << qls("android") << qls("linux") - << qls("unix")); - p.setValue(qls("qbs.toolchain"), QStringList(qls("gcc"))); + p.removeProfile(); + p.setBaseProfile(mainProfile.name()); + p.setValue(qls("qbs.architecture"), arch); } } diff --git a/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product1/product1.qbs b/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product1/product1.qbs index e0bf91cea..9dde6e174 100644 --- a/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product1/product1.qbs +++ b/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product1/product1.qbs @@ -5,7 +5,7 @@ Project { name: "p1lib1" files: ["src/main/jni/lib1.cpp"] Android.ndk.appStl: "stlport_shared" - architectures: ["mips", "x86"] + architectures: ["mipsel", "x86"] cpp.useRPaths: false } diff --git a/tests/auto/blackbox/testdata/android/teapot/teapot.qbs b/tests/auto/blackbox/testdata/android/teapot/teapot.qbs index 6096c1597..6701eaa49 100644 --- a/tests/auto/blackbox/testdata/android/teapot/teapot.qbs +++ b/tests/auto/blackbox/testdata/android/teapot/teapot.qbs @@ -1,7 +1,7 @@ import qbs Project { - property stringList architectures: ["arm64-v8a", "armeabi-v7a-hard", "x86_64", "mips"] + property stringList architectures: ["arm64", "armv7", "x86_64", "mipsel"] StaticLibrary { architectures: project.architectures name: "native-glue" |
