From 65cb0d3e2d669151560b53fdbbd3f2f0efb29c44 Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Mon, 22 Apr 2019 17:56:22 +0300 Subject: Android: Nuke support for old NDKs - Support NDK only r19+ - Remove deprecated and unsupported stl libs: "system", "gabi++_static", "gabi++_shared", "stlport_static", "stlport_shared", "gnustl_static", "gnustl_shared" - Fix armv7a link (we need to link against libc++.[a/so].API) - Use lldb - Use llvm bin utils [ChangeLog][Android] Support NDK only r19+, remove deprecated and unsupported stl libs, use lldb and llvm bin utils Change-Id: If9d5d5462dffb6c9bf481f910ee2c3ba03bc5649 Reviewed-by: Christian Kandeler --- doc/reference/modules/android-ndk-module.qdoc | 13 +- .../Qt/templates/android_support.qbs | 22 ++-- share/qbs/modules/Android/ndk/ndk.qbs | 79 ++---------- share/qbs/modules/Android/ndk/utils.js | 22 ++-- share/qbs/modules/cpp/android-gcc.qbs | 133 +++++---------------- 5 files changed, 68 insertions(+), 201 deletions(-) diff --git a/doc/reference/modules/android-ndk-module.qdoc b/doc/reference/modules/android-ndk-module.qdoc index 8113a7c68..d5145a67b 100644 --- a/doc/reference/modules/android-ndk-module.qdoc +++ b/doc/reference/modules/android-ndk-module.qdoc @@ -47,7 +47,7 @@ CppApplication { name: "HelloJni" Android.sdk.packageName: "com.example.hellojni" - qbs.architectures: ["mips", "x86"] + qbs.architectures: ["arm", "x86"] files: "app/src/main/jni/hello-jni.c" } \endcode @@ -86,16 +86,9 @@ \list \li \c "c++_shared" \li \c "c++_static" - \li \c "gabi++_shared" (until r17) - \li \c "gabi++_static" (until r17) - \li \c "gnustl_shared" (until r17) - \li \c "gnustl_static" (until r17) - \li \c "stlport_shared" (until r17) - \li \c "stlport_static" (until r17) - \li \c "system" \endlist - \defaultvalue \c{"system"} + \defaultvalue \c{"c++_shared"} */ /*! @@ -111,5 +104,5 @@ The versioned platform name. - \defaultvalue \c{"android-9"} + \defaultvalue \c{"android-16"} */ diff --git a/share/qbs/module-providers/Qt/templates/android_support.qbs b/share/qbs/module-providers/Qt/templates/android_support.qbs index 866d8dfe9..d11f8707a 100644 --- a/share/qbs/module-providers/Qt/templates/android_support.qbs +++ b/share/qbs/module-providers/Qt/templates/android_support.qbs @@ -24,6 +24,7 @@ Module { Depends { name: "Android.sdk"; condition: _enableSdkSupport } Depends { name: "Android.ndk"; condition: _enableNdkSupport } Depends { name: "java"; condition: _enableSdkSupport } + Depends { name: "cpp" } Properties { condition: _enableNdkSupport && qbs.toolchain.contains("clang") @@ -38,6 +39,10 @@ Module { Android.sdk.customManifestProcessing: true java._tagJniHeaders: false // prevent rule cycle } + Properties { + condition: _enableNdkSupport && Android.ndk.abi === "armeabi-v7a" + cpp.defines: "ANDROID_HAS_WSTRING" + } Rule { condition: _enableSdkSupport @@ -90,20 +95,9 @@ Module { f.writeLine('"sdkBuildToolsRevision": "' + product.Android.sdk.buildToolsVersion + '",'); f.writeLine('"ndk": "' + product.Android.sdk.ndkDir + '",'); - // GCC was dropped in r19+ - if (Utilities.versionCompare(product.Android.ndk.version, "19") >= 0) { - f.writeLine('"toolchain-prefix": "llvm",'); - f.writeLine('"tool-prefix": "llvm",'); - f.writeLine('"useLLVM": true,'); - } else { - var toolPrefix = theBinary.cpp.toolchainTriple; - var toolchainPrefix = toolPrefix.startsWith("i686-") ? "x86" : toolPrefix; - f.writeLine('"toolchain-prefix": "' + toolchainPrefix + '",'); - f.writeLine('"tool-prefix": "' + toolPrefix + '",'); - f.writeLine('"toolchain-version": "' + theBinary.Android.ndk.toolchainVersion - + '",'); - } - + f.writeLine('"toolchain-prefix": "llvm",'); + f.writeLine('"tool-prefix": "llvm",'); + f.writeLine('"useLLVM": true,'); f.writeLine('"ndk-host": "' + theBinary.Android.ndk.hostArch + '",'); f.writeLine('"target-architecture": "' + theBinary.Android.ndk.abi + '",'); f.writeLine('"qml-root-path": "' + product.Qt.android_support.qmlRootDir + '",'); diff --git a/share/qbs/modules/Android/ndk/ndk.qbs b/share/qbs/modules/Android/ndk/ndk.qbs index 5d86d6e3a..d639fcb91 100644 --- a/share/qbs/modules/Android/ndk/ndk.qbs +++ b/share/qbs/modules/Android/ndk/ndk.qbs @@ -51,21 +51,13 @@ Module { allowedValues: ["arm64-v8a", "armeabi", "armeabi-v7a", "mips", "mips64", "x86", "x86_64"] } - property string appStl: version && Utilities.versionCompare(version, "17") >= 0 - ? "c++_shared" : "system" - PropertyOptions { - name: "appStl" - description: "Corresponds to the 'APP_STL' variable in an Android.mk file." - allowedValues: [ - "system", "gabi++_static", "gabi++_shared", "stlport_static", "stlport_shared", - "gnustl_static", "gnustl_shared", "c++_static", "c++_shared" - ] - } + // See https://developer.android.com/ndk/guides/cpp-support.html + property string appStl: "c++_shared" - property string toolchainVersion: latestToolchainVersion PropertyOptions { - name: "toolchainVersion" - description: "Corresponds to the 'NDK_TOOLCHAIN_VERSION' variable in an Android.mk file." + name: "appStl" + description: "C++ Runtime Libraries." + allowedValues: ["c++_static", "c++_shared"] } property string hostArch: ndkProbe.hostArch @@ -73,41 +65,6 @@ Module { property string ndkSamplesDir: ndkProbe.samplesDir property string platform: ndkProbe.ndkPlatform - property bool useUnifiedHeaders: version && Utilities.versionCompare(version, "15") >= 0 - - // Internal properties. - property stringList availableToolchains: ndkProbe.toolchains - - property stringList availableToolchainVersions: { - var tcs = availableToolchains; - var versions = []; - for (var i = 0; i < tcs.length; ++i) { - if ((qbs.toolchain.contains("clang") && tcs[i].startsWith("llvm-")) - || toolchainDirPrefixAbis.contains(tcs[i].split("-")[0])) { - var re = /\-((?:[0-9]+)\.(?:[0-9]+))$/; - var m = tcs[i].match(re); - if (m) - versions.push(m[1]); - } - } - - // Sort by version number - versions.sort(function (a, b) { - var re = /^([0-9]+)\.([0-9]+)$/; - a = a.match(re); - a = {major: a[1], minor: a[2]}; - b = b.match(re); - b = {major: b[1], minor: b[2]}; - if (a.major === b.major) - return a.minor - b.minor; - return a.major - b.major; - }); - - return versions; - } - - property string latestToolchainVersion: availableToolchainVersions - [availableToolchainVersions.length - 1] property int platformVersion: { if (platform) { @@ -127,22 +84,6 @@ Module { return list; } - property stringList toolchainDirPrefixAbis: { - var list = ["arm"]; - if (platformVersion >= 9) - list.push("mipsel", "x86"); - if (platformVersion >= 21) - list.push("aarch64", "mips64el", "x86_64"); - return list; - } - - property string toolchainVersionNumber: { - var prefix = "clang"; - if (toolchainVersion && toolchainVersion.startsWith(prefix)) - return toolchainVersion.substr(prefix.length); - return toolchainVersion; - } - property string armMode: abi && abi.startsWith("armeabi") ? (qbs.buildVariant === "debug" ? "arm" : "thumb") : undefined; @@ -152,8 +93,6 @@ Module { allowedValues: ["arm", "thumb"] } - property bool haveUnifiedStl: version && Utilities.versionCompare(version, "12") >= 0 - validate: { if (!ndkDir) { throw ModUtils.ModuleError("Could not find an Android NDK at any of the following " @@ -163,15 +102,19 @@ Module { + "ANDROID_NDK_ROOT environment variable to a valid " + "Android NDK location."); } + + if (Utilities.versionCompare(version, "19") < 0) + throw ModUtils.ModuleError("Unsupported NDK version " + + Android.ndk.version + + ", please upgrade your NDK to r19+"); + if (product.aggregate && !product.multiplexConfigurationId) return; var validator = new ModUtils.PropertyValidator("Android.ndk"); validator.setRequiredProperty("abi", abi); validator.setRequiredProperty("appStl", appStl); - validator.setRequiredProperty("toolchainVersion", toolchainVersion); validator.setRequiredProperty("hostArch", hostArch); validator.setRequiredProperty("platform", platform); - validator.setRequiredProperty("toolchainVersionNumber", toolchainVersionNumber); return validator.validate(); } } diff --git a/share/qbs/modules/Android/ndk/utils.js b/share/qbs/modules/Android/ndk/utils.js index 3bc3b6d9d..dd3c95687 100644 --- a/share/qbs/modules/Android/ndk/utils.js +++ b/share/qbs/modules/Android/ndk/utils.js @@ -28,6 +28,8 @@ ** ****************************************************************************/ +var Utilities = require("qbs.Utilities") + function abiNameToDirName(abiName) { switch (abiName) { case "armeabi": @@ -61,10 +63,11 @@ function androidAbi(arch) { } } -function commonCompilerFlags(toolchain, buildVariant, abi, armMode) { - var flags = ["-ffunction-sections", "-funwind-tables", - "-Werror=format-security", "-fstack-protector-strong"]; +function commonCompilerFlags(toolchain, buildVariant, ndk) { + var flags = ["-Werror=format-security"]; + var abi = ndk.abi; + var armMode = ndk.armMode; if (abi === "arm64-v8a") flags.push("-fpic"); @@ -86,12 +89,17 @@ function commonCompilerFlags(toolchain, buildVariant, abi, armMode) { "-frerun-cse-after-loop", "-frename-registers"); } - if ((abi === "x86" || abi === "x86_64") && toolchain.contains("clang")) + if (abi === "x86" || abi === "x86_64") flags.push("-fPIC"); + flags.push("-fno-limit-debug-info"); + if (armMode) flags.push("-m" + armMode); + // TODO: Remove when https://github.com/android-ndk/ndk/issues/884 is fixed. + flags.push("-fno-addrsig"); + return flags; } @@ -99,8 +107,6 @@ function commonLinkerFlags(abi) { return ["-z", "noexecstack", "-z", "relro", "-z", "now"]; } -function getBinutilsPath(ndk, toolchainPrefix) { - if (["x86", "x86_64"].contains(ndk.abi)) - return ndk.abi + "-" + ndk.toolchainVersionNumber; - return toolchainPrefix + ndk.toolchainVersionNumber; +function stlFilePath(path, ndk, suffix) { + return path + ndk.appStl.slice(0, ndk.appStl.indexOf('_')) + suffix + "." + ndk.platformVersion; } diff --git a/share/qbs/modules/cpp/android-gcc.qbs b/share/qbs/modules/cpp/android-gcc.qbs index 23b50b14e..75f4299f7 100644 --- a/share/qbs/modules/cpp/android-gcc.qbs +++ b/share/qbs/modules/cpp/android-gcc.qbs @@ -39,44 +39,16 @@ import 'gcc.js' as Gcc LinuxGCC { Depends { name: "Android.ndk" } - condition: qbs.targetOS.contains("android") && - qbs.toolchain && qbs.toolchain.contains("gcc") + condition: qbs.targetOS.contains("android") && qbs.toolchain && qbs.toolchain.contains("llvm") priority: 2 rpaths: [rpathOrigin] - property string toolchainDir: { - if (qbs.toolchain && qbs.toolchain.contains("clang")) { - return Utilities.versionCompare(Android.ndk.version, "10") <= 0 - ? "llvm-" + Android.ndk.toolchainVersionNumber : "llvm"; - } - return NdkUtils.getBinutilsPath(Android.ndk, toolchainTriple + "-") - } - property string cxxStlBaseDir: FileInfo.joinPaths(Android.ndk.ndkDir, "sources", "cxx-stl") - property string gabiBaseDir: FileInfo.joinPaths(cxxStlBaseDir, "gabi++") - property string stlPortBaseDir: FileInfo.joinPaths(cxxStlBaseDir, "stlport") - property string gnuStlBaseDir: FileInfo.joinPaths(cxxStlBaseDir, "gnu-libstdc++", - Android.ndk.toolchainVersionNumber) - property string llvmStlBaseDir: FileInfo.joinPaths(cxxStlBaseDir, "llvm-libc++") - property string stlBaseDir: { - if (Android.ndk.appStl.startsWith("gabi++_")) - return gabiBaseDir; - else if (Android.ndk.appStl.startsWith("stlport_")) - return stlPortBaseDir; - else if (Android.ndk.appStl.startsWith("gnustl_")) - return gnuStlBaseDir; - else if (Android.ndk.appStl.startsWith("c++_")) - return llvmStlBaseDir; - return undefined; - } + property string stlBaseDir: FileInfo.joinPaths(cxxStlBaseDir, "llvm-libc++") property string stlLibsDir: { - if (stlBaseDir) { - var infix = Android.ndk.abi; - if (Android.ndk.armMode === "thumb" && !Android.ndk.haveUnifiedStl) - infix = FileInfo.joinPaths(infix, "thumb"); - return FileInfo.joinPaths(stlBaseDir, "libs", infix); - } + if (stlBaseDir) + return FileInfo.joinPaths(stlBaseDir, "libs", Android.ndk.abi); return undefined; } @@ -84,7 +56,7 @@ LinuxGCC { ? FileInfo.joinPaths(stlLibsDir, dynamicLibraryPrefix + Android.ndk.appStl + dynamicLibrarySuffix) : undefined property string staticStlFilePath: (stlLibsDir && Android.ndk.appStl.endsWith("_static")) - ? FileInfo.joinPaths(stlLibsDir, staticLibraryPrefix + Android.ndk.appStl + staticLibrarySuffix) + ? FileInfo.joinPaths(stlLibsDir, NdkUtils.stlFilePath(staticLibraryPrefix, Android.ndk, staticLibrarySuffix)) : undefined Group { @@ -104,17 +76,13 @@ LinuxGCC { } toolchainInstallPath: FileInfo.joinPaths(Android.ndk.ndkDir, "toolchains", - toolchainDir, "prebuilt", + "llvm", "prebuilt", Android.ndk.hostArch, "bin") property string toolchainTriple: [targetAbi === "androideabi" ? "arm" : targetArch, targetSystem, targetAbi].join("-") - toolchainPrefix: { - if (qbs.toolchain && qbs.toolchain.contains("clang")) - return undefined; - return toolchainTriple + "-"; - } + toolchainPrefix: undefined machineType: { if (Android.ndk.abi === "armeabi") @@ -128,20 +96,18 @@ LinuxGCC { enableExceptions: Android.ndk.appStl !== "system" enableRtti: Android.ndk.appStl !== "system" - commonCompilerFlags: NdkUtils.commonCompilerFlags(qbs.toolchain, qbs.buildVariant, - Android.ndk.abi, Android.ndk.armMode) + commonCompilerFlags: NdkUtils.commonCompilerFlags(qbs.toolchain, qbs.buildVariant, Android.ndk) - linkerFlags: { - var flags = NdkUtils.commonLinkerFlags(Android.ndk.abi); - if (qbs.toolchainType === "clang") { - flags = flags.concat(["--exclude-libs", "libgcc.a", "--exclude-libs", "libatomic.a"]); - if (Android.ndk.appStl.startsWith("c++") && Android.ndk.abi === "armeabi-v7a") - flags = flags.concat(["--exclude-libs", "libunwind.a"]); - } + linkerFlags: NdkUtils.commonLinkerFlags(Android.ndk.abi); + driverLinkerFlags: { + var flags = ["-fuse-ld=lld", "-Wl,--exclude-libs,libgcc.a", "-Wl,--exclude-libs,libatomic.a"]; + if (Android.ndk.appStl.startsWith("c++") && Android.ndk.abi === "armeabi-v7a") + flags = flags.concat(["-Wl,--exclude-libs,libunwind.a"]); return flags; } - platformDriverFlags: ["-no-canonical-prefixes"] + platformDriverFlags: ["-fdata-sections", "-ffunction-sections", "-funwind-tables", + "-fstack-protector-strong", "-no-canonical-prefixes"] libraryPaths: { var prefix = FileInfo.joinPaths(sysroot, "usr"); @@ -149,77 +115,42 @@ LinuxGCC { if (Android.ndk.abi === "mips64" || Android.ndk.abi === "x86_64") // no lib64 for arm64-v8a paths.push(FileInfo.joinPaths(prefix, "lib64")); paths.push(FileInfo.joinPaths(prefix, "lib")); + paths.push(stlLibsDir); return paths; } dynamicLibraries: { var libs = ["c", "m"]; if (sharedStlFilePath) - libs.push(sharedStlFilePath); - return libs; - } - staticLibraries: { - var libs = []; - if (qbs.toolchainType === "gcc") - libs.push("gcc"); - - if (staticStlFilePath) { - libs.push(staticStlFilePath); - if (Android.ndk.appStl === "c++_static") { - var libAbi = FileInfo.joinPaths(stlLibsDir, "libc++abi.a"); - if (File.exists(libAbi)) - libs.push(libAbi); - } - } + libs.push(FileInfo.joinPaths(stlLibsDir, NdkUtils.stlFilePath(dynamicLibraryPrefix, Android.ndk, dynamicLibrarySuffix))); return libs; } + staticLibraries: staticStlFilePath systemIncludePaths: { - var includes = []; - if (Android.ndk.useUnifiedHeaders) { - // Might not be needed with Clang in a future NDK release - includes.push(FileInfo.joinPaths(sysroot, "usr", "include", toolchainTriple)); - } - if (Android.ndk.appStl === "system") { - includes.push(FileInfo.joinPaths(cxxStlBaseDir, "system", "include")); - } else if (Android.ndk.appStl.startsWith("gabi++")) { - includes.push(FileInfo.joinPaths(gabiBaseDir, "include")); - } else if (Android.ndk.appStl.startsWith("stlport")) { - includes.push(FileInfo.joinPaths(stlPortBaseDir, "stlport")); - } else if (Android.ndk.appStl.startsWith("gnustl")) { - includes.push(FileInfo.joinPaths(gnuStlBaseDir, "include")); - includes.push(FileInfo.joinPaths(gnuStlBaseDir, "libs", Android.ndk.abi, "include")); - includes.push(FileInfo.joinPaths(gnuStlBaseDir, "include", "backward")); - } else if (Android.ndk.appStl.startsWith("c++_")) { - if (Utilities.versionCompare(Android.ndk.version, "13") >= 0) { - includes.push(FileInfo.joinPaths(llvmStlBaseDir, "include")); - includes.push(FileInfo.joinPaths(llvmStlBaseDir + "abi", "include")); - } else { - includes.push(FileInfo.joinPaths(llvmStlBaseDir, "libcxx", "include")); - includes.push(FileInfo.joinPaths(llvmStlBaseDir + "abi", "libcxxabi", "include")); - } + var includes = [FileInfo.joinPaths(sysroot, "usr", "include", toolchainTriple)]; + if (Android.ndk.abi === "armeabi-v7a") { + includes.push(FileInfo.joinPaths(Android.ndk.ndkDir, "sources", "android", + "support", "include")); } + includes.push(FileInfo.joinPaths(stlBaseDir, "include")); + includes.push(FileInfo.joinPaths(stlBaseDir + "abi", "include")); return includes; } + defines: { var list = ["ANDROID"]; - if (Android.ndk.useUnifiedHeaders) { - // Might be superseded by an -mandroid-version or similar Clang compiler flag in future - list.push("__ANDROID_API__=" + Android.ndk.platformVersion); - } + // Might be superseded by an -mandroid-version or similar Clang compiler flag in future + list.push("__ANDROID_API__=" + Android.ndk.platformVersion); return list; } - binutilsPath: FileInfo.joinPaths(Android.ndk.ndkDir, "toolchains", - NdkUtils.getBinutilsPath(Android.ndk, toolchainTriple + "-"), - "prebuilt", Android.ndk.hostArch, "bin"); - binutilsPathPrefix: Gcc.pathPrefix(binutilsPath, toolchainTriple + "-") - driverFlags: qbs.toolchain.contains("clang") && Utilities.versionCompare(Android.ndk.version, "19") < 0 - ? ["-gcc-toolchain", FileInfo.path(binutilsPath)].concat(base || []) : base + + binutilsPath: FileInfo.joinPaths(Android.ndk.ndkDir, "toolchains", "llvm", "prebuilt", + Android.ndk.hostArch, "bin"); + binutilsPathPrefix: "llvm-" syslibroot: FileInfo.joinPaths(Android.ndk.ndkDir, "platforms", Android.ndk.platform, "arch-" + NdkUtils.abiNameToDirName(Android.ndk.abi)) - sysroot: !Android.ndk.useUnifiedHeaders - ? syslibroot - : FileInfo.joinPaths(Android.ndk.ndkDir, "sysroot") + sysroot: FileInfo.joinPaths(Android.ndk.ndkDir, "sysroot") targetArch: { switch (qbs.architecture) { -- cgit v1.2.3