summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--share/qbs/imports/qbs/ModUtils/utils.js67
-rw-r--r--share/qbs/imports/qbs/Probes/GccProbe.qbs22
-rw-r--r--share/qbs/imports/qbs/base/Application.qbs2
-rw-r--r--share/qbs/imports/qbs/base/Library.qbs2
-rw-r--r--share/qbs/modules/Android/ndk/ndk.qbs17
-rw-r--r--share/qbs/modules/Android/ndk/utils.js41
-rw-r--r--share/qbs/modules/cpp/CppModule.qbs1
-rw-r--r--share/qbs/modules/cpp/GenericGCC.qbs50
-rw-r--r--share/qbs/modules/cpp/gcc.js4
-rw-r--r--src/app/qbs-setup-android/android-setup.cpp8
-rw-r--r--src/app/qbs-setup-toolchains/probe.cpp9
-rw-r--r--src/lib/corelib/jsextensions/utilitiesextension.cpp14
-rw-r--r--tests/auto/blackbox/testdata/android/multiple-apks-per-project/product1/product1.qbs2
-rw-r--r--tests/auto/blackbox/testdata/android/teapot/teapot.qbs2
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"