diff options
-rw-r--r-- | share/qbs/imports/qbs/ModUtils/utils.js | 67 | ||||
-rw-r--r-- | share/qbs/imports/qbs/Probes/GccProbe.qbs | 22 | ||||
-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 | 17 | ||||
-rw-r--r-- | share/qbs/modules/Android/ndk/utils.js | 41 | ||||
-rw-r--r-- | share/qbs/modules/cpp/CppModule.qbs | 1 | ||||
-rw-r--r-- | share/qbs/modules/cpp/GenericGCC.qbs | 50 | ||||
-rw-r--r-- | share/qbs/modules/cpp/gcc.js | 4 | ||||
-rw-r--r-- | src/app/qbs-setup-android/android-setup.cpp | 8 | ||||
-rw-r--r-- | src/app/qbs-setup-toolchains/probe.cpp | 9 | ||||
-rw-r--r-- | src/lib/corelib/jsextensions/utilitiesextension.cpp | 14 | ||||
-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 |
14 files changed, 204 insertions, 37 deletions
diff --git a/share/qbs/imports/qbs/ModUtils/utils.js b/share/qbs/imports/qbs/ModUtils/utils.js index 5829984b8..61216806c 100644 --- a/share/qbs/imports/qbs/ModUtils/utils.js +++ b/share/qbs/imports/qbs/ModUtils/utils.js @@ -33,6 +33,7 @@ var File = loadExtension("qbs.File"); var FileInfo = loadExtension("qbs.FileInfo"); var Process = loadExtension("qbs.Process"); var TemporaryDir = loadExtension("qbs.TemporaryDir"); +var Utilities = loadExtension("qbs.Utilities"); function artifactInstalledFilePath(artifact, product) { var relativeInstallDir = artifact.moduleProperty("qbs", "installDir"); @@ -470,3 +471,69 @@ var BlackboxOutputArtifactTracker = (function () { }; return BlackboxOutputArtifactTracker; })(); + +function guessArchitecture(m) { + function hasAnyOf(m, tokens) { + for (var i = 0; i < tokens.length; ++i) { + if (m[tokens[i]] !== undefined) + return true; + } + } + + var architecture; + if (m) { + // based on the search algorithm from qprocessordetection.h in qtbase + if (hasAnyOf(m, ["__arm__", "__TARGET_ARCH_ARM", "_M_ARM", "__aarch64__"])) { + if (hasAnyOf(m, ["__aarch64__"])) { + architecture = "arm64"; + } else { + architecture = "arm"; + + var foundSubarch = false; + for (var i = 7; i >= 4; --i) { + var codes = ["zk", "tej", "te", "t2"].concat([].concat.apply([], + new Array(26)).map(function(_, i) { return String.fromCharCode(122 - i); })); + for (var j = 0; j < codes.length; ++j) { + if (m["__ARM_ARCH_" + i + codes[j].toUpperCase() + "__"] !== undefined) { + architecture += "v" + i + codes[j].toLowerCase(); + foundSubarch = true; + break; + } + } + + if (i === 7 && m["_ARM_ARCH_7"] !== undefined) { + architecture += "v7"; + foundSubarch = true; + } + + if (foundSubarch) + break; + } + } + } else if (hasAnyOf(m, ["__i386", "__i386__", "_M_IX86"])) { + architecture = "x86"; + } else if (hasAnyOf(m, ["__x86_64", "__x86_64__", "__amd64", "_M_X64"])) { + architecture = "x86_64"; + } else if (hasAnyOf(m, ["__ia64", "__ia64__", "_M_IA64"])) { + architecture = "ia64"; + } else if (hasAnyOf(m, ["__mips", "__mips__", "_M_MRX000"])) { + architecture = "mips"; + if (hasAnyOf(m, ["_MIPS_ARCH_MIPS64", "__mips64"])) + architecture += "64"; + } else if (hasAnyOf(m, ["__ppc__", "__ppc", "__powerpc__", + "_ARCH_COM", "_ARCH_PWR", "_ARCH_PPC", "_M_MPPC", "_M_PPC"])) { + architecture = "ppc"; + if (hasAnyOf(m, ["__ppc64__", "__powerpc64__", "__64BIT__"])) + architecture += "64"; + } else if (hasAnyOf(m, ["__s390__"])) { + if (hasAnyOf(m, ["__s390x__"])) + architecture = "s390x"; + } else if (hasAnyOf(m, ["__sparc__"])) { + architecture = "sparc"; + if (hasAnyOf(m, ["__sparc64__"])) + architecture += "64"; + } + } + + return Utilities.canonicalArchitecture(architecture); +} diff --git a/share/qbs/imports/qbs/Probes/GccProbe.qbs b/share/qbs/imports/qbs/Probes/GccProbe.qbs index 1c7d0fb68..acbcc72c6 100644 --- a/share/qbs/imports/qbs/Probes/GccProbe.qbs +++ b/share/qbs/imports/qbs/Probes/GccProbe.qbs @@ -35,14 +35,36 @@ import "../../../modules/cpp/gcc.js" as Gcc PathProbe { // Inputs property string compilerFilePath + property string preferredArchitecture + property string preferredMachineType property stringList flags: [] + property bool _haveArchFlag: qbs.targetOS.contains("darwin") property string _nullDevice: qbs.nullDevice + // Outputs + property string architecture + configure: { var args = flags; + if (_haveArchFlag) { + if (preferredArchitecture) + args.push("-arch", preferredArchitecture); + } else { + if (preferredArchitecture === "i386") + args.push("-m32"); + else if (preferredArchitecture === "x86_64") + args.push("-m64"); + + if (preferredMachineType) + args.push("-march=" + preferredMachineType); + } var macros = Gcc.dumpMacros(compilerFilePath, args, _nullDevice); found = !!macros; + + // We have to dump the compiler's macros; -dumpmachine is not suitable because it is not + // always complete (for example, the subarch is not included for arm architectures). + architecture = ModUtils.guessArchitecture(macros) || preferredArchitecture; } } diff --git a/share/qbs/imports/qbs/base/Application.qbs b/share/qbs/imports/qbs/base/Application.qbs index 30e6278eb..b5c37484c 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 ? ["armv5"] : undefined + property stringList architectures: isForAndroid ? ["armv5te"] : 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 60927b18e..2057c0fdd 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 ? ["armv5"] : undefined + property stringList architectures: isForAndroid ? ["armv5te"] : 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 ea7d48352..0cbfa65e1 100644 --- a/share/qbs/modules/Android/ndk/ndk.qbs +++ b/share/qbs/modules/Android/ndk/ndk.qbs @@ -183,7 +183,7 @@ Module { property string gdbserverFileName: "gdbserver" - property string armMode: abi.startsWith("armeabi") + property string armMode: abi && abi.startsWith("armeabi") ? (qbs.buildVariant === "debug" ? "arm" : "thumb") : undefined; PropertyOptions { @@ -198,8 +198,19 @@ Module { cpp.toolchainPrefix: { if (qbs.toolchain && qbs.toolchain.contains("clang")) return undefined; - return [cpp.targetAbi === "androideabi" ? "arm" : cpp.targetArch, - cpp.targetSystem, cpp.targetAbi].join("-") + "-"; + var targetArch = cpp.targetArch; + if (cpp.targetAbi === "androideabi") + targetArch = "arm"; + if (qbs.architecture === "mips" || qbs.architecture === "mips64") + targetArch += "el"; + return [targetArch, cpp.targetSystem, cpp.targetAbi].join("-") + "-"; + } + + cpp.machineType: { + if (abi === "armeabi") + return "armv5te"; + if (abi === "armeabi-v7a") + return "armv7-a"; } qbs.optimization: cpp.targetAbi === "androideabi" ? "small" : base diff --git a/share/qbs/modules/Android/ndk/utils.js b/share/qbs/modules/Android/ndk/utils.js index 1ddd14f2f..040b7b154 100644 --- a/share/qbs/modules/Android/ndk/utils.js +++ b/share/qbs/modules/Android/ndk/utils.js @@ -29,23 +29,36 @@ ****************************************************************************/ function abiNameToDirName(abiName) { - if (abiName.startsWith("armeabi")) + switch (abiName) { + case "armeabi": + case "armeabi-v7a": return "arm"; - if (abiName.startsWith("arm64")) + case "arm64-v8a": return "arm64"; - return abiName; + default: + return abiName; + } } function androidAbi(arch) { - if (arch === "x86" || arch === "x86_64") + switch (arch) { + case "arm64": + return "arm64-v8a"; + case "armv5": + case "armv5te": + return "armeabi"; + case "armv7": + case "armv7a": + return "armeabi-v7a"; + case "mips": + case "mipsel": + return "mips"; + case "mips64": + case "mips64el": + return "mips64"; + default: return arch; - return { - "arm64": "arm64-v8a", - "armv5": "armeabi", - "armv7": "armeabi-v7a", - "mipsel": "mips", - "mips64el": "mips64" - }[arch]; + } } function commonCompilerFlags(buildVariant, abi, hardFloat, armMode) { @@ -67,10 +80,10 @@ function commonCompilerFlags(buildVariant, abi, hardFloat, armMode) { flags.push("-fpic", "-fstack-protector", "-finline-limit=64"); if (abi === "armeabi") - flags.push("-march=armv5te", "-mtune=xscale", "-msoft-float"); + flags.push("-mtune=xscale", "-msoft-float"); if (abi === "armeabi-v7a") { - flags.push("-march=armv7-a", "-mfpu=vfpv3-d16"); + flags.push("-mfpu=vfpv3-d16"); flags.push(hardFloat ? "-mhard-float" : "-mfloat-abi=softfp"); } @@ -102,7 +115,7 @@ 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"); + flags.push("-Wl,--fix-cortex-a8"); if (hardFloat) flags.push("-Wl,-no-warn-mismatch"); } diff --git a/share/qbs/modules/cpp/CppModule.qbs b/share/qbs/modules/cpp/CppModule.qbs index c0d7f3a8b..92ea3e595 100644 --- a/share/qbs/modules/cpp/CppModule.qbs +++ b/share/qbs/modules/cpp/CppModule.qbs @@ -40,6 +40,7 @@ Module { property string warningLevel : 'all' // 'none', 'all' property bool treatWarningsAsErrors : false property string architecture: qbs.architecture + property string machineType // undocumented property string optimization: qbs.optimization property bool debugInformation: qbs.debugInformation property bool enableReproducibleBuilds: false diff --git a/share/qbs/modules/cpp/GenericGCC.qbs b/share/qbs/modules/cpp/GenericGCC.qbs index 07f4cdba5..deb5b35ea 100644 --- a/share/qbs/modules/cpp/GenericGCC.qbs +++ b/share/qbs/modules/cpp/GenericGCC.qbs @@ -52,8 +52,17 @@ CppModule { Probes.GccProbe { id: gccProbe compilerFilePath: compilerPath + preferredArchitecture: targetArch + preferredMachineType: machineType } + // HACK: Preserve the original architecture set by the user if the probe fails on Android. + // The probe will always fail because the compiler path is set in the higher level module + // (which itself requires the architecture in order to determine) and thus creates a circular + // dependency. We could theoretically still enable the warning for clang (since the architecture + // is only part of the path for gcc) if the compiler path were visible from the cpp module here. + qbs.architecture: !qbs.targetOS.contains("android") ? gccProbe.architecture : original + property string target: [targetArch, targetVendor, targetSystem, targetAbi].join("-") property string targetArch: qbs.architecture === "x86" ? "i386" : qbs.architecture property string targetVendor: "unknown" @@ -172,6 +181,47 @@ CppModule { var validator = new ModUtils.PropertyValidator("cpp"); validator.setRequiredProperty("architecture", architecture, "you might want to re-run 'qbs-setup-toolchains'"); + if (gccProbe.architecture) { + validator.addCustomValidator("architecture", architecture, function (value) { + return Utilities.canonicalArchitecture(architecture) === Utilities.canonicalArchitecture(gccProbe.architecture); + }, "'" + architecture + "' differs from the architecture produced by this compiler (" + + gccProbe.architecture +")"); + } else { + // This is a warning and not an error on the rare chance some new architecture comes + // about which qbs does not know about the macros of. But it *might* still work. + // HACK: Ignore warning on Android. See note on qbs.architecture binding above. + if (architecture && !qbs.targetOS.contains("android")) + console.warn("Unknown architecture '" + architecture + "' " + + "may not be supported by this compiler."); + } + + var validateFlagsFunction = function (value) { + if (value) { + for (var i = 0; i < value.length; ++i) { + if (["-target", "-triple", "-arch"].contains(value[i]) + || value[i].startsWith("-march=")) + return false; + } + } + return true; + } + + var msg = "'-target', '-triple', '-arch' and '-march' cannot appear in flags; set qbs.architecture instead"; + validator.addCustomValidator("assemblerFlags", assemblerFlags, validateFlagsFunction, msg); + validator.addCustomValidator("cppFlags", cppFlags, validateFlagsFunction, msg); + validator.addCustomValidator("cFlags", cFlags, validateFlagsFunction, msg); + validator.addCustomValidator("cxxFlags", cxxFlags, validateFlagsFunction, msg); + validator.addCustomValidator("objcFlags", objcFlags, validateFlagsFunction, msg); + validator.addCustomValidator("objcxxFlags", objcxxFlags, validateFlagsFunction, msg); + validator.addCustomValidator("commonCompilerFlags", commonCompilerFlags, validateFlagsFunction, msg); + validator.addCustomValidator("platformAssemblerFlags", platformAssemblerFlags, validateFlagsFunction, msg); + //validator.addCustomValidator("platformCppFlags", platformCppFlags, validateFlagsFunction, msg); + validator.addCustomValidator("platformCFlags", platformCFlags, validateFlagsFunction, msg); + validator.addCustomValidator("platformCxxFlags", platformCxxFlags, validateFlagsFunction, msg); + validator.addCustomValidator("platformObjcFlags", platformObjcFlags, validateFlagsFunction, msg); + validator.addCustomValidator("platformObjcxxFlags", platformObjcxxFlags, validateFlagsFunction, msg); + validator.addCustomValidator("platformCommonCompilerFlags", platformCommonCompilerFlags, validateFlagsFunction, msg); + validator.validate(); } diff --git a/share/qbs/modules/cpp/gcc.js b/share/qbs/modules/cpp/gcc.js index 651c920c6..79ddc772f 100644 --- a/share/qbs/modules/cpp/gcc.js +++ b/share/qbs/modules/cpp/gcc.js @@ -360,6 +360,10 @@ function compilerFlags(product, input, output) { else if (arch === 'i386') args.push('-m32'); + var march = product.moduleProperty("cpp", "machineType"); + if (march) + args.push("-march=" + march); + var minimumDarwinVersion = ModUtils.moduleProperty(product, "minimumDarwinVersion"); if (minimumDarwinVersion) { var flag = ModUtils.moduleProperty(product, "minimumDarwinVersionCompilerFlag"); diff --git a/src/app/qbs-setup-android/android-setup.cpp b/src/app/qbs-setup-android/android-setup.cpp index 3177ae07e..ae7c2d9e1 100644 --- a/src/app/qbs-setup-android/android-setup.cpp +++ b/src/app/qbs-setup-android/android-setup.cpp @@ -48,10 +48,10 @@ static QStringList expectedArchs() { return QStringList() << QStringLiteral("arm64") - << QStringLiteral("armv5") - << QStringLiteral("armv7") - << QStringLiteral("mipsel") - << QStringLiteral("mips64el") + << QStringLiteral("armv5te") + << QStringLiteral("armv7a") + << QStringLiteral("mips") + << QStringLiteral("mips64") << QStringLiteral("x86") << QStringLiteral("x86_64"); } diff --git a/src/app/qbs-setup-toolchains/probe.cpp b/src/app/qbs-setup-toolchains/probe.cpp index eef8dc6f7..e21d7148f 100644 --- a/src/app/qbs-setup-toolchains/probe.cpp +++ b/src/app/qbs-setup-toolchains/probe.cpp @@ -124,7 +124,7 @@ static QStringList standardCompilerFileNames() } static void setCommonProperties(Profile &profile, const QString &compilerFilePath, - const QStringList &toolchainTypes, const QString &architecture) + const QStringList &toolchainTypes) { const QFileInfo cfi(compilerFilePath); const QString compilerName = cfi.fileName(); @@ -138,7 +138,6 @@ static void setCommonProperties(Profile &profile, const QString &compilerFilePat profile.setValue(QLatin1String("cpp.toolchainInstallPath"), cfi.absolutePath()); profile.setValue(QLatin1String("qbs.toolchain"), toolchainTypes); - profile.setValue(QLatin1String("qbs.architecture"), canonicalArchitecture(architecture)); setCompilerVersion(compilerFilePath, toolchainTypes, profile); const QString suffix = compilerName.right(compilerName.size() - prefix.size()); @@ -183,21 +182,17 @@ static Profile createGccProfile(const QString &compilerFilePath, Settings *setti const QString &profileName = QString()) { const QString machineName = gccMachineName(compilerFilePath); - const QStringList compilerTriplet = machineName.split(QLatin1Char('-')); if (toolchainTypes.contains(QLatin1String("mingw"))) { if (!validMinGWMachines().contains(machineName)) { throw ErrorInfo(Tr::tr("Detected gcc platform '%1' is not supported.") .arg(machineName)); } - } else if (compilerTriplet.count() < 2) { - throw qbs::ErrorInfo(Tr::tr("Architecture of compiler for platform '%1' at '%2' not understood.") - .arg(machineName, compilerFilePath)); } Profile profile(!profileName.isEmpty() ? profileName : machineName, settings); profile.removeProfile(); - setCommonProperties(profile, compilerFilePath, toolchainTypes, compilerTriplet.first()); + setCommonProperties(profile, compilerFilePath, toolchainTypes); // Check whether auxiliary tools reside within the toolchain's install path. // This might not be the case when using icecc or another compiler wrapper. diff --git a/src/lib/corelib/jsextensions/utilitiesextension.cpp b/src/lib/corelib/jsextensions/utilitiesextension.cpp index ab77e2fba..87f0a0535 100644 --- a/src/lib/corelib/jsextensions/utilitiesextension.cpp +++ b/src/lib/corelib/jsextensions/utilitiesextension.cpp @@ -104,11 +104,15 @@ QScriptValue UtilitiesExtension::js_ctor(QScriptContext *context, QScriptEngine QScriptValue UtilitiesExtension::js_canonicalArchitecture(QScriptContext *context, QScriptEngine *engine) { - if (Q_UNLIKELY(context->argumentCount() != 1)) - return context->throwError(QScriptContext::SyntaxError, - QLatin1String("canonicalArchitecture expects 1 argument")); - const QString architecture = context->argument(0).toString(); - return engine->toScriptValue(canonicalArchitecture(architecture)); + const QScriptValue value = context->argument(0); + if (value.isUndefined() || value.isNull()) + return value; + + if (context->argumentCount() == 1 && value.isString()) + return engine->toScriptValue(canonicalArchitecture(value.toString())); + + return context->throwError(QScriptContext::SyntaxError, + QStringLiteral("canonicalArchitecture expects one argument of type string")); } QScriptValue UtilitiesExtension::js_canonicalToolchain(QScriptContext *context, 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 9dde6e174..e0bf91cea 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: ["mipsel", "x86"] + architectures: ["mips", "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 b16cfade9..6d72138d5 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", "armv7", "x86_64", "mipsel"] + property stringList architectures: ["arm64", "armv7a", "x86_64", "mips"] StaticLibrary { architectures: project.architectures name: "native-glue" |