aboutsummaryrefslogtreecommitdiffstats
path: root/share/qbs
diff options
context:
space:
mode:
Diffstat (limited to 'share/qbs')
-rw-r--r--share/qbs/imports/qbs/DarwinTools/darwin-tools.js99
-rw-r--r--share/qbs/imports/qbs/ModUtils/utils.js51
-rw-r--r--share/qbs/imports/qbs/PathTools/path-tools.js24
-rw-r--r--share/qbs/imports/qbs/Probes/AndroidNdkProbe.qbs14
-rw-r--r--share/qbs/imports/qbs/Probes/AndroidSdkProbe.qbs29
-rw-r--r--share/qbs/imports/qbs/Probes/BinaryProbe.qbs6
-rw-r--r--share/qbs/imports/qbs/Probes/ClBinaryProbe.qbs71
-rw-r--r--share/qbs/imports/qbs/Probes/ClangClBinaryProbe.qbs73
-rw-r--r--share/qbs/imports/qbs/Probes/ClangClProbe.qbs28
-rw-r--r--share/qbs/imports/qbs/Probes/ConanfileProbe.qbs145
-rw-r--r--share/qbs/imports/qbs/Probes/CosmicProbe.qbs87
-rw-r--r--share/qbs/imports/qbs/Probes/DmcProbe.qbs97
-rw-r--r--share/qbs/imports/qbs/Probes/FrameworkProbe.qbs7
-rw-r--r--share/qbs/imports/qbs/Probes/GccBinaryProbe.qbs41
-rw-r--r--share/qbs/imports/qbs/Probes/GccProbe.qbs11
-rw-r--r--share/qbs/imports/qbs/Probes/GccVersionProbe.qbs4
-rw-r--r--share/qbs/imports/qbs/Probes/IarProbe.qbs31
-rw-r--r--share/qbs/imports/qbs/Probes/IncludeProbe.qbs2
-rw-r--r--share/qbs/imports/qbs/Probes/InnoSetupProbe.qbs27
-rw-r--r--share/qbs/imports/qbs/Probes/JdkProbe.qbs7
-rw-r--r--share/qbs/imports/qbs/Probes/KeilProbe.qbs27
-rw-r--r--share/qbs/imports/qbs/Probes/LibraryProbe.qbs49
-rw-r--r--share/qbs/imports/qbs/Probes/MsvcProbe.qbs5
-rw-r--r--share/qbs/imports/qbs/Probes/NodeJsProbe.qbs3
-rw-r--r--share/qbs/imports/qbs/Probes/NpmProbe.qbs35
-rw-r--r--share/qbs/imports/qbs/Probes/PathProbe.qbs31
-rw-r--r--share/qbs/imports/qbs/Probes/PkgConfigProbe.qbs19
-rw-r--r--share/qbs/imports/qbs/Probes/QbsPkgConfigProbe.qbs64
-rw-r--r--share/qbs/imports/qbs/Probes/QmakeProbe.qbs41
-rw-r--r--share/qbs/imports/qbs/Probes/SdccProbe.qbs44
-rw-r--r--share/qbs/imports/qbs/Probes/TypeScriptProbe.qbs31
-rw-r--r--share/qbs/imports/qbs/Probes/WatcomProbe.qbs98
-rw-r--r--share/qbs/imports/qbs/Probes/XcodeLocationProbe.qbs47
-rw-r--r--share/qbs/imports/qbs/Probes/XcodeProbe.qbs5
-rw-r--r--share/qbs/imports/qbs/Probes/path-probe.js36
-rw-r--r--share/qbs/imports/qbs/Probes/qbs-pkg-config-probe.js118
-rw-r--r--share/qbs/imports/qbs/Probes/qmake-probe.js1256
-rw-r--r--share/qbs/imports/qbs/ProviderUtils/provider-utils.js128
-rw-r--r--share/qbs/imports/qbs/base/AndroidApk.qbs2
-rw-r--r--share/qbs/imports/qbs/base/AppleApplicationDiskImage.qbs5
-rw-r--r--share/qbs/imports/qbs/base/Application.qbs14
-rw-r--r--share/qbs/imports/qbs/base/ApplicationExtension.qbs13
-rw-r--r--share/qbs/imports/qbs/base/AutotestRunner.qbs2
-rw-r--r--share/qbs/imports/qbs/base/DynamicLibrary.qbs20
-rw-r--r--share/qbs/imports/qbs/base/InnoSetup.qbs3
-rw-r--r--share/qbs/imports/qbs/base/Library.qbs57
-rw-r--r--share/qbs/imports/qbs/base/NativeBinary.qbs6
-rw-r--r--share/qbs/imports/qbs/base/QtGuiApplication.qbs2
-rw-r--r--share/qbs/imports/qbs/base/QtModule.qbs (renamed from share/qbs/module-providers/Qt/templates/QtModule.qbs)3
-rw-r--r--share/qbs/imports/qbs/base/QtPlugin.qbs (renamed from share/qbs/module-providers/Qt/templates/QtPlugin.qbs)2
-rw-r--r--share/qbs/imports/qbs/base/StaticLibrary.qbs9
-rw-r--r--share/qbs/module-providers/Qt/provider.qbs10
-rw-r--r--share/qbs/module-providers/Qt/setup-qt.js1462
-rw-r--r--share/qbs/module-providers/Qt/templates/android_support.qbs385
-rw-r--r--share/qbs/module-providers/Qt/templates/core.qbs112
-rw-r--r--share/qbs/module-providers/Qt/templates/dbus.js1
-rw-r--r--share/qbs/module-providers/Qt/templates/dbus.qbs11
-rw-r--r--share/qbs/module-providers/Qt/templates/gui.qbs13
-rw-r--r--share/qbs/module-providers/Qt/templates/moc.js25
-rw-r--r--share/qbs/module-providers/Qt/templates/module.qbs4
-rw-r--r--share/qbs/module-providers/Qt/templates/plugin.qbs2
-rw-r--r--share/qbs/module-providers/Qt/templates/plugin_support.qbs2
-rw-r--r--share/qbs/module-providers/Qt/templates/qml.js56
-rw-r--r--share/qbs/module-providers/Qt/templates/qml.qbs100
-rw-r--r--share/qbs/module-providers/Qt/templates/qmlcache.qbs4
-rw-r--r--share/qbs/module-providers/Qt/templates/quick.js14
-rw-r--r--share/qbs/module-providers/Qt/templates/quick.qbs22
-rw-r--r--share/qbs/module-providers/Qt/templates/rcc.js8
-rw-r--r--share/qbs/module-providers/Qt/templates/scxml.qbs8
-rw-r--r--share/qbs/module-providers/__fallback/fallback.qbs3
-rw-r--r--share/qbs/module-providers/conan.js239
-rw-r--r--share/qbs/module-providers/conan.qbs12
-rw-r--r--share/qbs/module-providers/qbspkgconfig.qbs226
-rw-r--r--share/qbs/modules/Android/ndk/ndk.qbs19
-rw-r--r--share/qbs/modules/Android/ndk/utils.js24
-rw-r--r--share/qbs/modules/Android/sdk/sdk.qbs316
-rw-r--r--share/qbs/modules/Android/sdk/utils.js311
-rw-r--r--share/qbs/modules/Exporter/cmake/cmakeexporter.js239
-rw-r--r--share/qbs/modules/Exporter/cmake/cmakeexporter.qbs84
-rw-r--r--share/qbs/modules/Exporter/exporter.js66
-rw-r--r--share/qbs/modules/Exporter/pkgconfig/pkgconfig.js32
-rw-r--r--share/qbs/modules/Exporter/pkgconfig/pkgconfig.qbs6
-rw-r--r--share/qbs/modules/Exporter/qbs/qbsexporter.js52
-rw-r--r--share/qbs/modules/Exporter/qbs/qbsexporter.qbs3
-rw-r--r--share/qbs/modules/Sanitizers/address/asan.qbs76
-rw-r--r--share/qbs/modules/archiver/archiver.qbs9
-rw-r--r--share/qbs/modules/bundle/BundleModule.qbs237
-rw-r--r--share/qbs/modules/bundle/MacOSX-Package-Types.xcspec943
-rw-r--r--share/qbs/modules/bundle/MacOSX-Product-Types.xcspec1345
-rw-r--r--share/qbs/modules/bundle/bundle.js96
-rw-r--r--share/qbs/modules/capnproto/capnproto.js97
-rw-r--r--share/qbs/modules/capnproto/capnprotobase.qbs69
-rw-r--r--share/qbs/modules/capnproto/cpp/capnprotocpp.qbs66
-rw-r--r--share/qbs/modules/cli/CLIModule.qbs21
-rw-r--r--share/qbs/modules/cli/cli.js10
-rw-r--r--share/qbs/modules/cli/mono.qbs7
-rw-r--r--share/qbs/modules/cli/windows-dotnet.qbs2
-rw-r--r--share/qbs/modules/codesign/CodeSignModule.qbs52
-rw-r--r--share/qbs/modules/codesign/android.qbs116
-rw-r--r--share/qbs/modules/codesign/apple.qbs387
-rw-r--r--share/qbs/modules/codesign/codesign.js493
-rw-r--r--share/qbs/modules/codesign/noop.qbs35
-rw-r--r--share/qbs/modules/codesign/signtool.qbs103
-rw-r--r--share/qbs/modules/cpp/CppModule.qbs59
-rw-r--r--share/qbs/modules/cpp/DarwinGCC.qbs52
-rw-r--r--share/qbs/modules/cpp/GenericGCC.qbs236
-rw-r--r--share/qbs/modules/cpp/LinuxGCC.qbs7
-rw-r--r--share/qbs/modules/cpp/MingwBaseModule.qbs9
-rw-r--r--share/qbs/modules/cpp/UnixGCC.qbs6
-rw-r--r--share/qbs/modules/cpp/android-gcc.qbs110
-rw-r--r--share/qbs/modules/cpp/cosmic.js443
-rw-r--r--share/qbs/modules/cpp/cosmic.qbs147
-rw-r--r--share/qbs/modules/cpp/cpp.js431
-rw-r--r--share/qbs/modules/cpp/darwin.js33
-rw-r--r--share/qbs/modules/cpp/dmc.js506
-rw-r--r--share/qbs/modules/cpp/dmc.qbs194
-rw-r--r--share/qbs/modules/cpp/freebsd-gcc.qbs7
-rw-r--r--share/qbs/modules/cpp/gcc.js408
-rw-r--r--share/qbs/modules/cpp/iar.js892
-rw-r--r--share/qbs/modules/cpp/iar.qbs64
-rw-r--r--share/qbs/modules/cpp/ios-gcc.qbs21
-rw-r--r--share/qbs/modules/cpp/keil.js1137
-rw-r--r--share/qbs/modules/cpp/keil.qbs64
-rw-r--r--share/qbs/modules/cpp/macos-gcc.qbs4
-rw-r--r--share/qbs/modules/cpp/msvc.js384
-rw-r--r--share/qbs/modules/cpp/qnx-qcc.qbs6
-rw-r--r--share/qbs/modules/cpp/sdcc.js562
-rw-r--r--share/qbs/modules/cpp/sdcc.qbs66
-rw-r--r--share/qbs/modules/cpp/setuprunenv.js27
-rw-r--r--share/qbs/modules/cpp/tvos-gcc.qbs8
-rw-r--r--share/qbs/modules/cpp/watchos-gcc.qbs8
-rw-r--r--share/qbs/modules/cpp/watcom.js568
-rw-r--r--share/qbs/modules/cpp/watcom.qbs196
-rw-r--r--share/qbs/modules/cpp/windows-clang-cl.qbs33
-rw-r--r--share/qbs/modules/cpp/windows-clang-mingw.qbs18
-rw-r--r--share/qbs/modules/cpp/windows-mingw.qbs18
-rw-r--r--share/qbs/modules/cpp/windows-msvc-base.qbs140
-rw-r--r--share/qbs/modules/cpp/windows-msvc.qbs13
-rw-r--r--share/qbs/modules/dmg/DMGModule.qbs10
-rw-r--r--share/qbs/modules/dmg/dmg.js27
-rw-r--r--share/qbs/modules/flatbuf/c/flatbuffers-c.qbs61
-rw-r--r--share/qbs/modules/flatbuf/cpp/flatbuffers-cpp.qbs69
-rw-r--r--share/qbs/modules/flatbuf/flatbuffers.js126
-rw-r--r--share/qbs/modules/flatbuf/flatbuffersbase.qbs58
-rw-r--r--share/qbs/modules/freedesktop/FreeDesktop.qbs122
-rw-r--r--share/qbs/modules/freedesktop/freedesktop.js69
-rw-r--r--share/qbs/modules/ib/IBModule.qbs5
-rw-r--r--share/qbs/modules/ib/ib.js18
-rw-r--r--share/qbs/modules/ico/ico.js7
-rw-r--r--share/qbs/modules/innosetup/InnoSetupModule.qbs6
-rw-r--r--share/qbs/modules/java/JavaModule.qbs19
-rw-r--r--share/qbs/modules/java/utils.js59
-rw-r--r--share/qbs/modules/nodejs/NodeJS.qbs7
-rw-r--r--share/qbs/modules/nsis/NSISModule.qbs15
-rw-r--r--share/qbs/modules/pkgconfig/pkgconfig.qbs3
-rw-r--r--share/qbs/modules/protobuf/cpp/protobufcpp.qbs113
-rw-r--r--share/qbs/modules/protobuf/nanopb/nanopb.qbs104
-rw-r--r--share/qbs/modules/protobuf/objc/protobufobjc.qbs58
-rw-r--r--share/qbs/modules/protobuf/protobuf.js74
-rw-r--r--share/qbs/modules/protobuf/protobufbase.qbs26
-rw-r--r--share/qbs/modules/qbs/common.qbs52
-rw-r--r--share/qbs/modules/qnx/qnx.qbs11
-rw-r--r--share/qbs/modules/typescript/TypeScriptModule.qbs2
-rw-r--r--share/qbs/modules/typescript/typescript.js6
-rw-r--r--share/qbs/modules/wix/WiXModule.qbs27
-rw-r--r--share/qbs/modules/xcode/xcode.js80
-rw-r--r--share/qbs/modules/xcode/xcode.qbs304
167 files changed, 13841 insertions, 5638 deletions
diff --git a/share/qbs/imports/qbs/DarwinTools/darwin-tools.js b/share/qbs/imports/qbs/DarwinTools/darwin-tools.js
index 5f9076004..9f7d92e59 100644
--- a/share/qbs/imports/qbs/DarwinTools/darwin-tools.js
+++ b/share/qbs/imports/qbs/DarwinTools/darwin-tools.js
@@ -166,7 +166,14 @@ var PropertyListVariableExpander = (function () {
var syntax;
var idx = -1;
for (var i in syntaxes) {
- var j = str.lastIndexOf(syntaxes[i].open);
+ var j;
+ // normal case - we search for the last occurrence to do a correct replacement
+ // for nested variables, e.g. ${VAR1_${VAR2}}. This doesn't work in case
+ // when start == end, e.g. @VAR@ - in that case we search from the start
+ if (syntaxes[i].open !== syntaxes[i].close)
+ j = str.lastIndexOf(syntaxes[i].open);
+ else
+ j = str.indexOf(syntaxes[i].open);
if (j > idx) {
syntax = syntaxes[i];
idx = j;
@@ -175,6 +182,48 @@ var PropertyListVariableExpander = (function () {
return { "syntax": syntax, "index": idx };
}
+ function expandString(key, str, env, seenVars) {
+ if (!str)
+ return str;
+ var repl = indexOfReplacementStart(syntaxes, str);
+ var i = repl.index;
+ while (i !== -1) {
+ var j = str.indexOf(repl.syntax.close, i + repl.syntax.open.length);
+ if (j === -1)
+ return str;
+ var varParts = str.slice(i + repl.syntax.open.length, j).split(':');
+ var varName = varParts[0];
+ var varFormatter = varParts[1];
+ var envValue = env[varName];
+ // if we end up expanding the same variable again, break the recursion
+ if (seenVars.indexOf(varName) !== -1)
+ envValue = "";
+ else
+ seenVars.push(varName);
+ var varValue = expandString(key, envValue, env, seenVars);
+ seenVars.pop();
+ if (undefined === varValue) {
+ // skip replacement
+ if ($this.undefinedVariableFunction)
+ $this.undefinedVariableFunction(key, varName);
+ varValue = "";
+ }
+ varValue = String(varValue);
+ if (varFormatter !== undefined) {
+ // TODO: XCode supports multiple formatters separated by a comma
+ var varFormatterLower = varFormatter.toLowerCase();
+ if (varFormatterLower === "rfc1034identifier" || varFormatterLower === "identifier")
+ varValue = Utilities.rfc1034Identifier(varValue);
+ if (varValue === "" && varFormatterLower.startsWith("default="))
+ varValue = varFormatter.split("=")[1];
+ }
+ str = str.slice(0, i) + varValue + str.slice(j + repl.syntax.close.length);
+ repl = indexOfReplacementStart(syntaxes, str);
+ i = repl.index;
+ }
+ return str;
+ }
+
function expandRecursive(obj, env, checked) {
checked.push(obj);
for (var key in obj) {
@@ -187,35 +236,9 @@ var PropertyListVariableExpander = (function () {
}
if (type !== "string")
continue;
- var repl = indexOfReplacementStart(syntaxes, value);
- var i = repl.index;
- var changes = false;
- while (i !== -1) {
- var j = value.indexOf(repl.syntax.close, i + repl.syntax.open.length);
- if (j === -1)
- break;
- var varParts = value.slice(i + repl.syntax.open.length, j).split(':');
- var varName = varParts[0];
- var varFormatter = varParts[1];
- var varValue = env[varName];
- if (undefined === varValue) {
- // skip replacement
- if ($this.undefinedVariableFunction)
- $this.undefinedVariableFunction(key, varName);
- varValue = "";
- }
- varValue = String(varValue);
- if (varFormatter !== undefined)
- varFormatter = varFormatter.toLowerCase();
- if (varFormatter === "rfc1034identifier")
- varValue = Utilities.rfc1034Identifier(varValue);
- value = value.slice(0, i) + varValue + value.slice(j + repl.syntax.close.length);
- changes = true;
- repl = indexOfReplacementStart(syntaxes, value);
- i = repl.index;
- }
- if (changes)
- obj[key] = value;
+ var expandedValue = expandString(key, value, env, []);
+ if (expandedValue !== value)
+ obj[key] = expandedValue;
}
}
expandRecursive(obj, env, []);
@@ -253,19 +276,3 @@ function cleanPropertyList(plist) {
cleanPropertyList(plist[key]);
}
}
-
-function _codeSignTimestampFlags(product) {
- // If signingTimestamp is undefined, do not specify the flag at all -
- // this uses the system-specific default behavior
- var signingTimestamp = product.moduleProperty("xcode", "signingTimestamp");
- if (signingTimestamp !== undefined) {
- // If signingTimestamp is an empty string, specify the flag but do
- // not specify a value - this uses a default Apple-provided server
- var flag = "--timestamp";
- if (signingTimestamp)
- flag += "=" + signingTimestamp;
- return [flag];
- }
-
- return [];
-}
diff --git a/share/qbs/imports/qbs/ModUtils/utils.js b/share/qbs/imports/qbs/ModUtils/utils.js
index b48b5eb94..a1ede5344 100644
--- a/share/qbs/imports/qbs/ModUtils/utils.js
+++ b/share/qbs/imports/qbs/ModUtils/utils.js
@@ -48,7 +48,7 @@ function mergeCFiles(inputs, outputFilePath)
}
function sanitizedList(list, product, fullPropertyName) {
- if (!Array.isArray(list))
+ if (!(list instanceof Array))
return list;
var filterFunc = function(elem) {
if (typeof elem === "string" && elem.length === 0) {
@@ -87,7 +87,7 @@ function artifactInstalledFilePath(artifact) {
throw "installSourceBase is not an absolute path";
if (!artifact.filePath.startsWith(installSourceBase))
throw "artifact file path doesn't start with the value of qbs.installSourceBase";
- return FileInfo.joinPaths(targetDir, artifact.filePath.substr(installSourceBase.length + 1));
+ return FileInfo.joinPaths(targetDir, artifact.filePath.substr(installSourceBase.length));
}
return FileInfo.joinPaths(targetDir, artifact.fileName);
}
@@ -408,7 +408,7 @@ var PropertyValidator = (function () {
errorMessage += "The following properties have invalid values:\n";
lines = [];
for (i in invalidProperties) {
- for (j in invalidProperties[i]) {
+ for (j = 0; j < invalidProperties[i].length; ++j) {
lines.push(this.moduleName + "." + i + ": " + invalidProperties[i][j]);
}
}
@@ -538,8 +538,13 @@ function guessArchitecture(m) {
break;
}
}
- } else if (hasAnyOf(m, ["__i386", "__i386__", "_M_IX86"])) {
+ } else if (hasAnyOf(m, ["__i386", "__i386__", "__386__"])) {
architecture = "x86";
+ } else if (hasAnyOf(m, ["_M_IX86"])) {
+ var code = parseInt(m["_M_IX86"]);
+ architecture = (code < 300) ? "x86_16" : "x86";
+ } else if (hasAnyOf(m, ["_M_I86"])) {
+ architecture = "x86_16";
} else if (hasAnyOf(m, ["__x86_64", "__x86_64__", "__amd64", "_M_X64", "_M_AMD64"])) {
architecture = "x86_64";
if (hasAnyOf(m, ["__x86_64h", "__x86_64h__"]))
@@ -570,6 +575,30 @@ function guessArchitecture(m) {
architecture = "msp430";
} else if (hasAnyOf(m, ["__RL78__"])) {
architecture = "rl78";
+ } else if (hasAnyOf(m, ["__RX__"])) {
+ architecture = "rx";
+ } else if (hasAnyOf(m, ["__v850__"])) {
+ architecture = "v850";
+ } else if (hasAnyOf(m, ["__riscv"])) {
+ architecture = "riscv";
+ } else if (hasAnyOf(m, ["__xtensa__", "__XTENSA__"])) {
+ architecture = "xtensa";
+ } else if (hasAnyOf(m, ["__m68k__"])) {
+ architecture = "m68k";
+ } else if (hasAnyOf(m, ["__m32c__"])) {
+ architecture = "m32c";
+ } else if (hasAnyOf(m, ["__m32r__", "__M32R__"])) {
+ architecture = "m32r";
+ } else if (hasAnyOf(m, ["__sh__", "__SH__"])) {
+ architecture = "sh";
+ } else if (hasAnyOf(m, ["__CR16__"])) {
+ architecture = "cr16";
+ } else if (hasAnyOf(m, ["__mc68hc1x__", "__mc68hc1x"])) {
+ architecture = "hcs12";
+ } else if (hasAnyOf(m, ["__e2k__"])) {
+ architecture = "e2k";
+ } else if (hasAnyOf(m, ["__hppa__"])) {
+ architecture = "hppa";
}
}
@@ -588,15 +617,19 @@ function guessTargetPlatform(m) {
return "vxworks";
if (hasAnyOf(m, ["__APPLE__"]))
return "darwin";
- if (hasAnyOf(m, ["WIN32", "_WIN32", "__WIN32__", "__NT__"]))
+ if (hasAnyOf(m, ["WIN32", "_WIN32", "__WIN32__", "__NT__", "__WINDOWS__", "_WINDOWS"]))
return "windows";
+ if (hasAnyOf(m, ["MSDOS", "__DOS__", "DOS386"]))
+ return "dos";
+ if (hasAnyOf(m, ["__OS2__"]))
+ return "os2";
if (hasAnyOf(m, ["_AIX"]))
return "aix";
if (hasAnyOf(m, ["hpux", "__hpux"]))
return "hpux";
if (hasAnyOf(m, ["__sun", "sun"]))
return "solaris";
- if (hasAnyOf(m, ["__linux__", "__linux"]))
+ if (hasAnyOf(m, ["__linux__", "__linux", "__LINUX__"]))
return "linux";
if (hasAnyOf(m, ["__FreeBSD__", "__DragonFly__", "__FreeBSD_kernel__"]))
return "freebsd";
@@ -610,3 +643,9 @@ function guessTargetPlatform(m) {
return "haiku";
}
}
+
+function toJSLiteral(v) {
+ if (v === undefined)
+ return "undefined";
+ return JSON.stringify(v);
+}
diff --git a/share/qbs/imports/qbs/PathTools/path-tools.js b/share/qbs/imports/qbs/PathTools/path-tools.js
index b2cb63e39..c928c33e4 100644
--- a/share/qbs/imports/qbs/PathTools/path-tools.js
+++ b/share/qbs/imports/qbs/PathTools/path-tools.js
@@ -107,6 +107,8 @@ function dynamicLibraryFilePath(product, variantSuffix, version, maxParts) {
version = undefined;
}
+ fileName += product.moduleProperty("cpp", "archSuffix");
+
// Append the suffix (i.e. libqbs.1.0.0.dylib, libqbs.so, qbs.dll)
fileName += product.moduleProperty("cpp", "dynamicLibrarySuffix");
@@ -230,3 +232,25 @@ function prependOrSetPath(path, pathList, separator) {
return path;
return path + separator + pathList;
}
+
+function librarySuffixes(targetOS, types, forImport) {
+ if (targetOS.includes("windows")) {
+ if (forImport)
+ return [".lib"];
+ return [].concat(types.includes("shared") ? [".dll"] : []);
+ }
+ if (targetOS.includes("darwin")) {
+ return []
+ .concat(types.includes("shared") ? [".dylib"] : [])
+ .concat(types.includes("static") ? [".a"] : []);
+ }
+ return []
+ .concat(types.includes("shared") ? [".so"] : [])
+ .concat(types.includes("static") ? [".a"] : []);
+}
+
+function libraryNameFilter(targetOS) {
+ if (targetOS.contains("unix"))
+ return function(name) { return "lib" + name; }
+ return function(name) { return name; }
+}
diff --git a/share/qbs/imports/qbs/Probes/AndroidNdkProbe.qbs b/share/qbs/imports/qbs/Probes/AndroidNdkProbe.qbs
index 4a86ee935..e50d4251a 100644
--- a/share/qbs/imports/qbs/Probes/AndroidNdkProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/AndroidNdkProbe.qbs
@@ -32,12 +32,12 @@
import qbs.Environment
import qbs.File
import qbs.FileInfo
+import qbs.Host
import qbs.TextFile
import "../../../modules/Android/android-utils.js" as AndroidUtils
PathProbe {
// Inputs
- property stringList hostOS: qbs.hostOS
property path sdkPath
environmentPaths: Environment.getEnv("ANDROID_NDK_ROOT")
@@ -45,13 +45,13 @@ PathProbe {
var paths = [];
if (sdkPath)
paths.push(FileInfo.joinPaths(sdkPath, "ndk-bundle"));
- if (qbs.hostOS.contains("windows"))
+ if (Host.os().contains("windows"))
paths.push(FileInfo.joinPaths(Environment.getEnv("LOCALAPPDATA"),
"Android", "sdk", "ndk-bundle"));
- if (qbs.hostOS.contains("macos"))
+ if (Host.os().contains("macos"))
paths.push(FileInfo.joinPaths(Environment.getEnv("HOME"),
"Library", "Android", "sdk", "ndk-bundle"));
- if (qbs.hostOS.contains("linux"))
+ if (Host.os().contains("linux"))
paths.push(FileInfo.joinPaths(Environment.getEnv("HOME"),
"Android", "Sdk", "ndk-bundle"));
return paths;
@@ -83,11 +83,11 @@ PathProbe {
candidatePaths = allPaths;
for (i in allPaths) {
var platforms = [];
- if (hostOS.contains("windows"))
+ if (Host.os().contains("windows"))
platforms.push("windows-x86_64", "windows");
- if (hostOS.contains("darwin"))
+ if (Host.os().contains("darwin"))
platforms.push("darwin-x86_64", "darwin-x86");
- if (hostOS.contains("linux"))
+ if (Host.os().contains("linux"))
platforms.push("linux-x86_64", "linux-x86");
for (j in platforms) {
if (File.exists(FileInfo.joinPaths(allPaths[i], "prebuilt", platforms[j]))) {
diff --git a/share/qbs/imports/qbs/Probes/AndroidSdkProbe.qbs b/share/qbs/imports/qbs/Probes/AndroidSdkProbe.qbs
index 38feecdfa..5b777d3e2 100644
--- a/share/qbs/imports/qbs/Probes/AndroidSdkProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/AndroidSdkProbe.qbs
@@ -31,17 +31,18 @@
import qbs.Environment
import qbs.File
import qbs.FileInfo
+import qbs.Host
import "../../../modules/Android/sdk/utils.js" as SdkUtils
import "../../../modules/Android/android-utils.js" as AndroidUtils
-BinaryProbe {
+PathProbe {
environmentPaths: Environment.getEnv("ANDROID_HOME")
platformSearchPaths: {
- if (qbs.hostOS.contains("windows"))
+ if (Host.os().contains("windows"))
return [FileInfo.joinPaths(Environment.getEnv("LOCALAPPDATA"), "Android", "sdk")];
- if (qbs.hostOS.contains("macos"))
+ if (Host.os().contains("macos"))
return [FileInfo.joinPaths(Environment.getEnv("HOME"), "Library", "Android", "sdk")];
- if (qbs.hostOS.contains("linux"))
+ if (Host.os().contains("linux"))
return [FileInfo.joinPaths(Environment.getEnv("HOME"), "Android", "Sdk")];
}
@@ -53,21 +54,17 @@ BinaryProbe {
property string platform
configure: {
- var suffixes = nameSuffixes || [""];
var i, allPaths = (environmentPaths || []).concat(platformSearchPaths || []);
candidatePaths = allPaths;
for (i in allPaths) {
- for (var j in suffixes) {
- if (File.exists(FileInfo.joinPaths(allPaths[i],
- "tools", "android" + suffixes[j]))) {
- path = allPaths[i];
- buildToolsVersions = SdkUtils.availableBuildToolsVersions(path)
- buildToolsVersion = buildToolsVersions[buildToolsVersions.length - 1];
- platforms = AndroidUtils.availablePlatforms(path)
- platform = platforms[platforms.length - 1];
- found = true;
- return;
- }
+ if (File.exists(FileInfo.joinPaths(allPaths[i], "build-tools"))) {
+ path = allPaths[i];
+ buildToolsVersions = SdkUtils.availableBuildToolsVersions(path)
+ buildToolsVersion = buildToolsVersions[buildToolsVersions.length - 1];
+ platforms = AndroidUtils.availablePlatforms(path)
+ platform = platforms[platforms.length - 1];
+ found = true;
+ return;
}
}
}
diff --git a/share/qbs/imports/qbs/Probes/BinaryProbe.qbs b/share/qbs/imports/qbs/Probes/BinaryProbe.qbs
index 0bb264bd6..52b78df03 100644
--- a/share/qbs/imports/qbs/Probes/BinaryProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/BinaryProbe.qbs
@@ -28,8 +28,10 @@
**
****************************************************************************/
+import qbs.Host
+
PathProbe {
- nameSuffixes: qbs.hostOS.contains("windows") ? [".com", ".exe", ".bat", ".cmd"] : undefined
- platformSearchPaths: hostOS.contains("unix") ? ["/usr/bin", "/usr/local/bin"] : []
+ nameSuffixes: Host.os().contains("windows") ? [".com", ".exe", ".bat", ".cmd"] : undefined
+ platformSearchPaths: Host.os().contains("unix") ? ["/usr/bin", "/usr/local/bin"] : []
platformEnvironmentPaths: [ "PATH" ]
}
diff --git a/share/qbs/imports/qbs/Probes/ClBinaryProbe.qbs b/share/qbs/imports/qbs/Probes/ClBinaryProbe.qbs
new file mode 100644
index 000000000..3b3959017
--- /dev/null
+++ b/share/qbs/imports/qbs/Probes/ClBinaryProbe.qbs
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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.FileInfo
+import qbs.ModUtils
+import qbs.Utilities
+import "path-probe.js" as PathProbeConfigure
+
+BinaryProbe {
+ // input
+ property string preferredArchitecture
+
+ configure: {
+ var _selectors;
+ var results = PathProbeConfigure.configure(_selectors, names, nameSuffixes, nameFilter,
+ candidateFilter, searchPaths, pathSuffixes,
+ platformSearchPaths, environmentPaths,
+ platformEnvironmentPaths);
+ if (!results.found) {
+ var msvcs = Utilities.installedMSVCs(preferredArchitecture);
+ if (msvcs.length >= 1) {
+ var result = {};
+ result.fileName = "cl.exe";
+ result.path = msvcs[0].binPath;
+ result.filePath = FileInfo.joinPaths(path, fileName);
+ result.candidatePaths = result.filePath;
+ results.found = true;
+ results.files = [result];
+ }
+ }
+
+ found = results.found;
+ allResults = results.files;
+
+ if (allResults.length === 1) {
+ var result = allResults[0];
+ candidatePaths = result.candidatePaths;
+ path = result.path;
+ filePath = result.filePath;
+ fileName = result.fileName;
+ }
+
+ }
+}
diff --git a/share/qbs/imports/qbs/Probes/ClangClBinaryProbe.qbs b/share/qbs/imports/qbs/Probes/ClangClBinaryProbe.qbs
new file mode 100644
index 000000000..8dc01d376
--- /dev/null
+++ b/share/qbs/imports/qbs/Probes/ClangClBinaryProbe.qbs
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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.FileInfo
+import qbs.ModUtils
+import qbs.Utilities
+import "path-probe.js" as PathProbeConfigure
+
+BinaryProbe {
+ // output
+ property string vcvarsallPath
+
+ configure: {
+ var _selectors;
+ var results = PathProbeConfigure.configure(_selectors, names, nameSuffixes, nameFilter,
+ candidateFilter, searchPaths, pathSuffixes,
+ platformSearchPaths, environmentPaths,
+ platformEnvironmentPaths);
+ var compilerPath;
+ if (results.found)
+ compilerPath = results.files[0].filePath;
+ var compilers = Utilities.installedClangCls(compilerPath);
+ if (compilers.length >= 1) {
+ var result = {};
+ result.fileName = "clang-cl.exe";
+ result.path = compilers[0].toolchainInstallPath;
+ result.filePath = FileInfo.joinPaths(result.path, result.fileName);
+ result.candidatePaths = result.filePath;
+ result.vcvarsallPath = compilers[0].vcvarsallPath;
+ results.found = true;
+ results.files = [result];
+ }
+
+ found = results.found;
+ allResults = results.files;
+
+ if (allResults.length === 1) {
+ var result = allResults[0];
+ candidatePaths = result.candidatePaths;
+ path = result.path;
+ filePath = result.filePath;
+ fileName = result.fileName;
+ vcvarsallPath = result.vcvarsallPath;
+ }
+ }
+}
diff --git a/share/qbs/imports/qbs/Probes/ClangClProbe.qbs b/share/qbs/imports/qbs/Probes/ClangClProbe.qbs
index c7687f0e9..f0d930be5 100644
--- a/share/qbs/imports/qbs/Probes/ClangClProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/ClangClProbe.qbs
@@ -30,6 +30,7 @@
import qbs.File
import qbs.FileInfo
+import qbs.Host
import qbs.ModUtils
import qbs.Utilities
import "../../../modules/cpp/gcc.js" as Gcc
@@ -39,15 +40,15 @@ PathProbe {
property string compilerFilePath
property string vcvarsallFilePath
property stringList enableDefinesByLanguage
- property string architecture
- property string _nullDevice: qbs.nullDevice
- property string _pathListSeparator: qbs.pathListSeparator
+ property string preferredArchitecture
+ property string winSdkVersion
// Outputs
property int versionMajor
property int versionMinor
property int versionPatch
property stringList includePaths
+ property string architecture
property var buildEnv
property var compilerDefinesByLanguage
@@ -57,9 +58,21 @@ PathProbe {
languages = ["c"];
var info = languages.contains("c")
- ? Utilities.clangClCompilerInfo(compilerFilePath, architecture, vcvarsallFilePath, "c") : {};
+ ? Utilities.clangClCompilerInfo(
+ compilerFilePath,
+ preferredArchitecture,
+ vcvarsallFilePath,
+ "c",
+ winSdkVersion)
+ : {};
var infoCpp = languages.contains("cpp")
- ? Utilities.clangClCompilerInfo(compilerFilePath, architecture, vcvarsallFilePath, "cpp") : {};
+ ? Utilities.clangClCompilerInfo(
+ compilerFilePath,
+ preferredArchitecture,
+ vcvarsallFilePath,
+ "cpp",
+ winSdkVersion)
+ : {};
found = (!languages.contains("c") ||
(!!info && !!info.macros && !!info.buildEnvironment))
&& (!languages.contains("cpp") ||
@@ -81,8 +94,9 @@ PathProbe {
var clangPath = FileInfo.joinPaths(FileInfo.path(compilerFilePath), "clang.exe");
var defaultPaths = Gcc.dumpDefaultPaths(buildEnv, clangPath,
- [], _nullDevice,
- _pathListSeparator, "", "");
+ [], Host.nullDevice(),
+ FileInfo.pathListSeparator(), "", "");
includePaths = defaultPaths.includePaths;
+ architecture = ModUtils.guessArchitecture(macros);
}
}
diff --git a/share/qbs/imports/qbs/Probes/ConanfileProbe.qbs b/share/qbs/imports/qbs/Probes/ConanfileProbe.qbs
new file mode 100644
index 000000000..097b1b6f1
--- /dev/null
+++ b/share/qbs/imports/qbs/Probes/ConanfileProbe.qbs
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 Richard Weickelt
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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.Process
+import qbs.File
+import qbs.FileInfo
+import qbs.TextFile
+import qbs.Utilities
+
+Probe {
+ // Inputs
+ property stringList additionalArguments: []
+ property path conanfilePath
+ property path packageReference
+ property path executable: "conan" + FileInfo.executableSuffix()
+ property stringList generators: ["json"]
+ property var options
+ property var settings
+ property bool verbose: false
+
+ // Output
+ property var dependencies
+ property path generatedFilesPath
+ property var json
+
+ // Internal
+ // Ensure that the probe is re-run automatically whenever conanfile changes
+ // by making a file system property part of the probe's signature.
+ property int _conanfileLastModified: conanfilePath ? File.lastModified(conanfilePath) : 0
+ property path _projectBuildDirectory: project.buildDirectory
+
+ configure: {
+ if (conanfilePath && packageReference)
+ throw("conanfilePath and packageReference must not be defined at the same time.");
+
+ if (!conanfilePath && !packageReference)
+ throw("Either conanfilePath or packageReference must be defined.");
+
+ var reference = packageReference || FileInfo.cleanPath(conanfilePath);
+ console.info("Probing '" + reference + "'. This might take a while...");
+ if (conanfilePath && !File.exists(reference))
+ throw("The conanfile '" + reference + "' does not exist.");
+
+ var args = [
+ "install", reference,
+ ];
+
+ if (options) {
+ if (typeof options !== "object")
+ throw("The property 'options' must be an object.");
+ Object.keys(options).forEach(function(key,index) {
+ args.push("-o");
+ args.push(key + "=" + options[key]);
+ });
+ }
+
+ if (settings) {
+ if (typeof settings !== "object")
+ throw("The property 'settings' must be an object.");
+ Object.keys(settings).forEach(function(key,index) {
+ args.push("-s");
+ args.push(key + "=" + settings[key]);
+ });
+ }
+
+ if (!generators.contains("json"))
+ generators.push("json");
+
+ for (var i = 0; i < generators.length; i++)
+ args = args.concat(["-g", generators[i]]);
+
+ for (var i = 0; i < additionalArguments.length; i++)
+ args.push(additionalArguments[i]);
+
+ generatedFilesPath = FileInfo.cleanPath(_projectBuildDirectory +
+ "/genconan/" +
+ Utilities.getHash(args.join()));
+
+ args = args.concat(["-if", generatedFilesPath]);
+ var p = new Process();
+ p.start(executable, args);
+ while (!p.waitForFinished(500)) {
+ const output = p.readStdOut();
+ if (verbose && output) {
+ console.info(output);
+ }
+ }
+ while (!p.atEnd()) {
+ const output = p.readStdOut();
+ if (verbose && output) {
+ console.info(output);
+ }
+ }
+ if (p.exitCode()) {
+ const errorOutput = p.readStdErr();
+ p.close();
+ throw errorOutput;
+ }
+ p.close();
+
+ if (generators.contains("json")) {
+ if (!File.exists(generatedFilesPath + "/conanbuildinfo.json"))
+ throw("No conanbuildinfo.json has been generated.");
+
+ var jsonFile = new TextFile(generatedFilesPath + "/conanbuildinfo.json", TextFile.ReadOnly);
+ json = JSON.parse(jsonFile.readAll());
+ jsonFile.close();
+
+ dependencies = {};
+ for (var i = 0; i < json.dependencies.length; ++i) {
+ var dep = json.dependencies[i];
+ dependencies[dep.name] = dep;
+ }
+ }
+
+ found = true;
+ }
+}
diff --git a/share/qbs/imports/qbs/Probes/CosmicProbe.qbs b/share/qbs/imports/qbs/Probes/CosmicProbe.qbs
new file mode 100644
index 000000000..7de781e6e
--- /dev/null
+++ b/share/qbs/imports/qbs/Probes/CosmicProbe.qbs
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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.File
+import "../../../modules/cpp/cosmic.js" as COSMIC
+
+PathProbe {
+ // Inputs
+ property string compilerFilePath
+ property stringList enableDefinesByLanguage
+
+ // Outputs
+ property string architecture
+ property string endianness
+ property int versionMajor
+ property int versionMinor
+ property int versionPatch
+ property stringList includePaths
+ property var compilerDefinesByLanguage
+
+ configure: {
+ compilerDefinesByLanguage = {};
+
+ if (!File.exists(compilerFilePath)) {
+ found = false;
+ return;
+ }
+
+ var languages = enableDefinesByLanguage;
+ if (!languages || languages.length === 0)
+ languages = ["c"];
+
+ // COSMIC compiler support only the C-language.
+ if (!languages.contains("c")) {
+ found = false;
+ return;
+ }
+
+ var macros = COSMIC.dumpMacros(compilerFilePath);
+ if (!macros) {
+ found = false;
+ return;
+ }
+
+ compilerDefinesByLanguage["c"] = macros;
+
+ architecture = COSMIC.guessArchitecture(compilerFilePath);
+ endianness = COSMIC.guessEndianness(architecture);
+ var defaultPaths = COSMIC.dumpDefaultPaths(compilerFilePath, architecture);
+ includePaths = defaultPaths.includePaths;
+
+ var version = COSMIC.dumpVersion(compilerFilePath);
+ if (version) {
+ versionMajor = version.major;
+ versionMinor = version.minor;
+ versionPatch = version.patch;
+ found = !!architecture && !!endianness;
+ }
+ }
+}
diff --git a/share/qbs/imports/qbs/Probes/DmcProbe.qbs b/share/qbs/imports/qbs/Probes/DmcProbe.qbs
new file mode 100644
index 000000000..6a8723a3b
--- /dev/null
+++ b/share/qbs/imports/qbs/Probes/DmcProbe.qbs
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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.File
+import qbs.ModUtils
+import "../../../modules/cpp/dmc.js" as DMC
+
+PathProbe {
+ // Inputs
+ property string compilerFilePath
+ property stringList enableDefinesByLanguage
+
+ property string _targetPlatform
+ property string _targetArchitecture
+ property string _targetExtender // Only for DOS 16/32 bit.
+
+ // Outputs
+ property string architecture
+ property string targetPlatform
+ property int versionMajor
+ property int versionMinor
+ property int versionPatch
+ property stringList includePaths
+ property var compilerDefinesByLanguage
+
+ configure: {
+ compilerDefinesByLanguage = {};
+
+ if (!File.exists(compilerFilePath)) {
+ found = false;
+ return;
+ }
+
+ var languages = enableDefinesByLanguage;
+ if (!languages || languages.length === 0)
+ languages = ["c"];
+
+ var defaultPathsByLanguage = {};
+ for (var i = 0; i < languages.length; ++i) {
+ var tag = languages[i];
+ compilerDefinesByLanguage[tag] = DMC.dumpMacros(
+ compilerFilePath,
+ _targetPlatform,
+ _targetArchitecture,
+ _targetExtender,
+ tag);
+ var paths = DMC.dumpDefaultPaths(compilerFilePath, tag);
+ defaultPathsByLanguage[tag] = paths;
+ }
+
+ var macros = compilerDefinesByLanguage["c"]
+ || compilerDefinesByLanguage["cpp"];
+
+ architecture = ModUtils.guessArchitecture(macros);
+ targetPlatform = ModUtils.guessTargetPlatform(macros);
+
+ var defaultPaths = defaultPathsByLanguage["cpp"]
+ || defaultPathsByLanguage["c"];
+
+ includePaths = defaultPaths.includePaths;
+
+ var version = DMC.guessVersion(macros);
+ if (version) {
+ versionMajor = version.major;
+ versionMinor = version.minor;
+ versionPatch = version.patch;
+ found = !!architecture;
+ }
+ }
+}
diff --git a/share/qbs/imports/qbs/Probes/FrameworkProbe.qbs b/share/qbs/imports/qbs/Probes/FrameworkProbe.qbs
index e0fe73b40..c3d98a49f 100644
--- a/share/qbs/imports/qbs/Probes/FrameworkProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/FrameworkProbe.qbs
@@ -35,10 +35,5 @@ PathProbe {
"/Library/Frameworks",
"/System/Library/Frameworks"
])
-
- nameFilter: {
- return function(name) {
- return name + ".framework";
- }
- }
+ nameSuffixes: ".framework"
}
diff --git a/share/qbs/imports/qbs/Probes/GccBinaryProbe.qbs b/share/qbs/imports/qbs/Probes/GccBinaryProbe.qbs
index 693fb6a01..0872e6cc0 100644
--- a/share/qbs/imports/qbs/Probes/GccBinaryProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/GccBinaryProbe.qbs
@@ -1,8 +1,10 @@
import qbs.Environment
import qbs.FileInfo
+import qbs.Host
import "path-probe.js" as PathProbeConfigure
BinaryProbe {
+ nameSuffixes: undefined // _compilerName already contains ".exe" suffix on Windows
// Inputs
property string _compilerName
property string _toolchainPrefix
@@ -12,7 +14,7 @@ BinaryProbe {
platformSearchPaths: {
var paths = base;
- if (qbs.targetOS.contains("windows") && qbs.hostOS.contains("windows"))
+ if (qbs.targetOS.contains("windows") && Host.os().contains("windows"))
paths.push(FileInfo.joinPaths(
Environment.getEnv("SystemDrive"), "MinGW", "bin"));
return paths;
@@ -48,20 +50,29 @@ BinaryProbe {
configure: {
var selectors;
- var _results = PathProbeConfigure.configure(
+ var results = PathProbeConfigure.configure(
selectors, names, nameSuffixes, nameFilter, candidateFilter, searchPaths,
- pathSuffixes, platformSearchPaths, environmentPaths, platformEnvironmentPaths,
- pathListSeparator);
- found = _results.found;
- var resultFile = _results.files[0];
- candidatePaths = resultFile.candidatePaths;
- path = resultFile.path;
- filePath = resultFile.filePath;
- fileName = resultFile.fileName;
- (nameSuffixes || [""]).forEach(function(suffix) {
- var end = _compilerName + suffix;
- if (fileName.endsWith(end))
- tcPrefix = fileName.slice(0, -end.length);
- });
+ pathSuffixes, platformSearchPaths, environmentPaths, platformEnvironmentPaths);
+
+ found = results.found;
+ if (!found)
+ return;
+
+ var resultsMapper = function(result) {
+ (nameSuffixes || [""]).forEach(function(suffix) {
+ var end = _compilerName + suffix;
+ if (result.fileName.endsWith(end))
+ result.tcPrefix = result.fileName.slice(0, -end.length);
+ });
+ return result;
+ };
+ results.files = results.files.map(resultsMapper);
+ allResults = results.files;
+ var result = results.files[0];
+ candidatePaths = result.candidatePaths;
+ path = result.path;
+ filePath = result.filePath;
+ fileName = result.fileName;
+ tcPrefix = result.tcPrefix;
}
}
diff --git a/share/qbs/imports/qbs/Probes/GccProbe.qbs b/share/qbs/imports/qbs/Probes/GccProbe.qbs
index 9106ff27b..5c6dc1936 100644
--- a/share/qbs/imports/qbs/Probes/GccProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/GccProbe.qbs
@@ -29,6 +29,8 @@
****************************************************************************/
import qbs.File
+import qbs.FileInfo
+import qbs.Host
import qbs.ModUtils
import "../../../modules/cpp/gcc.js" as Gcc
@@ -39,8 +41,6 @@ PathProbe {
property stringList flags: []
property var environment
- property string _nullDevice: qbs.nullDevice
- property string _pathListSeparator: qbs.pathListSeparator
property string _sysroot: qbs.sysroot
property stringList _targetOS: qbs.targetOS
@@ -63,7 +63,8 @@ PathProbe {
if (fp && File.exists(fp)) {
try {
compilerDefinesByLanguage[languages[i]] = Gcc.dumpMacros(environment, fp,
- flags, _nullDevice,
+ flags,
+ Host.nullDevice(),
languages[i]);
} catch (e) {
// Only throw errors when determining the compiler defines for the C language;
@@ -84,8 +85,8 @@ PathProbe {
|| compilerDefinesByLanguage["objcpp"];
var defaultPaths = Gcc.dumpDefaultPaths(environment, compilerFilePathByLanguage["cpp"] ||
compilerFilePathByLanguage["c"],
- flags, _nullDevice,
- _pathListSeparator, _sysroot, _targetOS);
+ flags, Host.nullDevice(),
+ FileInfo.pathListSeparator(), _sysroot, _targetOS);
found = !!macros && !!defaultPaths;
includePaths = defaultPaths.includePaths;
diff --git a/share/qbs/imports/qbs/Probes/GccVersionProbe.qbs b/share/qbs/imports/qbs/Probes/GccVersionProbe.qbs
index 528719e5b..497835479 100644
--- a/share/qbs/imports/qbs/Probes/GccVersionProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/GccVersionProbe.qbs
@@ -29,6 +29,7 @@
****************************************************************************/
import qbs.File
+import qbs.Host
import "../../../modules/cpp/gcc.js" as Gcc
PathProbe {
@@ -36,7 +37,6 @@ PathProbe {
property string compilerFilePath
property var environment
- property string _nullDevice: qbs.nullDevice
property stringList _toolchain: qbs.toolchain
// Outputs
@@ -50,7 +50,7 @@ PathProbe {
return;
}
- var macros = Gcc.dumpMacros(environment, compilerFilePath, undefined, _nullDevice);
+ var macros = Gcc.dumpMacros(environment, compilerFilePath, undefined, Host.nullDevice());
if (_toolchain.contains("clang")) {
versionMajor = parseInt(macros["__clang_major__"], 10);
diff --git a/share/qbs/imports/qbs/Probes/IarProbe.qbs b/share/qbs/imports/qbs/Probes/IarProbe.qbs
index d261e9065..a0008be47 100644
--- a/share/qbs/imports/qbs/Probes/IarProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/IarProbe.qbs
@@ -33,19 +33,17 @@ import "../../../modules/cpp/iar.js" as IAR
PathProbe {
// Inputs
- property string compilerFilePath;
- property stringList enableDefinesByLanguage;
-
- property string _nullDevice: qbs.nullDevice
+ property string compilerFilePath
+ property stringList enableDefinesByLanguage
// Outputs
- property string architecture;
- property string endianness;
- property int versionMajor;
- property int versionMinor;
- property int versionPatch;
- property stringList includePaths;
- property var compilerDefinesByLanguage;
+ property string architecture
+ property string endianness
+ property int versionMajor
+ property int versionMinor
+ property int versionPatch
+ property stringList includePaths
+ property var compilerDefinesByLanguage
configure: {
compilerDefinesByLanguage = {};
@@ -59,10 +57,13 @@ PathProbe {
if (!languages || languages.length === 0)
languages = ["c"];
+ var defaultPathsByLanguage = {};
for (var i = 0; i < languages.length; ++i) {
var tag = languages[i];
compilerDefinesByLanguage[tag] = IAR.dumpMacros(
compilerFilePath, tag);
+ var paths = IAR.dumpDefaultPaths(compilerFilePath, tag);
+ defaultPathsByLanguage[tag] = paths;
}
var macros = compilerDefinesByLanguage["c"]
@@ -71,10 +72,8 @@ PathProbe {
architecture = IAR.guessArchitecture(macros);
endianness = IAR.guessEndianness(macros);
- // FIXME: Do we need dump the default paths for both C
- // and C++ languages?
- var defaultPaths = IAR.dumpDefaultPaths(
- compilerFilePath, languages[0]);
+ var defaultPaths = defaultPathsByLanguage["cpp"]
+ || defaultPathsByLanguage["c"];
includePaths = defaultPaths.includePaths;
@@ -83,7 +82,7 @@ PathProbe {
versionMajor = version.major;
versionMinor = version.minor;
versionPatch = version.patch;
- found = version && architecture && endianness;
+ found = !!architecture && !!endianness;
}
}
}
diff --git a/share/qbs/imports/qbs/Probes/IncludeProbe.qbs b/share/qbs/imports/qbs/Probes/IncludeProbe.qbs
index 3c1059e64..6201cbc55 100644
--- a/share/qbs/imports/qbs/Probes/IncludeProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/IncludeProbe.qbs
@@ -32,6 +32,8 @@ PathProbe {
platformSearchPaths: qbs.targetOS.contains("unix") ? [
"/usr/include",
"/usr/local/include",
+ "/include",
+ "/app/include",
] : []
platformEnvironmentPaths: {
if (qbs.toolchain.contains('msvc'))
diff --git a/share/qbs/imports/qbs/Probes/InnoSetupProbe.qbs b/share/qbs/imports/qbs/Probes/InnoSetupProbe.qbs
index 2c06a6a0b..87475cb53 100644
--- a/share/qbs/imports/qbs/Probes/InnoSetupProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/InnoSetupProbe.qbs
@@ -35,18 +35,25 @@ PathProbe {
property var version
configure: {
- var keySuffix = "Microsoft\\Windows\\CurrentVersion\\Uninstall\\Inno Setup 5_is1";
var keys = [
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\" + keySuffix,
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\" + keySuffix
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\",
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\"
];
- for (var i in keys) {
- var v = Utilities.getNativeSetting(keys[i], "DisplayVersion");
- if (v) {
- path = Utilities.getNativeSetting(keys[i], "InstallLocation");
- version = v;
- found = path && version;
- return;
+ var keySuffixes = [
+ "Microsoft\\Windows\\CurrentVersion\\Uninstall\\Inno Setup 5_is1",
+ "Microsoft\\Windows\\CurrentVersion\\Uninstall\\Inno Setup 6_is1"
+ ];
+ for (var i = 0; i < keys.length; ++i) {
+ for (var j = 0; j < keySuffixes.length; ++j) {
+ var key = keys[i] + keySuffixes[j];
+
+ var v = Utilities.getNativeSetting(key, "DisplayVersion");
+ if (v) {
+ path = Utilities.getNativeSetting(key, "InstallLocation");
+ version = v;
+ found = path && version;
+ return;
+ }
}
}
}
diff --git a/share/qbs/imports/qbs/Probes/JdkProbe.qbs b/share/qbs/imports/qbs/Probes/JdkProbe.qbs
index 1f414b0fa..efb5a5336 100644
--- a/share/qbs/imports/qbs/Probes/JdkProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/JdkProbe.qbs
@@ -30,14 +30,14 @@
****************************************************************************/
import qbs.Environment
+import qbs.Host
import "../../../modules/java/utils.js" as JavaUtils
PathProbe {
// Inputs
- property stringList hostOS: qbs.hostOS
property string architecture: !_androidCrossCompiling ? qbs.architecture : undefined
property bool _androidCrossCompiling: qbs.targetOS.contains("android")
- && !qbs.hostOS.contains("android")
+ && !Host.os().contains("android")
environmentPaths: Environment.getEnv("JAVA_HOME")
platformSearchPaths: [
@@ -47,7 +47,8 @@ PathProbe {
]
configure: {
- path = JavaUtils.findJdkPath(hostOS, architecture, environmentPaths, platformSearchPaths);
+ path = JavaUtils.findJdkPath(Host.os(), architecture, environmentPaths,
+ platformSearchPaths);
found = !!path;
}
}
diff --git a/share/qbs/imports/qbs/Probes/KeilProbe.qbs b/share/qbs/imports/qbs/Probes/KeilProbe.qbs
index 34afecb64..b123584ad 100644
--- a/share/qbs/imports/qbs/Probes/KeilProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/KeilProbe.qbs
@@ -29,23 +29,22 @@
****************************************************************************/
import qbs.File
+import qbs.Host
import "../../../modules/cpp/keil.js" as KEIL
PathProbe {
// Inputs
- property string compilerFilePath;
- property stringList enableDefinesByLanguage;
-
- property string _nullDevice: qbs.nullDevice
+ property string compilerFilePath
+ property stringList enableDefinesByLanguage
// Outputs
- property string architecture;
- property string endianness;
- property int versionMajor;
- property int versionMinor;
- property int versionPatch;
- property stringList includePaths;
- property var compilerDefinesByLanguage;
+ property string architecture
+ property string endianness
+ property int versionMajor
+ property int versionMinor
+ property int versionPatch
+ property stringList includePaths
+ property var compilerDefinesByLanguage
configure: {
compilerDefinesByLanguage = {};
@@ -62,7 +61,7 @@ PathProbe {
for (var i = 0; i < languages.length; ++i) {
var tag = languages[i];
compilerDefinesByLanguage[tag] = KEIL.dumpMacros(
- compilerFilePath, tag, _nullDevice);
+ compilerFilePath, tag, Host.nullDevice());
}
var macros = compilerDefinesByLanguage["c"]
@@ -72,7 +71,7 @@ PathProbe {
endianness = KEIL.guessEndianness(macros);
var defaultPaths = KEIL.dumpDefaultPaths(
- compilerFilePath, architecture);
+ compilerFilePath, Host.nullDevice());
includePaths = defaultPaths.includePaths;
@@ -81,7 +80,7 @@ PathProbe {
versionMajor = version.major;
versionMinor = version.minor;
versionPatch = version.patch;
- found = version.found && architecture && endianness;
+ found = !!architecture && !!endianness;
}
}
}
diff --git a/share/qbs/imports/qbs/Probes/LibraryProbe.qbs b/share/qbs/imports/qbs/Probes/LibraryProbe.qbs
index 26787d1b4..d67a81372 100644
--- a/share/qbs/imports/qbs/Probes/LibraryProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/LibraryProbe.qbs
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 Ivan Komissarov.
+** Copyright (C) 2018 Ivan Komissarov (abbapoh@gmail.com)
** Contact: http://www.qt.io/licensing
**
** This file is part of Qbs.
@@ -28,29 +28,40 @@
**
****************************************************************************/
+import qbs.PathTools
+
PathProbe {
- nameSuffixes: {
- if (qbs.targetOS.contains("windows"))
- return [".lib"];
- if (qbs.targetOS.contains("macos"))
- return [".dylib", ".a"];
- return [".so", ".a"];
- }
- platformSearchPaths: qbs.targetOS.contains("unix") ? [
- "/usr/lib",
- "/usr/local/lib",
- ] : []
- nameFilter: {
+ property string endianness
+ nameSuffixes: PathTools.librarySuffixes(qbs.targetOS, ["shared", "static"], true)
+ platformSearchPaths: {
+ var result = [];
if (qbs.targetOS.contains("unix")) {
- return function(name) {
- return "lib" + name;
- }
- } else {
- return function(name) {
- return name;
+ if (qbs.targetOS.contains("linux") && qbs.architecture) {
+ if (qbs.architecture === "armv7")
+ result = ["/usr/lib/arm-linux-gnueabihf"]
+ else if (qbs.architecture === "arm64")
+ result = ["/usr/lib/aarch64-linux-gnu"]
+ else if (qbs.architecture === "mips" && endianness === "big")
+ result = ["/usr/lib/mips-linux-gnu"]
+ else if (qbs.architecture === "mips" && endianness === "little")
+ result = ["/usr/lib/mipsel-linux-gnu"]
+ else if (qbs.architecture === "mips64")
+ result = ["/usr/lib/mips64el-linux-gnuabi64"]
+ else if (qbs.architecture === "ppc")
+ result = ["/usr/lib/powerpc-linux-gnu"]
+ else if (qbs.architecture === "ppc64")
+ result = ["/usr/lib/powerpc64le-linux-gnu"]
+ else if (qbs.architecture === "x86_64")
+ result = ["/usr/lib64", "/usr/lib/x86_64-linux-gnu"]
+ else if (qbs.architecture === "x86")
+ result = ["/usr/lib32", "/usr/lib/i386-linux-gnu"]
}
+ result = result.concat(["/usr/lib", "/usr/local/lib", "/lib", "/app/lib"]);
}
+
+ return result;
}
+ nameFilter: PathTools.libraryNameFilter(qbs.targetOS)
platformEnvironmentPaths: {
if (qbs.targetOS.contains("windows"))
return [ "PATH" ];
diff --git a/share/qbs/imports/qbs/Probes/MsvcProbe.qbs b/share/qbs/imports/qbs/Probes/MsvcProbe.qbs
index 2d5faecdd..d3624e010 100644
--- a/share/qbs/imports/qbs/Probes/MsvcProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/MsvcProbe.qbs
@@ -38,6 +38,7 @@ PathProbe {
property string compilerFilePath
property stringList enableDefinesByLanguage
property string preferredArchitecture
+ property string winSdkVersion
// Outputs
property string architecture
@@ -54,9 +55,9 @@ PathProbe {
languages = ["c"];
var info = languages.contains("c")
- ? Utilities.msvcCompilerInfo(compilerFilePath, "c") : {};
+ ? Utilities.msvcCompilerInfo(compilerFilePath, "c", winSdkVersion) : {};
var infoCpp = languages.contains("cpp")
- ? Utilities.msvcCompilerInfo(compilerFilePath, "cpp") : {};
+ ? Utilities.msvcCompilerInfo(compilerFilePath, "cpp", winSdkVersion) : {};
found = (!languages.contains("c") ||
(!!info && !!info.macros && !!info.buildEnvironment))
&& (!languages.contains("cpp") ||
diff --git a/share/qbs/imports/qbs/Probes/NodeJsProbe.qbs b/share/qbs/imports/qbs/Probes/NodeJsProbe.qbs
index b0162c715..520e57f56 100644
--- a/share/qbs/imports/qbs/Probes/NodeJsProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/NodeJsProbe.qbs
@@ -30,12 +30,13 @@
import qbs.Environment
import qbs.FileInfo
+import qbs.Host
BinaryProbe {
names: ["node", "nodejs"]
platformSearchPaths: {
var paths = base;
- if (qbs.hostOS.contains("windows")) {
+ if (Host.os().contains("windows")) {
var env32 = Environment.getEnv("PROGRAMFILES(X86)");
var env64 = Environment.getEnv("PROGRAMFILES");
if (env64 === env32 && env64.endsWith(" (x86)"))
diff --git a/share/qbs/imports/qbs/Probes/NpmProbe.qbs b/share/qbs/imports/qbs/Probes/NpmProbe.qbs
index f6a99e826..08490065a 100644
--- a/share/qbs/imports/qbs/Probes/NpmProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/NpmProbe.qbs
@@ -28,6 +28,8 @@
**
****************************************************************************/
+import qbs.FileInfo
+import qbs.Host
import qbs.ModUtils
import "path-probe.js" as PathProbeConfigure
import "../../../modules/nodejs/nodejs.js" as NodeJs
@@ -50,25 +52,30 @@ NodeJsProbe {
var selectors;
var results = PathProbeConfigure.configure(
selectors, names, nameSuffixes, nameFilter, candidateFilter, searchPaths,
- pathSuffixes, platformSearchPaths, environmentPaths, platformEnvironmentPaths,
- pathListSeparator);
+ pathSuffixes, platformSearchPaths, environmentPaths, platformEnvironmentPaths);
- var v = new ModUtils.EnvironmentVariable("PATH", pathListSeparator,
- hostOS.contains("windows"));
+ var v = new ModUtils.EnvironmentVariable("PATH", FileInfo.pathListSeparator(),
+ Host.os().contains("windows"));
v.prepend(interpreterPath);
- var result = results.files[0];
- result.npmBin = results.found
- ? NodeJs.findLocation(result.filePath, "bin", v.value)
- : undefined;
- result.npmRoot = results.found
- ? NodeJs.findLocation(result.filePath, "root", v.value)
- : undefined;
- result.npmPrefix = results.found
- ? NodeJs.findLocation(result.filePath, "prefix", v.value)
- : undefined;
+ var resultsMapper = function(result) {
+ result.npmBin = result.found
+ ? NodeJs.findLocation(result.filePath, "bin", v.value)
+ : undefined;
+ result.npmRoot = result.found
+ ? NodeJs.findLocation(result.filePath, "root", v.value)
+ : undefined;
+ result.npmPrefix = result.found
+ ? NodeJs.findLocation(result.filePath, "prefix", v.value)
+ : undefined;
+ return result;
+ };
+ results.files = results.files.map(resultsMapper);
found = results.found;
+ allResults = results.files;
+
+ var result = results.files[0];
candidatePaths = result.candidatePaths;
path = result.path;
filePath = result.filePath;
diff --git a/share/qbs/imports/qbs/Probes/PathProbe.qbs b/share/qbs/imports/qbs/Probes/PathProbe.qbs
index d0edea682..dc3b32ab7 100644
--- a/share/qbs/imports/qbs/Probes/PathProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/PathProbe.qbs
@@ -29,6 +29,7 @@
****************************************************************************/
import "path-probe.js" as PathProbeConfigure
+import qbs.Host
import qbs.ModUtils
Probe {
@@ -38,15 +39,11 @@ Probe {
property var nameFilter
property var candidateFilter
property varList selectors
- property pathList pathPrefixes
property pathList searchPaths
property stringList pathSuffixes
- property pathList platformSearchPaths: hostOS.contains("unix") ? ['/usr', '/usr/local'] : []
- property pathList platformPaths
+ property pathList platformSearchPaths: Host.os().contains("unix") ? ['/usr', '/usr/local'] : []
property stringList environmentPaths
property stringList platformEnvironmentPaths
- property stringList hostOS: qbs.hostOS
- property string pathListSeparator: qbs.pathListSeparator
// Output
property stringList candidatePaths
@@ -57,23 +54,19 @@ Probe {
property varList allResults
configure: {
- if (pathPrefixes)
- console.warn("PathProbe.pathPrefixes is deprecated, use searchPaths instead");
- if (platformPaths)
- console.warn("PathProbe.platformPaths is deprecated, use platformSearchPaths instead");
- var _searchPaths = ModUtils.concatAll(pathPrefixes, searchPaths);
- var _platformSearchPaths = ModUtils.concatAll(platformPaths, platformSearchPaths);
var results = PathProbeConfigure.configure(selectors, names, nameSuffixes, nameFilter,
- candidateFilter, _searchPaths, pathSuffixes,
- _platformSearchPaths, environmentPaths,
- platformEnvironmentPaths, pathListSeparator);
+ candidateFilter, searchPaths, pathSuffixes,
+ platformSearchPaths, environmentPaths,
+ platformEnvironmentPaths);
found = results.found;
allResults = results.files;
- var result = allResults[0];
- candidatePaths = result.candidatePaths;
- path = result.path;
- filePath = result.filePath;
- fileName = result.fileName;
+ if (allResults.length === 1) {
+ var result = allResults[0];
+ candidatePaths = result.candidatePaths;
+ path = result.path;
+ filePath = result.filePath;
+ fileName = result.fileName;
+ }
}
}
diff --git a/share/qbs/imports/qbs/Probes/PkgConfigProbe.qbs b/share/qbs/imports/qbs/Probes/PkgConfigProbe.qbs
index b295c7441..0fe81c3cc 100644
--- a/share/qbs/imports/qbs/Probes/PkgConfigProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/PkgConfigProbe.qbs
@@ -28,6 +28,7 @@
**
****************************************************************************/
+import qbs.Host
import qbs.Process
import qbs.FileInfo
@@ -42,7 +43,6 @@ Probe {
property string maxVersion
property bool forStaticBuild: false
property stringList libDirs // Full, non-sysrooted paths, mirroring the environment variable
- property string pathListSeparator: qbs.pathListSeparator
// Output
property stringList cflags // Unmodified --cflags output
@@ -60,6 +60,7 @@ Probe {
if (!packageNames || packageNames.length === 0)
throw 'PkgConfigProbe.packageNames must be specified.';
var p = new Process();
+ var stdout;
try {
var libDirsToSet = libDirs;
if (sysroot) {
@@ -72,7 +73,7 @@ Probe {
}
}
if (libDirsToSet)
- p.setEnv("PKG_CONFIG_LIBDIR", libDirsToSet.join(pathListSeparator));
+ p.setEnv("PKG_CONFIG_LIBDIR", libDirsToSet.join(FileInfo.pathListSeparator()));
var versionArgs = [];
if (minVersion !== undefined)
versionArgs.push("--atleast-version=" + minVersion);
@@ -84,16 +85,22 @@ Probe {
&& p.exec(executable, versionArgs.concat(packageNames)) !== 0) {
return;
}
+
+ // protobuf is reserved as qbs module name, which depends on the protobuflib module
+ packageNames = packageNames.map(function(name) {
+ return name === "protobuflib" ? "protobuf" : name;
+ });
+
var args = packageNames;
if (p.exec(executable, args.concat([ '--cflags' ])) === 0) {
- cflags = p.readStdOut().trim();
- cflags = cflags ? cflags.split(/\s/) : [];
+ stdout = p.readStdOut().trim();
+ cflags = stdout ? stdout.split(/\s/): [];
var libsArgs = args.concat("--libs");
if (forStaticBuild)
libsArgs.push("--static");
if (p.exec(executable, libsArgs) === 0) {
- libs = p.readStdOut().trim();
- libs = libs ? libs.split(/\s/) : [];
+ stdout = p.readStdOut().trim();
+ libs = stdout ? stdout.split(/\s/): [];
if (p.exec(executable, [packageNames[0]].concat([ '--modversion' ])) === 0) {
modversion = p.readStdOut().trim();
found = true;
diff --git a/share/qbs/imports/qbs/Probes/QbsPkgConfigProbe.qbs b/share/qbs/imports/qbs/Probes/QbsPkgConfigProbe.qbs
new file mode 100644
index 000000000..5acec6bc0
--- /dev/null
+++ b/share/qbs/imports/qbs/Probes/QbsPkgConfigProbe.qbs
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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-pkg-config-probe.js" as PkgConfigProbeConfigure
+
+Probe {
+ // Inputs
+
+ property string _executableFilePath
+ property stringList _extraPaths
+ property stringList _libDirs
+ property bool _staticMode: false
+ property bool _definePrefix: false
+
+ property path _sysroot
+
+ // Output
+ property var packages
+ property var packagesByModuleName
+ property var brokenPackages
+ property stringList qmakePaths
+
+ configure: {
+ var result = PkgConfigProbeConfigure.configure(
+ _executableFilePath,
+ _extraPaths,
+ _libDirs,
+ _staticMode,
+ _definePrefix,
+ _sysroot);
+ packages = result.packages;
+ packagesByModuleName = result.packagesByModuleName;
+ brokenPackages = result.brokenPackages;
+ qmakePaths = result.qmakePaths;
+ found = true;
+ }
+}
diff --git a/share/qbs/imports/qbs/Probes/QmakeProbe.qbs b/share/qbs/imports/qbs/Probes/QmakeProbe.qbs
new file mode 100644
index 000000000..c50c6c851
--- /dev/null
+++ b/share/qbs/imports/qbs/Probes/QmakeProbe.qbs
@@ -0,0 +1,41 @@
+
+/****************************************************************************
+**
+** Copyright (C) 2023 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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 "qmake-probe.js" as QmakeProbeConfigure
+
+Probe {
+ property stringList qmakePaths
+ property varList qtInfos
+
+ configure: {
+ qtInfos = QmakeProbeConfigure.configure(qmakePaths);
+ }
+}
diff --git a/share/qbs/imports/qbs/Probes/SdccProbe.qbs b/share/qbs/imports/qbs/Probes/SdccProbe.qbs
index 3595bb158..ae616fa27 100644
--- a/share/qbs/imports/qbs/Probes/SdccProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/SdccProbe.qbs
@@ -33,17 +33,18 @@ import "../../../modules/cpp/sdcc.js" as SDCC
PathProbe {
// Inputs
- property string compilerFilePath;
- property string preferredArchitecture;
+ property string compilerFilePath
+ property stringList enableDefinesByLanguage
+ property string preferredArchitecture
// Outputs
- property string architecture;
- property string endianness;
- property int versionMajor;
- property int versionMinor;
- property int versionPatch;
- property stringList includePaths;
- property var compilerDefinesByLanguage;
+ property string architecture
+ property string endianness
+ property int versionMajor
+ property int versionMinor
+ property int versionPatch
+ property stringList includePaths
+ property var compilerDefinesByLanguage
configure: {
compilerDefinesByLanguage = {};
@@ -53,9 +54,22 @@ PathProbe {
return;
}
+ var languages = enableDefinesByLanguage;
+ if (!languages || languages.length === 0)
+ languages = ["c"];
+
+ // SDCC compiler support only the C-language.
+ if (!languages.contains("c")) {
+ found = false;
+ return;
+ }
+
var macros = SDCC.dumpMacros(compilerFilePath, preferredArchitecture);
+ if (!macros) {
+ found = false;
+ return;
+ }
- // SDCC it is only the C language compiler.
compilerDefinesByLanguage["c"] = macros;
architecture = SDCC.guessArchitecture(macros);
@@ -65,9 +79,11 @@ PathProbe {
includePaths = defaultPaths.includePaths;
var version = SDCC.guessVersion(macros);
- versionMajor = version.major;
- versionMinor = version.minor;
- versionPatch = version.patch;
- found = version.found;
+ if (version) {
+ versionMajor = version.major;
+ versionMinor = version.minor;
+ versionPatch = version.patch;
+ found = !!architecture && !!endianness;
+ }
}
}
diff --git a/share/qbs/imports/qbs/Probes/TypeScriptProbe.qbs b/share/qbs/imports/qbs/Probes/TypeScriptProbe.qbs
index a35e555cc..f494d6012 100644
--- a/share/qbs/imports/qbs/Probes/TypeScriptProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/TypeScriptProbe.qbs
@@ -30,6 +30,7 @@
import qbs.File
import qbs.FileInfo
+import qbs.Host
import qbs.ModUtils
import "path-probe.js" as PathProbeConfigure
import "../../../modules/typescript/typescript.js" as TypeScript
@@ -60,23 +61,29 @@ BinaryProbe {
var selectors;
var results = PathProbeConfigure.configure(
selectors, names, nameSuffixes, nameFilter, candidateFilter, searchPaths,
- pathSuffixes, platformSearchPaths, environmentPaths, platformEnvironmentPaths,
- pathListSeparator);
+ pathSuffixes, platformSearchPaths, environmentPaths, platformEnvironmentPaths);
- var v = new ModUtils.EnvironmentVariable("PATH", pathListSeparator,
- hostOS.contains("windows"));
+ var v = new ModUtils.EnvironmentVariable("PATH", FileInfo.pathListSeparator(),
+ Host.os().contains("windows"));
v.prepend(interpreterPath);
- var result = results.files[0];
- result.version = results.found
- ? TypeScript.findTscVersion(result.filePath, v.value)
- : undefined;
- if (FileInfo.fromNativeSeparators(packageManagerBinPath) !== result.path ||
- !File.exists(FileInfo.fromNativeSeparators(packageManagerRootPath, "typescript"))) {
- result = { found: false };
- }
+ var resultsMapper = function(result) {
+ result.version = result.found
+ ? TypeScript.findTscVersion(result.filePath, v.value)
+ : undefined;
+ if (FileInfo.fromNativeSeparators(packageManagerBinPath) !== result.path ||
+ !File.exists(
+ FileInfo.fromNativeSeparators(packageManagerRootPath, "typescript"))) {
+ result = { found: false };
+ }
+ return result;
+ };
+ results.files = results.files.map(resultsMapper);
found = results.found;
+ allResults = results.files;
+
+ var result = results.files[0];
candidatePaths = result.candidatePaths;
path = result.path;
filePath = result.filePath;
diff --git a/share/qbs/imports/qbs/Probes/WatcomProbe.qbs b/share/qbs/imports/qbs/Probes/WatcomProbe.qbs
new file mode 100644
index 000000000..3ea22acb3
--- /dev/null
+++ b/share/qbs/imports/qbs/Probes/WatcomProbe.qbs
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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.File
+import qbs.Host
+import qbs.ModUtils
+import "../../../modules/cpp/watcom.js" as WATCOM
+
+PathProbe {
+ // Inputs
+ property string compilerFilePath
+ property stringList enableDefinesByLanguage
+
+ property string _pathListSeparator
+ property string _toolchainInstallPath
+ property string _targetPlatform
+ property string _targetArchitecture
+
+ // Outputs
+ property string architecture
+ property string endianness
+ property string targetPlatform
+ property int versionMajor
+ property int versionMinor
+ property int versionPatch
+ property stringList includePaths
+ property var compilerDefinesByLanguage
+ property var environment
+
+ configure: {
+ compilerDefinesByLanguage = {};
+
+ if (!File.exists(compilerFilePath)) {
+ found = false;
+ return;
+ }
+
+ var languages = enableDefinesByLanguage;
+ if (!languages || languages.length === 0)
+ languages = ["c"];
+
+ environment = WATCOM.guessEnvironment(Host.os(), _targetPlatform, _targetArchitecture,
+ _toolchainInstallPath, _pathListSeparator);
+
+ includePaths = environment["INCLUDE"].split(_pathListSeparator).filter(function(path) {
+ return File.exists(path);
+ });
+
+ for (var i = 0; i < languages.length; ++i) {
+ var tag = languages[i];
+ compilerDefinesByLanguage[tag] = WATCOM.dumpMacros(
+ environment, compilerFilePath,
+ _targetPlatform, _targetArchitecture, tag);
+ }
+
+ var macros = compilerDefinesByLanguage["c"]
+ || compilerDefinesByLanguage["cpp"];
+
+ endianness = macros["__BIG_ENDIAN"] ? "big" : "little";
+ architecture = ModUtils.guessArchitecture(macros);
+ targetPlatform = ModUtils.guessTargetPlatform(macros);
+
+ var version = WATCOM.guessVersion(macros);
+ if (version) {
+ versionMajor = version.major;
+ versionMinor = version.minor;
+ versionPatch = version.patch;
+ found = !!architecture && !!targetPlatform;
+ }
+ }
+}
diff --git a/share/qbs/imports/qbs/Probes/XcodeLocationProbe.qbs b/share/qbs/imports/qbs/Probes/XcodeLocationProbe.qbs
new file mode 100644
index 000000000..3401315f7
--- /dev/null
+++ b/share/qbs/imports/qbs/Probes/XcodeLocationProbe.qbs
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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.Process
+
+Probe {
+ property path developerPath
+ configure: {
+ var p = new Process();
+ try {
+ p.exec("/usr/bin/xcode-select", ["--print-path"], true);
+ developerPath = p.readStdOut().trim();
+ } catch (e) {
+ developerPath = "/Applications/Xcode.app/Contents/Developer";
+ } finally {
+ p.close();
+ found = true;
+ }
+ }
+}
diff --git a/share/qbs/imports/qbs/Probes/XcodeProbe.qbs b/share/qbs/imports/qbs/Probes/XcodeProbe.qbs
index e0ed99346..9a0d01072 100644
--- a/share/qbs/imports/qbs/Probes/XcodeProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/XcodeProbe.qbs
@@ -48,6 +48,7 @@ Probe {
// Outputs
property var architectureSettings
property var availableSdks
+ property var platformSettings
property string xcodeVersion
configure: {
@@ -88,7 +89,7 @@ Probe {
architectureSettings = {};
var archSpecsPath = Xcode.archsSpecsPath(xcodeVersion, targetOS, platformType,
- platformPath, devicePlatformPath);
+ platformPath, devicePlatformPath, developerPath);
var archSpecsReader = new Xcode.XcodeArchSpecsReader(archSpecsPath);
archSpecsReader.getArchitectureSettings().map(function (setting) {
var val = archSpecsReader.getArchitectureSettingValue(setting);
@@ -97,6 +98,8 @@ Probe {
});
availableSdks = Xcode.sdkInfoList(sdksPath);
+ var platformInfoPlist = FileInfo.joinPaths(platformPath, "Info.plist");
+ platformSettings = Xcode.platformInfo(platformInfoPlist);
found = !!xcodeVersion;
}
}
diff --git a/share/qbs/imports/qbs/Probes/path-probe.js b/share/qbs/imports/qbs/Probes/path-probe.js
index a997f77f2..1858f5222 100644
--- a/share/qbs/imports/qbs/Probes/path-probe.js
+++ b/share/qbs/imports/qbs/Probes/path-probe.js
@@ -36,16 +36,16 @@ var ModUtils = require("qbs.ModUtils");
function asStringList(key, value) {
if (typeof(value) === "string")
return [value];
- if (Array.isArray(value))
+ if (value instanceof Array)
return value;
throw key + " must be a string or a stringList";
}
-function canonicalSelectors(selectors) {
+function canonicalSelectors(selectors, nameSuffixes) {
var mapper = function(selector) {
if (typeof(selector) === "string")
return {names : [selector]};
- if (Array.isArray(selector))
+ if (selector instanceof Array)
return {names : selector};
// dict
if (!selector.names)
@@ -53,14 +53,27 @@ function canonicalSelectors(selectors) {
selector.names = asStringList("names", selector.names);
if (selector.nameSuffixes)
selector.nameSuffixes = asStringList("nameSuffixes", selector.nameSuffixes);
+ else
+ selector.nameSuffixes = nameSuffixes;
return selector;
};
return selectors.map(mapper);
}
+function pathsFromEnvs(envs, pathListSeparator) {
+ envs = envs || [];
+ var result = [];
+ for (var i = 0; i < envs.length; ++i) {
+ var value = Environment.getEnv(envs[i]) || '';
+ if (value.length > 0)
+ result = result.concat(value.split(pathListSeparator));
+ }
+ return result;
+}
+
function configure(selectors, names, nameSuffixes, nameFilter, candidateFilter,
searchPaths, pathSuffixes, platformSearchPaths, environmentPaths,
- platformEnvironmentPaths, pathListSeparator) {
+ platformEnvironmentPaths) {
var result = { found: false, files: [] };
if (!selectors && !names)
throw '"names" or "selectors" must be specified';
@@ -70,7 +83,7 @@ function configure(selectors, names, nameSuffixes, nameFilter, candidateFilter,
{names: names, nameSuffixes: nameSuffixes}
];
} else {
- selectors = canonicalSelectors(selectors);
+ selectors = canonicalSelectors(selectors, nameSuffixes);
}
if (nameFilter) {
@@ -88,14 +101,11 @@ function configure(selectors, names, nameSuffixes, nameFilter, candidateFilter,
});
// FIXME: Suggest how to obtain paths from system
- var _paths = ModUtils.concatAll(searchPaths, platformSearchPaths);
- // FIXME: Add getenv support
- var envs = ModUtils.concatAll(platformEnvironmentPaths, environmentPaths);
- for (var i = 0; i < envs.length; ++i) {
- var value = Environment.getEnv(envs[i]) || '';
- if (value.length > 0)
- _paths = _paths.concat(value.split(pathListSeparator));
- }
+ var _paths = ModUtils.concatAll(
+ pathsFromEnvs(environmentPaths, FileInfo.pathListSeparator()),
+ searchPaths,
+ pathsFromEnvs(platformEnvironmentPaths, FileInfo.pathListSeparator()),
+ platformSearchPaths);
var _suffixes = ModUtils.concatAll('', pathSuffixes);
_paths = _paths.map(function(p) { return FileInfo.fromNativeSeparators(p); });
_suffixes = _suffixes.map(function(p) { return FileInfo.fromNativeSeparators(p); });
diff --git a/share/qbs/imports/qbs/Probes/qbs-pkg-config-probe.js b/share/qbs/imports/qbs/Probes/qbs-pkg-config-probe.js
new file mode 100644
index 000000000..d382dfb02
--- /dev/null
+++ b/share/qbs/imports/qbs/Probes/qbs-pkg-config-probe.js
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2023 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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.
+**
+****************************************************************************/
+
+var Environment = require("qbs.Environment");
+var File = require("qbs.File");
+var FileInfo = require("qbs.FileInfo");
+var PkgConfig = require("qbs.PkgConfig");
+var ProviderUtils = require("qbs.ProviderUtils");
+var Process = require("qbs.Process");
+
+function getQmakePaths(pkg) {
+ var packageName = pkg.baseFileName;
+ if (packageName === "QtCore"
+ || packageName === "Qt5Core"
+ || packageName === "Qt6Core") {
+ var binDir = pkg.variables["bindir"] || pkg.variables["host_bins"];
+ if (!binDir) {
+ if (packageName === "QtCore") { // Qt4 does not have host_bins
+ var mocLocation = pkg.variables["moc_location"];
+ if (!mocLocation) {
+ console.warn("No moc_location variable in " + packageName);
+ return;
+ }
+ binDir = FileInfo.path(mocLocation);
+ } else {
+ console.warn("No 'bindir' or 'host_bins' variable in " + packageName);
+ return;
+ }
+ }
+ var suffix = FileInfo.executableSuffix();
+ return [FileInfo.joinPaths(binDir, "qmake" + suffix)];
+ }
+}
+
+function configure(
+ executableFilePath, extraPaths, libDirs, staticMode, definePrefix, sysroot) {
+
+ var result = {};
+ result.packages = [];
+ result.packagesByModuleName = {};
+ result.brokenPackages = [];
+ result.qtInfos = [];
+
+ var options = {};
+ options.libDirs = libDirs;
+ options.sysroot = sysroot;
+ options.definePrefix = definePrefix;
+ if (options.sysroot)
+ options.allowSystemLibraryPaths = true;
+ options.staticMode = staticMode;
+ options.extraPaths = extraPaths;
+ if (options.sysroot && !options.libDirs) {
+ options.libDirs = [
+ options.sysroot + "/usr/lib/pkgconfig",
+ options.sysroot + "/usr/share/pkgconfig"
+ ];
+ }
+ if (!options.libDirs) {
+ // if we have pkg-config/pkgconf installed, let's ask it for its search paths (since
+ // built-in search paths can differ between platforms)
+ if (executableFilePath) {
+ var p = new Process()
+ if (p.exec(executableFilePath, ['pkg-config', '--variable=pc_path']) === 0) {
+ var stdout = p.readStdOut().trim();
+ options.libDirs = stdout ? stdout.split(FileInfo.pathListSeparator()): [];
+ var installDir = FileInfo.path(executableFilePath);
+ options.libDirs = options.libDirs.map(function(path){
+ if (FileInfo.isAbsolutePath(path))
+ return path;
+ return FileInfo.cleanPath(FileInfo.joinPaths(installDir, path));
+ });
+ }
+ }
+ }
+ var pkgConfig = new PkgConfig(options);
+ result.packages = pkgConfig.packages();
+ for (var packageName in result.packages) {
+ var pkg = result.packages[packageName];
+ var moduleName = ProviderUtils.pkgConfigToModuleName(packageName);
+ result.packagesByModuleName[moduleName] = pkg;
+
+ if (packageName.startsWith("Qt")) {
+ if (!sysroot) {
+ var qmakePaths = getQmakePaths(pkg);
+ if (qmakePaths !== undefined)
+ result.qmakePaths = qmakePaths;
+ }
+ }
+ }
+ return result;
+}
diff --git a/share/qbs/imports/qbs/Probes/qmake-probe.js b/share/qbs/imports/qbs/Probes/qmake-probe.js
new file mode 100644
index 000000000..746914e20
--- /dev/null
+++ b/share/qbs/imports/qbs/Probes/qmake-probe.js
@@ -0,0 +1,1256 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+var Environment = require("qbs.Environment");
+var File = require("qbs.File");
+var FileInfo = require("qbs.FileInfo");
+var Host = require("qbs.Host");
+var Process = require("qbs.Process");
+var ProviderUtils = require("qbs.ProviderUtils");
+var TextFile = require("qbs.TextFile");
+var Utilities = require("qbs.Utilities");
+
+function splitNonEmpty(s, c) { return s.split(c).filter(function(e) { return e; }); }
+
+function getQmakeFilePaths(qmakeFilePaths) {
+ if (qmakeFilePaths && qmakeFilePaths.length > 0)
+ return qmakeFilePaths;
+ console.info("Detecting Qt installations...");
+ var filePaths = [];
+ var pathValue = Environment.getEnv("PATH");
+ if (pathValue) {
+ var dirs = splitNonEmpty(pathValue, FileInfo.pathListSeparator());
+ for (var i = 0; i < dirs.length; ++i) {
+ var candidate = FileInfo.joinPaths(dirs[i], "qmake" + FileInfo.executableSuffix());
+ var canonicalCandidate = FileInfo.canonicalPath(candidate);
+ if (!canonicalCandidate || !File.exists(canonicalCandidate))
+ continue;
+ if (FileInfo.completeBaseName(canonicalCandidate) !== "qtchooser")
+ candidate = canonicalCandidate;
+ if (!filePaths.contains(candidate)) {
+ console.info("Found Qt at '" + FileInfo.toNativeSeparators(candidate) + "'.");
+ filePaths.push(candidate);
+ }
+ }
+ }
+ if (filePaths.length === 0) {
+ console.warn("Could not find any qmake executables in PATH. Either make sure a qmake "
+ + "executable is present in PATH or set the moduleProviders.Qt.qmakeFilePaths property "
+ + "to point to a qmake executable.");
+ }
+ return filePaths;
+}
+
+function queryQmake(qmakeFilePath) {
+ var qmakeProcess = new Process;
+ qmakeProcess.exec(qmakeFilePath, ["-query"]);
+ if (qmakeProcess.exitCode() !== 0) {
+ throw "The qmake executable '" + FileInfo.toNativeSeparators(qmakeFilePath)
+ + "' failed with exit code " + qmakeProcess.exitCode() + ".";
+ }
+ var queryResult = {};
+ while (!qmakeProcess.atEnd()) {
+ var line = qmakeProcess.readLine();
+ var index = (line || "").indexOf(":");
+ if (index !== -1)
+ queryResult[line.slice(0, index)] = line.slice(index + 1).trim();
+ }
+ return queryResult;
+}
+
+function pathQueryValue(queryResult, key) {
+ var p = queryResult[key];
+ if (p)
+ return FileInfo.fromNativeSeparators(p);
+}
+
+function readFileContent(filePath) {
+ var f = new TextFile(filePath, TextFile.ReadOnly);
+ var content = f.readAll();
+ f.close();
+ return content;
+}
+
+// TODO: Don't do the split every time...
+function configVariable(configContent, key) {
+ var configContentLines = configContent.split('\n');
+ var regexp = new RegExp("^\\s*" + key + "\\s*\\+{0,1}=(.*)");
+ for (var i = 0; i < configContentLines.length; ++i) {
+ var line = configContentLines[i];
+ var match = regexp.exec(line);
+ if (match)
+ return match[1].trim();
+ }
+}
+
+function configVariableItems(configContent, key) {
+ return splitNonEmpty(configVariable(configContent, key), ' ');
+}
+
+function msvcCompilerVersionForYear(year) {
+ var mapping = {
+ "2005": "14", "2008": "15", "2010": "16", "2012": "17", "2013": "18", "2015": "19",
+ "2017": "19.1", "2019": "19.2"
+ };
+ return mapping[year];
+}
+
+function msvcCompilerVersionFromMkspecName(mkspecName) {
+ return msvcCompilerVersionForYear(mkspecName.slice(msvcPrefix().length));
+}
+
+function addQtBuildVariant(qtProps, buildVariantName) {
+ if (qtProps.qtConfigItems.contains(buildVariantName))
+ qtProps.buildVariant.push(buildVariantName);
+}
+
+function checkForStaticBuild(qtProps) {
+ if (qtProps.qtMajorVersion >= 5)
+ return qtProps.qtConfigItems.contains("static");
+ if (qtProps.frameworkBuild)
+ return false; // there are no Qt4 static frameworks
+ var isWin = qtProps.mkspecName.startsWith("win");
+ var libDir = isWin ? qtProps.binaryPath : qtProps.libraryPath;
+ var coreLibFiles = File.directoryEntries(libDir, File.Files)
+ .filter(function(fp) { return fp.contains("Core"); });
+ if (coreLibFiles.length === 0)
+ throw "Could not determine whether Qt is a static build.";
+ for (var i = 0; i < coreLibFiles.length; ++i) {
+ if (Utilities.isSharedLibrary(coreLibFiles[i]))
+ return false;
+ }
+ return true;
+}
+
+function guessMinimumWindowsVersion(qtProps) {
+ if (qtProps.mkspecName.startsWith("winrt-"))
+ return "10.0";
+ if (!ProviderUtils.isDesktopWindowsQt(qtProps))
+ return "";
+ if (qtProps.qtMajorVersion >= 6)
+ return "10.0";
+ if (qtProps.architecture === "x86_64" || qtProps.architecture === "ia64")
+ return "5.2"
+ var match = qtProps.mkspecName.match(/^win32-msvc(\d+)$/);
+ if (match) {
+ var msvcVersion = match[1];
+ if (msvcVersion < 2012)
+ return "5.0";
+ return "5.1";
+ }
+ return qtProps.qtMajorVersion < 5 ? "5.0" : "5.1";
+}
+
+function fillEntryPointLibs(qtProps, debug) {
+ result = [];
+ var isMinGW = ProviderUtils.isMinGwQt(qtProps);
+
+ // Some Linux distributions rename the qtmain library.
+ var qtMainCandidates = ["qtmain"];
+ if (isMinGW && qtProps.qtMajorVersion === 5)
+ qtMainCandidates.push("qt5main");
+ if (qtProps.qtMajorVersion === 6)
+ qtMainCandidates.push("Qt6EntryPoint");
+
+ for (var i = 0; i < qtMainCandidates.length; ++i) {
+ var baseNameCandidate = qtMainCandidates[i];
+ var qtmain = qtProps.libraryPath + '/';
+ if (isMinGW)
+ qtmain += "lib";
+ qtmain += baseNameCandidate + qtProps.qtLibInfix;
+ if (debug && ProviderUtils.qtNeedsDSuffix(qtProps))
+ qtmain += 'd';
+ if (isMinGW) {
+ qtmain += ".a";
+ } else {
+ qtmain += ".lib";
+ if (Utilities.versionCompare(qtProps.qtVersion, "5.4.0") >= 0)
+ result.push("Shell32.lib");
+ }
+ if (File.exists(qtmain)) {
+ result.push(qtmain);
+ break;
+ }
+ }
+ if (result.length === 0) {
+ console.warn("Could not find the qtmain library at '"
+ + FileInfo.toNativeSeparators(qtProps.libraryPath)
+ + "'. You will not be able to link Qt applications.");
+ }
+ return result;
+}
+
+function getQtProperties(qmakeFilePath) {
+ var queryResult = queryQmake(qmakeFilePath);
+ var qtProps = {};
+ qtProps.installPrefixPath = pathQueryValue(queryResult, "QT_INSTALL_PREFIX");
+ qtProps.documentationPath = pathQueryValue(queryResult, "QT_INSTALL_DOCS");
+ qtProps.includePath = pathQueryValue(queryResult, "QT_INSTALL_HEADERS");
+ qtProps.libraryPath = pathQueryValue(queryResult, "QT_INSTALL_LIBS");
+ qtProps.hostLibraryPath = pathQueryValue(queryResult, "QT_HOST_LIBS");
+ qtProps.binaryPath = pathQueryValue(queryResult, "QT_HOST_BINS")
+ || pathQueryValue(queryResult, "QT_INSTALL_BINS");
+ qtProps.installPath = pathQueryValue(queryResult, "QT_INSTALL_BINS");
+ qtProps.documentationPath = pathQueryValue(queryResult, "QT_INSTALL_DOCS");
+ qtProps.pluginPath = pathQueryValue(queryResult, "QT_INSTALL_PLUGINS");
+ qtProps.qmlPath = pathQueryValue(queryResult, "QT_INSTALL_QML");
+ qtProps.qmlImportPath = pathQueryValue(queryResult, "QT_INSTALL_IMPORTS");
+ qtProps.qtVersion = queryResult.QT_VERSION;
+
+ var mkspecsBaseSrcPath;
+ if (Utilities.versionCompare(qtProps.qtVersion, "5") >= 0) {
+ qtProps.mkspecBasePath = FileInfo.joinPaths(pathQueryValue(queryResult, "QT_HOST_DATA"),
+ "mkspecs");
+ mkspecsBaseSrcPath = FileInfo.joinPaths(pathQueryValue(queryResult, "QT_HOST_DATA/src"),
+ "mkspecs");
+ } else {
+ qtProps.mkspecBasePath = FileInfo.joinPaths
+ (pathQueryValue(queryResult, "QT_INSTALL_DATA"), "mkspecs");
+ }
+
+ if (Utilities.versionCompare(qtProps.qtVersion, "6") >= 0) {
+ qtProps.libExecPath = pathQueryValue(queryResult, "QT_HOST_LIBEXECS")
+ || pathQueryValue(queryResult, "QT_INSTALL_LIBEXECS");
+ }
+
+ // QML tools were only moved in Qt 6.2.
+ qtProps.qmlLibExecPath = Utilities.versionCompare(qtProps.qtVersion, "6.2") >= 0
+ ? qtProps.libExecPath : qtProps.binaryPath;
+
+ // qhelpgenerator was only moved in Qt 6.3.
+ qtProps.helpGeneratorLibExecPath = Utilities.versionCompare(qtProps.qtVersion, "6.3") >= 0
+ ? qtProps.libExecPath : qtProps.binaryPath;
+
+ if (!File.exists(qtProps.mkspecBasePath))
+ throw "Cannot extract the mkspecs directory.";
+
+ var qconfigContent = readFileContent(FileInfo.joinPaths(qtProps.mkspecBasePath,
+ "qconfig.pri"));
+ qtProps.qtMajorVersion = parseInt(configVariable(qconfigContent, "QT_MAJOR_VERSION"));
+ qtProps.qtMinorVersion = parseInt(configVariable(qconfigContent, "QT_MINOR_VERSION"));
+ qtProps.qtPatchVersion = parseInt(configVariable(qconfigContent, "QT_PATCH_VERSION"));
+ qtProps.qtNameSpace = configVariable(qconfigContent, "QT_NAMESPACE");
+ qtProps.qtLibInfix = configVariable(qconfigContent, "QT_LIBINFIX") || "";
+ qtProps.architecture = configVariable(qconfigContent, "QT_TARGET_ARCH")
+ || configVariable(qconfigContent, "QT_ARCH") || "x86";
+ qtProps.configItems = configVariableItems(qconfigContent, "CONFIG");
+ qtProps.qtConfigItems = configVariableItems(qconfigContent, "QT_CONFIG");
+
+ // retrieve the mkspec
+ if (qtProps.qtMajorVersion >= 5) {
+ qtProps.mkspecName = queryResult.QMAKE_XSPEC;
+ qtProps.mkspecPath = FileInfo.joinPaths(qtProps.mkspecBasePath, qtProps.mkspecName);
+ if (mkspecsBaseSrcPath && !File.exists(qtProps.mkspecPath))
+ qtProps.mkspecPath = FileInfo.joinPaths(mkspecsBaseSrcPath, qtProps.mkspecName);
+ } else {
+ if (Host.os().contains("windows")) {
+ var baseDirPath = FileInfo.joinPaths(qtProps.mkspecBasePath, "default");
+ var fileContent = readFileContent(FileInfo.joinPaths(baseDirPath, "qmake.conf"));
+ qtProps.mkspecPath = configVariable(fileContent, "QMAKESPEC_ORIGINAL");
+ if (!File.exists(qtProps.mkspecPath)) {
+ // Work around QTBUG-28792.
+ // The value of QMAKESPEC_ORIGINAL is wrong for MinGW packages. Y u h8 me?
+ var match = fileContent.exec(/\binclude\(([^)]+)\/qmake\.conf\)/m);
+ if (match) {
+ qtProps.mkspecPath = FileInfo.cleanPath(FileInfo.joinPaths(
+ baseDirPath, match[1]));
+ }
+ }
+ } else {
+ qtProps.mkspecPath = FileInfo.canonicalPath(
+ FileInfo.joinPaths(qtProps.mkspecBasePath, "default"));
+ }
+
+ // E.g. in qmake.conf for Qt 4.8/mingw we find this gem:
+ // QMAKESPEC_ORIGINAL=C:\\Qt\\Qt\\4.8\\mingw482\\mkspecs\\win32-g++
+ qtProps.mkspecPath = FileInfo.cleanPath(qtProps.mkspecPath);
+
+ qtProps.mkspecName = qtProps.mkspecPath;
+ var idx = qtProps.mkspecName.lastIndexOf('/');
+ if (idx !== -1)
+ qtProps.mkspecName = qtProps.mkspecName.slice(idx + 1);
+ }
+ if (!File.exists(qtProps.mkspecPath))
+ throw "mkspec '" + FileInfo.toNativeSeparators(qtProps.mkspecPath) + "' does not exist";
+
+ // Starting with qt 5.14, android sdk provides multi-abi
+ if (Utilities.versionCompare(qtProps.qtVersion, "5.14.0") >= 0
+ && qtProps.mkspecPath.contains("android")) {
+ var qdeviceContent = readFileContent(FileInfo.joinPaths(qtProps.mkspecBasePath,
+ "qdevice.pri"));
+ qtProps.androidAbis = configVariable(qdeviceContent, "DEFAULT_ANDROID_ABIS").split(' ');
+ }
+
+ // determine MSVC version
+ if (ProviderUtils.isMsvcQt(qtProps)) {
+ var msvcMajor = configVariable(qconfigContent, "QT_MSVC_MAJOR_VERSION");
+ var msvcMinor = configVariable(qconfigContent, "QT_MSVC_MINOR_VERSION");
+ var msvcPatch = configVariable(qconfigContent, "QT_MSVC_PATCH_VERSION");
+ if (msvcMajor && msvcMinor && msvcPatch)
+ qtProps.msvcVersion = msvcMajor + "." + msvcMinor + "." + msvcPatch;
+ else
+ qtProps.msvcVersion = msvcCompilerVersionFromMkspecName(qtProps.mkspecName);
+ }
+
+ // determine whether we have a framework build
+ qtProps.frameworkBuild = qtProps.mkspecPath.contains("macx")
+ && qtProps.configItems.contains("qt_framework");
+
+ // determine whether Qt is built with debug, release or both
+ qtProps.buildVariant = [];
+ addQtBuildVariant(qtProps, "debug");
+ addQtBuildVariant(qtProps, "release");
+
+ qtProps.staticBuild = checkForStaticBuild(qtProps);
+
+ // determine whether user apps require C++11
+ if (qtProps.qtConfigItems.contains("c++11") && qtProps.staticBuild)
+ qtProps.configItems.push("c++11");
+
+ // Set the minimum operating system versions appropriate for this Qt version
+ qtProps.windowsVersion = guessMinimumWindowsVersion(qtProps);
+ if (qtProps.windowsVersion) { // Is target OS Windows?
+ if (qtProps.buildVariant.contains("debug"))
+ qtProps.entryPointLibsDebug = fillEntryPointLibs(qtProps, true);
+ if (qtProps.buildVariant.contains("release"))
+ qtProps.entryPointLibsRelease = fillEntryPointLibs(qtProps, false);
+ } else if (qtProps.mkspecPath.contains("macx")) {
+ if (qtProps.qtMajorVersion >= 5) {
+ // Since Qt 6.7.1, QMAKE_MACOSX|IOS_DEPLOYMENT_TARGET is no longer present in
+ // qmake.conf. But it is also present in qconfig.pri, so first try to read it from there
+ qtProps.macosVersion = configVariable(qconfigContent, "QMAKE_MACOSX_DEPLOYMENT_TARGET");
+ qtProps.iosVersion = configVariable(qconfigContent, "QMAKE_IOS_DEPLOYMENT_TARGET");
+
+ // Next, we override the value from qmake.conf, if present there
+ // Note, that TVOS/WATCHOS variables are only present in qmake.conf (as of Qt 6.7.1)
+ var lines = getFileContentsRecursively(FileInfo.joinPaths(qtProps.mkspecPath,
+ "qmake.conf"));
+ for (var i = 0; i < lines.length; ++i) {
+ var line = lines[i].trim();
+ match = line.match
+ (/^QMAKE_(MACOSX|IOS|TVOS|WATCHOS)_DEPLOYMENT_TARGET\s*=\s*(.*)\s*$/);
+ if (match) {
+ var platform = match[1];
+ var version = match[2];
+ if (platform === "MACOSX")
+ qtProps.macosVersion = version;
+ else if (platform === "IOS")
+ qtProps.iosVersion = version;
+ else if (platform === "TVOS")
+ qtProps.tvosVersion = version;
+ else if (platform === "WATCHOS")
+ qtProps.watchosVersion = version;
+ }
+ }
+ var isMac = qtProps.mkspecName !== "macx-ios-clang"
+ && qtProps.mkspecName !== "macx-tvos-clang"
+ && qtProps.mkspecName !== "macx-watchos-clang";
+ if (isMac) {
+ // Qt 5.0.x placed the minimum version in a different file
+ if (!qtProps.macosVersion)
+ qtProps.macosVersion = "10.6";
+
+ // If we're using C++11 with libc++, make sure the deployment target is >= 10.7
+ if (Utilities.versionCompare(qtProps.macosVersion, "10, 7") < 0
+ && qtProps.qtConfigItems.contains("c++11")) {
+ qtProps.macosVersion = "10.7";
+ }
+ }
+ } else if (qtProps.qtMajorVersion === 4 && qtProps.qtMinorVersion >= 6) {
+ var qconfigDir = qtProps.frameworkBuild
+ ? FileInfo.joinPaths(qtProps.libraryPath, "QtCore.framework", "Headers")
+ : FileInfo.joinPaths(qtProps.includePath, "Qt");
+ try {
+ var qconfig = new TextFile(FileInfo.joinPaths(qconfigDir, "qconfig.h"),
+ TextFile.ReadOnly);
+ var qtCocoaBuild = false;
+ var ok = true;
+ do {
+ line = qconfig.readLine();
+ if (line.match(/\s*#define\s+QT_MAC_USE_COCOA\s+1\s*/)) {
+ qtCocoaBuild = true;
+ break;
+ }
+ } while (!qconfig.atEof());
+ qtProps.macosVersion = qtCocoaBuild ? "10.5" : "10.4";
+ }
+ catch (e) {}
+ finally {
+ if (qconfig)
+ qconfig.close();
+ }
+ if (!qtProps.macosVersion) {
+ throw "Could not determine whether Qt is using Cocoa or Carbon from '"
+ + FileInfo.toNativeSeparators(qconfig.filePath()) + "'.";
+ }
+ }
+ } else if (qtProps.mkspecPath.contains("android")) {
+ if (qtProps.qtMajorVersion >= 5)
+ qtProps.androidVersion = "2.3";
+ else if (qtProps.qtMajorVersion === 4 && qtProps.qtMinorVersion >= 8)
+ qtProps.androidVersion = "1.6"; // Necessitas
+ }
+ return qtProps;
+}
+
+function makePluginData() {
+ var pluginData = {};
+ pluginData.type = undefined;
+ pluginData.className = undefined;
+ pluginData.autoLoad = true;
+ pluginData["extends"] = [];
+ return pluginData;
+}
+
+function makeQtModuleInfo(name, qbsName, deps) {
+ var moduleInfo = {};
+ moduleInfo.name = name; // As in the path to the headers and ".name" in the pri files.
+ if (moduleInfo.name === undefined)
+ moduleInfo.name = "";
+ moduleInfo.qbsName = qbsName; // Lower-case version without "qt" prefix.
+ moduleInfo.dependencies = deps || []; // qbs names.
+ if (moduleInfo.qbsName && moduleInfo.qbsName !== "core"
+ && !moduleInfo.dependencies.contains("core")) {
+ moduleInfo.dependencies.unshift("core");
+ }
+ moduleInfo.isPrivate = qbsName && qbsName.endsWith("-private");
+ moduleInfo.hasLibrary = !moduleInfo.isPrivate;
+ moduleInfo.isStaticLibrary = false;
+ moduleInfo.isPlugin = false;
+ moduleInfo.mustExist = true;
+ moduleInfo.modulePrefix = ""; // empty value means "Qt".
+ moduleInfo.version = undefined;
+ moduleInfo.includePaths = [];
+ moduleInfo.compilerDefines = [];
+ moduleInfo.staticLibrariesDebug = [];
+ moduleInfo.staticLibrariesRelease = [];
+ moduleInfo.dynamicLibrariesDebug = [];
+ moduleInfo.dynamicLibrariesRelease = [];
+ moduleInfo.linkerFlagsDebug = [];
+ moduleInfo.linkerFlagsRelease = [];
+ moduleInfo.libFilePathDebug = undefined;
+ moduleInfo.libFilePathRelease = undefined;
+ moduleInfo.frameworksDebug = [];
+ moduleInfo.frameworksRelease = [];
+ moduleInfo.frameworkPathsDebug = [];
+ moduleInfo.frameworkPathsRelease = [];
+ moduleInfo.libraryPaths = [];
+ moduleInfo.libDir = "";
+ moduleInfo.config = [];
+ moduleInfo.supportedPluginTypes = [];
+ moduleInfo.pluginData = makePluginData();
+ return moduleInfo;
+}
+
+function frameworkHeadersPath(qtModuleInfo, qtProps) {
+ return FileInfo.joinPaths(qtProps.libraryPath, qtModuleInfo.name + ".framework", "Headers");
+}
+
+function qt4ModuleIncludePaths(qtModuleInfo, qtProps) {
+ var paths = [];
+ if (ProviderUtils.qtIsFramework(qtModuleInfo, qtProps))
+ paths.push(frameworkHeadersPath(qtModuleInfo, qtProps));
+ else
+ paths.push(qtProps.includePath, FileInfo.joinPaths(qtProps.includePath, qtModuleInfo.name));
+ return paths;
+}
+
+// We erroneously called the "testlib" module "test" for quite a while. Let's not punish users
+// for that.
+function addTestModule(modules) {
+ var testModule = makeQtModuleInfo("QtTest", "test", ["testlib"]);
+ testModule.hasLibrary = false;
+ modules.push(testModule);
+}
+
+// See above.
+function addDesignerComponentsModule(modules) {
+ var module = makeQtModuleInfo("QtDesignerComponents", "designercomponents",
+ ["designercomponents-private"]);
+ module.hasLibrary = false;
+ modules.push(module);
+}
+
+function guessLibraryFilePath(prlFilePath, libDir, qtProps) {
+ var baseName = FileInfo.baseName(prlFilePath);
+ var prefixCandidates = ["", "lib"];
+ var suffixCandidates = ["so." + qtProps.qtVersion, "so", "a", "lib", "dll.a"];
+ for (var i = 0; i < prefixCandidates.length; ++i) {
+ var prefix = prefixCandidates[i];
+ for (var j = 0; j < suffixCandidates.length; ++j) {
+ var suffix = suffixCandidates[j];
+ var candidate = FileInfo.joinPaths(libDir, prefix + baseName + '.' + suffix);
+ if (File.exists(candidate))
+ return candidate;
+ }
+ }
+}
+
+function doReplaceQtLibNamesWithFilePath(namePathMap, libList) {
+ for (var i = 0; i < libList.length; ++i) {
+ var lib = libList[i];
+ var path = namePathMap[lib];
+ if (path)
+ libList[i] = path;
+ }
+}
+
+function replaceQtLibNamesWithFilePath(modules, qtProps) {
+ // We don't want to add the libraries for Qt modules via "-l", because of the
+ // danger that a wrong one will be picked up, e.g. from /usr/lib. Instead,
+ // we pull them in using the full file path.
+ var linkerNamesToFilePathsDebug = {};
+ var linkerNamesToFilePathsRelease = {};
+ for (var i = 0; i < modules.length; ++i) {
+ var m = modules[i];
+ linkerNamesToFilePathsDebug[
+ ProviderUtils.qtLibNameForLinker(m, qtProps, true)] = m.libFilePathDebug;
+ linkerNamesToFilePathsRelease[
+ ProviderUtils.qtLibNameForLinker(m, qtProps, false)] = m.libFilePathRelease;
+ }
+ for (i = 0; i < modules.length; ++i) {
+ var module = modules[i];
+ doReplaceQtLibNamesWithFilePath(linkerNamesToFilePathsDebug, module.dynamicLibrariesDebug);
+ doReplaceQtLibNamesWithFilePath(linkerNamesToFilePathsDebug, module.staticLibrariesDebug);
+ doReplaceQtLibNamesWithFilePath(linkerNamesToFilePathsRelease,
+ module.dynamicLibrariesRelease);
+ doReplaceQtLibNamesWithFilePath(linkerNamesToFilePathsRelease,
+ module.staticLibrariesRelease);
+ }
+}
+
+function doSetupLibraries(modInfo, qtProps, debugBuild, nonExistingPrlFiles, androidAbi) {
+ if (!modInfo.hasLibrary)
+ return; // Can happen for Qt4 convenience modules, like "widgets".
+
+ if (debugBuild) {
+ if (!qtProps.buildVariant.contains("debug"))
+ return;
+ var modulesNeverBuiltAsDebug = ["bootstrap", "qmldevtools"];
+ for (var i = 0; i < modulesNeverBuiltAsDebug.length; ++i) {
+ var m = modulesNeverBuiltAsDebug[i];
+ if (modInfo.qbsName === m || modInfo.qbsName === m + "-private")
+ return;
+ }
+ } else if (!qtProps.buildVariant.contains("release")) {
+ return;
+ }
+
+ var libs = modInfo.isStaticLibrary
+ ? (debugBuild ? modInfo.staticLibrariesDebug : modInfo.staticLibrariesRelease)
+ : (debugBuild ? modInfo.dynamicLibrariesDebug : modInfo.dynamicLibrariesRelease);
+ var frameworks = debugBuild ? modInfo.frameworksDebug : modInfo.frameworksRelease;
+ var frameworkPaths = debugBuild ? modInfo.frameworkPathsDebug : modInfo.frameworkPathsRelease;
+ var flags = debugBuild ? modInfo.linkerFlagsDebug : modInfo.linkerFlagsRelease;
+ var libFilePath;
+
+ if (qtProps.mkspecName.contains("ios") && modInfo.isStaticLibrary) {
+ libs.push("z", "m");
+ if (qtProps.qtMajorVersion === 5 && qtProps.qtMinorVersion < 8) {
+ var platformSupportModule = makeQtModuleInfo("QtPlatformSupport", "platformsupport");
+ libs.push(ProviderUtils.qtLibNameForLinker(platformSupportModule, qtProps, debugBuild));
+ }
+ if (modInfo.name === "qios") {
+ flags.push("-force_load", FileInfo.joinPaths(
+ qtProps.pluginPath, "platforms",
+ ProviderUtils.qtLibBaseName(
+ modInfo, "libqios", debugBuild, qtProps) + ".a"));
+ }
+ }
+ var prlFilePath = modInfo.isPlugin
+ ? FileInfo.joinPaths(qtProps.pluginPath, modInfo.pluginData.type)
+ : (modInfo.libDir ? modInfo.libDir : qtProps.libraryPath);
+ var libDir = prlFilePath;
+ if (ProviderUtils.qtIsFramework(modInfo, qtProps)) {
+ prlFilePath = FileInfo.joinPaths(
+ prlFilePath,
+ ProviderUtils.qtLibraryBaseName(modInfo, qtProps, false) + ".framework");
+ libDir = prlFilePath;
+ if (Utilities.versionCompare(qtProps.qtVersion, "5.14") >= 0)
+ prlFilePath = FileInfo.joinPaths(prlFilePath, "Resources");
+ }
+ var baseName = ProviderUtils.qtLibraryBaseName(modInfo, qtProps, debugBuild);
+ if (!qtProps.mkspecName.startsWith("win") && !ProviderUtils.qtIsFramework(modInfo, qtProps))
+ baseName = "lib" + baseName;
+ prlFilePath = FileInfo.joinPaths(prlFilePath, baseName);
+ var isNonStaticQt4OnWindows = qtProps.mkspecName.startsWith("win")
+ && !modInfo.isStaticLibrary && qtProps.qtMajorVersion < 5;
+ if (isNonStaticQt4OnWindows)
+ prlFilePath = prlFilePath.slice(0, prlFilePath.length - 1); // The prl file base name does *not* contain the version number...
+ // qt for android versions 6.0 and 6.1 don't have the architecture suffix in the prl file
+ if (androidAbi.length > 0
+ && modInfo.name !== "QtBootstrap"
+ && (modInfo.name !== "QtQmlDevTools" || modInfo.name === "QtQmlDevTools"
+ && Utilities.versionCompare(qtProps.qtVersion, "6.2") >= 0)
+ && (Utilities.versionCompare(qtProps.qtVersion, "6.0") < 0
+ || Utilities.versionCompare(qtProps.qtVersion, "6.2") >= 0)) {
+ prlFilePath += "_";
+ prlFilePath += androidAbi;
+ }
+
+ prlFilePath += ".prl";
+
+ try {
+ var prlFile = new TextFile(prlFilePath, TextFile.ReadOnly);
+ while (!prlFile.atEof()) {
+ var line = prlFile.readLine().trim();
+ var equalsOffset = line.indexOf('=');
+ if (equalsOffset === -1)
+ continue;
+ if (line.startsWith("QMAKE_PRL_TARGET")) {
+ var isMingw = qtProps.mkspecName.startsWith("win")
+ && qtProps.mkspecName.contains("g++");
+ var isQtVersionBefore56 = qtProps.qtMajorVersion < 5
+ || (qtProps.qtMajorVersion === 5 && qtProps.qtMinorVersion < 6);
+
+ // QMAKE_PRL_TARGET has a "lib" prefix, except for mingw.
+ // Of course, the exception has an exception too: For static libs, mingw *does*
+ // have the "lib" prefix.
+ var libFileName = "";
+ if (isQtVersionBefore56 && qtProps.qtMajorVersion === 5 && isMingw
+ && !modInfo.isStaticLibrary) {
+ libFileName += "lib";
+ }
+
+ libFileName += line.slice(equalsOffset + 1).trim();
+ if (isNonStaticQt4OnWindows)
+ libFileName += 4; // This is *not* part of QMAKE_PRL_TARGET...
+ if (isQtVersionBefore56) {
+ if (qtProps.mkspecName.contains("msvc")) {
+ libFileName += ".lib";
+ } else if (isMingw) {
+ libFileName += ".a";
+ if (!File.exists(FileInfo.joinPaths(libDir, libFileName)))
+ libFileName = libFileName.slice(0, -2) + ".dll";
+ }
+ }
+ libFilePath = FileInfo.joinPaths(libDir, libFileName);
+ continue;
+ }
+ if (line.startsWith("QMAKE_PRL_CONFIG")) {
+ modInfo.config = splitNonEmpty(line.slice(equalsOffset + 1).trim(), ' ');
+ continue;
+ }
+ if (!line.startsWith("QMAKE_PRL_LIBS ="))
+ continue;
+
+ var parts = extractPaths(line.slice(equalsOffset + 1).trim(), prlFilePath);
+ for (i = 0; i < parts.length; ++i) {
+ var part = parts[i];
+ part = part.replace("$$[QT_INSTALL_LIBS]", qtProps.libraryPath);
+ part = part.replace("$$[QT_INSTALL_PLUGINS]", qtProps.pluginPath);
+ part = part.replace("$$[QT_INSTALL_PREFIX]", qtProps.installPrefixPath);
+ if (part.startsWith("-l")) {
+ libs.push(part.slice(2));
+ } else if (part.startsWith("-L")) {
+ modInfo.libraryPaths.push(part.slice(2));
+ } else if (part.startsWith("-F")) {
+ frameworkPaths.push(part.slice(2));
+ } else if (part === "-framework") {
+ if (++i < parts.length)
+ frameworks.push(parts[i]);
+ } else if (part === "-pthread") {
+ // prl files for android have QMAKE_PRL_LIBS = -llog -pthread but the pthread
+ // functionality is included in libc.
+ if (androidAbi.length === 0)
+ libs.push("pthread");
+ } else if (part.startsWith('-')) { // Some other option
+ console.debug("QMAKE_PRL_LIBS contains non-library option '" + part
+ + "' in file '" + prlFilePath + "'");
+ flags.push(part);
+ } else if (part.startsWith("/LIBPATH:")) {
+ libraryPaths.push(part.slice(9).replace(/\\/g, '/'));
+ } else { // Assume it's a file path/name.
+ libs.push(part.replace(/\\/g, '/'));
+ }
+ }
+ }
+ } catch (e) {
+ // qt_ext_lib_extX.pri (usually) don't have a corresponding prl file.
+ // So the pri file variable QMAKE_LIBS_LIBX points to the library
+ if (modInfo.isExternal) {
+ libFilePath = debugBuild ? modInfo.staticLibrariesDebug[0] :
+ modInfo.staticLibrariesRelease[0];
+ }
+ if (!libFilePath || !File.exists(libFilePath))
+ libFilePath = guessLibraryFilePath(prlFilePath, libDir, qtProps);
+ if (nonExistingPrlFiles.contains(prlFilePath))
+ return;
+ nonExistingPrlFiles.push(prlFilePath);
+ if (modInfo.mustExist) {
+ console.warn("Could not open prl file '"
+ + FileInfo.toNativeSeparators(prlFilePath) + "' for module '"
+ + modInfo.name
+ + "' (" + e + "), and failed to deduce the library file path. "
+ + " This module will likely not be usable by qbs.");
+ }
+ }
+ finally {
+ if (prlFile)
+ prlFile.close();
+ }
+
+ if (debugBuild)
+ modInfo.libFilePathDebug = libFilePath;
+ else
+ modInfo.libFilePathRelease = libFilePath;
+}
+
+function setupLibraries(qtModuleInfo, qtProps, nonExistingPrlFiles, androidAbi) {
+ doSetupLibraries(qtModuleInfo, qtProps, true, nonExistingPrlFiles, androidAbi);
+ doSetupLibraries(qtModuleInfo, qtProps, false, nonExistingPrlFiles, androidAbi);
+}
+
+function allQt4Modules(qtProps) {
+ // as per http://doc.qt.io/qt-4.8/modules.html + private stuff.
+ var modules = [];
+
+ var core = makeQtModuleInfo("QtCore", "core");
+ core.compilerDefines.push("QT_CORE_LIB");
+ if (qtProps.qtNameSpace)
+ core.compilerDefines.push("QT_NAMESPACE=" + qtProps.qtNameSpace);
+ modules.push(core,
+ makeQtModuleInfo("QtCore", "core-private", ["core"]),
+ makeQtModuleInfo("QtGui", "gui"),
+ makeQtModuleInfo("QtGui", "gui-private", ["gui"]),
+ makeQtModuleInfo("QtMultimedia", "multimedia", ["gui", "network"]),
+ makeQtModuleInfo("QtMultimedia", "multimedia-private", ["multimedia"]),
+ makeQtModuleInfo("QtNetwork", "network"),
+ makeQtModuleInfo("QtNetwork", "network-private", ["network"]),
+ makeQtModuleInfo("QtOpenGL", "opengl", ["gui"]),
+ makeQtModuleInfo("QtOpenGL", "opengl-private", ["opengl"]),
+ makeQtModuleInfo("QtOpenVG", "openvg", ["gui"]),
+ makeQtModuleInfo("QtScript", "script"),
+ makeQtModuleInfo("QtScript", "script-private", ["script"]),
+ makeQtModuleInfo("QtScriptTools", "scripttools", ["script", "gui"]),
+ makeQtModuleInfo("QtScriptTools", "scripttools-private", ["scripttools"]),
+ makeQtModuleInfo("QtSql", "sql"),
+ makeQtModuleInfo("QtSql", "sql-private", ["sql"]),
+ makeQtModuleInfo("QtSvg", "svg", ["gui"]),
+ makeQtModuleInfo("QtSvg", "svg-private", ["svg"]),
+ makeQtModuleInfo("QtWebKit", "webkit", ["gui", "network"]),
+ makeQtModuleInfo("QtWebKit", "webkit-private", ["webkit"]),
+ makeQtModuleInfo("QtXml", "xml"),
+ makeQtModuleInfo("QtXml", "xml-private", ["xml"]),
+ makeQtModuleInfo("QtXmlPatterns", "xmlpatterns", ["network"]),
+ makeQtModuleInfo("QtXmlPatterns", "xmlpatterns-private", ["xmlpatterns"]),
+ makeQtModuleInfo("QtDeclarative", "declarative", ["gui", "script"]),
+ makeQtModuleInfo("QtDeclarative", "declarative-private", ["declarative"]),
+ makeQtModuleInfo("QtDesigner", "designer", ["gui", "xml"]),
+ makeQtModuleInfo("QtDesigner", "designer-private", ["designer"]),
+ makeQtModuleInfo("QtUiTools", "uitools"),
+ makeQtModuleInfo("QtUiTools", "uitools-private", ["uitools"]),
+ makeQtModuleInfo("QtHelp", "help", ["network", "sql"]),
+ makeQtModuleInfo("QtHelp", "help-private", ["help"]),
+ makeQtModuleInfo("QtTest", "testlib"),
+ makeQtModuleInfo("QtTest", "testlib-private", ["testlib"]));
+ if (qtProps.mkspecName.startsWith("win")) {
+ var axcontainer = makeQtModuleInfo("QAxContainer", "axcontainer");
+ axcontainer.modulePrefix = "Q";
+ axcontainer.isStaticLibrary = true;
+ axcontainer.includePaths.push(FileInfo.joinPaths(qtProps.includePath, "ActiveQt"));
+ modules.push(axcontainer);
+
+ var axserver = makeQtModuleInfo("QAxServer", "axserver");
+ axserver.modulePrefix = "Q";
+ axserver.isStaticLibrary = true;
+ axserver.compilerDefines.push("QAXSERVER");
+ axserver.includePaths.push(FileInfo.joinPaths(qtProps.includePath, "ActiveQt"));
+ modules.push(axserver);
+ } else {
+ modules.push(makeQtModuleInfo("QtDBus", "dbus"));
+ modules.push(makeQtModuleInfo("QtDBus", "dbus-private", ["dbus"]));
+ }
+
+ var designerComponentsPrivate = makeQtModuleInfo(
+ "QtDesignerComponents", "designercomponents-private",
+ ["gui-private", "designer-private"]);
+ designerComponentsPrivate.hasLibrary = true;
+ modules.push(designerComponentsPrivate);
+
+ var phonon = makeQtModuleInfo("Phonon", "phonon");
+ phonon.includePaths = qt4ModuleIncludePaths(phonon, qtProps);
+ modules.push(phonon);
+
+ // Set up include paths that haven't been set up before this point.
+ for (i = 0; i < modules.length; ++i) {
+ var module = modules[i];
+ if (module.includePaths.length > 0)
+ continue;
+ module.includePaths = qt4ModuleIncludePaths(module, qtProps);
+ }
+
+ // Set up compiler defines haven't been set up before this point.
+ for (i = 0; i < modules.length; ++i) {
+ module = modules[i];
+ if (module.compilerDefines.length > 0)
+ continue;
+ module.compilerDefines.push("QT_" + module.qbsName.toUpperCase() + "_LIB");
+ }
+
+ // These are for the convenience of project file authors. It allows them
+ // to add a dependency to e.g. "Qt.widgets" without a version check.
+ var virtualModule = makeQtModuleInfo(undefined, "widgets", ["core", "gui"]);
+ virtualModule.hasLibrary = false;
+ modules.push(virtualModule);
+ virtualModule = makeQtModuleInfo(undefined, "quick", ["declarative"]);
+ virtualModule.hasLibrary = false;
+ modules.push(virtualModule);
+ virtualModule = makeQtModuleInfo(undefined, "concurrent");
+ virtualModule.hasLibrary = false;
+ modules.push(virtualModule);
+ virtualModule = makeQtModuleInfo(undefined, "printsupport", ["core", "gui"]);
+ virtualModule.hasLibrary = false;
+ modules.push(virtualModule);
+
+ addTestModule(modules);
+ addDesignerComponentsModule(modules);
+
+ var modulesThatCanBeDisabled = [
+ "xmlpatterns", "multimedia", "phonon", "svg", "webkit", "script", "scripttools",
+ "declarative", "gui", "dbus", "opengl", "openvg"];
+ var nonExistingPrlFiles = [];
+ for (i = 0; i < modules.length; ++i) {
+ module = modules[i];
+ var name = module.qbsName;
+ var privateIndex = name.indexOf("-private");
+ if (privateIndex !== -1)
+ name = name.slice(0, privateIndex);
+ if (modulesThatCanBeDisabled.contains(name))
+ module.mustExist = false;
+ if (qtProps.staticBuild)
+ module.isStaticLibrary = true;
+ setupLibraries(module, qtProps, nonExistingPrlFiles, "");
+ }
+ replaceQtLibNamesWithFilePath(modules, qtProps);
+
+ return modules;
+}
+
+function getFileContentsRecursively(filePath) {
+ var file = new TextFile(filePath, TextFile.ReadOnly);
+ var lines = splitNonEmpty(file.readAll(), '\n');
+ for (var i = 0; i < lines.length; ++i) {
+ var includeString = "include(";
+ var line = lines[i].trim();
+ if (!line.startsWith(includeString))
+ continue;
+ var offset = includeString.length;
+ var closingParenPos = line.indexOf(')', offset);
+ if (closingParenPos === -1) {
+ console.warn("Invalid include statement in '"
+ + FileInfo.toNativeSeparators(filePath) + "'");
+ continue;
+ }
+ var includedFilePath = line.slice(offset, closingParenPos);
+ if (!FileInfo.isAbsolutePath(includedFilePath))
+ includedFilePath = FileInfo.joinPaths(FileInfo.path(filePath), includedFilePath);
+ var includedContents = getFileContentsRecursively(includedFilePath);
+ var j = i;
+ for (var k = 0; k < includedContents.length; ++k)
+ lines.splice(++j, 0, includedContents[k]);
+ lines.splice(i--, 1);
+ }
+ file.close();
+ return lines;
+}
+
+function extractPaths(rhs, filePath) {
+ var paths = [];
+ var startIndex = 0;
+ for (;;) {
+ while (startIndex < rhs.length && rhs.charAt(startIndex) === ' ')
+ ++startIndex;
+ if (startIndex >= rhs.length)
+ break;
+ var endIndex;
+ if (rhs.charAt(startIndex) === '"') {
+ ++startIndex;
+ endIndex = rhs.indexOf('"', startIndex);
+ if (endIndex === -1) {
+ console.warn("Unmatched quote in file '"
+ + FileInfo.toNativeSeparators(filePath) + "'");
+ break;
+ }
+ } else {
+ endIndex = rhs.indexOf(' ', startIndex + 1);
+ if (endIndex === -1)
+ endIndex = rhs.length;
+ }
+ paths.push(FileInfo.cleanPath(rhs.slice(startIndex, endIndex)
+ .replace("$$PWD", FileInfo.path(filePath))));
+ startIndex = endIndex + 1;
+ }
+ return paths;
+}
+
+function removeDuplicatedDependencyLibs(modules) {
+ var revDeps = {};
+ var currentPath = [];
+ var getLibraries;
+ var getLibFilePath;
+
+ function setupReverseDependencies(modules) {
+ var moduleByName = {};
+ for (var i = 0; i < modules.length; ++i)
+ moduleByName[modules[i].qbsName] = modules[i];
+ for (i = 0; i < modules.length; ++i) {
+ var module = modules[i];
+ for (var j = 0; j < module.dependencies.length; ++j) {
+ var depmod = moduleByName[module.dependencies[j]];
+ if (!depmod)
+ continue;
+ if (!revDeps[depmod.qbsName])
+ revDeps[depmod.qbsName] = [];
+ revDeps[depmod.qbsName].push(module);
+ }
+ }
+ }
+
+ function roots(modules) {
+ var result = [];
+ for (i = 0; i < modules.length; ++i) {
+ var module = modules[i]
+ if (module.dependencies.length === 0)
+ result.push(module);
+ }
+ return result;
+ }
+
+ function traverse(module, libs) {
+ if (currentPath.contains(module))
+ return;
+ currentPath.push(module);
+ var moduleLibraryLists = getLibraries(module);
+ for (var i = 0; i < moduleLibraryLists.length; ++i) {
+ var modLibList = moduleLibraryLists[i];
+ for (j = modLibList.length - 1; j >= 0; --j) {
+ if (libs.contains(modLibList[j]))
+ modLibList.splice(j, 1);
+ }
+ }
+
+ var libFilePath = getLibFilePath(module);
+ if (libFilePath)
+ libs.push(libFilePath);
+ for (i = 0; i < moduleLibraryLists.length; ++i)
+ libs = libs.concat(moduleLibraryLists[i]);
+ libs.sort();
+
+ var deps = revDeps[module.qbsName];
+ for (i = 0; i < (deps || []).length; ++i)
+ traverse(deps[i], libs);
+
+ currentPath.pop();
+ }
+
+ setupReverseDependencies(modules);
+
+ // Traverse the debug variants of modules.
+ getLibraries = function(module) {
+ return [module.dynamicLibrariesDebug, module.staticLibrariesDebug];
+ };
+ getLibFilePath = function(module) { return module.libFilePathDebug; };
+ var rootModules = roots(modules);
+ for (var i = 0; i < rootModules.length; ++i)
+ traverse(rootModules[i], []);
+
+ // Traverse the release variants of modules.
+ getLibraries = function(module) {
+ return [module.dynamicLibrariesRelease, module.staticLibrariesRelease];
+ };
+ getLibFilePath = function(module) { return module.libFilePathRelease; };
+ for (i = 0; i < rootModules.length; ++i)
+ traverse(rootModules[i], []);
+}
+
+function allQt5Modules(qtProps, androidAbi) {
+ var nonExistingPrlFiles = [];
+ var modules = [];
+ var modulesDir = FileInfo.joinPaths(qtProps.mkspecBasePath, "modules");
+ var modulePriFiles = File.directoryEntries(modulesDir, File.Files);
+ for (var i = 0; i < modulePriFiles.length; ++i) {
+ var priFileName = modulePriFiles[i];
+ var priFilePath = FileInfo.joinPaths(modulesDir, priFileName);
+ var externalFileNamePrefix = "qt_ext_";
+ var moduleFileNamePrefix = "qt_lib_";
+ var pluginFileNamePrefix = "qt_plugin_";
+ var moduleFileNameSuffix = ".pri";
+ var fileHasExternalPrefix = priFileName.startsWith(externalFileNamePrefix);
+ var fileHasModulePrefix = priFileName.startsWith(moduleFileNamePrefix);
+ var fileHasPluginPrefix = priFileName.startsWith(pluginFileNamePrefix);
+ if (!fileHasPluginPrefix && !fileHasModulePrefix && !fileHasExternalPrefix
+ || !priFileName.endsWith(moduleFileNameSuffix)) {
+ continue;
+ }
+ var moduleInfo = makeQtModuleInfo();
+ moduleInfo.isPlugin = fileHasPluginPrefix;
+ moduleInfo.isExternal = !moduleInfo.isPlugin && !fileHasModulePrefix;
+ var fileNamePrefix = moduleInfo.isPlugin ? pluginFileNamePrefix : moduleInfo.isExternal
+ ? externalFileNamePrefix : moduleFileNamePrefix;
+ moduleInfo.qbsName = priFileName.slice(fileNamePrefix.length, -moduleFileNameSuffix.length);
+ if (moduleInfo.isPlugin) {
+ moduleInfo.name = moduleInfo.qbsName;
+ moduleInfo.isStaticLibrary = true;
+ }
+ var moduleKeyPrefix = (moduleInfo.isPlugin ? "QT_PLUGIN" : "QT")
+ + '.' + moduleInfo.qbsName + '.';
+ moduleInfo.qbsName = moduleInfo.qbsName.replace("_private", "-private");
+ var hasV2 = false;
+ var hasModuleEntry = false;
+ var lines = getFileContentsRecursively(priFilePath);
+ if (moduleInfo.isExternal) {
+ moduleInfo.name = "qt" + moduleInfo.qbsName;
+ moduleInfo.isStaticLibrary = true;
+ for (var k = 0; k < lines.length; ++k) {
+ var extLine = lines[k].trim();
+ var extFirstEqualsOffset = extLine.indexOf('=');
+ if (extFirstEqualsOffset === -1)
+ continue;
+ var extKey = extLine.slice(0, extFirstEqualsOffset).trim();
+ var extValue = extLine.slice(extFirstEqualsOffset + 1).trim();
+ if (!extKey.startsWith("QMAKE_") || !extValue)
+ continue;
+
+ var elements = extKey.split('_');
+ if (elements.length >= 3) {
+ if (elements[1] === "LIBS") {
+ extValue = extValue.replace("/home/qt/work/qt/qtbase/lib",
+ qtProps.libraryPath);
+ extValue = extValue.replace("$$[QT_INSTALL_LIBS]", qtProps.libraryPath);
+ extValue = extValue.replace("$$[QT_INSTALL_LIBS/get]", qtProps.libraryPath);
+ if (elements.length === 4 ) {
+ if (elements[3] === androidAbi) {
+ moduleInfo.staticLibrariesRelease.push(extValue);
+ moduleInfo.staticLibrariesDebug.push(extValue);
+ }
+ } else if (elements.length === 5 ) {
+ // That's for "x86_64"
+ var abi = elements[3] + '_' + elements[4];
+ if (abi === androidAbi) {
+ moduleInfo.staticLibrariesRelease.push(extValue);
+ moduleInfo.staticLibrariesDebug.push(extValue);
+ }
+ } else {
+ moduleInfo.staticLibrariesRelease.push(extValue);
+ moduleInfo.staticLibrariesDebug.push(extValue);
+ }
+ } else if (elements[1] === "INCDIR") {
+ moduleInfo.includePaths.push(extValue.replace("$$[QT_INSTALL_HEADERS]",
+ qtProps.includePath));
+ }
+ }
+ }
+ moduleInfo.compilerDefines.push("QT_" + moduleInfo.qbsName.toUpperCase() + "_LIB");
+ moduleInfo.mustExist = false;
+ } else {
+ for (var j = 0; j < lines.length; ++j) {
+ var line = lines[j].trim();
+ var firstEqualsOffset = line.indexOf('=');
+ if (firstEqualsOffset === -1)
+ continue;
+ var key = line.slice(0, firstEqualsOffset).trim();
+ var value = line.slice(firstEqualsOffset + 1).trim();
+ if (!key.startsWith(moduleKeyPrefix) || !value)
+ continue;
+ if (key.endsWith(".name")) {
+ moduleInfo.name = value;
+ } else if (key.endsWith(".module")) {
+ hasModuleEntry = true;
+ } else if (key.endsWith(".depends")) {
+ moduleInfo.dependencies = splitNonEmpty(value, ' ');
+ for (var k = 0; k < moduleInfo.dependencies.length; ++k) {
+ moduleInfo.dependencies[k]
+ = moduleInfo.dependencies[k].replace("_private", "-private");
+ }
+ } else if (key.endsWith(".module_config")) {
+ var elems = splitNonEmpty(value, ' ');
+ for (k = 0; k < elems.length; ++k) {
+ var elem = elems[k];
+ if (elem === "no_link")
+ moduleInfo.hasLibrary = false;
+ else if (elem === "staticlib")
+ moduleInfo.isStaticLibrary = true;
+ else if (elem === "internal_module")
+ moduleInfo.isPrivate = true;
+ else if (elem === "v2")
+ hasV2 = true;
+ }
+ } else if (key.endsWith(".includes")) {
+ moduleInfo.includePaths = extractPaths(value, priFilePath);
+ for (k = 0; k < moduleInfo.includePaths.length; ++k) {
+ moduleInfo.includePaths[k] = moduleInfo.includePaths[k]
+ .replace("$$QT_MODULE_INCLUDE_BASE", qtProps.includePath)
+ .replace("$$QT_MODULE_HOST_LIB_BASE", qtProps.hostLibraryPath)
+ .replace("$$QT_MODULE_LIB_BASE", qtProps.libraryPath);
+ }
+ } else if (key.endsWith(".libs")) {
+ var libDirs = extractPaths(value, priFilePath);
+ if (libDirs.length === 1) {
+ moduleInfo.libDir = libDirs[0]
+ .replace("$$QT_MODULE_HOST_LIB_BASE", qtProps.hostLibraryPath)
+ .replace("$$QT_MODULE_LIB_BASE", qtProps.libraryPath);
+ } else {
+ moduleInfo.libDir = qtProps.libraryPath;
+ }
+ } else if (key.endsWith(".DEFINES")) {
+ moduleInfo.compilerDefines = splitNonEmpty(value, ' ');
+ } else if (key.endsWith(".VERSION")) {
+ moduleInfo.version = value;
+ } else if (key.endsWith(".plugin_types")) {
+ moduleInfo.supportedPluginTypes = splitNonEmpty(value, ' ');
+ } else if (key.endsWith(".TYPE")) {
+ moduleInfo.pluginData.type = value;
+ } else if (key.endsWith(".EXTENDS")) {
+ moduleInfo.pluginData["extends"] = splitNonEmpty(value, ' ');
+ for (k = 0; k < moduleInfo.pluginData["extends"].length; ++k) {
+ if (moduleInfo.pluginData["extends"][k] === "-") {
+ moduleInfo.pluginData["extends"].splice(k, 1);
+ moduleInfo.pluginData.autoLoad = false;
+ break;
+ }
+ }
+ } else if (key.endsWith(".CLASS_NAME")) {
+ moduleInfo.pluginData.className = value;
+ }
+ }
+ }
+ if (hasV2 && !hasModuleEntry && !moduleInfo.isStaticLibrary)
+ moduleInfo.hasLibrary = false;
+
+ // Fix include paths for Apple frameworks.
+ // The qt_lib_XXX.pri files contain wrong values for versions < 5.6.
+ if (!hasV2 && ProviderUtils.qtIsFramework(moduleInfo, qtProps)) {
+ moduleInfo.includePaths = [];
+ var baseIncDir = frameworkHeadersPath(moduleInfo, qtProps);
+ if (moduleInfo.isPrivate) {
+ baseIncDir = FileInfo.joinPaths(baseIncDir, moduleInfo.version);
+ moduleInfo.includePaths.push(baseIncDir,
+ FileInfo.joinPaths(baseIncDir, moduleInfo.name));
+ } else {
+ moduleInfo.includePaths.push(baseIncDir);
+ }
+ }
+
+ setupLibraries(moduleInfo, qtProps, nonExistingPrlFiles, androidAbi);
+
+ modules.push(moduleInfo);
+ if (moduleInfo.qbsName === "testlib")
+ addTestModule(modules);
+ if (moduleInfo.qbsName === "designercomponents-private")
+ addDesignerComponentsModule(modules);
+ }
+
+ replaceQtLibNamesWithFilePath(modules, qtProps);
+ removeDuplicatedDependencyLibs(modules);
+
+ return modules;
+}
+
+function getQtInfo(qmakeFilePath) {
+ if (!File.exists(qmakeFilePath)) {
+ throw "The specified qmake file path '"
+ + FileInfo.toNativeSeparators(qmakeFilePath) + "' does not exist.";
+ }
+ var qtProps = getQtProperties(qmakeFilePath);
+ var androidAbis = [];
+ if (qtProps.androidAbis !== undefined) {
+ // Multiple androidAbis detected: Qt >= 5.14
+ androidAbis = qtProps.androidAbis;
+ } else {
+ // Single abi detected: Qt < 5.14
+ androidAbis.push('');
+ }
+ if (androidAbis.length > 1)
+ console.info("Qt with multiple abi detected: '" + androidAbis + "'");
+
+ var result = {};
+ result.qtProps = qtProps;
+ result.abiInfos = [];
+ result.qmakeFilePath = qmakeFilePath;
+ for (a = 0; a < androidAbis.length; ++a) {
+ var abiInfo = {};
+ if (androidAbis.length > 1)
+ console.info("Found abi '" + androidAbis[a] + "'...");
+ abiInfo.androidAbi = androidAbis[a];
+ var allModules = qtProps.qtMajorVersion < 5
+ ? allQt4Modules(qtProps) : allQt5Modules(qtProps, androidAbis[a]);;
+ abiInfo.modules = {};
+ for (var i = 0; i < allModules.length; ++i) {
+ var module = allModules[i];
+ abiInfo.modules[module.qbsName] = module;
+ }
+ abiInfo.pluginsByType = {};
+ abiInfo.nonEssentialPlugins = [];
+ for (var moduleName in abiInfo.modules) {
+ var m = abiInfo.modules[moduleName];
+ if (m.isPlugin) {
+ if (!abiInfo.pluginsByType[m.pluginData.type])
+ abiInfo.pluginsByType[m.pluginData.type] = [];
+ abiInfo.pluginsByType[m.pluginData.type].push(m.name);
+ if (!m.pluginData.autoLoad)
+ abiInfo.nonEssentialPlugins.push(m.name);
+ }
+ }
+
+ result.abiInfos.push(abiInfo);
+ }
+ return result;
+}
+
+function configure(qmakeFilePaths) {
+ var result = [];
+ qmakeFilePaths = getQmakeFilePaths(qmakeFilePaths);
+ if (!qmakeFilePaths || qmakeFilePaths.length === 0)
+ return result;
+ for (var i = 0; i < qmakeFilePaths.length; ++i) {
+ var qtInfo = {};
+ try {
+ console.info("Getting info about Qt at '"
+ + FileInfo.toNativeSeparators(qmakeFilePaths[i]) + "'...");
+ qtInfo = getQtInfo(qmakeFilePaths[i]);
+ result.push(qtInfo);
+ } catch (e) {
+ console.warn("Error getting info about Qt for '"
+ + FileInfo.toNativeSeparators(qmakeFilePaths[i]) + "': " + e);
+ throw e;
+ }
+ }
+ return result;
+}
diff --git a/share/qbs/imports/qbs/ProviderUtils/provider-utils.js b/share/qbs/imports/qbs/ProviderUtils/provider-utils.js
new file mode 100644
index 000000000..06e703a7a
--- /dev/null
+++ b/share/qbs/imports/qbs/ProviderUtils/provider-utils.js
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Copyright (C) 2023 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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.
+**
+****************************************************************************/
+
+var Utilities = require("qbs.Utilities");
+
+function pkgConfigToModuleName(packageName) {
+ return packageName.replace(/\./g, '-');
+}
+
+function msvcPrefix() { return "win32-msvc"; }
+
+function isMsvcQt(qtProps) { return qtProps.mkspecName.startsWith(msvcPrefix()); }
+
+function isMinGwQt(qtProps) {
+ return qtProps.mkspecName.startsWith("win32-g++") || qtProps.mkspecName.startsWith("mingw");
+}
+
+function isDesktopWindowsQt(qtProps) {
+ return qtProps.mkspecName.startsWith("win32-") || isMinGwQt(qtProps);
+}
+
+function qtNeedsDSuffix(qtProps) {
+ return !isMinGwQt(qtProps)
+ || Utilities.versionCompare(qtProps.qtVersion, "5.14.0") < 0
+ || qtProps.configItems.contains("debug_and_release");
+}
+
+function qtIsFramework(modInfo, qtProps) {
+ if (!qtProps.frameworkBuild || modInfo.isStaticLibrary)
+ return false;
+ var modulesNeverBuiltAsFrameworks = [
+ "bootstrap", "openglextensions", "platformsupport", "qmldevtools", "harfbuzzng"
+ ];
+
+ if (qtProps.qtMajorVersion <= 5) {
+ modulesNeverBuiltAsFrameworks.push("uitools"); // is framework since qt6
+ }
+
+ return !modulesNeverBuiltAsFrameworks.contains(modInfo.qbsName);
+}
+
+function qtLibBaseName(modInfo, libName, debugBuild, qtProps) {
+ var name = libName;
+ if (qtProps.mkspecName.startsWith("win")) {
+ if (debugBuild && qtNeedsDSuffix(qtProps))
+ name += 'd';
+ if (!modInfo.isStaticLibrary && qtProps.qtMajorVersion < 5)
+ name += qtProps.qtMajorVersion;
+ }
+ if (qtProps.mkspecName.contains("macx")
+ || qtProps.mkspecName.contains("ios")
+ || qtProps.mkspecName.contains("darwin")) {
+ if (!qtIsFramework(modInfo, qtProps)
+ && qtProps.buildVariant.contains("debug")
+ && (!qtProps.buildVariant.contains("release") || debugBuild)) {
+ name += "_debug";
+ }
+ }
+ return name;
+}
+
+function qtModuleNameWithoutPrefix(modInfo) {
+ if (modInfo.name === "Phonon")
+ return "phonon";
+ if (!modInfo.modulePrefix && modInfo.name.startsWith("Qt"))
+ return modInfo.name.slice(2); // Strip off "Qt".
+ if (modInfo.name.startsWith(modInfo.modulePrefix))
+ return modInfo.name.slice(modInfo.modulePrefix.length);
+ return modInfo.name;
+}
+
+function qtLibraryBaseName(modInfo, qtProps, debugBuild) {
+ if (modInfo.isPlugin)
+ return qtLibBaseName(modInfo, modInfo.name, debugBuild, qtProps);
+
+ // Some modules use a different naming scheme, so it doesn't get boring.
+ var libNameBroken = modInfo.name === "Enginio"
+ || modInfo.name === "DataVisualization"
+ || modInfo.name === "Phonon";
+
+ var libName = "";
+ if (!modInfo.isExternal) {
+ libName += !modInfo.modulePrefix && !libNameBroken ? "Qt" : modInfo.modulePrefix;
+ if (qtProps.qtMajorVersion >= 5 && !qtIsFramework(modInfo, qtProps) && !libNameBroken)
+ libName += qtProps.qtMajorVersion;
+ }
+ libName += qtModuleNameWithoutPrefix(modInfo);
+ if (!modInfo.isExternal)
+ libName += qtProps.qtLibInfix;
+ return qtLibBaseName(modInfo, libName, debugBuild, qtProps);
+}
+
+function qtLibNameForLinker(modInfo, qtProps, debugBuild) {
+ if (!modInfo.hasLibrary)
+ return undefined;
+ var libName = qtLibraryBaseName(modInfo, qtProps, debugBuild);
+ if (qtProps.mkspecName.contains("msvc"))
+ libName += ".lib";
+ return libName;
+}
diff --git a/share/qbs/imports/qbs/base/AndroidApk.qbs b/share/qbs/imports/qbs/base/AndroidApk.qbs
index 5f86d8457..70cf6aa93 100644
--- a/share/qbs/imports/qbs/base/AndroidApk.qbs
+++ b/share/qbs/imports/qbs/base/AndroidApk.qbs
@@ -32,7 +32,7 @@ import qbs.File
import qbs.FileInfo
Product {
- type: ["android.apk"]
+ type: ["android.package"]
qbs.targetPlatform: "android"
Depends { name: "Android.sdk" }
}
diff --git a/share/qbs/imports/qbs/base/AppleApplicationDiskImage.qbs b/share/qbs/imports/qbs/base/AppleApplicationDiskImage.qbs
index 134f4dee0..462b96b7c 100644
--- a/share/qbs/imports/qbs/base/AppleApplicationDiskImage.qbs
+++ b/share/qbs/imports/qbs/base/AppleApplicationDiskImage.qbs
@@ -34,7 +34,8 @@ import qbs.ModUtils
AppleDiskImage {
property string sourceBase: "/Applications"
- readonly property string absoluteSourceBase: FileInfo.joinPaths(qbs.installRoot, sourceBase)
+ readonly property string absoluteSourceBase:
+ FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix, sourceBase)
property stringList symlinks: ["/Applications:Applications"]
readonly property string stageDirectory: FileInfo.joinPaths(destinationDirectory, "Volumes", dmg.volumeName)
@@ -56,7 +57,7 @@ AppleDiskImage {
prepare: Array.prototype.map.call(outputs["dmg.input"], function (symlink) {
var cmd = new Command("ln", ["-sfn", symlink.dmg.symlinkTarget, symlink.filePath]);
cmd.workingDirectory = product.stageDirectory;
- cmd.description = "symlinking " + symlink.fileName + " => " + symlink.dmg.symlinkTarget;
+ cmd.description = "symlinking " + symlink.fileName + " to " + symlink.dmg.symlinkTarget;
return cmd;
});
}
diff --git a/share/qbs/imports/qbs/base/Application.qbs b/share/qbs/imports/qbs/base/Application.qbs
index 694cfb83b..76536c68e 100644
--- a/share/qbs/imports/qbs/base/Application.qbs
+++ b/share/qbs/imports/qbs/base/Application.qbs
@@ -29,7 +29,7 @@
****************************************************************************/
NativeBinary {
- type: isForAndroid && !consoleApplication ? ["android.apk"] : ["application"]
+ type: isForAndroid && !consoleApplication ? ["android.package"] : ["application"]
property bool usesNativeCode
@@ -60,10 +60,18 @@ NativeBinary {
installDir: isBundle ? "Applications" : "bin"
Group {
- condition: install
- fileTagsFilter: isBundle ? "bundle.content" : "application";
+ condition: install && _installable
+ fileTagsFilter: isBundle ? "bundle.content" : "application"
qbs.install: true
qbs.installDir: installDir
qbs.installSourceBase: isBundle ? destinationDirectory : outer
}
+
+ Group {
+ condition: installDebugInformation && _installable
+ fileTagsFilter: ["debuginfo_app"]
+ qbs.install: true
+ qbs.installDir: debugInformationInstallDir
+ qbs.installSourceBase: destinationDirectory
+ }
}
diff --git a/share/qbs/imports/qbs/base/ApplicationExtension.qbs b/share/qbs/imports/qbs/base/ApplicationExtension.qbs
index 140475909..3d25d5f73 100644
--- a/share/qbs/imports/qbs/base/ApplicationExtension.qbs
+++ b/share/qbs/imports/qbs/base/ApplicationExtension.qbs
@@ -34,14 +34,21 @@ XPCService {
type: base.concat(["applicationextension"])
property bool _useLegacyExtensionLibraries:
- qbs.targetOS.contains("macos") && parseInt(xcode.sdkVersion.split(".")[1], 10) < 11 ||
- qbs.targetOS.contains("ios") && parseInt(xcode.sdkVersion.split(".")[0], 10) < 9
+ qbs.targetOS.contains("macos")
+ && xcode.present
+ && parseInt(xcode.sdkVersion.split(".")[1], 10) < 11
+ || qbs.targetOS.contains("ios")
+ && xcode.present
+ && parseInt(xcode.sdkVersion.split(".")[0], 10) < 9
cpp.entryPoint: "_NSExtensionMain"
+ cpp.frameworkPaths: base.concat(_useLegacyExtensionLibraries
+ ? qbs.sysroot + "/System/Library/PrivateFrameworks/"
+ : [])
cpp.frameworks: {
var frameworks = base.concat(["Foundation"]);
if (_useLegacyExtensionLibraries)
- frameworks.push(qbs.sysroot + "/System/Library/PrivateFrameworks/PlugInKit.framework");
+ frameworks.push("PlugInKit");
return frameworks;
}
diff --git a/share/qbs/imports/qbs/base/AutotestRunner.qbs b/share/qbs/imports/qbs/base/AutotestRunner.qbs
index 62ba7740b..30921eb38 100644
--- a/share/qbs/imports/qbs/base/AutotestRunner.qbs
+++ b/share/qbs/imports/qbs/base/AutotestRunner.qbs
@@ -94,7 +94,7 @@ Product {
.concat([commandFilePath])
.concat(arguments);
var cmd = new Command(fullCommandLine[0], fullCommandLine.slice(1));
- cmd.description = "Running test " + input.fileName;
+ cmd.description = "running test " + input.fileName;
cmd.environment = product.environment;
cmd.workingDirectory = workingDir;
cmd.timeout = timeout;
diff --git a/share/qbs/imports/qbs/base/DynamicLibrary.qbs b/share/qbs/imports/qbs/base/DynamicLibrary.qbs
index 267519a42..818665e38 100644
--- a/share/qbs/imports/qbs/base/DynamicLibrary.qbs
+++ b/share/qbs/imports/qbs/base/DynamicLibrary.qbs
@@ -30,24 +30,4 @@
Library {
type: ["dynamiclibrary"].concat(isForAndroid ? ["android.nativelibrary"] : [])
-
- installDir: isBundle ? "Library/Frameworks" : qbs.targetOS.contains("windows")
- ? "bin" : "lib"
- property bool installImportLib: false
- property string importLibInstallDir: "lib"
-
- Group {
- condition: install
- fileTagsFilter: isBundle ? "bundle.content" : ["dynamiclibrary", "dynamiclibrary_symlink"]
- qbs.install: true
- qbs.installDir: installDir
- qbs.installSourceBase: isBundle ? destinationDirectory : outer
- }
-
- Group {
- condition: installImportLib
- fileTagsFilter: "dynamiclibrary_import"
- qbs.install: true
- qbs.installDir: importLibInstallDir
- }
}
diff --git a/share/qbs/imports/qbs/base/InnoSetup.qbs b/share/qbs/imports/qbs/base/InnoSetup.qbs
index 5ea076eb3..e40a627f5 100644
--- a/share/qbs/imports/qbs/base/InnoSetup.qbs
+++ b/share/qbs/imports/qbs/base/InnoSetup.qbs
@@ -29,6 +29,7 @@
****************************************************************************/
Product {
- Depends { name: "innosetup"; condition: qbs.targetOS.contains("windows") }
+ condition: qbs.targetOS.contains("windows") && innosetup.present
+ Depends { name: "innosetup"; condition: qbs.targetOS.contains("windows"); required: false }
type: ["innosetup.exe"]
}
diff --git a/share/qbs/imports/qbs/base/Library.qbs b/share/qbs/imports/qbs/base/Library.qbs
index 615c2319f..914d79bcb 100644
--- a/share/qbs/imports/qbs/base/Library.qbs
+++ b/share/qbs/imports/qbs/base/Library.qbs
@@ -34,4 +34,61 @@ NativeBinary {
return ["staticlibrary"];
return ["dynamiclibrary"].concat(isForAndroid ? ["android.nativelibrary"] : []);
}
+
+ readonly property bool isDynamicLibrary: type.contains("dynamiclibrary")
+ readonly property bool isStaticLibrary: type.contains("staticlibrary")
+ readonly property bool isLoadableModule: type.contains("loadablemodule")
+
+ installDir: {
+ if (isBundle)
+ return "Library/Frameworks";
+ if (isDynamicLibrary)
+ return qbs.targetOS.contains("windows") ? "bin" : "lib";
+ if (isStaticLibrary)
+ return "lib";
+ }
+
+ property bool installImportLib: false
+ property string importLibInstallDir: "lib"
+
+ Group {
+ condition: install && _installable
+ fileTagsFilter: {
+ if (isBundle)
+ return ["bundle.content"];
+ if (isDynamicLibrary)
+ return ["dynamiclibrary", "dynamiclibrary_symlink"];
+ if (isStaticLibrary)
+ return ["staticlibrary"];
+ if (isLoadableModule)
+ return ["loadablemodule"];
+ return [];
+ }
+ qbs.install: true
+ qbs.installDir: installDir
+ qbs.installSourceBase: isBundle ? destinationDirectory : outer
+ }
+
+ Group {
+ condition: installImportLib
+ && type.contains("dynamiclibrary")
+ && _installable
+ fileTagsFilter: "dynamiclibrary_import"
+ qbs.install: true
+ qbs.installDir: importLibInstallDir
+ }
+
+ Group {
+ condition: installDebugInformation && _installable
+ fileTagsFilter: {
+ if (isDynamicLibrary)
+ return ["debuginfo_dll"];
+ else if (isLoadableModule)
+ return ["debuginfo_loadablemodule"];
+ return [];
+ }
+ qbs.install: true
+ qbs.installDir: debugInformationInstallDir
+ qbs.installSourceBase: destinationDirectory
+ }
}
diff --git a/share/qbs/imports/qbs/base/NativeBinary.qbs b/share/qbs/imports/qbs/base/NativeBinary.qbs
index 3597f348f..900ed9faa 100644
--- a/share/qbs/imports/qbs/base/NativeBinary.qbs
+++ b/share/qbs/imports/qbs/base/NativeBinary.qbs
@@ -35,6 +35,12 @@ Product {
property bool install: false
property string installDir
+ // Product artifacts should be installed if it's not multiplexed or aggregated,
+ // or if it is multiplexed and it's the aggregate product
+ readonly property bool _installable: !multiplexed || !aggregate || !multiplexConfigurationId
+
+ property bool installDebugInformation: install
+ property string debugInformationInstallDir: installDir
Depends { name: "bundle"; condition: isForDarwin }
diff --git a/share/qbs/imports/qbs/base/QtGuiApplication.qbs b/share/qbs/imports/qbs/base/QtGuiApplication.qbs
index 61bc69752..7b2abf017 100644
--- a/share/qbs/imports/qbs/base/QtGuiApplication.qbs
+++ b/share/qbs/imports/qbs/base/QtGuiApplication.qbs
@@ -28,6 +28,6 @@
**
****************************************************************************/
-CppApplication {
+QtApplication {
Depends { name: "Qt.gui" }
}
diff --git a/share/qbs/module-providers/Qt/templates/QtModule.qbs b/share/qbs/imports/qbs/base/QtModule.qbs
index aa7c1d15a..35421436f 100644
--- a/share/qbs/module-providers/Qt/templates/QtModule.qbs
+++ b/share/qbs/imports/qbs/base/QtModule.qbs
@@ -23,6 +23,7 @@ Module {
// We have to pull in all plugins here, because dependency resolving happens
// before module merging, and we don't know yet if someone set
// Qt.pluginSupport.pluginsByType in the product.
+ // TODO: We might be able to use Qt.pluginSupport.pluginsByType now.
// The real filtering is done later by the plugin module files themselves.
var list = [];
var allPlugins = Qt.plugin_support.allPluginsByType;
@@ -81,6 +82,6 @@ Module {
cpp.dynamicLibraries: dynamicLibs
cpp.frameworks: mFrameworks.concat(!isStaticLibrary && Qt.core.frameworkBuild
? [libNameForLinker] : [])
- cpp.frameworkPaths: mFrameworkPaths
+ cpp.systemFrameworkPaths: mFrameworkPaths
}
}
diff --git a/share/qbs/module-providers/Qt/templates/QtPlugin.qbs b/share/qbs/imports/qbs/base/QtPlugin.qbs
index 88bfa5a65..883e34465 100644
--- a/share/qbs/module-providers/Qt/templates/QtPlugin.qbs
+++ b/share/qbs/imports/qbs/base/QtPlugin.qbs
@@ -38,7 +38,7 @@ QtModule {
prepare: {
var cmd = new JavaScriptCommand();
var pluginName = product.moduleProperty(product.moduleName, "qtModuleName");
- cmd.description = "Creating static import for plugin '" + pluginName + "'.";
+ cmd.description = "creating static import for plugin '" + pluginName + "'";
cmd.sourceCode = function() {
var f = new TextFile(output.filePath, TextFile.WriteOnly);
var className = product.moduleProperty(product.moduleName, "className");
diff --git a/share/qbs/imports/qbs/base/StaticLibrary.qbs b/share/qbs/imports/qbs/base/StaticLibrary.qbs
index 4eea3c991..5a78a83b0 100644
--- a/share/qbs/imports/qbs/base/StaticLibrary.qbs
+++ b/share/qbs/imports/qbs/base/StaticLibrary.qbs
@@ -30,13 +30,4 @@
Library {
type: ["staticlibrary"]
-
- installDir: isBundle ? "Library/Frameworks" : "lib"
- Group {
- condition: install
- fileTagsFilter: isBundle ? "bundle.content" : "staticlibrary";
- qbs.install: true
- qbs.installDir: installDir
- qbs.installSourceBase: isBundle ? destinationDirectory : outer
- }
}
diff --git a/share/qbs/module-providers/Qt/provider.qbs b/share/qbs/module-providers/Qt/provider.qbs
index 33083c51d..0d036c04d 100644
--- a/share/qbs/module-providers/Qt/provider.qbs
+++ b/share/qbs/module-providers/Qt/provider.qbs
@@ -1,6 +1,14 @@
import "setup-qt.js" as SetupQt
+import qbs.Probes
ModuleProvider {
+ Probes.QmakeProbe {
+ id: probe
+ qmakePaths: qmakeFilePaths
+ }
property stringList qmakeFilePaths
- relativeSearchPaths: SetupQt.doSetup(qmakeFilePaths, outputBaseDir, path, qbs)
+ readonly property varList _qtInfos: probe.qtInfos
+ condition: moduleName.startsWith("Qt.")
+ isEager: false
+ relativeSearchPaths: SetupQt.doSetup(moduleName, _qtInfos, outputBaseDir, path)
}
diff --git a/share/qbs/module-providers/Qt/setup-qt.js b/share/qbs/module-providers/Qt/setup-qt.js
index 3ddc214d3..9a314822b 100644
--- a/share/qbs/module-providers/Qt/setup-qt.js
+++ b/share/qbs/module-providers/Qt/setup-qt.js
@@ -37,1103 +37,13 @@
**
****************************************************************************/
-var Environment = require("qbs.Environment");
var File = require("qbs.File");
var FileInfo = require("qbs.FileInfo");
-var Process = require("qbs.Process");
+var ModUtils = require("qbs.ModUtils");
+var ProviderUtils = require("qbs.ProviderUtils");
var TextFile = require("qbs.TextFile");
var Utilities = require("qbs.Utilities");
-function splitNonEmpty(s, c) { return s.split(c).filter(function(e) { return e; }); }
-function toNative(p) { return FileInfo.toNativeSeparators(p); }
-function exeSuffix(qbs) { return qbs.hostOS.contains("windows") ? ".exe" : ""; }
-
-function getQmakeFilePaths(qmakeFilePaths, qbs) {
- if (qmakeFilePaths && qmakeFilePaths.length > 0)
- return qmakeFilePaths;
- console.info("Detecting Qt installations...");
- var pathValue = Environment.getEnv("PATH");
- if (!pathValue)
- return [];
- var dirs = splitNonEmpty(pathValue, qbs.pathListSeparator);
- var suffix = exeSuffix(qbs);
- var filePaths = [];
- for (var i = 0; i < dirs.length; ++i) {
- var candidate = FileInfo.joinPaths(dirs[i], "qmake" + suffix);
- var canonicalCandidate = FileInfo.canonicalPath(candidate);
- if (!canonicalCandidate || !File.exists(canonicalCandidate))
- continue;
- if (FileInfo.completeBaseName(canonicalCandidate) !== "qtchooser")
- candidate = canonicalCandidate;
- if (!filePaths.contains(candidate)) {
- console.info("Found Qt at '" + toNative(candidate) + "'.");
- filePaths.push(candidate);
- }
- }
- return filePaths;
-}
-
-function queryQmake(qmakeFilePath) {
- var qmakeProcess = new Process;
- qmakeProcess.exec(qmakeFilePath, ["-query"]);
- if (qmakeProcess.exitCode() !== 0) {
- throw "The qmake executable '" + toNative(qmakeFilePath) + "' failed with exit code "
- + qmakeProcess.exitCode() + ".";
- }
- var queryResult = {};
- while (!qmakeProcess.atEnd()) {
- var line = qmakeProcess.readLine();
- var index = (line || "").indexOf(":");
- if (index !== -1)
- queryResult[line.slice(0, index)] = line.slice(index + 1).trim();
- }
- return queryResult;
-}
-
-function pathQueryValue(queryResult, key) {
- var p = queryResult[key];
- if (p)
- return FileInfo.fromNativeSeparators(p);
-}
-
-function readFileContent(filePath) {
- var f = new TextFile(filePath, TextFile.ReadOnly);
- var content = f.readAll();
- f.close();
- return content;
-}
-
-// TODO: Don't do the split every time...
-function configVariable(configContent, key) {
- var configContentLines = configContent.split('\n');
- var regexp = new RegExp("\\s*" + key + "\\s*\\+{0,1}=(.*)");
- for (var i = 0; i < configContentLines.length; ++i) {
- var line = configContentLines[i];
- var match = regexp.exec(line);
- if (match)
- return match[1].trim();
- }
-}
-
-function configVariableItems(configContent, key) {
- return splitNonEmpty(configVariable(configContent, key), ' ');
-}
-
-function msvcPrefix() { return "win32-msvc"; }
-
-function isMsvcQt(qtProps) { return qtProps.mkspecName.startsWith(msvcPrefix()); }
-
-function msvcCompilerVersionForYear(year) {
- var mapping = {
- "2005": "14", "2008": "15", "2010": "16", "2012": "17", "2013": "18", "2015": "19",
- "2017": "19.1", "2019": "19.2"
- };
- return mapping[year];
-}
-
-function msvcCompilerVersionFromMkspecName(mkspecName) {
- return msvcCompilerVersionForYear(mkspecName.slice(msvcPrefix().length));
-}
-
-function addQtBuildVariant(qtProps, buildVariantName) {
- if (qtProps.qtConfigItems.contains(buildVariantName))
- qtProps.buildVariant.push(buildVariantName);
-}
-
-function checkForStaticBuild(qtProps) {
- if (qtProps.qtMajorVersion >= 5)
- return qtProps.qtConfigItems.contains("static");
- if (qtProps.frameworkBuild)
- return false; // there are no Qt4 static frameworks
- var isWin = qtProps.mkspecName.startsWith("win");
- var libDir = isWin ? qtProps.binaryPath : qtProps.libraryPath;
- var coreLibFiles = File.directoryEntries(libDir, File.Files)
- .filter(function(fp) { return fp.contains("Core"); });
- if (coreLibFiles.length === 0)
- throw "Could not determine whether Qt is a static build.";
- for (var i = 0; i < coreLibFiles.length; ++i) {
- if (Utilities.isSharedLibrary(coreLibFiles[i]))
- return false;
- }
- return true;
-}
-
-function isForMinGw(qtProps) {
- return qtProps.mkspecName.startsWith("win32-g++") || qtProps.mkspecName.startsWith("mingw");
-}
-
-function targetsDesktopWindows(qtProps) {
- return qtProps.mkspecName.startsWith("win32-") || isForMinGw(qtProps);
-}
-
-function guessMinimumWindowsVersion(qtProps) {
- if (qtProps.mkspecName.startsWith("winrt-"))
- return "10.0";
- if (!targetsDesktopWindows(qtProps))
- return "";
- if (qtProps.architecture === "x86_64" || qtProps.architecture === "ia64")
- return "5.2"
- var match = qtProps.mkspecName.match(/^win32-msvc(\d+)$/);
- if (match) {
- var msvcVersion = match[1];
- if (msvcVersion < 2012)
- return "5.0";
- return "5.1";
- }
- return qtProps.qtMajorVersion < 5 ? "5.0" : "5.1";
-}
-
-function fillEntryPointLibs(qtProps, debug) {
- result = [];
- var isMinGW = isForMinGw(qtProps);
-
- // Some Linux distributions rename the qtmain library.
- var qtMainCandidates = ["qtmain"];
- if (isMinGW && qtProps.qtMajorVersion === 5)
- qtMainCandidates.push("qt5main");
-
- for (var i = 0; i < qtMainCandidates.length; ++i) {
- var baseNameCandidate = qtMainCandidates[i];
- var qtmain = qtProps.libraryPath + '/';
- if (isMinGW)
- qtmain += "lib";
- qtmain += baseNameCandidate + qtProps.qtLibInfix;
- if (debug)
- qtmain += 'd';
- if (isMinGW) {
- qtmain += ".a";
- } else {
- qtmain += ".lib";
- if (Utilities.versionCompare(qtProps.qtVersion, "5.4.0") >= 0)
- result.push("Shell32.lib");
- }
- if (File.exists(qtmain)) {
- result.push(qtmain);
- break;
- }
- }
- if (result.length === 0) {
- console.warn("Could not find the qtmain library at '" + toNative(qtProps.libraryPath)
- + "'. You will not be able to link Qt applications.");
- }
- return result;
-}
-
-function getQtProperties(qmakeFilePath, qbs) {
- var queryResult = queryQmake(qmakeFilePath);
- var qtProps = {};
- qtProps.installPrefixPath = pathQueryValue(queryResult, "QT_INSTALL_PREFIX");
- qtProps.documentationPath = pathQueryValue(queryResult, "QT_INSTALL_DOCS");
- qtProps.includePath = pathQueryValue(queryResult, "QT_INSTALL_HEADERS");
- qtProps.libraryPath = pathQueryValue(queryResult, "QT_INSTALL_LIBS");
- qtProps.hostLibraryPath = pathQueryValue(queryResult, "QT_HOST_LIBS");
- qtProps.binaryPath = pathQueryValue(queryResult, "QT_HOST_BINS")
- || pathQueryValue(queryResult, "QT_INSTALL_BINS");
- qtProps.documentationPath = pathQueryValue(queryResult, "QT_INSTALL_DOCS");
- qtProps.pluginPath = pathQueryValue(queryResult, "QT_INSTALL_PLUGINS");
- qtProps.qmlPath = pathQueryValue(queryResult, "QT_INSTALL_QML");
- qtProps.qmlImportPath = pathQueryValue(queryResult, "QT_INSTALL_IMPORTS");
- qtProps.qtVersion = queryResult.QT_VERSION;
-
- var mkspecsBaseSrcPath;
- if (Utilities.versionCompare(qtProps.qtVersion, "5") >= 0) {
- qtProps.mkspecBasePath = FileInfo.joinPaths(pathQueryValue(queryResult, "QT_HOST_DATA"),
- "mkspecs");
- mkspecsBaseSrcPath = FileInfo.joinPaths(pathQueryValue(queryResult, "QT_HOST_DATA/src"),
- "mkspecs");
- } else {
- qtProps.mkspecBasePath = FileInfo.joinPaths
- (pathQueryValue(queryResult, "QT_INSTALL_DATA"), "mkspecs");
- }
- if (!File.exists(qtProps.mkspecBasePath))
- throw "Cannot extract the mkspecs directory.";
-
- var qconfigContent = readFileContent(FileInfo.joinPaths(qtProps.mkspecBasePath,
- "qconfig.pri"));
- qtProps.qtMajorVersion = parseInt(configVariable(qconfigContent, "QT_MAJOR_VERSION"));
- qtProps.qtMinorVersion = parseInt(configVariable(qconfigContent, "QT_MINOR_VERSION"));
- qtProps.qtPatchVersion = parseInt(configVariable(qconfigContent, "QT_PATCH_VERSION"));
- qtProps.qtNameSpace = configVariable(qconfigContent, "QT_NAMESPACE");
- qtProps.qtLibInfix = configVariable(qconfigContent, "QT_LIBINFIX") || "";
- qtProps.architecture = configVariable(qconfigContent, "QT_TARGET_ARCH")
- || configVariable(qconfigContent, "QT_ARCH") || "x86";
- qtProps.configItems = configVariableItems(qconfigContent, "CONFIG");
- qtProps.qtConfigItems = configVariableItems(qconfigContent, "QT_CONFIG");
-
- // retrieve the mkspec
- if (qtProps.qtMajorVersion >= 5) {
- qtProps.mkspecName = queryResult.QMAKE_XSPEC;
- qtProps.mkspecPath = FileInfo.joinPaths(qtProps.mkspecBasePath, qtProps.mkspecName);
- if (mkspecsBaseSrcPath && !File.exists(qtProps.mkspecPath))
- qtProps.mkspecPath = FileInfo.joinPaths(mkspecsBaseSrcPath, qtProps.mkspecName);
- } else {
- if (qbs.hostOS.contains("windows")) {
- var baseDirPath = FileInfo.joinPaths(qtProps.mkspecBasePath, "default");
- var fileContent = readFileContent(FileInfo.joinPaths(baseDirPath, "qmake.conf"));
- qtProps.mkspecPath = configVariable(fileContent, "QMAKESPEC_ORIGINAL");
- if (!File.exists(qtProps.mkspecPath)) {
- // Work around QTBUG-28792.
- // The value of QMAKESPEC_ORIGINAL is wrong for MinGW packages. Y u h8 me?
- var match = fileContent.exec(/\binclude\(([^)]+)\/qmake\.conf\)/m);
- if (match) {
- qtProps.mkspecPath = FileInfo.cleanPath(FileInfo.joinPaths(
- baseDirPath, match[1]));
- }
- }
- } else {
- qtProps.mkspecPath = FileInfo.canonicalPath(
- FileInfo.joinPaths(qtProps.mkspecBasePath, "default"));
- }
-
- // E.g. in qmake.conf for Qt 4.8/mingw we find this gem:
- // QMAKESPEC_ORIGINAL=C:\\Qt\\Qt\\4.8\\mingw482\\mkspecs\\win32-g++
- qtProps.mkspecPath = FileInfo.cleanPath(qtProps.mkspecPath);
-
- qtProps.mkspecName = qtProps.mkspecPath;
- var idx = qtProps.mkspecName.lastIndexOf('/');
- if (idx !== -1)
- qtProps.mkspecName = qtProps.mkspecName.slice(idx + 1);
- }
- if (!File.exists(qtProps.mkspecPath))
- throw "mkspec '" + toNative(qtProps.mkspecPath) + "' does not exist";
-
- // determine MSVC version
- if (isMsvcQt(qtProps)) {
- var msvcMajor = configVariable(qconfigContent, "QT_MSVC_MAJOR_VERSION");
- var msvcMinor = configVariable(qconfigContent, "QT_MSVC_MINOR_VERSION");
- var msvcPatch = configVariable(qconfigContent, "QT_MSVC_PATCH_VERSION");
- if (msvcMajor && msvcMinor && msvcPatch)
- qtProps.msvcVersion = msvcMajor + "." + msvcMinor + "." + msvcPatch;
- else
- qtProps.msvcVersion = msvcCompilerVersionFromMkspecName(qtProps.mkspecName);
- }
-
- // determine whether we have a framework build
- qtProps.frameworkBuild = qtProps.mkspecPath.contains("macx")
- && qtProps.configItems.contains("qt_framework");
-
- // determine whether Qt is built with debug, release or both
- qtProps.buildVariant = [];
- addQtBuildVariant(qtProps, "debug");
- addQtBuildVariant(qtProps, "release");
-
- qtProps.staticBuild = checkForStaticBuild(qtProps);
-
- // determine whether user apps require C++11
- if (qtProps.qtConfigItems.contains("c++11") && qtProps.staticBuild)
- qtProps.configItems.push("c++11");
-
- // Set the minimum operating system versions appropriate for this Qt version
- qtProps.windowsVersion = guessMinimumWindowsVersion(qtProps);
- if (qtProps.windowsVersion) { // Is target OS Windows?
- if (qtProps.buildVariant.contains("debug"))
- qtProps.entryPointLibsDebug = fillEntryPointLibs(qtProps, true);
- if (qtProps.buildVariant.contains("release"))
- qtProps.entryPointLibsRelease = fillEntryPointLibs(qtProps, false);
- } else if (qtProps.mkspecPath.contains("macx")) {
- if (qtProps.qtMajorVersion >= 5) {
- var lines = getFileContentsRecursively(FileInfo.joinPaths(qtProps.mkspecPath,
- "qmake.conf"));
- for (var i = 0; i < lines.length; ++i) {
- var line = lines[i].trim();
- match = line.match
- (/^QMAKE_(MACOSX|IOS|TVOS|WATCHOS)_DEPLOYMENT_TARGET\s*=\s*(.*)\s*$/);
- if (match) {
- var platform = match[1];
- var version = match[2];
- if (platform === "MACOSX")
- qtProps.macosVersion = version;
- else if (platform === "IOS")
- qtProps.iosVersion = version;
- else if (platform === "TVOS")
- qtProps.tvosVersion = version;
- else if (platform === "WATCHOS")
- qtProps.watchosVersion = version;
- }
- }
- var isMac = qtProps.mkspecName !== "macx-ios-clang"
- && qtProps.mkspecName !== "macx-tvos-clang"
- && qtProps.mkspecName !== "macx-watchos-clang";
- if (isMac) {
- // Qt 5.0.x placed the minimum version in a different file
- if (!qtProps.macosVersion)
- qtProps.macosVersion = "10.6";
-
- // If we're using C++11 with libc++, make sure the deployment target is >= 10.7
- if (Utilities.versionCompare(qtProps.macosVersion, "10, 7") < 0
- && qtProps.qtConfigItems.contains("c++11")) {
- qtProps.macosVersion = "10.7";
- }
- }
- } else if (qtProps.qtMajorVersion === 4 && qtProps.qtMinorVersion >= 6) {
- var qconfigDir = qtProps.frameworkBuild
- ? FileInfo.joinPaths(qtProps.libraryPath, "QtCore.framework", "Headers")
- : FileInfo.joinPaths(qtProps.includePath, "Qt");
- try {
- var qconfig = new TextFile(FileInfo.joinPaths(qconfigDir, "qconfig.h"),
- TextFile.ReadOnly);
- var qtCocoaBuild = false;
- var ok = true;
- do {
- line = qconfig.readLine();
- if (line.match(/\s*#define\s+QT_MAC_USE_COCOA\s+1\s*/)) {
- qtCocoaBuild = true;
- break;
- }
- } while (!qconfig.atEof());
- qtProps.macosVersion = qtCocoaBuild ? "10.5" : "10.4";
- }
- catch (e) {}
- finally {
- if (qconfig)
- qconfig.close();
- }
- if (!qtProps.macosVersion) {
- throw "Could not determine whether Qt is using Cocoa or Carbon from '"
- + toNative(qconfig.filePath()) + "'.";
- }
- }
- } else if (qtProps.mkspecPath.contains("android")) {
- if (qtProps.qtMajorVersion >= 5)
- qtProps.androidVersion = "2.3";
- else if (qtProps.qtMajorVersion === 4 && qtProps.qtMinorVersion >= 8)
- qtProps.androidVersion = "1.6"; // Necessitas
- }
- return qtProps;
-}
-
-function makePluginData() {
- var pluginData = {};
- pluginData.type = undefined;
- pluginData.className = undefined;
- pluginData.autoLoad = true;
- pluginData["extends"] = [];
- return pluginData;
-}
-
-function makeQtModuleInfo(name, qbsName, deps) {
- var moduleInfo = {};
- moduleInfo.name = name; // As in the path to the headers and ".name" in the pri files.
- if (moduleInfo.name === undefined)
- moduleInfo.name = "";
- moduleInfo.qbsName = qbsName; // Lower-case version without "qt" prefix.
- moduleInfo.dependencies = deps || []; // qbs names.
- if (moduleInfo.qbsName && moduleInfo.qbsName !== "core"
- && !moduleInfo.dependencies.contains("core")) {
- moduleInfo.dependencies.unshift("core");
- }
- moduleInfo.isPrivate = qbsName && qbsName.endsWith("-private");
- moduleInfo.hasLibrary = !moduleInfo.isPrivate;
- moduleInfo.isStaticLibrary = false;
- moduleInfo.isPlugin = false;
- moduleInfo.mustExist = true;
- moduleInfo.modulePrefix = ""; // empty value means "Qt".
- moduleInfo.version = undefined;
- moduleInfo.includePaths = [];
- moduleInfo.compilerDefines = [];
- moduleInfo.staticLibrariesDebug = [];
- moduleInfo.staticLibrariesRelease = [];
- moduleInfo.dynamicLibrariesDebug = [];
- moduleInfo.dynamicLibrariesRelease = [];
- moduleInfo.linkerFlagsDebug = [];
- moduleInfo.linkerFlagsRelease = [];
- moduleInfo.libFilePathDebug = undefined;
- moduleInfo.libFilePathRelease = undefined;
- moduleInfo.frameworksDebug = [];
- moduleInfo.frameworksRelease = [];
- moduleInfo.frameworkPathsDebug = [];
- moduleInfo.frameworkPathsRelease = [];
- moduleInfo.libraryPaths = [];
- moduleInfo.libDir = "";
- moduleInfo.config = [];
- moduleInfo.supportedPluginTypes = [];
- moduleInfo.pluginData = makePluginData();
- return moduleInfo;
-}
-
-function frameworkHeadersPath(qtModuleInfo, qtProps) {
- return FileInfo.joinPaths(qtProps.libraryPath, qtModuleInfo.name + ".framework", "Headers");
-}
-
-function qt4ModuleIncludePaths(qtModuleInfo, qtProps) {
- var paths = [];
- if (isFramework(qtModuleInfo, qtProps))
- paths.push(frameworkHeadersPath(qtModuleInfo, qtProps));
- else
- paths.push(qtProps.includePath, FileInfo.joinPaths(qtProps.includePath, qtModuleInfo.name));
- return paths;
-}
-
-// We erroneously called the "testlib" module "test" for quite a while. Let's not punish users
-// for that.
-function addTestModule(modules) {
- var testModule = makeQtModuleInfo("QtTest", "test", ["testlib"]);
- testModule.hasLibrary = false;
- modules.push(testModule);
-}
-
-// See above.
-function addDesignerComponentsModule(modules) {
- var module = makeQtModuleInfo("QtDesignerComponents", "designercomponents",
- ["designercomponents-private"]);
- module.hasLibrary = false;
- modules.push(module);
-}
-
-function isFramework(modInfo, qtProps) {
- if (!qtProps.frameworkBuild || modInfo.isStaticLibrary)
- return false;
- var modulesNeverBuiltAsFrameworks = [
- "bootstrap", "openglextensions", "platformsupport", "qmldevtools", "uitools", "harfbuzzng"
- ];
- return !modulesNeverBuiltAsFrameworks.contains(modInfo.qbsName);
-}
-
-function libBaseName(modInfo, libName, debugBuild, qtProps) {
- var name = libName;
- if (qtProps.mkspecName.startsWith("win")) {
- if (debugBuild)
- name += 'd';
- if (!modInfo.isStaticLibrary && qtProps.qtMajorVersion < 5)
- name += qtProps.qtMajorVersion;
- }
- if (qtProps.mkspecName.contains("macx")
- || qtProps.mkspecName.contains("ios")
- || qtProps.mkspecName.contains("darwin")) {
- if (!isFramework(modInfo, qtProps)
- && qtProps.buildVariant.contains("debug")
- && (!qtProps.buildVariant.contains("release") || debugBuild)) {
- name += "_debug";
- }
- }
- return name;
-}
-
-function moduleNameWithoutPrefix(modInfo) {
- if (modInfo.name === "Phonon")
- return "phonon";
- if (!modInfo.modulePrefix && modInfo.name.startsWith("Qt"))
- return modInfo.name.slice(2); // Strip off "Qt".
- if (modInfo.name.startsWith(modInfo.modulePrefix))
- return modInfo.name.slice(modInfo.modulePrefix.length);
- return modInfo.name;
-}
-
-function libraryBaseName(modInfo, qtProps, debugBuild) {
- if (modInfo.isPlugin)
- return libBaseName(modInfo, modInfo.name, debugBuild, qtProps);
-
- // Some modules use a different naming scheme, so it doesn't get boring.
- var libNameBroken = modInfo.name === "Enginio"
- || modInfo.name === "DataVisualization"
- || modInfo.name === "Phonon";
-
- var libName = !modInfo.modulePrefix && !libNameBroken ? "Qt" : modInfo.modulePrefix;
- if (qtProps.qtMajorVersion >= 5 && !isFramework(modInfo, qtProps) && !libNameBroken)
- libName += qtProps.qtMajorVersion;
- libName += moduleNameWithoutPrefix(modInfo);
- libName += qtProps.qtLibInfix;
- return libBaseName(modInfo, libName, debugBuild, qtProps);
-}
-
-function libNameForLinker(modInfo, qtProps, debugBuild) {
- if (!modInfo.hasLibrary)
- return undefined;
- var libName = libraryBaseName(modInfo, qtProps, debugBuild);
- if (qtProps.mkspecName.contains("msvc"))
- libName += ".lib";
- return libName;
-}
-
-function guessLibraryFilePath(prlFilePath, libDir, qtProps) {
- var baseName = FileInfo.baseName(prlFilePath);
- var prefixCandidates = ["", "lib"];
- var suffixCandidates = ["so." + qtProps.qtVersion, "so", "a", "lib", "dll.a"];
- for (var i = 0; i < prefixCandidates.length; ++i) {
- var prefix = prefixCandidates[i];
- for (var j = 0; j < suffixCandidates.length; ++j) {
- var suffix = suffixCandidates[j];
- var candidate = FileInfo.joinPaths(libDir, prefix + baseName + '.' + suffix);
- if (File.exists(candidate))
- return candidate;
- }
- }
-}
-
-function doReplaceQtLibNamesWithFilePath(namePathMap, libList) {
- for (var i = 0; i < libList.length; ++i) {
- var lib = libList[i];
- var path = namePathMap[lib];
- if (path)
- libList[i] = path;
- }
-}
-
-function replaceQtLibNamesWithFilePath(modules, qtProps) {
- // We don't want to add the libraries for Qt modules via "-l", because of the
- // danger that a wrong one will be picked up, e.g. from /usr/lib. Instead,
- // we pull them in using the full file path.
- var linkerNamesToFilePathsDebug = {};
- var linkerNamesToFilePathsRelease = {};
- for (var i = 0; i < modules.length; ++i) {
- var m = modules[i];
- linkerNamesToFilePathsDebug[libNameForLinker(m, qtProps, true)] = m.libFilePathDebug;
- linkerNamesToFilePathsRelease[libNameForLinker(m, qtProps, false)] = m.libFilePathRelease;
- }
- for (i = 0; i < modules.length; ++i) {
- var module = modules[i];
- doReplaceQtLibNamesWithFilePath(linkerNamesToFilePathsDebug, module.dynamicLibrariesDebug);
- doReplaceQtLibNamesWithFilePath(linkerNamesToFilePathsDebug, module.staticLibrariesDebug);
- doReplaceQtLibNamesWithFilePath(linkerNamesToFilePathsRelease,
- module.dynamicLibrariesRelease);
- doReplaceQtLibNamesWithFilePath(linkerNamesToFilePathsRelease,
- module.staticLibrariesRelease);
- }
-}
-
-function doSetupLibraries(modInfo, qtProps, debugBuild, nonExistingPrlFiles) {
- if (!modInfo.hasLibrary)
- return; // Can happen for Qt4 convenience modules, like "widgets".
-
- if (debugBuild) {
- if (!qtProps.buildVariant.contains("debug"))
- return;
- var modulesNeverBuiltAsDebug = ["bootstrap", "qmldevtools"];
- for (var i = 0; i < modulesNeverBuiltAsDebug.length; ++i) {
- var m = modulesNeverBuiltAsDebug[i];
- if (modInfo.qbsName === m || modInfo.qbsName === m + "-private")
- return;
- }
- } else if (!qtProps.buildVariant.contains("release")) {
- return;
- }
-
- var libs = modInfo.isStaticLibrary
- ? (debugBuild ? modInfo.staticLibrariesDebug : modInfo.staticLibrariesRelease)
- : (debugBuild ? modInfo.dynamicLibrariesDebug : modInfo.dynamicLibrariesRelease);
- var frameworks = debugBuild ? modInfo.frameworksDebug : modInfo.frameworksRelease;
- var frameworkPaths = debugBuild ? modInfo.frameworkPathsDebug : modInfo.frameworkPathsRelease;
- var flags = debugBuild ? modInfo.linkerFlagsDebug : modInfo.linkerFlagsRelease;
- var libFilePath;
-
- if (qtProps.mkspecName.contains("ios") && modInfo.isStaticLibrary) {
- libs.push("z", "m");
- if (qtProps.qtMajorVersion === 5 && qtProps.qtMinorVersion < 8) {
- var platformSupportModule = makeQtModuleInfo("QtPlatformSupport", "platformsupport");
- libs.push(libNameForLinker(platformSupportModule, qtProps, debugBuild));
- }
- if (modInfo.name === "qios") {
- flags.push("-force_load", FileInfo.joinPaths(
- qtProps.pluginPath, "platforms",
- libBaseName(modInfo, "libqios", debugBuild, qtProps) + ".a"));
- }
- }
- var prlFilePath = modInfo.isPlugin
- ? FileInfo.joinPaths(qtProps.pluginPath, modInfo.pluginData.type)
- : (modInfo.libDir ? modInfo.libDir : qtProps.libraryPath);
- if (isFramework(modInfo, qtProps)) {
- prlFilePath = FileInfo.joinPaths(prlFilePath,
- libraryBaseName(modInfo, qtProps, false) + ".framework");
- }
- var libDir = prlFilePath;
- var baseName = libraryBaseName(modInfo, qtProps, debugBuild);
- if (!qtProps.mkspecName.startsWith("win") && !isFramework(modInfo, qtProps))
- baseName = "lib" + baseName;
- prlFilePath = FileInfo.joinPaths(prlFilePath, baseName);
- var isNonStaticQt4OnWindows = qtProps.mkspecName.startsWith("win")
- && !modInfo.isStaticLibrary && qtProps.qtMajorVersion < 5;
- if (isNonStaticQt4OnWindows)
- prlFilePath = prlFilePath.slice(0, prlFilePath.length - 1); // The prl file base name does *not* contain the version number...
- prlFilePath += ".prl";
- try {
- var prlFile = new TextFile(prlFilePath, TextFile.ReadOnly);
- while (!prlFile.atEof()) {
- var line = prlFile.readLine().trim();
- var equalsOffset = line.indexOf('=');
- if (equalsOffset === -1)
- continue;
- if (line.startsWith("QMAKE_PRL_TARGET")) {
- var isMingw = qtProps.mkspecName.startsWith("win")
- && qtProps.mkspecName.contains("g++");
- var isQtVersionBefore56 = qtProps.qtMajorVersion < 5
- || (qtProps.qtMajorVersion === 5 && qtProps.qtMinorVersion < 6);
-
- // QMAKE_PRL_TARGET has a "lib" prefix, except for mingw.
- // Of course, the exception has an exception too: For static libs, mingw *does*
- // have the "lib" prefix.
- var libFileName = "";
- if (isQtVersionBefore56 && qtProps.qtMajorVersion === 5 && isMingw
- && !modInfo.isStaticLibrary) {
- libFileName += "lib";
- }
-
- libFileName += line.slice(equalsOffset + 1).trim();
- if (isNonStaticQt4OnWindows)
- libFileName += 4; // This is *not* part of QMAKE_PRL_TARGET...
- if (isQtVersionBefore56) {
- if (qtProps.mkspecName.contains("msvc")) {
- libFileName += ".lib";
- } else if (isMingw) {
- libFileName += ".a";
- if (!File.exists(FileInfo.joinPaths(libDir, libFileName)))
- libFileName = libFileName.slice(0, -2) + ".dll";
- }
- }
- libFilePath = FileInfo.joinPaths(libDir, libFileName);
- continue;
- }
- if (line.startsWith("QMAKE_PRL_CONFIG")) {
- modInfo.config = splitNonEmpty(line.slice(equalsOffset + 1).trim(), ' ');
- continue;
- }
- if (!line.startsWith("QMAKE_PRL_LIBS ="))
- continue;
-
- var parts = extractPaths(line.slice(equalsOffset + 1).trim(), prlFilePath);
- for (i = 0; i < parts.length; ++i) {
- var part = parts[i];
- part = part.replace("$$[QT_INSTALL_LIBS]", qtProps.libraryPath);
- if (part.startsWith("-l")) {
- libs.push(part.slice(2));
- } else if (part.startsWith("-L")) {
- modInfo.libraryPaths.push(part.slice(2));
- } else if (part.startsWith("-F")) {
- frameworkPaths.push(part.slice(2));
- } else if (part === "-framework") {
- if (++i < parts.length)
- frameworks.push(parts[i]);
- } else if (part === "-pthread") {
- libs.push("pthread");
- } else if (part.startsWith('-')) { // Some other option
- console.debug("QMAKE_PRL_LIBS contains non-library option '" + part
- + "' in file '" + prlFilePath + "'");
- flags.push(part);
- } else if (part.startsWith("/LIBPATH:")) {
- libraryPaths.push(part.slice(9).replace(/\\/g, '/'));
- } else { // Assume it's a file path/name.
- libs.push(part.replace(/\\/g, '/'));
- }
- }
- }
- } catch (e) {
- libFilePath = guessLibraryFilePath(prlFilePath, libDir, qtProps);
- if (nonExistingPrlFiles.contains(prlFilePath))
- return;
- nonExistingPrlFiles.push(prlFilePath);
- if (!libFilePath && modInfo.mustExist) {
- console.warn("Could not open prl file '" + toNative(prlFilePath) + "' for module '"
- + modInfo.name
- + "' (" + e + "), and failed to deduce the library file path. "
- + " This module will likely not be usable by qbs.");
- }
- }
- finally {
- if (prlFile)
- prlFile.close();
- }
-
- if (debugBuild)
- modInfo.libFilePathDebug = libFilePath;
- else
- modInfo.libFilePathRelease = libFilePath;
-}
-
-function setupLibraries(qtModuleInfo, qtProps, nonExistingPrlFiles) {
- doSetupLibraries(qtModuleInfo, qtProps, true, nonExistingPrlFiles);
- doSetupLibraries(qtModuleInfo, qtProps, false, nonExistingPrlFiles);
-}
-
-function allQt4Modules(qtProps) {
- // as per http://doc.qt.io/qt-4.8/modules.html + private stuff.
- var modules = [];
-
- var core = makeQtModuleInfo("QtCore", "core");
- core.compilerDefines.push("QT_CORE_LIB");
- if (qtProps.qtNameSpace)
- core.compilerDefines.push("QT_NAMESPACE=" + qtProps.qtNameSpace);
- modules.push(core,
- makeQtModuleInfo("QtCore", "core-private", ["core"]),
- makeQtModuleInfo("QtGui", "gui"),
- makeQtModuleInfo("QtGui", "gui-private", ["gui"]),
- makeQtModuleInfo("QtMultimedia", "multimedia", ["gui", "network"]),
- makeQtModuleInfo("QtMultimedia", "multimedia-private", ["multimedia"]),
- makeQtModuleInfo("QtNetwork", "network"),
- makeQtModuleInfo("QtNetwork", "network-private", ["network"]),
- makeQtModuleInfo("QtOpenGL", "opengl", ["gui"]),
- makeQtModuleInfo("QtOpenGL", "opengl-private", ["opengl"]),
- makeQtModuleInfo("QtOpenVG", "openvg", ["gui"]),
- makeQtModuleInfo("QtScript", "script"),
- makeQtModuleInfo("QtScript", "script-private", ["script"]),
- makeQtModuleInfo("QtScriptTools", "scripttools", ["script", "gui"]),
- makeQtModuleInfo("QtScriptTools", "scripttools-private", ["scripttools"]),
- makeQtModuleInfo("QtSql", "sql"),
- makeQtModuleInfo("QtSql", "sql-private", ["sql"]),
- makeQtModuleInfo("QtSvg", "svg", ["gui"]),
- makeQtModuleInfo("QtSvg", "svg-private", ["svg"]),
- makeQtModuleInfo("QtWebKit", "webkit", ["gui", "network"]),
- makeQtModuleInfo("QtWebKit", "webkit-private", ["webkit"]),
- makeQtModuleInfo("QtXml", "xml"),
- makeQtModuleInfo("QtXml", "xml-private", ["xml"]),
- makeQtModuleInfo("QtXmlPatterns", "xmlpatterns", ["network"]),
- makeQtModuleInfo("QtXmlPatterns", "xmlpatterns-private", ["xmlpatterns"]),
- makeQtModuleInfo("QtDeclarative", "declarative", ["gui", "script"]),
- makeQtModuleInfo("QtDeclarative", "declarative-private", ["declarative"]),
- makeQtModuleInfo("QtDesigner", "designer", ["gui", "xml"]),
- makeQtModuleInfo("QtDesigner", "designer-private", ["designer"]),
- makeQtModuleInfo("QtUiTools", "uitools"),
- makeQtModuleInfo("QtUiTools", "uitools-private", ["uitools"]),
- makeQtModuleInfo("QtHelp", "help", ["network", "sql"]),
- makeQtModuleInfo("QtHelp", "help-private", ["help"]),
- makeQtModuleInfo("QtTest", "testlib"),
- makeQtModuleInfo("QtTest", "testlib-private", ["testlib"]));
- if (qtProps.mkspecName.startsWith("win")) {
- var axcontainer = makeQtModuleInfo("QAxContainer", "axcontainer");
- axcontainer.modulePrefix = "Q";
- axcontainer.isStaticLibrary = true;
- axcontainer.includePaths.push(FileInfo.joinPaths(qtProps.includePath, "ActiveQt"));
- modules.push(axcontainer);
-
- var axserver = makeQtModuleInfo("QAxServer", "axserver");
- axserver.modulePrefix = "Q";
- axserver.isStaticLibrary = true;
- axserver.compilerDefines.push("QAXSERVER");
- axserver.includePaths.push(FileInfo.joinPaths(qtProps.includePath, "ActiveQt"));
- modules.push(axserver);
- } else {
- modules.push(makeQtModuleInfo("QtDBus", "dbus"));
- modules.push(makeQtModuleInfo("QtDBus", "dbus-private", ["dbus"]));
- }
-
- var designerComponentsPrivate = makeQtModuleInfo(
- "QtDesignerComponents", "designercomponents-private",
- ["gui-private", "designer-private"]);
- designerComponentsPrivate.hasLibrary = true;
- modules.push(designerComponentsPrivate);
-
- var phonon = makeQtModuleInfo("Phonon", "phonon");
- phonon.includePaths = qt4ModuleIncludePaths(phonon, qtProps);
- modules.push(phonon);
-
- // Set up include paths that haven't been set up before this point.
- for (i = 0; i < modules.length; ++i) {
- var module = modules[i];
- if (module.includePaths.length > 0)
- continue;
- module.includePaths = qt4ModuleIncludePaths(module, qtProps);
- }
-
- // Set up compiler defines haven't been set up before this point.
- for (i = 0; i < modules.length; ++i) {
- module = modules[i];
- if (module.compilerDefines.length > 0)
- continue;
- module.compilerDefines.push("QT_" + module.qbsName.toUpperCase() + "_LIB");
- }
-
- // These are for the convenience of project file authors. It allows them
- // to add a dependency to e.g. "Qt.widgets" without a version check.
- var virtualModule = makeQtModuleInfo(undefined, "widgets", ["core", "gui"]);
- virtualModule.hasLibrary = false;
- modules.push(virtualModule);
- virtualModule = makeQtModuleInfo(undefined, "quick", ["declarative"]);
- virtualModule.hasLibrary = false;
- modules.push(virtualModule);
- virtualModule = makeQtModuleInfo(undefined, "concurrent");
- virtualModule.hasLibrary = false;
- modules.push(virtualModule);
- virtualModule = makeQtModuleInfo(undefined, "printsupport", ["core", "gui"]);
- virtualModule.hasLibrary = false;
- modules.push(virtualModule);
-
- addTestModule(modules);
- addDesignerComponentsModule(modules);
-
- var modulesThatCanBeDisabled = [
- "xmlpatterns", "multimedia", "phonon", "svg", "webkit", "script", "scripttools",
- "declarative", "gui", "dbus", "opengl", "openvg"];
- var nonExistingPrlFiles = [];
- for (i = 0; i < modules.length; ++i) {
- module = modules[i];
- var name = module.qbsName;
- var privateIndex = name.indexOf("-private");
- if (privateIndex !== -1)
- name = name.slice(0, privateIndex);
- if (modulesThatCanBeDisabled.contains(name))
- module.mustExist = false;
- if (qtProps.staticBuild)
- module.isStaticLibrary = true;
- setupLibraries(module, qtProps, nonExistingPrlFiles);
- }
- replaceQtLibNamesWithFilePath(modules, qtProps);
-
- return modules;
-}
-
-function getFileContentsRecursively(filePath) {
- var file = new TextFile(filePath, TextFile.ReadOnly);
- var lines = splitNonEmpty(file.readAll(), '\n');
- for (var i = 0; i < lines.length; ++i) {
- var includeString = "include(";
- var line = lines[i].trim();
- if (!line.startsWith(includeString))
- continue;
- var offset = includeString.length;
- var closingParenPos = line.indexOf(')', offset);
- if (closingParenPos === -1) {
- console.warn("Invalid include statement in '" + toNative(filePath) + "'");
- continue;
- }
- var includedFilePath = line.slice(offset, closingParenPos);
- if (!FileInfo.isAbsolutePath(includedFilePath))
- includedFilePath = FileInfo.joinPaths(FileInfo.path(filePath), includedFilePath);
- var includedContents = getFileContentsRecursively(includedFilePath);
- var j = i;
- for (var k = 0; k < includedContents.length; ++k)
- lines.splice(++j, 0, includedContents[k]);
- lines.splice(i--, 1);
- }
- file.close();
- return lines;
-}
-
-function extractPaths(rhs, filePath) {
- var paths = [];
- var startIndex = 0;
- for (;;) {
- while (startIndex < rhs.length && rhs.charAt(startIndex) === ' ')
- ++startIndex;
- if (startIndex >= rhs.length)
- break;
- var endIndex;
- if (rhs.charAt(startIndex) === '"') {
- ++startIndex;
- endIndex = rhs.indexOf('"', startIndex);
- if (endIndex === -1) {
- console.warn("Unmatched quote in file '" + toNative(filePath) + "'");
- break;
- }
- } else {
- endIndex = rhs.indexOf(' ', startIndex + 1);
- if (endIndex === -1)
- endIndex = rhs.length;
- }
- paths.push(FileInfo.cleanPath(rhs.slice(startIndex, endIndex)));
- startIndex = endIndex + 1;
- }
- return paths;
-}
-
-function removeDuplicatedDependencyLibs(modules) {
- var revDeps = {};
- var currentPath = [];
- var getLibraries;
- var getLibFilePath;
-
- function setupReverseDependencies(modules) {
- var moduleByName = {};
- for (var i = 0; i < modules.length; ++i)
- moduleByName[modules[i].qbsName] = modules[i];
- for (i = 0; i < modules.length; ++i) {
- var module = modules[i];
- for (var j = 0; j < module.dependencies.length; ++j) {
- var depmod = moduleByName[module.dependencies[j]];
- if (!depmod)
- continue;
- if (!revDeps[depmod.qbsName])
- revDeps[depmod.qbsName] = [];
- revDeps[depmod.qbsName].push(module);
- }
- }
- }
-
- function roots(modules) {
- var result = [];
- for (i = 0; i < modules.length; ++i) {
- var module = modules[i]
- if (module.dependencies.length === 0)
- result.push(module);
- }
- return result;
- }
-
- function traverse(module, libs) {
- if (currentPath.contains(module))
- return;
- currentPath.push(module);
- var moduleLibraryLists = getLibraries(module);
- for (var i = 0; i < moduleLibraryLists.length; ++i) {
- var modLibList = moduleLibraryLists[i];
- for (j = modLibList.length - 1; j >= 0; --j) {
- if (libs.contains(modLibList[j]))
- modLibList.splice(j, 1);
- }
- }
-
- var libFilePath = getLibFilePath(module);
- if (libFilePath)
- libs.push(libFilePath);
- for (i = 0; i < moduleLibraryLists.length; ++i)
- libs = libs.concat(moduleLibraryLists[i]);
- libs.sort();
-
- var deps = revDeps[module.qbsName];
- for (i = 0; i < (deps || []).length; ++i)
- traverse(deps[i], libs);
-
- currentPath.pop();
- }
-
- setupReverseDependencies(modules);
-
- // Traverse the debug variants of modules.
- getLibraries = function(module) {
- return [module.dynamicLibrariesDebug, module.staticLibrariesDebug];
- };
- getLibFilePath = function(module) { return module.libFilePathDebug; };
- var rootModules = roots(modules);
- for (var i = 0; i < rootModules.length; ++i)
- traverse(rootModules[i], []);
-
- // Traverse the release variants of modules.
- getLibraries = function(module) {
- return [module.dynamicLibrariesRelease, module.staticLibrariesRelease];
- };
- getLibFilePath = function(module) { return module.libFilePathRelease; };
- for (i = 0; i < rootModules.length; ++i)
- traverse(rootModules[i], []);
-}
-
-function allQt5Modules(qtProps) {
- var nonExistingPrlFiles = [];
- var modules = [];
- var modulesDir = FileInfo.joinPaths(qtProps.mkspecBasePath, "modules");
- var modulePriFiles = File.directoryEntries(modulesDir, File.Files);
- for (var i = 0; i < modulePriFiles.length; ++i) {
- var priFileName = modulePriFiles[i];
- var priFilePath = FileInfo.joinPaths(modulesDir, priFileName);
- var moduleFileNamePrefix = "qt_lib_";
- var pluginFileNamePrefix = "qt_plugin_";
- var moduleFileNameSuffix = ".pri";
- var fileHasPluginPrefix = priFileName.startsWith(pluginFileNamePrefix);
- if (!fileHasPluginPrefix && (!priFileName.startsWith(moduleFileNamePrefix))
- || !priFileName.endsWith(moduleFileNameSuffix)) {
- continue;
- }
- var moduleInfo = makeQtModuleInfo();
- moduleInfo.isPlugin = fileHasPluginPrefix;
- var fileNamePrefix = moduleInfo.isPlugin ? pluginFileNamePrefix : moduleFileNamePrefix;
- moduleInfo.qbsName = priFileName.slice(fileNamePrefix.length, -moduleFileNameSuffix.length);
- if (moduleInfo.isPlugin) {
- moduleInfo.name = moduleInfo.qbsName;
- moduleInfo.isStaticLibrary = true;
- }
- var moduleKeyPrefix = (moduleInfo.isPlugin ? "QT_PLUGIN" : "QT")
- + '.' + moduleInfo.qbsName + '.';
- moduleInfo.qbsName = moduleInfo.qbsName.replace("_private", "-private");
- var hasV2 = false;
- var hasModuleEntry = false;
- var lines = getFileContentsRecursively(priFilePath);
- for (var j = 0; j < lines.length; ++j) {
- var line = lines[j].trim();
- var firstEqualsOffset = line.indexOf('=');
- if (firstEqualsOffset === -1)
- continue;
- var key = line.slice(0, firstEqualsOffset).trim();
- var value = line.slice(firstEqualsOffset + 1).trim();
- if (!key.startsWith(moduleKeyPrefix) || !value)
- continue;
- if (key.endsWith(".name")) {
- moduleInfo.name = value;
- } else if (key.endsWith(".module")) {
- hasModuleEntry = true;
- } else if (key.endsWith(".depends")) {
- moduleInfo.dependencies = splitNonEmpty(value, ' ');
- for (var k = 0; k < moduleInfo.dependencies.length; ++k) {
- moduleInfo.dependencies[k]
- = moduleInfo.dependencies[k].replace("_private", "-private");
- }
- } else if (key.endsWith(".module_config")) {
- var elems = splitNonEmpty(value, ' ');
- for (k = 0; k < elems.length; ++k) {
- var elem = elems[k];
- if (elem === "no_link")
- moduleInfo.hasLibrary = false;
- else if (elem === "staticlib")
- moduleInfo.isStaticLibrary = true;
- else if (elem === "internal_module")
- moduleInfo.isPrivate = true;
- else if (elem === "v2")
- hasV2 = true;
- }
- } else if (key.endsWith(".includes")) {
- moduleInfo.includePaths = extractPaths(value, priFilePath);
- for (k = 0; k < moduleInfo.includePaths.length; ++k) {
- moduleInfo.includePaths[k] = moduleInfo.includePaths[k]
- .replace("$$QT_MODULE_INCLUDE_BASE", qtProps.includePath)
- .replace("$$QT_MODULE_HOST_LIB_BASE", qtProps.hostLibraryPath)
- .replace("$$QT_MODULE_LIB_BASE", qtProps.libraryPath);
- }
- } else if (key.endsWith(".libs")) {
- var libDirs = extractPaths(value, priFilePath);
- if (libDirs.length === 1) {
- moduleInfo.libDir = libDirs[0]
- .replace("$$QT_MODULE_HOST_LIB_BASE", qtProps.hostLibraryPath)
- .replace("$$QT_MODULE_LIB_BASE", qtProps.libraryPath);
- } else {
- moduleInfo.libDir = qtProps.libraryPath;
- }
- } else if (key.endsWith(".DEFINES")) {
- moduleInfo.compilerDefines = splitNonEmpty(value, ' ');
- } else if (key.endsWith(".VERSION")) {
- moduleInfo.version = value;
- } else if (key.endsWith(".plugin_types")) {
- moduleInfo.supportedPluginTypes = splitNonEmpty(value, ' ');
- } else if (key.endsWith(".TYPE")) {
- moduleInfo.pluginData.type = value;
- } else if (key.endsWith(".EXTENDS")) {
- moduleInfo.pluginData["extends"] = splitNonEmpty(value, ' ');
- for (k = 0; k < moduleInfo.pluginData["extends"].length; ++k) {
- if (moduleInfo.pluginData["extends"][k] === "-") {
- moduleInfo.pluginData["extends"].splice(k, 1);
- moduleInfo.pluginData.autoLoad = false;
- break;
- }
- }
- } else if (key.endsWith(".CLASS_NAME")) {
- moduleInfo.pluginData.className = value;
- }
- }
- if (hasV2 && !hasModuleEntry)
- moduleInfo.hasLibrary = false;
-
- // Fix include paths for Apple frameworks.
- // The qt_lib_XXX.pri files contain wrong values for versions < 5.6.
- if (!hasV2 && isFramework(moduleInfo, qtProps)) {
- moduleInfo.includePaths = [];
- var baseIncDir = frameworkHeadersPath(moduleInfo, qtProps);
- if (moduleInfo.isPrivate) {
- baseIncDir = FileInfo.joinPaths(baseIncDir, moduleInfo.version);
- moduleInfo.includePaths.push(baseIncDir,
- FileInfo.joinPaths(baseIncDir, moduleInfo.name));
- } else {
- moduleInfo.includePaths.push(baseIncDir);
- }
- }
-
- setupLibraries(moduleInfo, qtProps, nonExistingPrlFiles);
-
- modules.push(moduleInfo);
- if (moduleInfo.qbsName === "testlib")
- addTestModule(modules);
- if (moduleInfo.qbsName === "designercomponents-private")
- addDesignerComponentsModule(modules);
- }
-
- replaceQtLibNamesWithFilePath(modules, qtProps);
- removeDuplicatedDependencyLibs(modules);
- return modules;
-}
-
function extractQbsArchs(module, qtProps) {
if (qtProps.mkspecName.startsWith("macx-")) {
var archs = [];
@@ -1144,7 +54,6 @@ function extractQbsArchs(module, qtProps) {
var qbsArch = Utilities.canonicalArchitecture(qtProps.architecture);
if (qbsArch === "arm" && qtProps.mkspecPath.contains("android"))
qbsArch = "armv7a";
-
// Qt4 has "QT_ARCH = windows" in qconfig.pri for both MSVC and mingw.
if (qbsArch === "windows")
return []
@@ -1196,7 +105,7 @@ function qbsTargetPlatformFromQtMkspec(qtProps) {
return "solaris";
if (mkspec.startsWith("vxworks-"))
return "vxworks";
- if (targetsDesktopWindows(qtProps) || mkspec.startsWith("winrt-"))
+ if (ProviderUtils.isDesktopWindowsQt(qtProps) || mkspec.startsWith("winrt-"))
return "windows";
}
@@ -1252,7 +161,7 @@ function defaultQpaPlugin(module, qtProps) {
function libraryFileTag(module, qtProps) {
if (module.isStaticLibrary)
return "staticlibrary";
- return isMsvcQt(qtProps) || qtProps.mkspecName.startsWith("win32-g++")
+ return ProviderUtils.isMsvcQt(qtProps) || qtProps.mkspecName.startsWith("win32-g++")
? "dynamiclibrary_import" : "dynamiclibrary";
}
@@ -1276,67 +185,86 @@ function findVariable(content, start) {
return result;
}
-function toJSLiteral(v) {
- if (v === undefined)
- return "undefined";
- return JSON.stringify(v);
+function minVersionJsString(minVersion) {
+ return !minVersion ? "" : ModUtils.toJSLiteral(minVersion);
}
-function minVersionJsString(minVersion) {
- return !minVersion ? "original" : toJSLiteral(minVersion);
+function abiToArchitecture(abi) {
+ switch (abi) {
+ case "armeabi-v7a":
+ return "armv7a";
+ case "arm64-v8a":
+ return "arm64";
+ case "x86":
+ case "x86_64":
+ default:
+ return abi;
+ }
}
-function replaceSpecialValues(content, module, qtProps) {
+function replaceSpecialValues(content, module, qtProps, abi) {
+ var architectures = [];
+ if (abi.length > 0)
+ architectures.push(abiToArchitecture(abi));
+ else
+ architectures = extractQbsArchs(module, qtProps);
var dict = {
- archs: toJSLiteral(extractQbsArchs(module, qtProps)),
- targetPlatform: toJSLiteral(qbsTargetPlatformFromQtMkspec(qtProps)),
- config: toJSLiteral(qtProps.configItems),
- qtConfig: toJSLiteral(qtProps.qtConfigItems),
- binPath: toJSLiteral(qtProps.binaryPath),
- libPath: toJSLiteral(qtProps.libraryPath),
- pluginPath: toJSLiteral(qtProps.pluginPath),
- incPath: toJSLiteral(qtProps.includePath),
- docPath: toJSLiteral(qtProps.documentationPath),
- mkspecName: toJSLiteral(qtProps.mkspecName),
- mkspecPath: toJSLiteral(qtProps.mkspecPath),
- version: toJSLiteral(qtProps.qtVersion),
- libInfix: toJSLiteral(qtProps.qtLibInfix),
- availableBuildVariants: toJSLiteral(qtProps.buildVariant),
- staticBuild: toJSLiteral(qtProps.staticBuild),
- frameworkBuild: toJSLiteral(qtProps.frameworkBuild),
- name: toJSLiteral(moduleNameWithoutPrefix(module)),
- has_library: toJSLiteral(module.hasLibrary),
- dependencies: toJSLiteral(module.dependencies),
- includes: toJSLiteral(module.includePaths),
- staticLibsDebug: toJSLiteral(module.staticLibrariesDebug),
- staticLibsRelease: toJSLiteral(module.staticLibrariesRelease),
- dynamicLibsDebug: toJSLiteral(module.dynamicLibrariesDebug),
- dynamicLibsRelease: toJSLiteral(module.dynamicLibrariesRelease),
- linkerFlagsDebug: toJSLiteral(module.linkerFlagsDebug),
- linkerFlagsRelease: toJSLiteral(module.linkerFlagsRelease),
- libraryPaths: toJSLiteral(module.libraryPaths),
- frameworkPathsDebug: toJSLiteral(module.frameworkPathsDebug),
- frameworkPathsRelease: toJSLiteral(module.frameworkPathsRelease),
- frameworksDebug: toJSLiteral(module.frameworksDebug),
- frameworksRelease: toJSLiteral(module.frameworksRelease),
- libFilePathDebug: toJSLiteral(module.libFilePathDebug),
- libFilePathRelease: toJSLiteral(module.libFilePathRelease),
- libNameForLinkerDebug: toJSLiteral(libNameForLinker(module, qtProps, true)),
- pluginTypes: toJSLiteral(module.supportedPluginTypes),
- moduleConfig: toJSLiteral(module.config),
- libNameForLinkerRelease: toJSLiteral(libNameForLinker(module, qtProps, false)),
- entryPointLibsDebug: toJSLiteral(qtProps.entryPointLibsDebug),
- entryPointLibsRelease: toJSLiteral(qtProps.entryPointLibsRelease),
- minWinVersion: minVersionJsString(qtProps.windowsVersion),
- minMacVersion: minVersionJsString(qtProps.macosVersion),
- minIosVersion: minVersionJsString(qtProps.iosVersion),
- minTvosVersion: minVersionJsString(qtProps.tvosVersion),
- minWatchosVersion: minVersionJsString(qtProps.watchosVersion),
- minAndroidVersion: minVersionJsString(qtProps.androidVersion),
+ archs: ModUtils.toJSLiteral(architectures),
+ targetPlatform: ModUtils.toJSLiteral(qbsTargetPlatformFromQtMkspec(qtProps)),
+ config: ModUtils.toJSLiteral(qtProps.configItems),
+ qtConfig: ModUtils.toJSLiteral(qtProps.qtConfigItems),
+ binPath: ModUtils.toJSLiteral(qtProps.binaryPath),
+ installPath: ModUtils.toJSLiteral(qtProps.installPath),
+ installPrefixPath: ModUtils.toJSLiteral(qtProps.installPrefixPath),
+ libPath: ModUtils.toJSLiteral(qtProps.libraryPath),
+ libExecPath: ModUtils.toJSLiteral(qtProps.libExecPath),
+ qmlLibExecPath: ModUtils.toJSLiteral(qtProps.qmlLibExecPath),
+ pluginPath: ModUtils.toJSLiteral(qtProps.pluginPath),
+ incPath: ModUtils.toJSLiteral(qtProps.includePath),
+ docPath: ModUtils.toJSLiteral(qtProps.documentationPath),
+ helpGeneratorLibExecPath: ModUtils.toJSLiteral(qtProps.helpGeneratorLibExecPath),
+ mkspecName: ModUtils.toJSLiteral(qtProps.mkspecName),
+ mkspecPath: ModUtils.toJSLiteral(qtProps.mkspecPath),
+ version: ModUtils.toJSLiteral(qtProps.qtVersion),
+ libInfix: ModUtils.toJSLiteral(qtProps.qtLibInfix),
+ availableBuildVariants: ModUtils.toJSLiteral(qtProps.buildVariant),
+ staticBuild: ModUtils.toJSLiteral(qtProps.staticBuild),
+ frameworkBuild: ModUtils.toJSLiteral(qtProps.frameworkBuild),
+ name: ModUtils.toJSLiteral(ProviderUtils.qtModuleNameWithoutPrefix(module)),
+ has_library: ModUtils.toJSLiteral(module.hasLibrary),
+ dependencies: ModUtils.toJSLiteral(module.dependencies),
+ includes: ModUtils.toJSLiteral(module.includePaths),
+ staticLibsDebug: ModUtils.toJSLiteral(module.staticLibrariesDebug),
+ staticLibsRelease: ModUtils.toJSLiteral(module.staticLibrariesRelease),
+ dynamicLibsDebug: ModUtils.toJSLiteral(module.dynamicLibrariesDebug),
+ dynamicLibsRelease: ModUtils.toJSLiteral(module.dynamicLibrariesRelease),
+ linkerFlagsDebug: ModUtils.toJSLiteral(module.linkerFlagsDebug),
+ linkerFlagsRelease: ModUtils.toJSLiteral(module.linkerFlagsRelease),
+ libraryPaths: ModUtils.toJSLiteral(module.libraryPaths),
+ frameworkPathsDebug: ModUtils.toJSLiteral(module.frameworkPathsDebug),
+ frameworkPathsRelease: ModUtils.toJSLiteral(module.frameworkPathsRelease),
+ frameworksDebug: ModUtils.toJSLiteral(module.frameworksDebug),
+ frameworksRelease: ModUtils.toJSLiteral(module.frameworksRelease),
+ libFilePathDebug: ModUtils.toJSLiteral(module.libFilePathDebug),
+ libFilePathRelease: ModUtils.toJSLiteral(module.libFilePathRelease),
+ libNameForLinkerDebug:
+ ModUtils.toJSLiteral(ProviderUtils.qtLibNameForLinker(module, qtProps, true)),
+ pluginTypes: ModUtils.toJSLiteral(module.supportedPluginTypes),
+ moduleConfig: ModUtils.toJSLiteral(module.config),
+ libNameForLinkerRelease:
+ ModUtils.toJSLiteral(ProviderUtils.qtLibNameForLinker(module, qtProps, false)),
+ entryPointLibsDebug: ModUtils.toJSLiteral(qtProps.entryPointLibsDebug),
+ entryPointLibsRelease: ModUtils.toJSLiteral(qtProps.entryPointLibsRelease),
+ minWinVersion_optional: minVersionJsString(qtProps.windowsVersion),
+ minMacVersion_optional: minVersionJsString(qtProps.macosVersion),
+ minIosVersion_optional: minVersionJsString(qtProps.iosVersion),
+ minTvosVersion_optional: minVersionJsString(qtProps.tvosVersion),
+ minWatchosVersion_optional: minVersionJsString(qtProps.watchosVersion),
+ minAndroidVersion_optional: minVersionJsString(qtProps.androidVersion),
};
var additionalContent = "";
- var compilerDefines = toJSLiteral(module.compilerDefines);
+ var compilerDefines = ModUtils.toJSLiteral(module.compilerDefines);
if (module.qbsName === "declarative" || module.qbsName === "quick") {
var debugMacro = module.qbsName === "declarative" || qtProps.qtMajorVersion < 5
? "QT_DECLARATIVE_DEBUG" : "QT_QML_DEBUG";
@@ -1360,7 +288,7 @@ function replaceSpecialValues(content, module, qtProps) {
}
dict.defines = compilerDefines;
if (module.qbsName === "gui")
- dict.defaultQpaPlugin = toJSLiteral(defaultQpaPlugin(module, qtProps));
+ dict.defaultQpaPlugin = ModUtils.toJSLiteral(defaultQpaPlugin(module, qtProps));
if (module.qbsName === "qml")
dict.qmlPath = pathToJSLiteral(qtProps.qmlPath);
if (module.isStaticLibrary && module.qbsName !== "core") {
@@ -1369,20 +297,30 @@ function replaceSpecialValues(content, module, qtProps) {
additionalContent += "isStaticLibrary: true";
}
if (module.isPlugin) {
- dict.className = toJSLiteral(module.pluginData.className);
- dict["extends"] = toJSLiteral(module.pluginData["extends"]);
+ dict.className = ModUtils.toJSLiteral(module.pluginData.className);
+ dict["extends"] = ModUtils.toJSLiteral(module.pluginData["extends"]);
+ }
+ indent = " ";
+ var metaTypesFile = qtProps.libraryPath + "/metatypes/qt"
+ + qtProps.qtMajorVersion + module.qbsName + "_metatypes.json";
+ if (File.exists(metaTypesFile)) {
+ if (additionalContent)
+ additionalContent += "\n" + indent;
+ additionalContent += "Group {\n";
+ additionalContent += indent + indent + "files: " + JSON.stringify(metaTypesFile) + "\n"
+ + indent + indent + "filesAreTargets: true\n"
+ + indent + indent + "fileTags: [\"qt.core.metatypes\"]\n"
+ + indent + "}";
}
- if (module.hasLibrary && !isFramework(module, qtProps)) {
+ if (module.hasLibrary && !ProviderUtils.qtIsFramework(module, qtProps)) {
if (additionalContent)
- additionalContent += "\n";
- indent = " ";
+ additionalContent += "\n" + indent;
additionalContent += "Group {\n";
if (module.isPlugin) {
additionalContent += indent + indent
- + "condition: Qt[\"" + module.qbsName + "\"].enableLinking\n";
+ + "condition: enableLinking\n";
}
- additionalContent += indent + indent + "files: [Qt[\"" + module.qbsName + "\"]"
- + ".libFilePath]\n"
+ additionalContent += indent + indent + "files: libFilePath\n"
+ indent + indent + "filesAreTargets: true\n"
+ indent + indent + "fileTags: [\"" + libraryFileTag(module, qtProps)
+ "\"]\n"
@@ -1392,29 +330,42 @@ function replaceSpecialValues(content, module, qtProps) {
for (var pos = findVariable(content, 0); pos[0] !== -1;
pos = findVariable(content, pos[0])) {
- var replacement = dict[content.slice(pos[0] + 1, pos[1])] || "";
- content = content.slice(0, pos[0]) + replacement + content.slice(pos[1] + 1);
- pos[0] += replacement.length;
+ var varName = content.slice(pos[0] + 1, pos[1]);
+ var replacement = dict[varName] || "";
+ if (!replacement && varName.endsWith("_optional")) {
+ var prevNewline = content.lastIndexOf('\n', pos[0]);
+ if (prevNewline === -1)
+ prevNewline = 0;
+ var nextNewline = content.indexOf('\n', pos[0]);
+ if (nextNewline === -1)
+ prevNewline = content.length;
+ content = content.slice(0, prevNewline) + content.slice(nextNewline);
+ pos[0] = prevNewline;
+ } else {
+ content = content.slice(0, pos[0]) + replacement + content.slice(pos[1] + 1);
+ pos[0] += replacement.length;
+ }
}
return content;
}
-function copyTemplateFile(fileName, targetDirectory, qtProps, location, allFiles, module, pluginMap,
- nonEssentialPlugins)
+function copyTemplateFile(fileName, targetDirectory, qtProps, abi, location, allFiles, module,
+ pluginMap, nonEssentialPlugins)
{
if (!File.makePath(targetDirectory)) {
- throw "Cannot create directory '" + toNative(targetDirectory) + "'.";
+ throw "Cannot create directory '" + FileInfo.toNativeSeparators(targetDirectory) + "'.";
}
var sourceFile = new TextFile(FileInfo.joinPaths(location, "templates", fileName),
TextFile.ReadOnly);
var newContent = sourceFile.readAll();
if (module) {
- newContent = replaceSpecialValues(newContent, module, qtProps);
+ newContent = replaceSpecialValues(newContent, module, qtProps, abi);
} else {
newContent = newContent.replace("@allPluginsByType@",
- '(' + toJSLiteral(pluginMap) + ')');
+ '(' + ModUtils.toJSLiteral(pluginMap) + ')');
newContent = newContent.replace("@nonEssentialPlugins@",
- toJSLiteral(nonEssentialPlugins));
+ ModUtils.toJSLiteral(nonEssentialPlugins));
+ newContent = newContent.replace("@version@", ModUtils.toJSLiteral(qtProps.qtVersion));
}
sourceFile.close();
var targetPath = FileInfo.joinPaths(targetDirectory, fileName);
@@ -1424,98 +375,117 @@ function copyTemplateFile(fileName, targetDirectory, qtProps, location, allFiles
targetFile.close();
}
-function setupOneQt(qmakeFilePath, outputBaseDir, uniquify, location, qbs) {
- if (!File.exists(qmakeFilePath))
- throw "The specified qmake file path '" + toNative(qmakeFilePath) + "' does not exist.";
- var qtProps = getQtProperties(qmakeFilePath, qbs);
- var modules = qtProps.qtMajorVersion < 5 ? allQt4Modules(qtProps) : allQt5Modules(qtProps);
- var pluginsByType = {};
- var nonEssentialPlugins = [];
- for (var i = 0; i < modules.length; ++i) {
- var m = modules[i];
- if (m.isPlugin) {
- if (!pluginsByType[m.pluginData.type])
- pluginsByType[m.pluginData.type] = [];
- pluginsByType[m.pluginData.type].push(m.name);
- if (!m.pluginData.autoLoad)
- nonEssentialPlugins.push(m.name);
- }
- }
-
- var relativeSearchPath = uniquify ? Utilities.getHash(qmakeFilePath) : "";
- var qbsQtModuleBaseDir = FileInfo.joinPaths(outputBaseDir, relativeSearchPath, "modules", "Qt");
- if (File.exists(qbsQtModuleBaseDir))
- File.remove(qbsQtModuleBaseDir);
-
- var allFiles = [];
- copyTemplateFile("QtModule.qbs", qbsQtModuleBaseDir, qtProps, location, allFiles);
- copyTemplateFile("QtPlugin.qbs", qbsQtModuleBaseDir, qtProps, location, allFiles);
- copyTemplateFile("plugin_support.qbs", FileInfo.joinPaths(qbsQtModuleBaseDir, "plugin_support"),
- qtProps, location, allFiles, undefined, pluginsByType, nonEssentialPlugins);
-
- for (i = 0; i < modules.length; ++i) {
- var module = modules[i];
- var qbsQtModuleDir = FileInfo.joinPaths(qbsQtModuleBaseDir, module.qbsName);
- var moduleTemplateFileName;
- if (module.qbsName === "core") {
- moduleTemplateFileName = "core.qbs";
- copyTemplateFile("moc.js", qbsQtModuleDir, qtProps, location, allFiles);
- copyTemplateFile("qdoc.js", qbsQtModuleDir, qtProps, location, allFiles);
- } else if (module.qbsName === "gui") {
- moduleTemplateFileName = "gui.qbs";
- } else if (module.qbsName === "scxml") {
- moduleTemplateFileName = "scxml.qbs";
- } else if (module.qbsName === "dbus") {
- moduleTemplateFileName = "dbus.qbs";
- copyTemplateFile("dbus.js", qbsQtModuleDir, qtProps, location, allFiles);
- } else if (module.qbsName === "qml") {
- moduleTemplateFileName = "qml.qbs";
- copyTemplateFile("qml.js", qbsQtModuleDir, qtProps, location, allFiles);
+function setupOneQt(moduleName, qtInfo, outputBaseDir, uniquify, location) {
+ var qtProps = qtInfo.qtProps;
+
+ var relativeSearchPaths = [];
+ for (a = 0; a < qtInfo.abiInfos.length; ++a) {
+ var abiInfo = qtInfo.abiInfos[a];
+ var androidAbi = abiInfo.androidAbi;
+ if (qtInfo.abiInfos.length > 1)
+ console.info("Configuring abi '" + androidAbi + "'...");
+
+ var relativeSearchPath = uniquify ? Utilities.getHash(qtInfo.qmakeFilePath) : "";
+ relativeSearchPath = FileInfo.joinPaths(relativeSearchPath, androidAbi);
+ var qbsQtModuleBaseDir = FileInfo.joinPaths(outputBaseDir, relativeSearchPath,
+ "modules", "Qt");
+ // TODO:
+ // if (File.exists(qbsQtModuleBaseDir))
+ // File.remove(qbsQtModuleBaseDir);
+
+ var allFiles = [];
+ if (moduleName === "plugin_support") {
+ copyTemplateFile("plugin_support.qbs",
+ FileInfo.joinPaths(qbsQtModuleBaseDir, "plugin_support"), qtProps,
+ androidAbi, location, allFiles, undefined, abiInfo.pluginsByType,
+ abiInfo.nonEssentialPlugins);
+ relativeSearchPaths.push(relativeSearchPath);
+ return relativeSearchPaths;
+ } else if (moduleName === "android_support") {
+ // Note that it's not strictly necessary to copy this one, as it has no variable content.
+ // But we do it anyway for consistency.
+ copyTemplateFile("android_support.qbs",
+ FileInfo.joinPaths(qbsQtModuleBaseDir, "android_support"),
+ qtProps, androidAbi, location, allFiles);
+ relativeSearchPaths.push(relativeSearchPath);
+ return relativeSearchPaths;
+ } else if (moduleName === "qmlcache") {
var qmlcacheStr = "qmlcache";
- if (File.exists(FileInfo.joinPaths(qtProps.binaryPath,
- "qmlcachegen" + exeSuffix(qbs)))) {
+ if (File.exists(FileInfo.joinPaths(qtProps.qmlLibExecPath,
+ "qmlcachegen" + FileInfo.executableSuffix()))) {
copyTemplateFile(qmlcacheStr + ".qbs",
FileInfo.joinPaths(qbsQtModuleBaseDir, qmlcacheStr), qtProps,
- location, allFiles);
+ androidAbi, location, allFiles);
}
- } else if (module.qbsName === "quick") {
- moduleTemplateFileName = "quick.qbs";
- copyTemplateFile("quick.js", qbsQtModuleDir, qtProps, location, allFiles);
- } else if (module.isPlugin) {
- moduleTemplateFileName = "plugin.qbs";
- } else {
- moduleTemplateFileName = "module.qbs";
+ relativeSearchPaths.push(relativeSearchPath);
+ return relativeSearchPaths;
}
- copyTemplateFile(moduleTemplateFileName, qbsQtModuleDir, qtProps, location, allFiles,
- module);
- }
- // Note that it's not strictly necessary to copy this one, as it has no variable content.
- // But we do it anyway for consistency.
- copyTemplateFile("android_support.qbs",
- FileInfo.joinPaths(qbsQtModuleBaseDir, "android_support"),
- qtProps, location, allFiles);
- return relativeSearchPath;
+ if (abiInfo.modules[moduleName] !== undefined) {
+ var module = abiInfo.modules[moduleName];
+ var qbsQtModuleDir = FileInfo.joinPaths(qbsQtModuleBaseDir, module.qbsName);
+ var moduleTemplateFileName;
+
+ if (module.qbsName === "core") {
+ moduleTemplateFileName = "core.qbs";
+ copyTemplateFile("moc.js", qbsQtModuleDir, qtProps, androidAbi, location,
+ allFiles);
+ copyTemplateFile("qdoc.js", qbsQtModuleDir, qtProps, androidAbi, location,
+ allFiles);
+ copyTemplateFile("rcc.js", qbsQtModuleDir, qtProps, androidAbi, location,
+ allFiles);
+ } else if (module.qbsName === "gui") {
+ moduleTemplateFileName = "gui.qbs";
+ } else if (module.qbsName === "scxml") {
+ moduleTemplateFileName = "scxml.qbs";
+ } else if (module.qbsName === "dbus") {
+ moduleTemplateFileName = "dbus.qbs";
+ copyTemplateFile("dbus.js", qbsQtModuleDir, qtProps, androidAbi, location,
+ allFiles);
+ } else if (module.qbsName === "qml") {
+ moduleTemplateFileName = "qml.qbs";
+ copyTemplateFile("qml.js", qbsQtModuleDir, qtProps, androidAbi, location,
+ allFiles);
+ } else if (module.qbsName === "quick") {
+ moduleTemplateFileName = "quick.qbs";
+ copyTemplateFile("quick.js", qbsQtModuleDir, qtProps, androidAbi, location,
+ allFiles);
+ copyTemplateFile("rcc.js", qbsQtModuleDir, qtProps, androidAbi, location,
+ allFiles);
+ } else if (module.isPlugin) {
+ moduleTemplateFileName = "plugin.qbs";
+ } else {
+ moduleTemplateFileName = "module.qbs";
+ }
+ copyTemplateFile(moduleTemplateFileName, qbsQtModuleDir, qtProps, androidAbi,
+ location, allFiles, module);
+ relativeSearchPaths.push(relativeSearchPath);
+ }
+ }
+ return relativeSearchPaths;
}
-function doSetup(qmakeFilePaths, outputBaseDir, location, qbs) {
- qmakeFilePaths = getQmakeFilePaths(qmakeFilePaths, qbs);
- if (!qmakeFilePaths || qmakeFilePaths.length === 0)
+function doSetup(moduleName, qtInfos, outputBaseDir, location) {
+ if (!qtInfos || qtInfos.length === 0)
return [];
- var uniquifySearchPath = qmakeFilePaths.length > 1;
- var searchPaths = [];
- for (var i = 0; i < qmakeFilePaths.length; ++i) {
+ var uniquifySearchPath = qtInfos.length > 1;
+ var allSearchPaths = [];
+ moduleName = moduleName.substring(3);
+ for (var i = 0; i < qtInfos.length; ++i) {
try {
- console.info("Setting up Qt at '" + toNative(qmakeFilePaths[i]) + "'...");
- var searchPath = setupOneQt(qmakeFilePaths[i], outputBaseDir, uniquifySearchPath,
- location, qbs);
- if (searchPath !== undefined) {
- searchPaths.push(searchPath);
- console.info("Qt was set up successfully.");
+ console.info("Setting up Qt module '" + moduleName + "' for Qt located at '"
+ + FileInfo.toNativeSeparators(qtInfos[i].qmakeFilePath) + "'.");
+ var searchPaths = setupOneQt(moduleName, qtInfos[i], outputBaseDir, uniquifySearchPath,
+ location);
+ if (searchPaths.length > 0) {
+ for (var j = 0; j < searchPaths.length; ++j )
+ allSearchPaths.push(searchPaths[j]);
}
} catch (e) {
- console.warn("Error setting up Qt for '" + toNative(qmakeFilePaths[i]) + "': " + e);
+ console.warn("Error setting up Qt module '" + moduleName + "' for '"
+ + FileInfo.toNativeSeparators(qtInfos[i].qmakeFilePath) + "': " + e);
+ throw e;
}
}
- return searchPaths;
+ return allSearchPaths;
}
diff --git a/share/qbs/module-providers/Qt/templates/android_support.qbs b/share/qbs/module-providers/Qt/templates/android_support.qbs
index c5f842a1f..6d548f194 100644
--- a/share/qbs/module-providers/Qt/templates/android_support.qbs
+++ b/share/qbs/module-providers/Qt/templates/android_support.qbs
@@ -3,29 +3,39 @@ import qbs.FileInfo
import qbs.ModUtils
import qbs.TextFile
import qbs.Utilities
+import qbs.Process
+import qbs.Xml
Module {
- property bool useMinistro: false
+ version: @version@
property string qmlRootDir: product.sourceDirectory
property stringList extraPrefixDirs
+ property stringList qmlImportPaths
property stringList deploymentDependencies // qmake: ANDROID_DEPLOYMENT_DEPENDENCIES
property stringList extraPlugins // qmake: ANDROID_EXTRA_PLUGINS
property stringList extraLibs // qmake: ANDROID_EXTRA_LIBS
property bool verboseAndroidDeployQt: false
-
- property string _androidDeployQtFilePath: FileInfo.joinPaths(_qtInstallDir, "bin",
+ property string _androidDeployQtFilePath: FileInfo.joinPaths(_qtBinaryDir, "bin",
"androiddeployqt")
+ property string rccFilePath
+ property string _qtBinaryDir
property string _qtInstallDir
- property bool _enableSdkSupport: product.type && product.type.contains("android.apk")
- && !consoleApplication
+ property bool _enableSdkSupport: product.type && product.type.contains("android.package")
+ && !product.consoleApplication
property bool _enableNdkSupport: !product.aggregate || product.multiplexConfigurationId
property string _templatesBaseDir: FileInfo.joinPaths(_qtInstallDir, "src", "android")
property string _deployQtOutDir: FileInfo.joinPaths(product.buildDirectory, "deployqt_out")
+ property bool _multiAbi: Utilities.versionCompare(version, "5.14") >= 0
+
+ // QTBUG-87288: correct QtNetwork jar dependencies for 5.15.0 < Qt < 5.15.3
+ property bool _correctQtNetworkDependencies: Utilities.versionCompare(version, "5.15.0") > 0 &&
+ Utilities.versionCompare(version, "5.15.3") < 0
+
Depends { name: "Android.sdk"; condition: _enableSdkSupport }
Depends { name: "Android.ndk"; condition: _enableNdkSupport }
Depends { name: "java"; condition: _enableSdkSupport }
- Depends { name: "cpp" }
+ Depends { name: "cpp"; condition: _enableNdkSupport }
Properties {
condition: _enableNdkSupport && qbs.toolchain.contains("clang")
@@ -40,15 +50,45 @@ Module {
Android.sdk.customManifestProcessing: true
java._tagJniHeaders: false // prevent rule cycle
}
+ readonly property string _qtAndroidJarFileName: Utilities.versionCompare(version, "6.0") >= 0 ?
+ "Qt6Android.jar" : "QtAndroid.jar"
+ Properties {
+ condition: _enableSdkSupport && Utilities.versionCompare(version, "5.15") >= 0
+ && Utilities.versionCompare(version, "6.0") < 0
+ java.additionalClassPaths: [FileInfo.joinPaths(_qtInstallDir, "jar", "QtAndroid.jar")]
+ }
+ Properties {
+ condition: _enableSdkSupport && Utilities.versionCompare(version, "6.0") >= 0
+ java.additionalClassPaths: [FileInfo.joinPaths(_qtInstallDir, "jar", "Qt6Android.jar")]
+ }
+ // "ANDROID_HAS_WSTRING" was removed from qtcore qstring.h in Qt 5.14.0
Properties {
- condition: _enableNdkSupport && (Android.ndk.abi === "armeabi-v7a" || Android.ndk.abi === "x86")
+ condition: _enableNdkSupport && Utilities.versionCompare(version, "5.14.0") < 0 &&
+ (Android.ndk.abi === "armeabi-v7a" || Android.ndk.abi === "x86")
cpp.defines: "ANDROID_HAS_WSTRING"
}
+ Properties {
+ condition: _enableSdkSupport
+ Android.sdk._bundledInAssets: _multiAbi
+ }
+ Properties {
+ condition: _enableSdkSupport && Utilities.versionCompare(version, "6.0") < 0
+ Android.sdk.minimumVersion: "21"
+ }
+ Properties {
+ condition: _enableSdkSupport && Utilities.versionCompare(version, "6.0") >= 0
+ Android.sdk.minimumVersion: "23"
+ }
+
+ Properties {
+ condition: _enableNdkSupport
+ cpp.archSuffix: _multiAbi ? "_" + Android.ndk.abi : ""
+ }
Rule {
condition: _enableSdkSupport
multiplex: true
- property stringList inputTags: "android.nativelibrary"
+ property stringList inputTags: ["android.nativelibrary", "qrc"]
inputsFromDependencies: inputTags
inputs: product.aggregate ? [] : inputTags
Artifact {
@@ -61,37 +101,78 @@ Module {
cmd.sourceCode = function() {
var theBinary;
var nativeLibs = inputs["android.nativelibrary"];
+ var architectures = [];
+ var triples = [];
+ var qtInstallDirectories = [];
+ var hostArch;
+ var targetArchitecture;
if (nativeLibs.length === 1) {
theBinary = nativeLibs[0];
+ hostArch = theBinary.Android.ndk.hostArch;
+ targetArchitecture = theBinary.Android.ndk.abi;
+ if (product.Qt.android_support._multiAbi) {
+ architectures.push(theBinary.Android.ndk.abi);
+ triples.push(theBinary.cpp.toolchainTriple);
+ qtInstallDirectories.push(theBinary.Qt.android_support._qtInstallDir);
+ }
} else {
for (i = 0; i < nativeLibs.length; ++i) {
var candidate = nativeLibs[i];
- if (!candidate.fileName.contains(candidate.product.targetName))
- continue;
- if (!theBinary) {
- theBinary = candidate;
- continue;
- }
- if (theBinary.product.name === product.name
- && candidate.product.name !== product.name) {
- continue; // We already have a better match.
- }
- if (candidate.product.name === product.name
- && theBinary.product.name !== product.name) {
- theBinary = candidate; // The new candidate is a better match.
- continue;
+ if (product.Qt.android_support._multiAbi) {
+ if (candidate.product.name === product.name) {
+ architectures.push(candidate.Android.ndk.abi);
+ triples.push(candidate.cpp.toolchainTriple);
+ qtInstallDirectories.push(
+ candidate.Qt.android_support._qtInstallDir);
+ hostArch = candidate.Android.ndk.hostArch;
+ targetArchitecture = candidate.Android.ndk.abi;
+ theBinary = candidate;
+ }
+ } else {
+ if (!candidate.fileName.contains(candidate.product.targetName))
+ continue;
+ if (!theBinary) {
+ theBinary = candidate;
+ hostArch = theBinary.Android.ndk.hostArch;
+ targetArchitecture = theBinary.Android.ndk.abi;
+ continue;
+ }
+ if (candidate.product.name !== product.name) {
+ continue; // This is not going to be a match
+ }
+ if (candidate.product.name === product.name
+ && theBinary.product.name !== product.name) {
+ theBinary = candidate; // The new candidate is a better match.
+ hostArch = theBinary.Android.ndk.hostArch;
+ targetArchitecture = theBinary.Android.ndk.abi;
+ continue;
+ }
+
+ throw "Qt applications for Android support only one native binary "
+ + "per package.\n"
+ + "In particular, you cannot build a Qt app for more than "
+ + "one architecture at the same time.";
}
- throw "Qt applications for Android support only one native binary "
- + "per package.\n"
- + "In particular, you cannot build a Qt app for more than "
- + "one architecture at the same time.";
}
}
var f = new TextFile(output.filePath, TextFile.WriteOnly);
f.writeLine("{");
f.writeLine('"description": "This file was generated by qbs to be read by '
+ 'androiddeployqt and should not be modified by hand.",');
- f.writeLine('"qt": "' + product.Qt.android_support._qtInstallDir + '",');
+ if (Utilities.versionCompare(product.Qt.core.version, "6.3.0") >= 0) {
+ var line = '"qt": {';
+ for (var i = 0; i < qtInstallDirectories.length && i < architectures.length;
+ ++i) {
+ line = line + '"' + architectures[i] + '":"' +
+ qtInstallDirectories[i] + '"';
+ if (i < qtInstallDirectories.length-1 || i < architectures.length-1)
+ line = line + ',';
+ }
+ line = line + "},";
+ f.writeLine(line);
+ } else {
+ f.writeLine('"qt": "' + product.Qt.android_support._qtInstallDir + '",');
+ }
f.writeLine('"sdk": "' + product.Android.sdk.sdkDir + '",');
f.writeLine('"sdkBuildToolsRevision": "' + product.Android.sdk.buildToolsVersion
+ '",');
@@ -99,8 +180,20 @@ Module {
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('"ndk-host": "' + hostArch + '",');
+ if (!product.Qt.android_support._multiAbi) {
+ f.writeLine('"target-architecture": "' + targetArchitecture + '",');
+ }
+ else {
+ var line = '"architectures": {';
+ for (var i in architectures) {
+ line = line + '"' + architectures[i] + '":"' + triples[i] + '"';
+ if (i < architectures.length-1)
+ line = line + ',';
+ }
+ line = line + "},";
+ f.writeLine(line);
+ }
f.writeLine('"qml-root-path": "' + product.Qt.android_support.qmlRootDir + '",');
var deploymentDeps = product.Qt.android_support.deploymentDependencies;
if (deploymentDeps && deploymentDeps.length > 0)
@@ -120,15 +213,41 @@ Module {
var prefixDirs = product.Qt.android_support.extraPrefixDirs;
if (prefixDirs && prefixDirs.length > 0)
f.writeLine('"extraPrefixDirs": ' + JSON.stringify(prefixDirs) + ',');
- if (Array.isArray(product.qmlImportPaths) && product.qmlImportPaths.length > 0)
+ var qmlImportPaths = product.Qt.android_support.qmlImportPaths;
+ if (qmlImportPaths && qmlImportPaths.length > 0)
+ f.writeLine('"qml-import-paths": "' + qmlImportPaths.join(',') + '",');
+ else if ((product.qmlImportPaths instanceof Array) && product.qmlImportPaths.length > 0)
f.writeLine('"qml-import-paths": "' + product.qmlImportPaths.join(',') + '",');
+ if (Utilities.versionCompare(product.Qt.android_support.version, "6.0") >= 0) {
+ f.writeLine('"qml-importscanner-binary": "'
+ + product.Qt.core.qmlImportScannerFilePath + FileInfo.executableSuffix()
+ + '",');
+ f.writeLine('"rcc-binary": "' + product.Qt.android_support.rccFilePath
+ + FileInfo.executableSuffix() + '",');
+
+ if (inputs["qrc"] && inputs["qrc"].length > 0) {
+ var qrcFiles = [];
+ var qrcInputs = inputs["qrc"];
+ for (i = 0; i < qrcInputs.length; ++i) {
+ qrcFiles.push(qrcInputs[i].filePath);
+ }
+ f.writeLine('"qrcFiles": "' + qrcFiles.join(',') + '",');
+ }
+ }
+
// QBS-1429
- f.writeLine('"stdcpp-path": "' + (product.cpp.sharedStlFilePath
+ if (!product.Qt.android_support._multiAbi) {
+ f.writeLine('"stdcpp-path": "' + (product.cpp.sharedStlFilePath
? product.cpp.sharedStlFilePath : product.cpp.staticStlFilePath)
+ '",');
+ f.writeLine('"application-binary": "' + theBinary.filePath + '"');
+ } else {
+ f.writeLine('"stdcpp-path": "' + product.Android.sdk.ndkDir +
+ '/toolchains/llvm/prebuilt/' + hostArch + '/sysroot/usr/lib/",');
+ f.writeLine('"application-binary": "' + theBinary.product.targetName + '"');
+ }
- f.writeLine('"application-binary": "' + theBinary.filePath + '"');
f.writeLine("}");
f.close();
};
@@ -167,45 +286,48 @@ Module {
Rule {
condition: _enableSdkSupport
multiplex: true
- inputs: ["qt_androiddeployqt_input", "android.manifest_processed"]
+ property stringList defaultInputs: ["qt_androiddeployqt_input",
+ "android.manifest_processed"]
+ property stringList allInputs: ["qt_androiddeployqt_input", "android.manifest_processed",
+ "android.nativelibrary"]
+ inputsFromDependencies: "android.nativelibrary"
+ inputs: product.aggregate ? defaultInputs : allInputs
outputFileTags: [
"android.manifest_final", "android.resources", "android.assets", "bundled_jar",
"android.deployqt_list",
]
- outputArtifacts: {
- var artifacts = [
- {
- filePath: "AndroidManifest.xml",
- fileTags: "android.manifest_final"
- },
- {
- filePath: product.Qt.android_support._deployQtOutDir + "/res/values/libs.xml",
- fileTags: "android.resources"
- },
- {
- filePath: product.Qt.android_support._deployQtOutDir
- + "/res/values/strings.xml",
- fileTags: "android.resources"
- },
- {
- filePath: product.Qt.android_support._deployQtOutDir + "/assets/.dummy",
- fileTags: "android.assets"
- },
- {
- filePath: "deployqt.list",
- fileTags: "android.deployqt_list"
- },
-
- ];
- if (!product.Qt.android_support.useMinistro) {
- artifacts.push({
- filePath: FileInfo.joinPaths(product.java.classFilesDir, "QtAndroid.jar"),
- fileTags: ["bundled_jar"]
- });
+ outputArtifacts: [
+ {
+ filePath: "AndroidManifest.xml",
+ fileTags: "android.manifest_final"
+ },
+ {
+ filePath: product.Qt.android_support._deployQtOutDir + "/res/values/libs.xml",
+ fileTags: "android.resources"
+ },
+ {
+ filePath: product.Qt.android_support._deployQtOutDir
+ + "/res/values/strings.xml",
+ fileTags: "android.resources"
+ },
+ {
+ filePath: product.Qt.android_support._deployQtOutDir + "/assets/.dummy",
+ fileTags: "android.assets"
+ },
+ {
+ filePath: "deployqt.list",
+ fileTags: "android.deployqt_list"
+ },
+ // androiddeployqt potentially copies more jar files but this one will always be there
+ // since it comes with Qt.core
+ {
+ filePath: FileInfo.joinPaths(product.java.classFilesDir,
+ product.Qt.android_support._qtAndroidJarFileName),
+ fileTags: "bundled_jar"
}
- return artifacts;
- }
+ ]
prepare: {
+ var cmds = [];
var copyCmd = new JavaScriptCommand();
copyCmd.description = "copying Qt resource templates";
copyCmd.sourceCode = function() {
@@ -216,22 +338,36 @@ Module {
File.copy(product.Qt.android_support._templatesBaseDir
+ "/templates/res/values/libs.xml",
product.Qt.android_support._deployQtOutDir + "/res/values/libs.xml");
- try {
- File.remove(FileInfo.path(outputs["android.assets"][0].filePath));
- } catch (e) {
+ if (!product.Qt.android_support._multiAbi) {
+ try {
+ File.remove(FileInfo.path(outputs["android.assets"][0].filePath));
+ } catch (e) {
+ }
+ }
+ else {
+ for (var i in inputs["android.nativelibrary"]) {
+ var input = inputs["android.nativelibrary"][i];
+ File.copy(input.filePath,
+ FileInfo.joinPaths(product.Qt.android_support._deployQtOutDir,
+ "libs", input.Android.ndk.abi,
+ input.fileName));
+ }
}
};
+ cmds.push(copyCmd);
+
var androidDeployQtArgs = [
"--output", product.Qt.android_support._deployQtOutDir,
"--input", inputs["qt_androiddeployqt_input"][0].filePath, "--aux-mode",
- "--deployment", product.Qt.android_support.useMinistro ? "ministro" : "bundled",
+ "--deployment", "bundled",
"--android-platform", product.Android.sdk.platform,
];
if (product.Qt.android_support.verboseAndroidDeployQt)
- args.push("--verbose");
+ androidDeployQtArgs.push("--verbose");
var androidDeployQtCmd = new Command(
product.Qt.android_support._androidDeployQtFilePath, androidDeployQtArgs);
androidDeployQtCmd.description = "running androiddeployqt";
+ cmds.push(androidDeployQtCmd);
// We do not want androiddeployqt to write directly into our APK base dir, so
// we ran it on an isolated directory and now we move stuff over.
@@ -239,12 +375,11 @@ Module {
// of androiddeployqt creates fewer files, the other ones are removed from
// the APK base dir.
var moveCmd = new JavaScriptCommand();
- moveCmd.description = "processing androiddeployqt outout";
+ moveCmd.description = "processing androiddeployqt output";
moveCmd.sourceCode = function() {
- File.move(product.Qt.android_support._deployQtOutDir + "/AndroidManifest.xml",
- outputs["android.manifest_final"][0].filePath);
+ File.makePath(product.java.classFilesDir);
var libsDir = product.Qt.android_support._deployQtOutDir + "/libs";
- var libDir = product.Android.sdk.apkContentsDir + "/lib";
+ var libDir = product.Android.sdk.packageContentsDir + "/lib";
var listFilePath = outputs["android.deployqt_list"][0].filePath;
var oldLibs = [];
try {
@@ -286,7 +421,107 @@ Module {
File.remove(oldLibs[i]);
}
};
- return [copyCmd, androidDeployQtCmd, moveCmd];
+ cmds.push(moveCmd);
+
+ // androiddeployqt doesn't strip the deployed libraries anymore so it has to done here
+ // but only for release build
+ if (product.qbs.buildVariant == "release") {
+ var stripLibsCmd = new JavaScriptCommand();
+ stripLibsCmd.description = "stripping unneeded symbols from deployed qt libraries";
+ stripLibsCmd.sourceCode = function() {
+ var stripArgs = ["--strip-all"];
+ var architectures = [];
+ for (var i in inputs["android.nativelibrary"])
+ architectures.push(inputs["android.nativelibrary"][i].Android.ndk.abi);
+ for (var i in architectures) {
+ var abiDirPath = FileInfo.joinPaths(product.Android.sdk.packageContentsDir,
+ "lib", architectures[i]);
+ var files = File.directoryEntries(abiDirPath, File.Files);
+ for (var i = 0; i < files.length; ++i) {
+ var filePath = FileInfo.joinPaths(abiDirPath, files[i]);
+ if (FileInfo.suffix(filePath) == "so") {
+ stripArgs.push(filePath);
+ }
+ }
+ }
+ var process = new Process();
+ process.exec(product.cpp.stripPath, stripArgs, false);
+ }
+ cmds.push(stripLibsCmd);
+ }
+
+ var correctingCmd = new JavaScriptCommand();
+ if (product.Qt.android_support._correctQtNetworkDependencies) {
+ correctingCmd.description = "correcting network jar dependency";
+ correctingCmd.sourceCode = function() {
+ var findNetworkLib = function() {
+ var libsDir = product.Android.sdk.packageContentsDir + "/lib";
+ var dirList = File.directoryEntries(libsDir, File.Dirs |
+ File.NoDotAndDotDot);
+ for (var i = 0; i < dirList.length; ++i) {
+ var archDir = FileInfo.joinPaths(libsDir, dirList[i]);
+ var fileList = File.directoryEntries(archDir, File.Files);
+ if (fileList) {
+ for (var j = 0; j < fileList.length; ++j) {
+ if (fileList[j].contains("libQt5Network")) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ if (findNetworkLib()) {
+ var manifestData = new Xml.DomDocument();
+ var manifestFilePath = product.Qt.android_support._deployQtOutDir +
+ "/AndroidManifest.xml"
+ manifestData.load(manifestFilePath);
+
+ var rootElem = manifestData.documentElement();
+ if (!rootElem || !rootElem.isElement() || rootElem.tagName() != "manifest")
+ throw "No manifest tag found in '" + manifestFilePath + "'.";
+ var appElem = rootElem.firstChild("application");
+ if (!appElem || !appElem.isElement() || appElem.tagName() != "application")
+ throw "No application tag found in '" + manifestFilePath + "'.";
+ var activityElem = appElem.firstChild("activity");
+ if (!activityElem || !activityElem.isElement() ||
+ activityElem.tagName() != "activity")
+ throw "No activity tag found in '" + manifestFilePath + "'.";
+ var metaDataElem = activityElem.firstChild("meta-data");
+ while (metaDataElem && metaDataElem.isElement()) {
+ if (metaDataElem.attribute("android:name") ==
+ "android.app.load_local_jars" ) {
+ var value = metaDataElem.attribute("android:value");
+ var fileName = "QtAndroidNetwork.jar";
+ metaDataElem.setAttribute("android:value", value + ":jar/" +
+ fileName);
+ var jarFilePath = FileInfo.joinPaths(
+ product.Qt.android_support._qtInstallDir, "jar",
+ fileName);
+ var targetFilePath = FileInfo.joinPaths(product.java.classFilesDir,
+ fileName);
+ File.copy(jarFilePath, targetFilePath);
+ break;
+ }
+ metaDataElem = metaDataElem.nextSibling("meta-data");
+ }
+ manifestData.save(outputs["android.manifest_final"][0].filePath, 4);
+ } else {
+ File.move(product.Qt.android_support._deployQtOutDir + "/AndroidManifest.xml",
+ outputs["android.manifest_final"][0].filePath);
+ }
+ };
+ } else {
+ correctingCmd.description = "copying manifest";
+ correctingCmd.sourceCode = function() {
+ File.move(product.Qt.android_support._deployQtOutDir + "/AndroidManifest.xml",
+ outputs["android.manifest_final"][0].filePath);
+ }
+ }
+ cmds.push(correctingCmd);
+
+ return cmds;
}
}
diff --git a/share/qbs/module-providers/Qt/templates/core.qbs b/share/qbs/module-providers/Qt/templates/core.qbs
index 8e990db22..485402716 100644
--- a/share/qbs/module-providers/Qt/templates/core.qbs
+++ b/share/qbs/module-providers/Qt/templates/core.qbs
@@ -5,6 +5,7 @@ import qbs.Utilities
import qbs.Xml
import "moc.js" as Moc
import "qdoc.js" as Qdoc
+import "rcc.js" as Rcc
Module {
condition: (qbs.targetPlatform === targetPlatform || isCombinedUIKitBuild)
@@ -17,13 +18,21 @@ Module {
&& qbs.targetPlatform === targetPlatform + "-simulator"
Depends { name: "cpp" }
+ Depends { name: "Sanitizers.address"; condition: config.contains("sanitize_address") }
Depends { name: "Qt.android_support"; condition: qbs.targetOS.contains("android") }
Properties {
condition: qbs.targetOS.contains("android")
- Qt.android_support._qtInstallDir: FileInfo.path(binPath)
+ Qt.android_support._qtBinaryDir: FileInfo.path(binPath)
+ Qt.android_support._qtInstallDir: FileInfo.path(installPath)
Qt.android_support.version: version
+ Qt.android_support.rccFilePath: Rcc.fullPath(product)
}
+ // qmlImportScanner is required by androiddeployqt even if the project doesn't
+ // depend on qml. That's why the scannerName must be defined here and not in the
+ // qml module
+ property string qmlImportScannerName: "qmlimportscanner"
+ property string qmlImportScannerFilePath: qmlLibExecPath + '/' + qmlImportScannerName
version: @version@
property stringList architectures: @archs@
@@ -32,17 +41,23 @@ Module {
property stringList config: @config@
property stringList qtConfig: @qtConfig@
property path binPath: @binPath@
+ property path installPath: @installPath@
property path incPath: @incPath@
property path libPath: @libPath@
+ property path installPrefixPath: @installPrefixPath@
+ property path libExecPath: @libExecPath@
+ property path qmlLibExecPath: @qmlLibExecPath@
property path pluginPath: @pluginPath@
property string mkspecName: @mkspecName@
property path mkspecPath: @mkspecPath@
property string mocName: "moc"
property stringList mocFlags: []
property string lreleaseName: "lrelease"
+ property string rccName: "rcc"
property string qdocName: versionMajor >= 5 ? "qdoc" : "qdoc3"
property stringList qdocEnvironment
property path docPath: @docPath@
+ property string helpGeneratorLibExecPath: @helpGeneratorLibExecPath@
property stringList helpGeneratorArgs: versionMajor >= 5 ? ["-platform", "minimal"] : []
property var versionParts: version ? version.split('.').map(function(item) { return parseInt(item, 10); }) : []
property int versionMajor: versionParts[0]
@@ -52,11 +67,17 @@ Module {
property bool staticBuild: @staticBuild@
property stringList pluginMetaData: []
property bool enableKeywords: true
+ property bool generateMetaTypesFile
+ readonly property bool _generateMetaTypesFile: generateMetaTypesFile
+ && Utilities.versionCompare(version, "5.15") >= 0
+ property string metaTypesInstallDir
property stringList availableBuildVariants: @availableBuildVariants@
property string qtBuildVariant: {
if (availableBuildVariants.contains(qbs.buildVariant))
return qbs.buildVariant;
+ if (qbs.buildVariant === "profiling" && availableBuildVariants.contains("release"))
+ return "release";
return availableBuildVariants.length > 0 ? availableBuildVariants[0] : "";
}
@@ -88,6 +109,7 @@ Module {
property string libFilePathRelease: @libFilePathRelease@
property string libFilePath: qtBuildVariant === "debug"
? libFilePathDebug : libFilePathRelease
+ property bool useRPaths: qbs.targetOS.contains("linux") && !qbs.targetOS.contains("android")
property stringList coreLibPaths: @libraryPaths@
property bool hasLibrary: true
@@ -101,6 +123,7 @@ Module {
property bool lreleaseMultiplexMode: false
property stringList moduleConfig: @moduleConfig@
+
Properties {
condition: moduleConfig.contains("use_gold_linker")
cpp.linkerVariant: "gold"
@@ -110,14 +133,16 @@ Module {
cpp.linkerVariant: original
}
- cpp.cxxLanguageVersion: Utilities.versionCompare(version, "5.7.0") >= 0 ? "c++11" : original
+ cpp.cxxLanguageVersion: Utilities.versionCompare(version, "6.0.0") >= 0
+ ? "c++17"
+ : Utilities.versionCompare(version, "5.7.0") >= 0 ? "c++11" : original
cpp.enableCompilerDefinesByLanguage: ["cpp"].concat(
qbs.targetOS.contains("darwin") ? ["objcpp"] : [])
cpp.defines: {
var defines = @defines@;
- // ### QT_NO_DEBUG must be added if the current build variant is derived
- // from the build variant "release"
- if (!qbs.debugInformation)
+ // ### QT_NO_DEBUG must be added if the current build variant is not derived
+ // from the build variant "debug"
+ if (!qbs.enableDebugCode)
defines.push("QT_NO_DEBUG");
if (!enableKeywords)
defines.push("QT_NO_KEYWORDS");
@@ -127,13 +152,13 @@ Module {
if (Utilities.versionCompare(version, "5.6.0") < 0)
defines.push("main=qtmn");
}
+ if (qbs.toolchain.contains("msvc"))
+ defines.push("_ENABLE_EXTENDED_ALIGNED_STORAGE");
return defines;
}
cpp.driverFlags: {
var flags = [];
if (qbs.toolchain.contains("gcc")) {
- if (config.contains("sanitize_address"))
- flags.push("-fsanitize=address");
if (config.contains("sanitize_undefined"))
flags.push("-fsanitize=undefined");
if (config.contains("sanitize_thread"))
@@ -143,11 +168,8 @@ Module {
}
return flags;
}
- cpp.includePaths: {
- var paths = @includes@;
- paths.push(mkspecPath, generatedHeadersDir);
- return paths;
- }
+ cpp.includePaths: generatedHeadersDir
+ cpp.systemIncludePaths: @includes@.concat(mkspecPath)
cpp.libraryPaths: {
var libPaths = [libPath];
if (staticBuild && pluginPath)
@@ -166,7 +188,7 @@ Module {
}
cpp.dynamicLibraries: dynamicLibs
cpp.linkerFlags: coreLinkerFlags
- cpp.frameworkPaths: coreFrameworkPaths.concat(frameworkBuild ? [libPath] : [])
+ cpp.systemFrameworkPaths: coreFrameworkPaths.concat(frameworkBuild ? [libPath] : [])
cpp.frameworks: {
var frameworks = coreFrameworks
if (frameworkBuild)
@@ -177,18 +199,21 @@ Module {
return undefined;
return frameworks;
}
- cpp.rpaths: qbs.targetOS.contains('linux') ? [libPath] : undefined
+ cpp.rpaths: useRPaths ? libPath : undefined
cpp.runtimeLibrary: qbs.toolchain.contains("msvc")
? config.contains("static_runtime") ? "static" : "dynamic"
: original
- cpp.positionIndependentCode: versionMajor >= 5 ? true : undefined
+ cpp.positionIndependentCode: versionMajor >= 5 ? true : original
cpp.cxxFlags: {
var flags = [];
if (qbs.toolchain.contains('msvc')) {
if (versionMajor < 5)
flags.push('/Zc:wchar_t-');
+ if (Utilities.versionCompare(version, "6.3") >= 0
+ && Utilities.versionCompare(cpp.compilerVersion, "19.10") >= 0) {
+ flags.push("/permissive-");
+ }
}
-
return flags;
}
cpp.cxxStandardLibrary: {
@@ -197,19 +222,19 @@ Module {
return "libc++";
return original;
}
- cpp.minimumWindowsVersion: @minWinVersion@
- cpp.minimumMacosVersion: @minMacVersion@
- cpp.minimumIosVersion: @minIosVersion@
- cpp.minimumTvosVersion: @minTvosVersion@
- cpp.minimumWatchosVersion: @minWatchosVersion@
- cpp.minimumAndroidVersion: @minAndroidVersion@
+ cpp.minimumWindowsVersion: @minWinVersion_optional@
+ cpp.minimumMacosVersion: @minMacVersion_optional@
+ cpp.minimumIosVersion: @minIosVersion_optional@
+ cpp.minimumTvosVersion: @minTvosVersion_optional@
+ cpp.minimumWatchosVersion: @minWatchosVersion_optional@
+ cpp.minimumAndroidVersion: @minAndroidVersion_optional@
// Universal Windows Platform support
cpp.windowsApiFamily: mkspecName.startsWith("winrt-") ? "pc" : undefined
cpp.windowsApiAdditionalPartitions: mkspecPath.startsWith("winrt-") ? ["phone"] : undefined
cpp.requireAppContainer: mkspecName.startsWith("winrt-")
- additionalProductTypes: ["qm"]
+ additionalProductTypes: ["qm", "qt.core.metatypes"]
validate: {
var validator = new ModUtils.PropertyValidator("Qt.core");
@@ -279,24 +304,29 @@ Module {
property bool combineMocOutput: cpp.combineCxxSources
property bool enableBigResources: false
+ // Product should not moc in the aggregate when multiplexing.
+ property bool enableMoc: !(product.multiplexed || product.aggregate)
+ || product.multiplexConfigurationId
Rule {
name: "QtCoreMocRuleCpp"
+ condition: enableMoc
property string cppInput: cpp.combineCxxSources ? "cpp.combine" : "cpp"
property string objcppInput: cpp.combineObjcxxSources ? "objcpp.combine" : "objcpp"
inputs: [objcppInput, cppInput]
auxiliaryInputs: "qt_plugin_metadata"
excludedInputs: "unmocable"
- outputFileTags: ["hpp", "unmocable"]
+ outputFileTags: ["hpp", "unmocable", "qt.core.metatypes.in"]
outputArtifacts: Moc.outputArtifacts.apply(Moc, arguments)
prepare: Moc.commands.apply(Moc, arguments)
}
Rule {
name: "QtCoreMocRuleHpp"
+ condition: enableMoc
inputs: "hpp"
auxiliaryInputs: ["qt_plugin_metadata", "cpp", "objcpp"];
excludedInputs: "unmocable"
- outputFileTags: ["hpp", "cpp", "moc_cpp", "unmocable"]
+ outputFileTags: ["hpp", "cpp", "moc_cpp", "unmocable", "qt.core.metatypes.in"]
outputArtifacts: Moc.outputArtifacts.apply(Moc, arguments)
prepare: Moc.commands.apply(Moc, arguments)
}
@@ -319,6 +349,27 @@ Module {
}
}
+ Rule {
+ multiplex: true
+ inputs: "qt.core.metatypes.in"
+ Artifact {
+ filePath: product.targetName.toLowerCase() + "_metatypes.json"
+ fileTags: "qt.core.metatypes"
+ qbs.install: product.Qt.core.metaTypesInstallDir
+ qbs.installDir: product.Qt.core.metaTypesInstallDir
+ }
+ prepare: {
+ var inputFilePaths = inputs["qt.core.metatypes.in"].map(function(a) {
+ return a.filePath;
+ });
+ var cmd = new Command(Moc.fullPath(product),
+ ["--collect-json", "-o", output.filePath].concat(inputFilePaths));
+ cmd.description = "generating " + output.fileName;
+ cmd.highlight = "codegen";
+ return cmd;
+ }
+ }
+
property path resourceSourceBase
property string resourcePrefix: "/"
property string resourceFileBaseName: product.targetName
@@ -393,7 +444,7 @@ Module {
"-o", output.filePath];
if (input.Qt.core.enableBigResources)
args.push("-pass", "1");
- var cmd = new Command(product.Qt.core.binPath + '/rcc', args);
+ var cmd = new Command(Rcc.fullPath(product), args);
cmd.description = "rcc "
+ (input.Qt.core.enableBigResources ? "(pass 1) " : "")
+ input.fileName;
@@ -405,7 +456,7 @@ Module {
Rule {
inputs: ["intermediate_obj"]
Artifact {
- filePath: input.completeBaseName + ".2.o"
+ filePath: input.completeBaseName + ".2" + input.cpp.objectSuffix
fileTags: ["obj"]
}
prepare: {
@@ -424,7 +475,7 @@ Module {
}
var qrcArtifact = findChild(input, function(c) { return c.fileTags.contains("qrc"); });
var cppArtifact = findChild(input, function(c) { return c.fileTags.contains("cpp"); });
- var cmd = new Command(product.Qt.core.binPath + '/rcc',
+ var cmd = new Command(Rcc.fullPath(product),
[qrcArtifact.filePath,
"-temp", input.filePath,
"-name", FileInfo.completeBaseName(input.filePath),
@@ -457,7 +508,7 @@ Module {
var args = ['-silent', '-qm', output.filePath].concat(inputFilePaths);
var cmd = new Command(product.Qt.core.binPath + '/'
+ product.Qt.core.lreleaseName, args);
- cmd.description = 'Creating ' + output.fileName;
+ cmd.description = 'creating ' + output.fileName;
cmd.highlight = 'filegen';
return cmd;
}
@@ -497,7 +548,8 @@ Module {
args = args.concat(product.Qt.core.helpGeneratorArgs);
args.push("-o");
args.push(output.filePath);
- var cmd = new Command(product.Qt.core.binPath + "/qhelpgenerator", args);
+ var cmd = new Command(
+ product.Qt.core.helpGeneratorLibExecPath + "/qhelpgenerator", args);
cmd.description = 'qhelpgenerator ' + input.fileName;
cmd.highlight = 'filegen';
cmd.stdoutFilterFunction = function(output) {
diff --git a/share/qbs/module-providers/Qt/templates/dbus.js b/share/qbs/module-providers/Qt/templates/dbus.js
index 0674bf684..3cdd6fb90 100644
--- a/share/qbs/module-providers/Qt/templates/dbus.js
+++ b/share/qbs/module-providers/Qt/templates/dbus.js
@@ -29,6 +29,7 @@
****************************************************************************/
var FileInfo = require("qbs.FileInfo");
+var ModUtils = require("qbs.ModUtils");
function outputFileName(input, suffix)
{
diff --git a/share/qbs/module-providers/Qt/templates/dbus.qbs b/share/qbs/module-providers/Qt/templates/dbus.qbs
index 6556e2c9b..bbda5a4f2 100644
--- a/share/qbs/module-providers/Qt/templates/dbus.qbs
+++ b/share/qbs/module-providers/Qt/templates/dbus.qbs
@@ -1,6 +1,5 @@
import qbs.FileInfo
import qbs.ModUtils
-import "../QtModule.qbs" as QtModule
import "dbus.js" as DBus
QtModule {
@@ -23,9 +22,7 @@ QtModule {
fileTags: ["cpp"]
}
- prepare: {
- return DBus.createCommands(product, input, outputs, "-a");
- }
+ prepare: DBus.createCommands(product, input, outputs, "-a")
}
Rule {
@@ -41,9 +38,7 @@ QtModule {
fileTags: ["cpp"]
}
- prepare: {
- return DBus.createCommands(product, input, outputs, "-p");
- }
+ prepare: DBus.createCommands(product, input, outputs, "-p")
}
architectures: @archs@
@@ -66,7 +61,7 @@ QtModule {
moduleConfig: @moduleConfig@
cpp.defines: @defines@
- cpp.includePaths: @includes@
+ cpp.systemIncludePaths: @includes@
cpp.libraryPaths: @libraryPaths@
@additionalContent@
diff --git a/share/qbs/module-providers/Qt/templates/gui.qbs b/share/qbs/module-providers/Qt/templates/gui.qbs
index a3c427175..db491eafe 100644
--- a/share/qbs/module-providers/Qt/templates/gui.qbs
+++ b/share/qbs/module-providers/Qt/templates/gui.qbs
@@ -1,7 +1,6 @@
import qbs.FileInfo
import qbs.ModUtils
import qbs.Utilities
-import '../QtModule.qbs' as QtModule
QtModule {
qtModuleName: "Gui"
@@ -23,10 +22,12 @@ QtModule {
}
prepare: {
- var cmd = new Command(ModUtils.moduleProperty(product, "binPath") + '/'
- + ModUtils.moduleProperty(product, "uicName"),
- [input.filePath, '-o', output.filePath])
- cmd.description = 'uic ' + input.fileName;
+ var uicPath = Utilities.versionCompare(product.Qt.gui.version, "6.1") < 0
+ ? product.Qt.core.binPath + '/' + product.Qt.gui.uicName
+ : product.Qt.core.libExecPath + '/' + product.Qt.gui.uicName;
+
+ var cmd = new Command(uicPath, [input.filePath, '-o', output.filePath]);
+ cmd.description = 'generating ' + output.fileName;
cmd.highlight = 'codegen';
return cmd;
}
@@ -57,7 +58,7 @@ QtModule {
: undefined
cpp.defines: @defines@
- cpp.includePaths: @includes@
+ cpp.systemIncludePaths: @includes@
cpp.libraryPaths: @libraryPaths@
Properties {
diff --git a/share/qbs/module-providers/Qt/templates/moc.js b/share/qbs/module-providers/Qt/templates/moc.js
index aa67766b9..7d230267c 100644
--- a/share/qbs/module-providers/Qt/templates/moc.js
+++ b/share/qbs/module-providers/Qt/templates/moc.js
@@ -29,13 +29,14 @@
****************************************************************************/
var ModUtils = require("qbs.ModUtils");
+var Utilities = require("qbs.Utilities");
-function args(product, input, outputFileName)
+function args(product, input, outputs)
{
var defines = product.cpp.compilerDefinesByLanguage;
if (input.fileTags.contains("objcpp"))
defines = ModUtils.flattenDictionary(defines["objcpp"]) || [];
- else if (input.fileTags.contains("cpp"))
+ else if (input.fileTags.contains("cpp") || input.fileTags.contains("hpp"))
defines = ModUtils.flattenDictionary(defines["cpp"]) || [];
else
defines = [];
@@ -56,6 +57,15 @@ function args(product, input, outputFileName)
}
var pluginMetaData = product.Qt.core.pluginMetaData;
var args = [];
+ if (product.Qt.core._generateMetaTypesFile)
+ args.push("--output-json");
+ var outputFileName;
+ for (tag in outputs) {
+ if (tag !== "qt.core.metatypes.in") {
+ outputFileName = outputs[tag][0].filePath;
+ break;
+ }
+ }
args = args.concat(
defines.map(function(item) { return '-D' + item; }),
includePaths.map(function(item) { return '-I' + item; }),
@@ -69,7 +79,9 @@ function args(product, input, outputFileName)
function fullPath(product)
{
- return product.Qt.core.binPath + '/' + product.Qt.core.mocName;
+ if (Utilities.versionCompare(product.Qt.core.version, "6.1") < 0)
+ return product.Qt.core.binPath + '/' + product.Qt.core.mocName;
+ return product.Qt.core.libExecPath + '/' + product.Qt.core.mocName;
}
function outputArtifacts(project, product, inputs, input)
@@ -90,12 +102,15 @@ function outputArtifacts(project, product, inputs, input)
+ input.completeBaseName + ".moc";
artifact.fileTags.push("hpp");
}
- return [artifact];
+ var artifacts = [artifact];
+ if (product.Qt.core._generateMetaTypesFile)
+ artifacts.push({filePath: artifact.filePath + ".json", fileTags: "qt.core.metatypes.in"});
+ return artifacts;
}
function commands(project, product, inputs, outputs, input, output)
{
- var cmd = new Command(fullPath(product), args(product, input, output.filePath));
+ var cmd = new Command(fullPath(product), args(product, input, outputs));
cmd.description = 'moc ' + input.fileName;
cmd.highlight = 'codegen';
return cmd;
diff --git a/share/qbs/module-providers/Qt/templates/module.qbs b/share/qbs/module-providers/Qt/templates/module.qbs
index b09f79a87..9f0313ab5 100644
--- a/share/qbs/module-providers/Qt/templates/module.qbs
+++ b/share/qbs/module-providers/Qt/templates/module.qbs
@@ -1,5 +1,3 @@
-import '../QtModule.qbs' as QtModule
-
QtModule {
qtModuleName: @name@
Depends { name: "Qt"; submodules: @dependencies@}
@@ -24,7 +22,7 @@ QtModule {
pluginTypes: @pluginTypes@
moduleConfig: @moduleConfig@
cpp.defines: @defines@
- cpp.includePaths: @includes@
+ cpp.systemIncludePaths: @includes@
cpp.libraryPaths: @libraryPaths@
@additionalContent@
}
diff --git a/share/qbs/module-providers/Qt/templates/plugin.qbs b/share/qbs/module-providers/Qt/templates/plugin.qbs
index e73e2a4d9..34d4f4153 100644
--- a/share/qbs/module-providers/Qt/templates/plugin.qbs
+++ b/share/qbs/module-providers/Qt/templates/plugin.qbs
@@ -1,5 +1,3 @@
-import '../QtPlugin.qbs' as QtPlugin
-
QtPlugin {
qtModuleName: @name@
Depends { name: "Qt"; submodules: @dependencies@}
diff --git a/share/qbs/module-providers/Qt/templates/plugin_support.qbs b/share/qbs/module-providers/Qt/templates/plugin_support.qbs
index 1de923f17..19a739589 100644
--- a/share/qbs/module-providers/Qt/templates/plugin_support.qbs
+++ b/share/qbs/module-providers/Qt/templates/plugin_support.qbs
@@ -32,7 +32,7 @@ Module {
newValue = [];
else if (typeof newValue == "string")
newValue = [newValue];
- if (!Array.isArray(newValue))
+ if (!newValue instanceof Array)
throw "Invalid value '" + newValue + "' in Qt.plugin_support.pluginsByType";
eppt[pluginType] = (eppt[pluginType] || []).uniqueConcat(newValue);
}
diff --git a/share/qbs/module-providers/Qt/templates/qml.js b/share/qbs/module-providers/Qt/templates/qml.js
index df69034fe..38462dcf7 100644
--- a/share/qbs/module-providers/Qt/templates/qml.js
+++ b/share/qbs/module-providers/Qt/templates/qml.js
@@ -3,14 +3,31 @@ var FileInfo = require("qbs.FileInfo");
var Process = require("qbs.Process");
var TextFile = require("qbs.TextFile");
-function scannerData(scannerFilePath, qmlFiles, qmlPath)
+function scannerData(scannerFilePath, qmlFiles, qmlPath, hostOS)
{
var p;
try {
p = new Process();
- p.exec(scannerFilePath, ["-qmlFiles"].concat(qmlFiles).concat(["-importPath", qmlPath]),
- true);
- return JSON.parse(p.readStdOut());
+ if (!hostOS.contains("windows")) {
+ p.exec(scannerFilePath, ["-qmlFiles"].concat(qmlFiles).concat(["-importPath", qmlPath]),
+ true);
+ return JSON.parse(p.readStdOut());
+ }
+ var data = [];
+ var nextFileIndex = 0;
+ while (nextFileIndex < qmlFiles.length) {
+ var currentFileList = [];
+ var currentFileListStringLength = 0;
+ while (nextFileIndex < qmlFiles.length && currentFileListStringLength < 30000) {
+ var currentFile = qmlFiles[nextFileIndex++];
+ currentFileList.push(currentFile);
+ currentFileListStringLength += currentFile.length;
+ }
+ p.exec(scannerFilePath, ["-qmlFiles"].concat(currentFileList)
+ .concat(["-importPath", qmlPath]), true);
+ data = data.concat(JSON.parse(p.readStdOut()));
+ }
+ return data;
} finally {
if (p)
p.close();
@@ -22,16 +39,32 @@ function getPrlRhs(line)
return line.split('=')[1].trim();
}
-function getLibsForPlugin(pluginData, buildVariant, targetOS, toolchain, qtLibDir)
+function getLibsForPlugin(pluginData, product)
{
+ var targetOS = product.qbs.targetOS;
+ var toolchain = product.qbs.toolchain;
+ var buildVariant = product.Qt.core.qtBuildVariant;
+ var qtLibDir = product.Qt.core.libPath;
+ var qtPluginDir = product.Qt.core.pluginPath;
+ var qtDir = product.Qt.core.installPrefixPath;
+ var qtQmlPath = product.Qt.qml.qmlPath;
+
if (!pluginData.path)
return "";
var prlFileName = "";
if (!targetOS.contains("windows"))
prlFileName += "lib";
prlFileName += pluginData.plugin;
- if (buildVariant === "debug" && targetOS.contains("windows"))
- prlFileName += "d";
+ if (buildVariant === "debug") {
+ if (targetOS.contains("windows")) {
+ prlFileName += "d";
+ } else if (product.Qt.core.versionMajor >= 6 &&
+ (targetOS.contains("ios")
+ || targetOS.contains("tvos")
+ || targetOS.contains("watchos"))) {
+ prlFileName += "_debug";
+ }
+ }
prlFileName += ".prl";
var prlFilePath = FileInfo.joinPaths(pluginData.path, prlFileName);
if (!File.exists(prlFilePath)) {
@@ -42,7 +75,7 @@ function getLibsForPlugin(pluginData, buildVariant, targetOS, toolchain, qtLibDi
var prlFile = new TextFile(prlFilePath, TextFile.ReadOnly);
try {
var pluginLib;
- var otherLibs = "";
+ var otherLibs = [];
var line;
while (!prlFile.atEof()) {
line = prlFile.readLine().trim();
@@ -57,12 +90,15 @@ function getLibsForPlugin(pluginData, buildVariant, targetOS, toolchain, qtLibDi
otherLibsLine = otherLibsLine.replace(/-l([^ ]+)/g, "$1" + ".lib");
}
otherLibsLine = otherLibsLine.replace(/\$\$\[QT_INSTALL_LIBS\]/g, qtLibDir);
- otherLibs += otherLibsLine + '\n';
+ otherLibsLine = otherLibsLine.replace(/\$\$\[QT_INSTALL_PLUGINS\]/g, qtPluginDir);
+ otherLibsLine = otherLibsLine.replace(/\$\$\[QT_INSTALL_PREFIX\]/g, qtDir);
+ otherLibsLine = otherLibsLine.replace(/\$\$\[QT_INSTALL_QML\]/g, qtQmlPath);
+ otherLibs = otherLibs.concat(otherLibsLine.split(' ').map(FileInfo.cleanPath));
}
}
if (!pluginLib)
throw "Malformed prl file '" + prlFilePath + "'.";
- return pluginLib + ' ' + otherLibs;
+ return [pluginLib].concat(otherLibs);
} finally {
prlFile.close();
}
diff --git a/share/qbs/module-providers/Qt/templates/qml.qbs b/share/qbs/module-providers/Qt/templates/qml.qbs
index c95c0f367..0a938e58d 100644
--- a/share/qbs/module-providers/Qt/templates/qml.qbs
+++ b/share/qbs/module-providers/Qt/templates/qml.qbs
@@ -1,13 +1,14 @@
+import qbs.FileInfo
+import qbs.Host
import qbs.TextFile
-import '../QtModule.qbs' as QtModule
import "qml.js" as Qml
QtModule {
qtModuleName: "Qml"
Depends { name: "Qt"; submodules: @dependencies@}
- property string qmlImportScannerName: "qmlimportscanner"
- property string qmlImportScannerFilePath: Qt.core.binPath + '/' + qmlImportScannerName
+ property string qmlImportScannerName: Qt.core.qmlImportScannerName
+ property string qmlImportScannerFilePath: Qt.core.qmlImportScannerFilePath
property string qmlPath: @qmlPath@
property bool generateCacheFiles: false
@@ -46,7 +47,7 @@ QtModule {
pluginTypes: @pluginTypes@
moduleConfig: @moduleConfig@
cpp.defines: @defines@
- cpp.includePaths: @includes@
+ cpp.systemIncludePaths: @includes@
cpp.libraryPaths: @libraryPaths@
@additionalContent@
@@ -60,6 +61,60 @@ QtModule {
fileTags: ["qt.qml.js"]
}
+ // Type registration
+ property string importName
+ property string importVersion: product.version
+ readonly property stringList _importVersionParts: (importVersion || "").split(".")
+ property string typesFileName: {
+ if (product.type && product.type.contains("application"))
+ return product.targetName + ".qmltypes";
+ return "plugins.qmltypes";
+ }
+ property string typesInstallDir
+ property stringList extraMetaTypesFiles
+ Properties {
+ condition: importName
+ Qt.core.generateMetaTypesFile: true
+ }
+ Qt.core.generateMetaTypesFile: original
+ Rule {
+ condition: importName
+ inputs: "qt.core.metatypes"
+ multiplex: true
+ explicitlyDependsOnFromDependencies: "qt.core.metatypes"
+ Artifact {
+ filePath: product.targetName.toLowerCase() + "_qmltyperegistrations.cpp"
+ fileTags: ["cpp", "unmocable"]
+ }
+ Artifact {
+ filePath: product.Qt.qml.typesFileName
+ fileTags: "qt.qml.types"
+ qbs.install: product.Qt.qml.typesInstallDir
+ qbs.installDir: product.Qt.qml.typesInstallDir
+ }
+ prepare: {
+ var versionParts = product.Qt.qml._importVersionParts;
+ var args = [
+ "--generate-qmltypes=" + outputs["qt.qml.types"][0].filePath,
+ "--import-name=" + product.Qt.qml.importName,
+ "--major-version=" + versionParts[0],
+ "--minor-version=" + (versionParts.length > 1 ? versionParts[1] : "0")
+ ];
+ var foreignTypes = product.Qt.qml.extraMetaTypesFiles || [];
+ var metaTypeArtifactsFromDeps = explicitlyDependsOn["qt.core.metatypes"] || [];
+ var filePathFromArtifact = function(a) { return a.filePath; };
+ foreignTypes = foreignTypes.concat(metaTypeArtifactsFromDeps.map(filePathFromArtifact));
+ if (foreignTypes.length > 0)
+ args.push("--foreign-types=" + foreignTypes.join(","));
+ args.push("-o", outputs.cpp[0].filePath);
+ args = args.concat(inputs["qt.core.metatypes"].map(filePathFromArtifact));
+ var cmd = new Command(product.Qt.core.qmlLibExecPath + "/qmltyperegistrar", args);
+ cmd.description = "running qmltyperegistrar";
+ cmd.highlight = "codegen";
+ return cmd;
+ }
+ }
+
Rule {
condition: linkPlugins
multiplex: true
@@ -81,7 +136,7 @@ QtModule {
prepare: {
var cmd = new JavaScriptCommand();
if (inputs["qt.qml.qml"])
- cmd.description = "Creating " + outputs["cpp"][0].fileName;
+ cmd.description = "creating " + outputs["cpp"][0].fileName;
else
cmd.silent = true;
cmd.sourceCode = function() {
@@ -90,7 +145,7 @@ QtModule {
qmlInputs = [];
var scannerData = Qml.scannerData(product.Qt.qml.qmlImportScannerFilePath,
qmlInputs.map(function(inp) { return inp.filePath; }),
- product.Qt.qml.qmlPath);
+ product.Qt.qml.qmlPath, Host.os());
var cppFile;
var listFile;
try {
@@ -101,6 +156,7 @@ QtModule {
if (cppFile)
cppFile.writeLine("#include <QtPlugin>");
var plugins = { };
+ var libsWithUniqueObjects = [];
for (var p in scannerData) {
var plugin = scannerData[p].plugin;
if (!plugin || plugins[plugin])
@@ -113,13 +169,17 @@ QtModule {
}
if (cppFile)
cppFile.writeLine("Q_IMPORT_PLUGIN(" + className + ")");
- var libs = Qml.getLibsForPlugin(scannerData[p],
- product.Qt.core.qtBuildVariant,
- product.qbs.targetOS,
- product.qbs.toolchain,
- product.Qt.core.libPath);
- listFile.write(libs + ' ');
+ var libs = Qml.getLibsForPlugin(scannerData[p], product);
+ for (var i = 0; i < libs.length; ++i) {
+ var lib = libs[i];
+ if (!lib.endsWith(product.cpp.objectSuffix)
+ || (!libsWithUniqueObjects.contains(lib)
+ && !product.cpp.staticLibraries.contains(FileInfo.cleanPath(lib)))) {
+ libsWithUniqueObjects.push(lib);
+ }
+ }
}
+ listFile.write(libsWithUniqueObjects.join("\n"));
} finally {
if (cppFile)
cppFile.close();
@@ -130,4 +190,20 @@ QtModule {
return [cmd];
}
}
+
+ validate: {
+ if (importName) {
+ if (!importVersion)
+ throw "Qt.qml.importVersion must be set if Qt.qml.importName is set.";
+ var isInt = function(value) {
+ return !isNaN(value) && parseInt(Number(value)) == value
+ && !isNaN(parseInt(value, 10));
+ }
+ if (!isInt(_importVersionParts[0])
+ || (_importVersionParts.length > 1 && !isInt(_importVersionParts[1]))) {
+ throw "Qt.qml.importVersion must be of the form x.y, where x and y are integers.";
+ }
+
+ }
+ }
}
diff --git a/share/qbs/module-providers/Qt/templates/qmlcache.qbs b/share/qbs/module-providers/Qt/templates/qmlcache.qbs
index 9111eb500..7047884c0 100644
--- a/share/qbs/module-providers/Qt/templates/qmlcache.qbs
+++ b/share/qbs/module-providers/Qt/templates/qmlcache.qbs
@@ -9,8 +9,8 @@ Module {
if (!qmlcachegenProbe.found)
throw "qmlcachegen unsupported for this target";
}
- property string qmlCacheGenPath: FileInfo.joinPaths(Qt.core.binPath, "qmlcachegen")
- + (qbs.hostOS.contains("windows") ? ".exe" : "")
+ property string qmlCacheGenPath: FileInfo.joinPaths(Qt.core.qmlLibExecPath, "qmlcachegen")
+ + FileInfo.executableSuffix()
property bool supportsAllArchitectures: Utilities.versionCompare(Qt.core.version, "5.11") >= 0
property string installDir
diff --git a/share/qbs/module-providers/Qt/templates/quick.js b/share/qbs/module-providers/Qt/templates/quick.js
index 4f3da2fb0..d7e58984f 100644
--- a/share/qbs/module-providers/Qt/templates/quick.js
+++ b/share/qbs/module-providers/Qt/templates/quick.js
@@ -30,13 +30,14 @@
var FileInfo = require("qbs.FileInfo");
var Process = require("qbs.Process");
+var Rcc = require("rcc.js");
-function scanQrc(qrcFilePath) {
+function scanQrc(product, qrcFilePath) {
var absInputDir = FileInfo.path(qrcFilePath);
var result = [];
var process = new Process();
try {
- var rcc = FileInfo.joinPaths(product.Qt.core.binPath, 'rcc' + product.cpp.executableSuffix);
+ var rcc = FileInfo.joinPaths(Rcc.fullPath(product) + FileInfo.executableSuffix());
var exitCode = process.exec(rcc, ["--list", qrcFilePath], true);
for (;;) {
var line = process.readLine();
@@ -65,13 +66,14 @@ function qtQuickResourceFileOutputName(fileName) {
return fileName.replace(/\.qrc$/, "_qtquickcompiler.qrc");
}
-function contentFromQrc(qrcFilePath) {
- var filesInQrc = scanQrc(qrcFilePath);
+function contentFromQrc(product, qrcFilePath) {
+ var supportsFiltering = product.Qt.quick._supportsQmlJsFiltering;
+ var filesInQrc = scanQrc(product, qrcFilePath);
var qmlJsFiles = filesInQrc.filter(function (filePath) {
- return (/\.(js|qml)$/).test(filePath);
+ return (/\.(mjs|js|qml)$/).test(filePath);
} );
var content = {};
- if (filesInQrc.length - qmlJsFiles.length > 0) {
+ if (!supportsFiltering || filesInQrc.length - qmlJsFiles.length > 0) {
content.newQrcFileName = qtQuickResourceFileOutputName(input.fileName);
}
content.qmlJsFiles = qmlJsFiles.map(function (filePath) {
diff --git a/share/qbs/module-providers/Qt/templates/quick.qbs b/share/qbs/module-providers/Qt/templates/quick.qbs
index 5968949c8..5fc4aa349 100644
--- a/share/qbs/module-providers/Qt/templates/quick.qbs
+++ b/share/qbs/module-providers/Qt/templates/quick.qbs
@@ -33,12 +33,11 @@ import qbs.FileInfo
import qbs.Process
import qbs.TextFile
import qbs.Utilities
-import '../QtModule.qbs' as QtModule
import 'quick.js' as QC
QtModule {
qtModuleName: @name@
- Depends { name: "Qt"; submodules: @dependencies@.concat("qml-private") }
+ Depends { name: "Qt"; submodules: @dependencies@ }
hasLibrary: @has_library@
architectures: @archs@
@@ -60,18 +59,23 @@ QtModule {
pluginTypes: @pluginTypes@
moduleConfig: @moduleConfig@
cpp.defines: @defines@
- cpp.includePaths: @includes@
+ cpp.systemIncludePaths: @includes@
cpp.libraryPaths: @libraryPaths@
@additionalContent@
readonly property bool _compilerIsQmlCacheGen: Utilities.versionCompare(Qt.core.version,
"5.11") >= 0
+ readonly property bool _supportsQmlJsFiltering: Utilities.versionCompare(Qt.core.version,
+ "5.15") < 0
readonly property string _generatedLoaderFileName: _compilerIsQmlCacheGen
? "qmlcache_loader.cpp"
: "qtquickcompiler_loader.cpp"
+ property string _compilerBaseDir: _compilerIsQmlCacheGen ? Qt.core.qmlLibExecPath
+ : Qt.core.binPath
property string compilerBaseName: (_compilerIsQmlCacheGen ? "qmlcachegen" : "qtquickcompiler")
- property string compilerFilePath: FileInfo.joinPaths(Qt.core.binPath,
- compilerBaseName + product.cpp.executableSuffix)
+ property string compilerFilePath: FileInfo.joinPaths(_compilerBaseDir,
+ compilerBaseName + FileInfo.executableSuffix())
+
property bool compilerAvailable: File.exists(compilerFilePath);
property bool useCompiler: compilerAvailable && !_compilerIsQmlCacheGen
@@ -79,7 +83,7 @@ QtModule {
condition: useCompiler
inputs: 'qt.quick.qrc'
searchPaths: [FileInfo.path(input.filePath)]
- scan: QC.scanQrc(input.filePath)
+ scan: QC.scanQrc(product, input.filePath)
}
FileTagger {
@@ -100,7 +104,7 @@ QtModule {
var cmd = new JavaScriptCommand();
cmd.silent = true;
cmd.sourceCode = function() {
- var content = QC.contentFromQrc(input.filePath);
+ var content = QC.contentFromQrc(product, input.filePath);
content.qrcFilePath = input.filePath;
var tf = new TextFile(output.filePath, TextFile.WriteOnly);
@@ -174,7 +178,9 @@ QtModule {
if (info.newQrcFileName) {
loaderFlags.push("--resource-file-mapping="
+ FileInfo.fileName(info.qrcFilePath)
- + ":" + info.newQrcFileName);
+ + '=' + info.newQrcFileName);
+ // Qt 5.15 doesn't really filter anyting but merely copies the qrc
+ // content to the new location
var args = ["--filter-resource-file",
info.qrcFilePath];
if (useCacheGen)
diff --git a/share/qbs/module-providers/Qt/templates/rcc.js b/share/qbs/module-providers/Qt/templates/rcc.js
new file mode 100644
index 000000000..89c57d99b
--- /dev/null
+++ b/share/qbs/module-providers/Qt/templates/rcc.js
@@ -0,0 +1,8 @@
+var Utilities = require("qbs.Utilities");
+
+function fullPath(product)
+{
+ if (Utilities.versionCompare(product.Qt.core.version, "6.1") < 0)
+ return product.Qt.core.binPath + '/' + product.Qt.core.rccName;
+ return product.Qt.core.libExecPath + '/' + product.Qt.core.rccName;
+}
diff --git a/share/qbs/module-providers/Qt/templates/scxml.qbs b/share/qbs/module-providers/Qt/templates/scxml.qbs
index 7125ec53c..757041b52 100644
--- a/share/qbs/module-providers/Qt/templates/scxml.qbs
+++ b/share/qbs/module-providers/Qt/templates/scxml.qbs
@@ -1,10 +1,11 @@
import qbs.FileInfo
import qbs.Utilities
-import "../QtModule.qbs" as QtModule
QtModule {
qtModuleName: "Scxml"
+ property string _qscxmlcDir: Utilities.versionCompare(Qt.core.version, "6.3") >= 0
+ ? Qt.core.libExecPath : Qt.core.binPath
property string qscxmlcName: "qscxmlc"
property string className
property string namespace
@@ -26,8 +27,7 @@ QtModule {
prepare: {
var compilerName = product.moduleProperty("Qt.scxml", "qscxmlcName");
- var compilerPath = FileInfo.joinPaths(input.moduleProperty("Qt.core", "binPath"),
- compilerName);
+ var compilerPath = FileInfo.joinPaths(input.Qt.scxml._qscxmlcDir, compilerName);
var args = ["--header", outputs["hpp"][0].filePath,
"--impl", outputs["cpp"][0].filePath];
var cxx98 = input.moduleProperty("cpp", "cxxLanguageVersion") === "c++98";
@@ -73,7 +73,7 @@ QtModule {
moduleConfig: @moduleConfig@
cpp.defines: @defines@
- cpp.includePaths: @includes@
+ cpp.systemIncludePaths: @includes@
cpp.libraryPaths: @libraryPaths@
@additionalContent@
diff --git a/share/qbs/module-providers/__fallback/fallback.qbs b/share/qbs/module-providers/__fallback/fallback.qbs
index 632d1aa7a..349af3a52 100644
--- a/share/qbs/module-providers/__fallback/fallback.qbs
+++ b/share/qbs/module-providers/__fallback/fallback.qbs
@@ -37,7 +37,6 @@
**
****************************************************************************/
-import qbs
import qbs.FileInfo
import qbs.Probes
@@ -47,6 +46,8 @@ Module {
property string theName: FileInfo.completeBaseName(filePath)
+ readonly property bool __fallback: true // Hack, please look away
+
Probes.PkgConfigProbe {
id: pkgConfigProbe
condition: pkgconfig.present
diff --git a/share/qbs/module-providers/conan.js b/share/qbs/module-providers/conan.js
new file mode 100644
index 000000000..a44af7eec
--- /dev/null
+++ b/share/qbs/module-providers/conan.js
@@ -0,0 +1,239 @@
+/****************************************************************************
+**
+** Copyright (C) 2024 Kai Dohmen
+** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+var File = require("qbs.File");
+var FileInfo = require("qbs.FileInfo");
+var ModUtils = require("qbs.ModUtils");
+var PathProbe = require("../imports/qbs/Probes/path-probe.js")
+var PathTools = require("qbs.PathTools");
+var TextFile = require("qbs.TextFile");
+var Utilities = require("qbs.Utilities");
+
+const architectureMap = {
+ 'x86': 'x86',
+ 'x86_64': 'x86_64',
+ 'ppc32be': 'ppc',
+ 'ppc32': 'ppc',
+ 'ppc64le': 'ppc64',
+ 'ppc64': 'ppc64',
+ 'armv4': 'arm',
+ 'armv4i': 'arm',
+ 'armv5el': 'arm',
+ 'armv5hf': 'arm',
+ 'armv6': 'arm',
+ 'armv7': 'arm',
+ 'armv7hf': 'arm',
+ 'armv7s': 'arm',
+ 'armv7k': 'arm',
+ 'armv8': 'arm64',
+ 'armv8_32': 'arm64',
+ 'armv8.3': 'arm64',
+ 'sparc': 'sparc',
+ 'sparcv9': 'sparc64',
+ 'mips': 'mips',
+ 'mips64': 'mips64',
+ 'avr': 'avr',
+ 's390': 's390x',
+ 's390x': 's390x',
+ 'sh4le': 'sh'
+}
+
+const platformMap = {
+ 'Windows': 'windows',
+ 'WindowsStore': 'windows',
+ 'WindowsCE': 'windows',
+ 'Linux': 'linux',
+ 'Macos': 'macos',
+ 'Android': 'android',
+ 'iOS': 'ios',
+ 'watchOS': 'watchos',
+ 'tvOS': 'tvos',
+ 'FreeBSD': 'freebsd',
+ 'SunOS': 'solaris',
+ 'AIX': 'aix',
+ 'Emscripten': undefined,
+ 'Arduino': 'none',
+ 'Neutrino': 'qnx',
+ 'baremetal': 'none',
+ 'VxWorks': 'vxworks',
+}
+
+function findLibs(libnames, libdirs, libtypes, targetOS, forImport) {
+ var result = [];
+ if (libnames === null || libdirs === null)
+ return result;
+ libnames.forEach(function(libraryName) {
+ const suffixes = PathTools.librarySuffixes(targetOS, libtypes, forImport);
+ const lib = PathProbe.configure(
+ undefined, // selectors
+ [libraryName],
+ suffixes,
+ PathTools.libraryNameFilter(targetOS),
+ undefined, // candidateFilter
+ libdirs, // searchPaths
+ undefined, // pathSuffixes
+ [], // platformSearchPaths
+ undefined, // environmentPaths
+ undefined // platformEnvironmentPaths
+ );
+ if (lib.found)
+ result.push(lib.files[0].filePath);
+ });
+ return result;
+}
+
+function getLibraryTypes(options) {
+ if (options !== undefined && options !== null) {
+ if (options.shared === undefined)
+ return ["shared", "static"];
+ else if (options.shared === "True")
+ return ["shared"];
+ else if (options.shared === "False")
+ return ["static"];
+ }
+ return ["shared", "static"];
+}
+
+function configure(installDirectory, moduleName, outputBaseDir, jsonProbe) {
+ const moduleMapping = {"protobuflib": "protobuf"}
+ const realModuleName = moduleMapping[moduleName] || moduleName;
+
+ const moduleFilePath =
+ FileInfo.joinPaths(installDirectory, "conan-qbs-deps", realModuleName + ".json")
+ if (!File.exists(moduleFilePath))
+ return [];
+
+ var reverseMapping = {}
+ for (var key in moduleMapping)
+ reverseMapping[moduleMapping[key]] = key
+
+ console.info("Setting up Conan module '" + moduleName + "'");
+
+ var moduleFile = new TextFile(moduleFilePath, TextFile.ReadOnly);
+ const moduleInfo = JSON.parse(moduleFile.readAll());
+
+ const outputDir = FileInfo.joinPaths(outputBaseDir, "modules", moduleName.replace(".", "/"));
+ File.makePath(outputDir);
+ const outputFilePath = FileInfo.joinPaths(outputDir, "module.qbs");
+
+ const cppInfo = moduleInfo.cpp_info;
+
+ var moduleContent = "";
+
+ // function write(data) { moduleContent = moduleContent + data }
+ function writeLine(data) { moduleContent = moduleContent + data + "\n"; }
+
+ function writeProperty(propertyName, propertyValue) {
+ if (propertyValue === undefined || propertyValue === null)
+ propertyValue = [];
+ writeLine(" readonly property stringList " + propertyName
+ + ": " + ModUtils.toJSLiteral(propertyValue));
+ }
+ function writeCppProperty(propertyName, propertyValue) {
+ writeProperty(propertyName, propertyValue);
+ // skip empty props for simplicity of the module file
+ if (propertyValue !== undefined && propertyValue != null && propertyValue.length !== 0) {
+ writeLine(" cpp." + propertyName + ": " + propertyName);
+ }
+ }
+
+ writeLine("Module {");
+
+ writeLine(" version: " + ModUtils.toJSLiteral(moduleInfo.version));
+
+ const architecture = architectureMap[moduleInfo.settings.arch];
+ const platform = platformMap[moduleInfo.settings.os];
+ const targetOS = Utilities.canonicalPlatform(platform);
+
+ writeLine(" readonly property string architecture: " + ModUtils.toJSLiteral(architecture));
+ writeLine(" readonly property string platform: " + ModUtils.toJSLiteral(platform));
+ writeLine(" condition: true");
+ if (architecture !== undefined) {
+ writeLine(" && (!qbs.architecture || qbs.architecture === architecture)");
+ }
+ if (platform !== undefined) {
+ if (["ios", "tvos", "watchos"].includes(platform)) {
+ writeLine(" && (qbs.targetPlatform === platform || qbs.targetPlatform === platform + \"-simulator\")");
+ } else {
+ writeLine(" && qbs.targetPlatform === platform");
+ }
+ }
+
+ writeLine(" Depends { name: 'cpp' }");
+
+ moduleInfo.dependencies.forEach(function(dep) {
+ const realDepName = reverseMapping[dep.name] || dep.name;
+ writeLine(" Depends { name: " + ModUtils.toJSLiteral(realDepName)
+ + "; version: " + ModUtils.toJSLiteral(dep.version) + "}");
+ });
+
+ writeLine(" readonly property stringList hostBinDirs: (" + ModUtils.toJSLiteral(moduleInfo.build_bindirs) + ")");
+ // target bindirs
+ writeLine(" readonly property stringList binDirs: (" + ModUtils.toJSLiteral(cppInfo.bindirs) + ")");
+
+ // TODO: there's a weird issue with system include dirs with xcode-less clang - incorrect include order?
+ writeCppProperty("includePaths", cppInfo.includedirs);
+ writeCppProperty("frameworkPaths", cppInfo.frameworkdirs);
+ writeCppProperty("frameworks", cppInfo.frameworks);
+ writeCppProperty("defines", cppInfo.defines);
+ writeCppProperty("cFlags", cppInfo.cflags);
+ writeCppProperty("cxxFlags", cppInfo.cxxflags);
+ writeCppProperty("linkerFlags", (cppInfo.sharedlinkflags || []).concat(cppInfo.exelinkflags || []));
+
+ writeProperty("resources", cppInfo.resdirs);
+
+ const isForImport = targetOS.includes("windows")
+ const libraryTypes = getLibraryTypes(moduleInfo.options);
+ libraryTypes.forEach(function(libraryType){
+ const cppInfoLibs = cppInfo.libs === null ? [] : cppInfo.libs;
+ const libs = findLibs(cppInfoLibs, cppInfo.libdirs, libraryType, targetOS, isForImport)
+ .concat(cppInfo.system_libs === null ? [] : cppInfo.system_libs);
+ const property = libraryType === "shared" ? "dynamicLibraries" : "staticLibraries";
+ writeCppProperty(property, libs);
+ });
+
+ writeLine("}");
+
+ var moduleFile = new TextFile(outputFilePath, TextFile.WriteOnly);
+ moduleFile.write(moduleContent);
+ moduleFile.close();
+
+ return "";
+}
diff --git a/share/qbs/module-providers/conan.qbs b/share/qbs/module-providers/conan.qbs
new file mode 100644
index 000000000..6391eeb65
--- /dev/null
+++ b/share/qbs/module-providers/conan.qbs
@@ -0,0 +1,12 @@
+import "conan.js" as ConanHelper
+
+ModuleProvider {
+ /* input */
+ property path installDirectory
+
+ isEager: false
+
+ relativeSearchPaths: {
+ return ConanHelper.configure(installDirectory, moduleName, outputBaseDir);
+ }
+}
diff --git a/share/qbs/module-providers/qbspkgconfig.qbs b/share/qbs/module-providers/qbspkgconfig.qbs
new file mode 100644
index 000000000..885a6da7a
--- /dev/null
+++ b/share/qbs/module-providers/qbspkgconfig.qbs
@@ -0,0 +1,226 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import qbs.Environment
+import qbs.File
+import qbs.FileInfo
+import qbs.Host
+import qbs.ModUtils
+import qbs.PkgConfig
+import qbs.ProviderUtils
+import qbs.Probes
+import qbs.Process
+import qbs.TextFile
+
+import "Qt/setup-qt.js" as SetupQt
+
+ModuleProvider {
+ property stringList executableNames: ["pkgconf", "pkg-config"]
+ property string executableFilePath: pkgConfigProbe.filePath
+ property stringList extraPaths
+ property stringList libDirs
+ property bool staticMode: false
+ property bool definePrefix: Host.os().includes("windows")
+
+ // We take the sysroot default from qbs.sysroot, except for Xcode toolchains, where
+ // the sysroot points into the Xcode installation and does not contain .pc files.
+ property path sysroot: qbs.toolchain && qbs.toolchain.includes("xcode")
+ ? undefined : qbs.sysroot
+
+ Probes.BinaryProbe {
+ id: pkgConfigProbe
+ condition: !executableFilePath
+ names: executableNames
+ }
+
+ Probes.QbsPkgConfigProbe {
+ id: theProbe
+ _executableFilePath: executableFilePath
+ _extraPaths: extraPaths
+ _sysroot: sysroot
+ _libDirs: libDirs
+ _staticMode: staticMode
+ _definePrefix: definePrefix
+ }
+
+ Probes.QmakeProbe {
+ id: qmakeProbe
+ condition: moduleName.startsWith("Qt") && theProbe.qmakePaths
+ qmakePaths: theProbe.qmakePaths
+ }
+
+ isEager: false
+
+ relativeSearchPaths: {
+ function getModuleInfo(pkg, staticMode) {
+ var result = {};
+
+ var mapper = function(flag) { return flag.value; }
+ var typeFilter = function(type) {
+ return function(flag) { return flag.type === type; }
+ }
+
+ function getLibsInfo(libs) {
+ var result = {};
+ result.dynamicLibraries = libs.filter(typeFilter(PkgConfig.LibraryName)).map(mapper);
+ result.staticLibraries =
+ libs.filter(typeFilter(PkgConfig.StaticLibraryName)).map(mapper);
+ result.libraryPaths = libs.filter(typeFilter(PkgConfig.LibraryPath)).map(mapper);
+ result.frameworks = libs.filter(typeFilter(PkgConfig.Framework)).map(mapper);
+ result.frameworkPaths =
+ libs.filter(typeFilter(PkgConfig.FrameworkPath)).map(mapper);
+ result.driverLinkerFlags =
+ libs.filter(typeFilter(PkgConfig.LinkerFlag)).map(mapper);
+ return result;
+ }
+
+ result.version = pkg.version;
+ result.includePaths = pkg.cflags.filter(typeFilter(PkgConfig.IncludePath)).map(mapper);
+ result.systemIncludePaths =
+ pkg.cflags.filter(typeFilter(PkgConfig.SystemIncludePath)).map(mapper);
+ result.defines = pkg.cflags.filter(typeFilter(PkgConfig.Define)).map(mapper);
+ result.commonCompilerFlags =
+ pkg.cflags.filter(typeFilter(PkgConfig.CompilerFlag)).map(mapper);
+
+ var allLibs = pkg.libs;
+ if (staticMode)
+ allLibs = allLibs.concat(pkg.libsPrivate);
+ var libsInfo = getLibsInfo(allLibs);
+ for (var key in libsInfo) {
+ result[key] = libsInfo[key];
+ }
+
+ return result;
+ }
+
+ function getModuleDependencies(pkg, staticMode) {
+ var mapper = function(p) {
+ var result = {};
+ for (var key in p)
+ result[key] = p[key];
+ result.name = ProviderUtils.pkgConfigToModuleName(result.name);
+ return result;
+ }
+ var result = pkg.requires.map(mapper);
+ if (staticMode)
+ result = result.concat(pkg.requiresPrivate.map(mapper));
+ return result;
+ }
+
+ console.debug("Running pkgconfig provider for " + moduleName + ".");
+
+ var outputDir = FileInfo.joinPaths(outputBaseDir, "modules");
+ File.makePath(outputDir);
+
+ var moduleMapping = {
+ "protobuf": "protobuflib"
+ }
+ var reverseMapping = {}
+ for (var key in moduleMapping)
+ reverseMapping[moduleMapping[key]] = key
+
+ if (moduleName.startsWith("Qt")) {
+ function setupQt(packageName, qtInfos) {
+ if (qtInfos === undefined || qtInfos.length === 0)
+ return [];
+ var qtProviderDir = FileInfo.joinPaths(path, "Qt");
+ return SetupQt.doSetup(packageName, qtInfos, outputBaseDir, qtProviderDir);
+ }
+
+ if (!sysroot) {
+ return setupQt(moduleName, qmakeProbe.qtInfos);
+ }
+ return [];
+ }
+
+ var pkg;
+ pkg = theProbe.packages[reverseMapping[moduleName]];
+ if (pkg === undefined)
+ pkg = theProbe.packagesByModuleName[moduleName];
+ if (pkg === undefined)
+ return [];
+
+ if (pkg.isBroken) {
+ console.warn("Failed to load " + moduleName + " as it's pkg-config package is broken");
+ return [];
+ }
+ var moduleInfo = getModuleInfo(pkg, staticMode);
+ var deps = getModuleDependencies(pkg, staticMode);
+
+ var moduleDir = FileInfo.joinPaths(outputDir, moduleName);
+ File.makePath(moduleDir);
+ var module =
+ new TextFile(FileInfo.joinPaths(moduleDir, "module.qbs"), TextFile.WriteOnly);
+ module.writeLine("Module {");
+ module.writeLine(" version: " + ModUtils.toJSLiteral(moduleInfo.version));
+ module.writeLine(" Depends { name: 'cpp' }");
+ deps.forEach(function(dep) {
+ var depName = ProviderUtils.pkgConfigToModuleName(
+ moduleMapping[dep.name] ? moduleMapping[dep.name] : dep.name);
+ module.write(" Depends { name: '" + depName + "'");
+ for (var k in dep) {
+ if (k === "name")
+ continue;
+ module.write("; " + k + ": " + ModUtils.toJSLiteral(dep[k]));
+ }
+ module.writeLine(" }");
+ })
+ function writeProperty(propertyName) {
+ var value = moduleInfo[propertyName];
+ if (value.length !== 0) { // skip empty props for simplicity of the module file
+ module.writeLine(
+ " cpp." + propertyName + ":" + ModUtils.toJSLiteral(value));
+ }
+ }
+ writeProperty("includePaths");
+ writeProperty("systemIncludePaths");
+ writeProperty("defines");
+ writeProperty("commonCompilerFlags");
+ writeProperty("dynamicLibraries");
+ writeProperty("staticLibraries");
+ writeProperty("libraryPaths");
+ writeProperty("frameworks");
+ writeProperty("frameworkPaths");
+ writeProperty("driverLinkerFlags");
+ module.writeLine("}");
+ module.close();
+
+ return "";
+ }
+}
diff --git a/share/qbs/modules/Android/ndk/ndk.qbs b/share/qbs/modules/Android/ndk/ndk.qbs
index 3b104558c..3b223e4fb 100644
--- a/share/qbs/modules/Android/ndk/ndk.qbs
+++ b/share/qbs/modules/Android/ndk/ndk.qbs
@@ -48,8 +48,22 @@ Module {
PropertyOptions {
name: "abi"
description: "Supported Android ABIs"
- allowedValues: ["arm64-v8a", "armeabi", "armeabi-v7a", "x86", "x86_64"]
+ allowedValues: ["arm64-v8a", "armeabi-v7a", "x86", "x86_64"]
}
+ // From https://android.googlesource.com/platform/ndk/+/refs/heads/ndk-release-r21/docs/BuildSystemMaintainers.md
+ // Android Studio‘s LLDB debugger uses a binary’s build ID to locate debug information. To
+ // ensure that LLDB works with a binary, pass an option like -Wl,--build-id=sha1 to Clang when
+ // linking. Other --build-id= modes are OK, but avoid a plain --build-id argument when using
+ // LLD, because Android Studio‘s version of LLDB doesn’t recognize LLD's default 8-byte build
+ // ID. See Issue 885.
+
+ // Plain --build-id option is nevertheless implemented when buildId property is empty.
+
+ // Possible values (from man page of ld.lld — ELF linker from the LLVM project):
+ // one of fast, md5, sha1, tree, uuid, 0xhex-string, and none. tree is an alias for sha1.
+ // Build-IDs of type fast, md5, sha1, and tree are calculated from the object contents. fast is
+ // not intended to be cryptographically secure.
+ property string buildId: "sha1"
// See https://developer.android.com/ndk/guides/cpp-support.html
property string appStl: "c++_shared"
@@ -65,7 +79,6 @@ Module {
property string ndkSamplesDir: ndkProbe.samplesDir
property string platform: {
switch (abi) {
- case "armeabi":
case "armeabi-v7a":
// case "x86": // x86 has broken wstring support
return "android-19";
@@ -84,7 +97,7 @@ Module {
}
property stringList abis: {
- var list = ["armeabi", "armeabi-v7a"];
+ var list = ["armeabi-v7a"];
if (platformVersion >= 16)
list.push("x86");
if (platformVersion >= 21)
diff --git a/share/qbs/modules/Android/ndk/utils.js b/share/qbs/modules/Android/ndk/utils.js
index 739c205ae..ab312921e 100644
--- a/share/qbs/modules/Android/ndk/utils.js
+++ b/share/qbs/modules/Android/ndk/utils.js
@@ -77,12 +77,6 @@ function commonCompilerFlags(toolchain, buildVariant, ndk) {
}
}
- 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 (abi === "x86" || abi === "x86_64")
flags.push("-fPIC");
@@ -91,16 +85,22 @@ function commonCompilerFlags(toolchain, buildVariant, ndk) {
if (armMode)
flags.push("-m" + armMode);
- // TODO: Remove when https://github.com/android-ndk/ndk/issues/884 is fixed.
- flags.push("-fno-addrsig");
+ // https://github.com/android-ndk/ndk/issues/884 is fixed in r21
+ if (ndk.version < 21)
+ flags.push("-fno-addrsig");
+
+ // https://github.com/android/ndk/issues/635 is fixed in api 24
+ if (abi === "x86" && ndk.platformVersion < 24)
+ flags.push("-mstackrealign");
return flags;
}
-function commonLinkerFlags(abi) {
- return ["-z", "noexecstack", "-z", "relro", "-z", "now"];
+function commonLinkerFlags(ndk) {
+ var buildId = (ndk.buildId) ? "--build-id=" + ndk.buildId : "--build-id";
+ return ["-z", "noexecstack", "-z", "relro", "-z", "now", buildId, "--gc-sections"];
}
-function stlFilePath(path, ndk, suffix) {
- return path + ndk.appStl.slice(0, ndk.appStl.indexOf('_')) + suffix + "." + ndk.platformVersion;
+function stlFileName(prefix, ndk, suffix) {
+ return prefix + ndk.appStl.slice(0, ndk.appStl.indexOf('_')) + suffix;
}
diff --git a/share/qbs/modules/Android/sdk/sdk.qbs b/share/qbs/modules/Android/sdk/sdk.qbs
index f8a046c3a..440448dcf 100644
--- a/share/qbs/modules/Android/sdk/sdk.qbs
+++ b/share/qbs/modules/Android/sdk/sdk.qbs
@@ -50,6 +50,16 @@ Module {
environmentPaths: (ndkDir ? [ndkDir] : []).concat(base)
}
+ Probes.PathProbe {
+ id: bundletoolProbe
+ platformSearchPaths: [sdkDir]
+ names: ["bundletool-all"]
+ nameSuffixes: ["-0.11.0.jar", "-0.12.0.jar", "-0.13.0.jar", "-0.13.3.jar", "-0.13.4.jar",
+ "-0.14.0.jar", "-0.15.0.jar", "-1.0.0.jar", "-1.1.0.jar", "-1.2.0.jar", "-1.3.0.jar",
+ "-1.4.0.jar", "-1.5.0.jar", "-1.6.0.jar", "-1.6.1.jar", "-1.7.0.jar", "-1.7.1.jar",
+ "-1.8.0.jar"]
+ }
+
property path sdkDir: sdkProbe.path
property path ndkDir: ndkProbe.path
property path ndkSamplesDir: ndkProbe.samplesDir
@@ -59,6 +69,10 @@ Module {
property int buildToolsVersionMinor: buildToolsVersionParts[1]
property int buildToolsVersionPatch: buildToolsVersionParts[2]
property string platform: sdkProbe.platform
+ property string minimumVersion: "21"
+ property string targetVersion: platformVersion.toString()
+
+ property path bundletoolFilePath: bundletoolProbe.filePath
// Product-specific properties and files
property string packageName: {
@@ -72,50 +86,52 @@ Module {
property string apkBaseName: packageName
property bool automaticSources: true
property bool legacyLayout: false
- property string sourceSetDir: legacyLayout
+ property path sourceSetDir: legacyLayout
? product.sourceDirectory
: FileInfo.joinPaths(product.sourceDirectory, "src/main")
- property string resourcesDir: FileInfo.joinPaths(sourceSetDir, "res")
- property string assetsDir: FileInfo.joinPaths(sourceSetDir, "assets")
- property string sourcesDir: FileInfo.joinPaths(sourceSetDir, legacyLayout ? "src" : "java")
+ property path resourcesDir: FileInfo.joinPaths(sourceSetDir, "res")
+ property path assetsDir: FileInfo.joinPaths(sourceSetDir, "assets")
+ property path sourcesDir: FileInfo.joinPaths(sourceSetDir, legacyLayout ? "src" : "java")
property string manifestFile: defaultManifestFile
readonly property string defaultManifestFile: FileInfo.joinPaths(sourceSetDir,
"AndroidManifest.xml")
property bool _enableRules: !product.multiplexConfigurationId && !!packageName
+ property bool _bundledInAssets: true
+
Group {
name: "java sources"
- condition: Android.sdk.automaticSources
- prefix: Android.sdk.sourcesDir + '/'
+ condition: product.Android.sdk.automaticSources
+ prefix: FileInfo.resolvePath(product.sourceDirectory, product.Android.sdk.sourcesDir + '/')
files: "**/*.java"
}
Group {
name: "android resources"
- condition: Android.sdk.automaticSources
+ condition: product.Android.sdk.automaticSources
fileTags: ["android.resources"]
- prefix: Android.sdk.resourcesDir + '/'
+ prefix: FileInfo.resolvePath(product.sourceDirectory, product.Android.sdk.resourcesDir + '/')
files: "**/*"
}
Group {
name: "android assets"
- condition: Android.sdk.automaticSources
+ condition: product.Android.sdk.automaticSources
fileTags: ["android.assets"]
- prefix: Android.sdk.assetsDir + '/'
+ prefix: FileInfo.resolvePath(product.sourceDirectory, product.Android.sdk.assetsDir + '/')
files: "**/*"
}
Group {
name: "manifest"
- condition: Android.sdk.automaticSources
+ condition: product.Android.sdk.automaticSources
fileTags: ["android.manifest"]
- files: Android.sdk.manifestFile
- && Android.sdk.manifestFile !== Android.sdk.defaultManifestFile
- ? [Android.sdk.manifestFile]
- : (File.exists(Android.sdk.defaultManifestFile)
- ? [Android.sdk.defaultManifestFile] : [])
+ files: product.Android.sdk.manifestFile
+ && product.Android.sdk.manifestFile !== product.Android.sdk.defaultManifestFile
+ ? [product.Android.sdk.manifestFile]
+ : (File.exists(product.Android.sdk.defaultManifestFile)
+ ? [product.Android.sdk.defaultManifestFile] : [])
}
@@ -136,10 +152,30 @@ Module {
}
property path buildToolsDir: FileInfo.joinPaths(sdkDir, "build-tools", buildToolsVersion)
- property path aaptFilePath: FileInfo.joinPaths(buildToolsDir, "aapt")
+ property string aaptName: "aapt2"
+ PropertyOptions {
+ name: "aaptName"
+ allowedValues: ["aapt", "aapt2"]
+ }
+ property path aaptFilePath: FileInfo.joinPaths(buildToolsDir, aaptName)
+ readonly property bool _enableAapt2: aaptName === "aapt2"
+ property string packageType: "apk"
+ PropertyOptions {
+ name: "packageType"
+ allowedValues: ["apk", "aab"]
+ }
+ readonly property bool _generateAab: packageType == "aab"
+
property path apksignerFilePath: FileInfo.joinPaths(buildToolsDir, "apksigner")
property path aidlFilePath: FileInfo.joinPaths(buildToolsDir, "aidl")
property path dxFilePath: FileInfo.joinPaths(buildToolsDir, "dx")
+ property path d8FilePath: FileInfo.joinPaths(buildToolsDir, "d8")
+ property string dexCompilerName: "d8"
+ PropertyOptions {
+ name: "dexCompilerName"
+ allowedValues: ["dx", "d8"]
+ }
+ readonly property bool _useD8: dexCompilerName === "d8"
property path zipalignFilePath: FileInfo.joinPaths(buildToolsDir, "zipalign")
property path androidJarFilePath: FileInfo.joinPaths(sdkDir, "platforms", platform,
"android.jar")
@@ -148,21 +184,21 @@ Module {
property path generatedJavaFilesBaseDir: FileInfo.joinPaths(product.buildDirectory, "gen")
property path generatedJavaFilesDir: FileInfo.joinPaths(generatedJavaFilesBaseDir,
(packageName || "").split('.').join('/'))
- property string apkContentsDir: FileInfo.joinPaths(product.buildDirectory, "bin")
- property string debugKeyStorePath: FileInfo.joinPaths(
- Environment.getEnv(qbs.hostOS.contains("windows")
- ? "USERPROFILE" : "HOME"),
- ".android", "debug.keystore")
- property bool useApksigner: buildToolsVersion && Utilities.versionCompare(
- buildToolsVersion, "24.0.3") >= 0
+ property path compiledResourcesDir: FileInfo.joinPaths(product.buildDirectory,
+ "compiled_resources")
+ property string packageContentsDir: FileInfo.joinPaths(product.buildDirectory, packageType)
property stringList aidlSearchPaths
Depends { name: "java"; condition: _enableRules }
+ Depends { name: "codesign"; condition: _enableRules }
Properties {
condition: _enableRules
java.languageVersion: platformJavaVersion
java.runtimeVersion: platformJavaVersion
java.bootClassPaths: androidJarFilePath
+ codesign.apksignerFilePath: apksignerFilePath
+ codesign._packageName: apkBaseName + (_generateAab ? ".aab" : ".apk")
+ codesign.useApksigner: !_generateAab
}
validate: {
@@ -174,6 +210,19 @@ Module {
+ "ANDROID_HOME environment variable to a valid "
+ "Android SDK location.");
}
+ if (!bundletoolFilePath && _generateAab) {
+ throw ModUtils.ModuleError("Could not find Android bundletool at the following "
+ + "location:\n\t" + Android.sdk.sdkDir
+ + "\nInstall the Android bundletool to the above location, "
+ + "or set the Android.sdk.bundletoolFilePath property.\n"
+ + "Android bundletool can be downloaded from "
+ + "https://github.com/google/bundletool");
+ }
+ if (Utilities.versionCompare(buildToolsVersion, "24.0.3") < 0) {
+ throw ModUtils.ModuleError("Version of Android SDK build tools too old. This version "
+ + "is " + buildToolsVersion + " and minimum version is "
+ + "24.0.3. Please update the Android SDK.")
+ }
}
FileTagger {
@@ -186,36 +235,6 @@ Module {
fileTags: ["android.aidl"]
}
- FileTagger {
- patterns: ["*.keystore"]
- fileTags: ["android.keystore"]
- }
-
- // Typically there is a debug keystore in ~/.android/debug.keystore which gets created
- // by the native build tools the first time a build is done. However, we don't want to create it
- // ourselves, because writing to a location outside the qbs build directory is both polluting
- // and has the potential for race conditions. So we'll instruct the user what to do.
- Group {
- name: "Android debug keystore"
- files: {
- if (!File.exists(Android.sdk.debugKeyStorePath)) {
- throw ModUtils.ModuleError("Could not find an Android debug keystore at " +
- Android.sdk.debugKeyStorePath + ". " +
- "If you are developing for Android on this machine for the first time and " +
- "have never built an application using the native Gradle / Android Studio " +
- "tooling, this is normal. You must create the debug keystore now using the " +
- "following command, in order to continue:\n\n" +
- SdkUtils.createDebugKeyStoreCommandString(java.keytoolFilePath,
- Android.sdk.debugKeyStorePath) +
- "\n\n" +
- "See the following URL for more information: " +
- "https://developer.android.com/studio/publish/app-signing.html#debug-mode");
- }
- return [Android.sdk.debugKeyStorePath];
- }
- fileTags: ["android.keystore"]
- }
-
Parameter {
property bool embedJar: true
}
@@ -236,15 +255,15 @@ Module {
for (var i = 0; i < (aidlSearchPaths ? aidlSearchPaths.length : 0); ++i)
args.push("-I" + aidlSearchPaths[i]);
args.push(input.filePath, output.filePath);
- cmd = new Command(aidl, args);
- cmd.description = "Processing " + input.fileName;
+ var cmd = new Command(aidl, args);
+ cmd.description = "processing " + input.fileName;
return [cmd];
}
}
property bool customManifestProcessing: false
Group {
- condition: !Android.sdk.customManifestProcessing
+ condition: !product.Android.sdk.customManifestProcessing
fileTagsFilter: "android.manifest_processed"
fileTags: "android.manifest_final"
}
@@ -257,7 +276,7 @@ Module {
}
prepare: {
var cmd = new JavaScriptCommand();
- cmd.description = "Ensuring correct package name in Android manifest file";
+ cmd.description = "ensuring correct package name in Android manifest file";
cmd.sourceCode = function() {
var manifestData = new Xml.DomDocument();
manifestData.load(input.filePath);
@@ -277,6 +296,44 @@ Module {
rootElem.setAttribute("android:versionCode", product.Android.sdk.versionCode);
if (product.Android.sdk.versionName !== undefined)
rootElem.setAttribute("android:versionName", product.Android.sdk.versionName);
+
+ if (product.Android.sdk._bundledInAssets) {
+ // Remove <meta-data android:name="android.app.bundled_in_assets_resource_id"
+ // android:resource="@array/bundled_in_assets"/>
+ // custom AndroidManifest.xml because assets are in rcc files for qt >= 5.14
+ var appElem = rootElem.firstChild("application");
+ if (!appElem || !appElem.isElement() || appElem.tagName() != "application")
+ throw "No application tag found in '" + input.filePath + "'.";
+ var activityElem = appElem.firstChild("activity");
+ if (!activityElem || !activityElem.isElement() ||
+ activityElem.tagName() != "activity")
+ throw "No activity tag found in '" + input.filePath + "'.";
+ var metaDataElem = activityElem.firstChild("meta-data");
+ while (metaDataElem && metaDataElem.isElement()) {
+ if (SdkUtils.elementHasBundledAttributes(metaDataElem)) {
+ var elemToRemove = metaDataElem;
+ metaDataElem = metaDataElem.nextSibling("meta-data");
+ activityElem.removeChild(elemToRemove);
+ } else {
+ metaDataElem = metaDataElem.nextSibling("meta-data");
+ }
+ }
+ }
+
+ var usedSdkElem = rootElem.firstChild("uses-sdk");
+ if (!usedSdkElem || !usedSdkElem.isElement()) {
+ usedSdkElem = manifestData.createElement("uses-sdk");
+ rootElem.appendChild(usedSdkElem);
+ } else {
+ if (!usedSdkElem.isElement())
+ throw "Tag uses-sdk is not an element in '" + input.filePath + "'.";
+ }
+ usedSdkElem.setAttribute("android:minSdkVersion",
+ product.Android.sdk.minimumVersion);
+ usedSdkElem.setAttribute("android:targetSdkVersion",
+ product.Android.sdk.targetVersion);
+
+ rootElem.appendChild(usedSdkElem);
manifestData.save(output.filePath, 4);
}
return cmd;
@@ -284,7 +341,7 @@ Module {
}
Rule {
- condition: _enableRules
+ condition: _enableRules && !_enableAapt2
multiplex: true
inputs: ["android.resources", "android.assets", "android.manifest_final"]
@@ -307,6 +364,52 @@ Module {
}
Rule {
+ condition: _enableRules && _enableAapt2
+ inputs: ["android.resources"]
+ outputArtifacts: {
+ var outputs = [];
+ var resources = inputs["android.resources"];
+ for (var i = 0; i < resources.length; ++i) {
+ var filePath = resources[i].filePath;
+ var resourceFileName = SdkUtils.generateAapt2ResourceFileName(filePath);
+ var compiledName = FileInfo.joinPaths(product.Android.sdk.compiledResourcesDir,
+ resourceFileName);
+ outputs.push({filePath: compiledName, fileTags: "android.resources_compiled"});
+ }
+ return outputs;
+ }
+ outputFileTags: ["android.resources_compiled"]
+
+ prepare: SdkUtils.prepareAapt2CompileResource.apply(SdkUtils, arguments)
+ }
+
+ Rule {
+ condition: _enableRules && _enableAapt2
+ multiplex: true
+ inputs: ["android.resources_compiled", "android.assets", "android.manifest_final"]
+ outputFileTags: ["java.java", "android.apk_resources"]
+ outputArtifacts: {
+ var artifacts = [];
+ artifacts.push({
+ filePath: product.Android.sdk.apkBaseName + (product.Android.sdk._generateAab ?
+ ".apk_aab" : ".apk_apk"),
+ fileTags: ["android.apk_resources"]
+ });
+ var resources = inputs["android.resources_compiled"];
+ if (resources && resources.length) {
+ artifacts.push({
+ filePath: FileInfo.joinPaths(product.Android.sdk.generatedJavaFilesDir,
+ "R.java"),
+ fileTags: ["java.java"]
+ });
+ }
+
+ return artifacts;
+ }
+ prepare: SdkUtils.prepareAapt2Link.apply(SdkUtils, arguments)
+ }
+
+ Rule {
condition: _enableRules
multiplex: true
@@ -318,7 +421,7 @@ Module {
prepare: {
var cmd = new JavaScriptCommand();
- cmd.description = "Generating BuildConfig.java";
+ cmd.description = "generating BuildConfig.java";
cmd.sourceCode = function() {
var debugValue = product.qbs.buildVariant === "debug" ? "true" : "false";
var ofile = new TextFile(output.filePath, TextFile.WriteOnly);
@@ -336,9 +439,12 @@ Module {
condition: _enableRules
multiplex: true
inputs: ["java.class"]
- inputsFromDependencies: ["java.jar"]
+ inputsFromDependencies: ["java.jar", "bundled_jar"]
Artifact {
- filePath: FileInfo.joinPaths(product.Android.sdk.apkContentsDir, "classes.dex")
+ filePath: product.Android.sdk._generateAab ?
+ FileInfo.joinPaths(product.Android.sdk.packageContentsDir, "dex",
+ "classes.dex") :
+ FileInfo.joinPaths(product.Android.sdk.packageContentsDir, "classes.dex")
fileTags: ["android.dex"]
}
prepare: SdkUtils.prepareDex.apply(SdkUtils, arguments)
@@ -350,8 +456,10 @@ Module {
inputsFromDependencies: inputTags
inputs: product.aggregate ? [] : inputTags
Artifact {
- filePath: FileInfo.joinPaths(product.Android.sdk.apkContentsDir, "lib",
- input.Android.ndk.abi, input.fileName)
+ filePath: FileInfo.joinPaths(product.Android.sdk.packageContentsDir, "lib",
+ input.Android.ndk.abi, product.Android.sdk._archInName ?
+ input.baseName + "_" + input.Android.ndk.abi + ".so" :
+ input.fileName)
fileTags: "android.nativelibrary_deployed"
}
prepare: {
@@ -365,46 +473,14 @@ Module {
Rule {
condition: _enableRules
multiplex: true
- property stringList inputTags: "android.gdbserver"
- inputsFromDependencies: inputTags
- inputs: product.aggregate ? [] : inputTags
- outputFileTags: "android.gdbserver_deployed"
- outputArtifacts: {
- var deploymentData = SdkUtils.gdbserverOrStlDeploymentData(product, inputs,
- "gdbserver");
- var outputs = [];
- for (i = 0; i < deploymentData.outputFilePaths.length; ++i) {
- outputs.push({filePath: deploymentData.outputFilePaths[i],
- fileTags: "android.gdbserver_deployed"});
- }
- return outputs;
- }
- prepare: {
- var cmd = new JavaScriptCommand;
- cmd.description = "deploying gdbserver binaries";
- cmd.sourceCode = function() {
- var deploymentData = SdkUtils.gdbserverOrStlDeploymentData(product, inputs,
- "gdbserver");
- for (var i = 0; i < deploymentData.uniqueInputs.length; ++i) {
- File.copy(deploymentData.uniqueInputs[i].filePath,
- deploymentData.outputFilePaths[i]);
- }
- };
- return cmd;
- }
- }
-
- Rule {
- condition: _enableRules
- multiplex: true
property stringList inputTags: "android.stl"
inputsFromDependencies: inputTags
inputs: product.aggregate ? [] : inputTags
outputFileTags: "android.stl_deployed"
outputArtifacts: {
- var deploymentData = SdkUtils.gdbserverOrStlDeploymentData(product, inputs, "stl");
+ var deploymentData = SdkUtils.stlDeploymentData(product, inputs, "stl");
var outputs = [];
- for (i = 0; i < deploymentData.outputFilePaths.length; ++i) {
+ for (var i = 0; i < deploymentData.outputFilePaths.length; ++i) {
outputs.push({filePath: deploymentData.outputFilePaths[i],
fileTags: "android.stl_deployed"});
}
@@ -412,10 +488,10 @@ Module {
}
prepare: {
var cmds = [];
- var deploymentData = SdkUtils.gdbserverOrStlDeploymentData(product, inputs);
+ var deploymentData = SdkUtils.stlDeploymentData(product, inputs);
for (var i = 0; i < deploymentData.uniqueInputs.length; ++i) {
var input = deploymentData.uniqueInputs[i];
- var stripArgs = ["--strip-unneeded", "-o", deploymentData.outputFilePaths[i],
+ var stripArgs = ["--strip-all", "-o", deploymentData.outputFilePaths[i],
input.filePath];
var cmd = new Command(input.cpp.stripPath, stripArgs);
cmd.description = "deploying " + input.fileName;
@@ -426,17 +502,47 @@ Module {
}
Rule {
- condition: _enableRules
+ condition: _enableRules && !_enableAapt2 && !_generateAab
multiplex: true
inputs: [
"android.resources", "android.assets", "android.manifest_final",
- "android.dex", "android.gdbserver_deployed", "android.stl_deployed",
- "android.nativelibrary_deployed", "android.keystore"
+ "android.dex", "android.stl_deployed",
+ "android.nativelibrary_deployed"
]
Artifact {
- filePath: product.Android.sdk.apkBaseName + ".apk"
- fileTags: "android.apk"
+ filePath: product.Android.sdk.apkBaseName + ".apk_unsigned"
+ fileTags: "android.package_unsigned"
}
prepare: SdkUtils.prepareAaptPackage.apply(SdkUtils, arguments)
}
+
+ Rule {
+ condition: _enableRules && _enableAapt2 && !_generateAab
+ multiplex: true
+ inputs: [
+ "android.apk_resources", "android.manifest_final",
+ "android.dex", "android.stl_deployed",
+ "android.nativelibrary_deployed"
+ ]
+ Artifact {
+ filePath: product.Android.sdk.apkBaseName + ".apk_unsigned"
+ fileTags: "android.package_unsigned"
+ }
+ prepare: SdkUtils.prepareApkPackage.apply(SdkUtils, arguments)
+ }
+
+ Rule {
+ condition: _enableRules && _enableAapt2 && _generateAab
+ multiplex: true
+ inputs: [
+ "android.apk_resources", "android.manifest_final",
+ "android.dex", "android.stl_deployed",
+ "android.nativelibrary_deployed"
+ ]
+ Artifact {
+ filePath: product.Android.sdk.apkBaseName + ".aab_unsigned"
+ fileTags: "android.package_unsigned"
+ }
+ prepare: SdkUtils.prepareBundletoolPackage.apply(SdkUtils, arguments)
+ }
}
diff --git a/share/qbs/modules/Android/sdk/utils.js b/share/qbs/modules/Android/sdk/utils.js
index 3af179df2..232ee5a30 100644
--- a/share/qbs/modules/Android/sdk/utils.js
+++ b/share/qbs/modules/Android/sdk/utils.js
@@ -30,9 +30,11 @@
var File = require("qbs.File");
var FileInfo = require("qbs.FileInfo");
+var ModUtils = require("qbs.ModUtils");
var Process = require("qbs.Process");
var TextFile = require("qbs.TextFile");
var Utilities = require("qbs.Utilities");
+var Xml = require("qbs.Xml");
function availableBuildToolsVersions(sdkDir) {
var re = /^([0-9]+)\.([0-9]+)\.([0-9]+)$/;
@@ -55,8 +57,21 @@ function availableBuildToolsVersions(sdkDir) {
}
function prepareDex(project, product, inputs, outputs, input, output, explicitlyDependsOn) {
- var dxFilePath = product.Android.sdk.dxFilePath;
- var args = ["--dex", "--output", output.filePath, product.java.classFilesDir];
+ var dexCompilerFilePath = product.Android.sdk._useD8 ? product.Android.sdk.d8FilePath
+ : product.Android.sdk.dxFilePath;
+ var args = ["--output", FileInfo.path(output.filePath)];
+
+ if (product.Android.sdk._useD8) {
+ args.push("--no-desugaring", "--release");
+ var classes = inputs["java.class"];
+ if (classes) {
+ args = args.concat(classes.map(function(javaClass) {
+ return FileInfo.relativePath(product.java.classFilesDir, javaClass.filePath) }));
+ }
+ } else {
+ args.unshift("--dex");
+ args.push(product.java.classFilesDir);
+ }
var jarFiles = [];
function traverseJarDeps(dep) {
@@ -69,17 +84,58 @@ function prepareDex(project, product, inputs, outputs, input, output, explicitly
return;
dep.artifacts["java.jar"].forEach(function(artifact) {
- if (!jarFiles.contains(artifact.filePath))
+ if (!jarFiles.includes(artifact.filePath))
jarFiles.push(artifact.filePath);
});
dep.dependencies.forEach(traverseJarDeps);
}
product.dependencies.forEach(traverseJarDeps);
+ if (typeof product.artifacts["java.jar"] !== "undefined") {
+ product.artifacts["java.jar"].forEach(function(artifact) {
+ if (!jarFiles.includes(artifact.filePath))
+ jarFiles.push(artifact.filePath);
+ });
+ }
+
args = args.concat(jarFiles);
- var cmd = new Command(dxFilePath, args);
- cmd.description = "Creating " + output.fileName;
+ var cmd;
+ if (product.Android.sdk._useD8) {
+ cmd = new JavaScriptCommand();
+ cmd.args = args;
+ cmd.dexCompilerFilePath = dexCompilerFilePath;
+ cmd.description = "creating " + output.fileName;
+ cmd.workingDirectory = product.java.classFilesDir;
+ cmd.extendedDescription = dexCompilerFilePath + " " + args.join(' ');
+ cmd.highlight = "compiler";
+ cmd.sourceCode = function() {
+ // androiddeployqt copied jar files in product.java.classFilesDir
+ // but the rule only tags one jar file ("QtAndroid.jar"/"Qt6Android.jar")
+ // So to pass all files to d8, Qbs needs to read the directory
+ var bundledJarFilesDir = product.java.classFilesDir;
+ var bundledJarFiles = File.directoryEntries(bundledJarFilesDir, File.Files
+ | File.NoDotAndDotDot);
+ args = args.concat(bundledJarFiles.map(function(jarFile) {
+ return FileInfo.joinPaths(bundledJarFilesDir, jarFile) }));
+ var process = new Process();
+ var exitCode;
+ process.setWorkingDirectory(workingDirectory);
+ process.exec(dexCompilerFilePath, args, true);
+ try {
+ process.exec(dexCompilerFilePath, args, true);
+ } catch (e) {
+ throw new Error("Error while running dex compiler command: '"
+ + Process.shellQuote(dexCompilerFilePath, args) + "': " + e.toString());
+ } finally {
+ process.close();
+ }
+ }
+ } else {
+ cmd = new Command(dexCompilerFilePath, args);
+ cmd.description = "creating " + output.fileName;
+ cmd.workingDirectory = product.java.classFilesDir;
+ }
return [cmd];
}
@@ -98,7 +154,7 @@ function findParentDir(filePath, parentDirName)
function commonAaptPackageArgs(project, product, inputs, outputs, input, output,
explicitlyDependsOn) {
var manifestFilePath = inputs["android.manifest_final"][0].filePath;
- var args = ["package", "-f",
+ var args = ["package", "--auto-add-overlay", "-f",
"-M", manifestFilePath,
"-I", product.Android.sdk.androidJarFilePath];
var resources = inputs["android.resources"];
@@ -110,7 +166,7 @@ function commonAaptPackageArgs(project, product, inputs, outputs, input, output,
throw "File '" + resources[i].filePath + "' is tagged as an Android resource, "
+ "but is not located under a directory called 'res'.";
}
- if (!resourceDirs.contains(resDir))
+ if (!resourceDirs.includes(resDir))
resourceDirs.push(resDir);
}
}
@@ -125,7 +181,7 @@ function commonAaptPackageArgs(project, product, inputs, outputs, input, output,
throw "File '" + assets[i].filePath + "' is tagged as an Android asset, "
+ "but is not located under a directory called 'assets'.";
}
- if (!assetDirs.contains(assetDir))
+ if (!assetDirs.includes(assetDir))
assetDirs.push(assetDir);
}
}
@@ -136,6 +192,97 @@ function commonAaptPackageArgs(project, product, inputs, outputs, input, output,
return args;
}
+// Rules: from https://developer.android.com/studio/command-line/aapt2
+// Input Output
+// XML resource files, such as Resource table with *.arsc.flat as its extension.
+// String and Style, which are
+// located in the res/values/
+// directory.
+
+// All other resource files. All files other than the files under res/values/ directory are
+// converted to binary XML files with *.flat extensions.
+// Additionally all PNG files are crunched by default and adopt
+// *.png.flat extensions.
+function generateAapt2ResourceFileName(filePath) {
+ var suffix = FileInfo.suffix(filePath);
+ if (suffix === "xml") {
+ var data = new Xml.DomDocument();
+ data.load(filePath);
+ var rootElem = data.documentElement();
+ if (rootElem && rootElem.isElement() && rootElem.tagName() === "resources")
+ // This is a valid XML resource file
+ suffix = "arsc";
+ // If the xml file is not a "resources" one then it's treated like any other resource file.
+ }
+ var dir = FileInfo.path(filePath);
+ var baseName = FileInfo.completeBaseName(filePath)
+ return FileInfo.fileName(dir) + "_" + baseName + "." + suffix + ".flat";
+}
+
+function prepareAapt2CompileResource(project, product, inputs, outputs, input, output,
+ explicitlyDependsOn) {
+ var cmds = [];
+ var resources = inputs["android.resources"];
+ var compilesResourcesDir = product.Android.sdk.compiledResourcesDir;
+ if (!File.makePath(compilesResourcesDir)) {
+ throw "Cannot create directory '" + FileInfo.toNativeSeparators(compilesResourcesDir) +
+ "'.";
+ }
+ var args = ["compile", FileInfo.toNativeSeparators(input.filePath),
+ "-o", FileInfo.toNativeSeparators(compilesResourcesDir)];
+ var cmd = new Command(product.Android.sdk.aaptFilePath, args);
+ var outputFileName = generateAapt2ResourceFileName(input.filePath);
+ cmd.description = "compiling resource " + input.fileName + " into " + outputFileName;
+ cmds.push(cmd);
+
+ return cmds;
+}
+
+function prepareAapt2Link(project, product, inputs, outputs, input, output, explicitlyDependsOn) {
+ var cmds = [];
+ var baseOutputFilePath = outputs["android.apk_resources"][0].filePath;
+ var manifestFilePath = inputs["android.manifest_final"][0].filePath;
+ var compilesResourcesDir = product.Android.sdk.compiledResourcesDir;
+ var compiledResources = inputs["android.resources_compiled"];
+
+ var args = ["link", "-o", baseOutputFilePath, "-I", product.Android.sdk.androidJarFilePath];
+ var i = 0;
+ if (compiledResources) {
+ for (i = 0; i < compiledResources.length; ++i)
+ args.push(compiledResources[i].filePath);
+ }
+ args.push("--no-auto-version");
+ args.push("--auto-add-overlay");
+ args.push("--manifest", manifestFilePath);
+ args.push("--java", product.Android.sdk.generatedJavaFilesBaseDir);
+
+ var assets = inputs["android.assets"];
+ var assetDirs = [];
+ if (assets) {
+ for (i = 0; i < assets.length; ++i) {
+ var assetDir = findParentDir(assets[i].filePath, "assets");
+ if (!assetDir) {
+ throw "File '" + assets[i].filePath + "' is tagged as an Android asset, "
+ + "but is not located under a directory called 'assets'.";
+ }
+ if (!assetDirs.includes(assetDir))
+ assetDirs.push(assetDir);
+ }
+ }
+ for (i = 0; i < assetDirs.length; ++i)
+ args.push("-A", assetDirs[i]);
+ if (product.qbs.buildVariant === "debug")
+ args.push("-v");
+ if (product.Android.sdk._generateAab)
+ args.push("--proto-format");
+ var cmd = new Command(product.Android.sdk.aaptFilePath, args);
+ cmd.description = "linking resources";
+ cmd.workingDirectory = product.buildDirectory;
+ cmds.push(cmd);
+
+ return cmds;
+}
+
function prepareAaptGenerate(project, product, inputs, outputs, input, output,
explicitlyDependsOn) {
var args = commonAaptPackageArgs.apply(this, arguments);
@@ -144,31 +291,20 @@ function prepareAaptGenerate(project, product, inputs, outputs, input, output,
if (resources && resources.length)
args.push("-J", ModUtils.moduleProperty(product, "generatedJavaFilesBaseDir"));
var cmd = new Command(product.Android.sdk.aaptFilePath, args);
- cmd.description = "Processing resources";
+ cmd.description = "processing resources";
return [cmd];
}
function prepareAaptPackage(project, product, inputs, outputs, input, output, explicitlyDependsOn) {
var cmds = [];
- var apkOutput = outputs["android.apk"][0];
+ var apkOutput = outputs["android.package_unsigned"][0];
var args = commonAaptPackageArgs.apply(this, arguments);
args.push("-F", apkOutput.filePath + ".unaligned");
- args.push(product.Android.sdk.apkContentsDir);
+ args.push(product.Android.sdk.packageContentsDir);
var cmd = new Command(product.Android.sdk.aaptFilePath, args);
- cmd.description = "Generating " + apkOutput.filePath;
+ cmd.description = "generating " + apkOutput.fileName;
cmds.push(cmd);
- if (!product.Android.sdk.useApksigner) {
- args = ["-sigalg", "SHA1withRSA", "-digestalg", "SHA1",
- "-keystore", inputs["android.keystore"][0].filePath,
- "-storepass", "android",
- apkOutput.filePath + ".unaligned",
- "androiddebugkey"];
- cmd = new Command(product.java.jarsignerFilePath, args);
- cmd.description = "Signing " + apkOutput.fileName;
- cmds.push(cmd);
- }
-
cmd = new Command(product.Android.sdk.zipalignFilePath,
["-f", "4", apkOutput.filePath + ".unaligned", apkOutput.filePath]);
cmd.silent = true;
@@ -179,46 +315,135 @@ function prepareAaptPackage(project, product, inputs, outputs, input, output, ex
cmd.unalignedApk = apkOutput.filePath + ".unaligned";
cmd.sourceCode = function() { File.remove(unalignedApk); };
cmds.push(cmd);
+ return cmds;
+}
+
+function prepareApkPackage(project, product, inputs, outputs, input, output, explicitlyDependsOn) {
+ var cmds = [];
+ var apkInputFilePath = inputs["android.apk_resources"][0].filePath;
+ var apkOutput = outputs["android.package_unsigned"][0];
+ var apkOutputFilePathUnaligned = apkOutput.filePath + ".unaligned";
+ var dexFilePath = inputs["android.dex"][0].filePath;
- if (product.Android.sdk.useApksigner) {
- // TODO: Implement full signing support, not just using the debug keystore
- args = ["sign",
- "--ks", inputs["android.keystore"][0].filePath,
- "--ks-pass", "pass:android",
- apkOutput.filePath];
- cmd = new Command(product.Android.sdk.apksignerFilePath, args);
- cmd.description = "Signing " + apkOutput.fileName;
- cmds.push(cmd);
+ var copyCmd = new JavaScriptCommand();
+ copyCmd.description = "copying apk";
+ copyCmd.source = apkInputFilePath;
+ copyCmd.target = apkOutputFilePathUnaligned;
+ copyCmd.sourceCode = function() {
+ File.copy(source, target);
}
+ cmds.push(copyCmd);
+
+ var jarArgs = ["-uvf", apkOutputFilePathUnaligned, "."];
+ var libPath = FileInfo.joinPaths(product.Android.sdk.packageContentsDir);
+ var jarCmd = new Command(product.java.jarFilePath, jarArgs);
+ jarCmd.description = "packaging files";
+ jarCmd.workingDirectory = libPath;
+ cmds.push(jarCmd);
+
+ cmd = new Command(product.Android.sdk.zipalignFilePath,
+ ["-f", "4", apkOutputFilePathUnaligned, apkOutput.filePath]);
+ cmd.silent = true;
+ cmds.push(cmd);
+ cmd = new JavaScriptCommand();
+ cmd.silent = true;
+ cmd.unalignedApk = apkOutputFilePathUnaligned;
+ cmd.sourceCode = function() { File.remove(unalignedApk); };
+ cmds.push(cmd);
return cmds;
}
-function createDebugKeyStoreCommandString(keytoolFilePath, keystoreFilePath) {
- var args = ["-genkey", "-keystore", keystoreFilePath, "-alias", "androiddebugkey",
- "-storepass", "android", "-keypass", "android", "-keyalg", "RSA",
- "-keysize", "2048", "-validity", "10000", "-dname",
- "CN=Android Debug,O=Android,C=US"];
- return Process.shellQuote(keytoolFilePath, args);
+function prepareBundletoolPackage(project, product, inputs, outputs, input, output,
+ explicitlyDependsOn) {
+ var cmds = [];
+ var baseModuleDir = product.Android.sdk.packageContentsDir;
+ var manifestDirName = FileInfo.joinPaths(baseModuleDir, "manifest");
+ var pkgBaseFileName = inputs["android.apk_resources"][0].filePath;
+
+ var jarResourcesArgs = ["xf", pkgBaseFileName];
+ var jarResourcesCmd = new Command(product.java.jarFilePath, jarResourcesArgs);
+ jarResourcesCmd.description = "extracting resources apk";
+ jarResourcesCmd.workingDirectory = baseModuleDir;
+ cmds.push(jarResourcesCmd);
+
+ var moveManifestCmd = new JavaScriptCommand();
+ moveManifestCmd.description = "moving manifest in manifest directory";
+ moveManifestCmd.path = manifestDirName;
+ moveManifestCmd.manifestFilePath = baseModuleDir + "/AndroidManifest.xml";
+ moveManifestCmd.sourceCode = function() {
+ if (!File.exists(path))
+ File.makePath(path);
+ if (File.exists(manifestFilePath))
+ File.move(manifestFilePath, path + "/AndroidManifest.xml");
+ }
+ cmds.push(moveManifestCmd);
+
+ var baseFilePath = FileInfo.joinPaths(product.buildDirectory, "base.zip");
+ var jarBaseArgs = ["cfM", baseFilePath, "."];
+ var jarBaseCmd = new Command(product.java.jarFilePath, jarBaseArgs);
+ jarBaseCmd.description = "compressing base module";
+ jarBaseCmd.workingDirectory = baseModuleDir;
+ cmds.push(jarBaseCmd);
+
+ var aabFilePath = outputs["android.package_unsigned"][0].filePath;
+ var removeCmd = new JavaScriptCommand();
+ removeCmd.description = "removing previous aab";
+ removeCmd.filePath = aabFilePath;
+ removeCmd.sourceCode = function() {
+ if (File.exists(filePath))
+ File.remove(filePath);
+ }
+ cmds.push(removeCmd);
+
+ var bundleConfigFilePath = FileInfo.joinPaths(product.buildDirectory, "BundleConfig.json");
+ var createBundleConfigCmd = new JavaScriptCommand();
+ createBundleConfigCmd.description = "create BundleConfig.json";
+ createBundleConfigCmd.filePath = bundleConfigFilePath;
+ createBundleConfigCmd.sourceCode = function() {
+ var bc = new TextFile(filePath, TextFile.WriteOnly);
+ bc.writeLine('{"optimizations": {');
+ bc.writeLine('"uncompress_native_libraries": {');
+ bc.writeLine('"enabled": false');
+ bc.writeLine('}}}');
+ }
+ cmds.push(createBundleConfigCmd);
+
+ var args = ["-jar", product.Android.sdk.bundletoolFilePath, "build-bundle"];
+ args.push("--modules=" + baseFilePath);
+ args.push("--output=" + aabFilePath);
+ args.push("--config=" + bundleConfigFilePath);
+ var cmd = new Command(product.java.interpreterFilePath, args);
+ cmd.description = "generating " + aabFilePath.fileName;
+ cmds.push(cmd);
+
+ return cmds;
}
-function gdbserverOrStlDeploymentData(product, inputs, type)
+function stlDeploymentData(product, inputs, type)
{
var data = { uniqueInputs: [], outputFilePaths: []};
var uniqueFilePaths = [];
- var theInputs = inputs[type === "gdbserver" ? "android.gdbserver" : "android.stl"];
+ var theInputs = inputs["android.stl"];
if (!theInputs)
return data;
for (var i = 0; i < theInputs.length; ++i) {
var currentInput = theInputs[i];
- if (uniqueFilePaths.contains(currentInput.filePath))
+ if (uniqueFilePaths.includes(currentInput.filePath))
continue;
uniqueFilePaths.push(currentInput.filePath);
data.uniqueInputs.push(currentInput);
- var outputFileName = type === "gdbserver" ? "libgdbserver.so" : currentInput.fileName;
- data.outputFilePaths.push(FileInfo.joinPaths(product.Android.sdk.apkContentsDir, "lib",
+ var outputFileName = currentInput.fileName;
+ data.outputFilePaths.push(FileInfo.joinPaths(product.Android.sdk.packageContentsDir, "lib",
currentInput.Android.ndk.abi,
outputFileName));
}
return data;
}
+
+function elementHasBundledAttributes(element)
+{
+ return element.hasAttribute("android:name") &&
+ (element.attribute("android:name") === "android.app.bundled_in_assets_resource_id") ||
+ (element.attribute("android:name") === "android.app.bundled_in_lib_resource_id");
+}
diff --git a/share/qbs/modules/Exporter/cmake/cmakeexporter.js b/share/qbs/modules/Exporter/cmake/cmakeexporter.js
new file mode 100644
index 000000000..093032f2e
--- /dev/null
+++ b/share/qbs/modules/Exporter/cmake/cmakeexporter.js
@@ -0,0 +1,239 @@
+/****************************************************************************
+**
+** Copyright (C) 2024 Raphaël Cotty <raphael.cotty@gmail.com>
+** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of the Qbs.
+**
+** 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.
+**
+****************************************************************************/
+
+var FileInfo = require("qbs.FileInfo");
+var ModUtils = require("qbs.ModUtils");
+var ExporterHelpers = require("../exporter.js");
+
+function tagListToString(tagList)
+{
+ return JSON.stringify(tagList);
+}
+
+function collectAutodetectedData(project, topLevelProduct, outputs)
+{
+ var packageName = topLevelProduct.Exporter.cmake.packageName;
+
+ var data = {};
+ data.packageName = packageName;
+ data.installPrefixDir = "_" + packageName.toUpperCase() + "_INSTALL_PREFIX";
+ data.packages = [];
+
+ function quote(value)
+ {
+ return "\"" + value + "\"";
+ }
+
+ function quoteAndPrefixify(propName)
+ {
+ function quoteAndPrefixifyHelper(value) {
+ var prefixToStrip =
+ ExporterHelpers.getPrefixToStrip(project, topLevelProduct, propName, value);
+ if (typeof value !== "string"
+ || !prefixToStrip
+ || (value.length > prefixToStrip.length
+ && value[prefixToStrip.length] !== '/')) {
+ return quote(value);
+ }
+ return quote("${" + data.installPrefixDir + "}" + value.slice(prefixToStrip.length));
+ }
+ return quoteAndPrefixifyHelper;
+ }
+
+ var installedOutputFilePath = ModUtils.artifactInstalledFilePath(
+ outputs["Exporter.cmake.configFile"][0]);
+ var installedOutputPathName = FileInfo.path(installedOutputFilePath);
+
+ var installRootPath = FileInfo.joinPaths(topLevelProduct.qbs.installRoot, topLevelProduct.qbs.installPrefix);
+ data.installPrefix = FileInfo.relativePath(installedOutputPathName, installRootPath);
+
+ var libArtifacts;
+ var libImportArtifacts;
+ var isProduct = !topLevelProduct.present;
+ var considerFramework = !isProduct || (topLevelProduct.type
+ && topLevelProduct.type.includes("bundle.content"))
+ && topLevelProduct.bundle
+ && topLevelProduct.bundle.isBundle
+ && topLevelProduct.qbs.targetOS.includes("darwin");
+ var considerDynamicLibs = !isProduct || (topLevelProduct.type
+ && topLevelProduct.type.includes("dynamiclibrary"));
+ var considerStaticLibs = !isProduct || (topLevelProduct.type
+ && topLevelProduct.type.includes("staticlibrary"));
+ if (considerFramework) {
+ libArtifacts = topLevelProduct.artifacts["bundle.symlink.executable"];
+ if (considerDynamicLibs)
+ data.type = "SHARED";
+ else if (considerStaticLibs)
+ data.type = "STATIC";
+ else
+ data.type = "INTERFACE";
+ } else if (considerDynamicLibs) {
+ libArtifacts = topLevelProduct.artifacts.dynamiclibrary;
+ libImportArtifacts = topLevelProduct.artifacts.dynamiclibrary_import;
+ data.type = "SHARED";
+ } else if (considerStaticLibs) {
+ libArtifacts = topLevelProduct.artifacts.staticlibrary;
+ data.type = "STATIC";
+ } else {
+ data.type = "INTERFACE";
+ }
+
+ for (var i = 0; i < (libArtifacts || []).length; ++i) {
+ var libArtifact = libArtifacts[i];
+ var libImportArtifact = (libImportArtifacts || [])[i];
+ if (libArtifact.qbs.install) {
+ var installPath = ModUtils.artifactInstalledFilePath(libArtifact);
+ data.importedLocation = quoteAndPrefixify("installRoot")(installPath);
+ data.soName = topLevelProduct.targetName;
+ if (libImportArtifact && libImportArtifact.qbs.install) {
+ installPath = ModUtils.artifactInstalledFilePath(libImportArtifact);
+ data.importedImplibLocation = quoteAndPrefixify("installRoot")(installPath);
+ }
+ break;
+ }
+ }
+ var cpp = topLevelProduct.exports.cpp;
+ if (cpp) {
+ data.libraryPaths = (cpp.libraryPaths || []).map(quoteAndPrefixify("cpp.libraryPaths"));
+
+ data.linkLibraries = [];
+ data.linkLibraries = data.linkLibraries.concat(cpp.dynamicLibraries || []);
+ data.linkLibraries = data.linkLibraries.concat(cpp.staticLibraries || []);
+ data.linkLibraries = data.linkLibraries.map(quoteAndPrefixify("cpp.dynamicLibraries"));
+
+ data.linkOptions = [];
+ data.linkOptions = data.linkOptions.concat(cpp.driverLinkerFlags || []);
+ if ((cpp.linkerFlags || []).length > 0) {
+ data.linkOptions =
+ data.linkOptions.concat("LINKER:" + (cpp.linkerFlags || []).join(","));
+ }
+ data.linkOptions = data.linkOptions.map(quote);
+
+ data.includeDirectories =
+ (cpp.includePaths || []).map(quoteAndPrefixify("cpp.includePaths"));
+ data.compileDefinitions = (cpp.defines || []).map(quote);
+
+ data.compileOptions = [];
+ data.compileOptions = data.compileOptions.concat(cpp.commonCompilerFlags || []);
+ data.compileOptions = data.compileOptions.concat(cpp.driverFlags || []);
+ data.compileOptions = data.compileOptions.concat(cpp.cxxFlags || []);
+ data.compileOptions = data.compileOptions.concat(cpp.cFlags || []);
+ data.compileOptions = data.compileOptions.map(quote);
+ }
+
+ function gatherDeps(dep) {
+ if (dep.name === "Exporter.cmake")
+ return;
+ var depHasExporter = dep.Exporter && dep.Exporter.cmake;
+ if (!depHasExporter)
+ return;
+ data.packages.push(dep.Exporter.cmake.packageName);
+ }
+
+ var exportedDeps = topLevelProduct.exports ? topLevelProduct.exports.dependencies : [];
+ exportedDeps.forEach(gatherDeps);
+
+ return data;
+}
+
+function writeConfigFile(project, product, outputs)
+{
+ var autoDetectedData = collectAutodetectedData(project, product, outputs);
+ var packageName = autoDetectedData.packageName;
+
+ function writeCommand(command, lines)
+ {
+ if ((lines || []).length === 0)
+ return;
+ cmakeConfigFile.writeLine(command + "(" + packageName + " INTERFACE");
+ for (i = 0; i < lines.length; i++) {
+ cmakeConfigFile.writeLine(" " + lines[i]);
+ }
+ cmakeConfigFile.writeLine(")");
+ }
+
+ var cmakeConfigFile = new TextFile(outputs["Exporter.cmake.configFile"][0].filePath,
+ TextFile.WriteOnly);
+ cmakeConfigFile.writeLine("# Generated by Qbs");
+
+ cmakeConfigFile.writeLine("cmake_minimum_required(VERSION 3.5)");
+
+ cmakeConfigFile.writeLine("if(TARGET " + packageName + ")");
+ cmakeConfigFile.writeLine(" return()");
+ cmakeConfigFile.writeLine("endif()");
+
+ cmakeConfigFile.writeLine("set(" + autoDetectedData.installPrefixDir +
+ " \"${CMAKE_CURRENT_LIST_DIR}/" +
+ autoDetectedData.installPrefix + "\")");
+
+ autoDetectedData.packages.forEach(function(packageName) {
+ cmakeConfigFile.writeLine("find_package(" + packageName + " REQUIRED SILENT)");
+ });
+ cmakeConfigFile.writeLine(
+ "add_library(" + packageName + " " + autoDetectedData.type + " IMPORTED)");
+ var configuration = (product.qbs.buildVariant) ?
+ product.qbs.buildVariant.toUpperCase() : "NONE";
+ cmakeConfigFile.writeLine("set_property(TARGET " + packageName +
+ " APPEND PROPERTY IMPORTED_CONFIGURATIONS " +
+ configuration + ")");
+
+ cmakeConfigFile.writeLine("set_target_properties(" + packageName + " PROPERTIES");
+ cmakeConfigFile.writeLine(" IMPORTED_LINK_INTERFACE_LANGUAGES_" + configuration +
+ " CXX");
+ if (autoDetectedData.type !== "INTERFACE") {
+ cmakeConfigFile.writeLine(" IMPORTED_LOCATION_" + configuration + " " +
+ autoDetectedData.importedLocation);
+ }
+ if (autoDetectedData.importedImplibLocation) {
+ cmakeConfigFile.writeLine(" IMPORTED_IMPLIB_" + configuration + " " +
+ autoDetectedData.importedImplibLocation);
+ }
+ cmakeConfigFile.writeLine(")");
+
+ writeCommand("target_link_directories", autoDetectedData.libraryPaths);
+ writeCommand("target_link_libraries",
+ autoDetectedData.linkLibraries.concat(autoDetectedData.packages));
+ writeCommand("target_link_options", autoDetectedData.linkOptions);
+ writeCommand("target_include_directories", autoDetectedData.includeDirectories);
+ writeCommand("target_compile_definitions", autoDetectedData.compileDefinitions);
+ writeCommand("target_compile_options", autoDetectedData.compileOptions);
+
+ cmakeConfigFile.close();
+}
+
+function writeVersionFile(product, outputs)
+{
+ var cmakeVersionFile = new TextFile(
+ outputs["Exporter.cmake.versionFile"][0].filePath, TextFile.WriteOnly);
+ cmakeVersionFile.writeLine("# Generated by Qbs");
+ cmakeVersionFile.writeLine("set(PACKAGE_VERSION \"" + product.version + "\")");
+ cmakeVersionFile.close();
+}
diff --git a/share/qbs/modules/Exporter/cmake/cmakeexporter.qbs b/share/qbs/modules/Exporter/cmake/cmakeexporter.qbs
new file mode 100644
index 000000000..a578e938b
--- /dev/null
+++ b/share/qbs/modules/Exporter/cmake/cmakeexporter.qbs
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2024 Raphaël Cotty <raphael.cotty@gmail.com>
+** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import qbs.File
+import qbs.FileInfo
+import qbs.ModUtils
+import qbs.TextFile
+
+import "cmakeexporter.js" as HelperFunctions
+
+Module {
+ property string configFileName: packageName + "Config.cmake"
+ property string versionFileName: packageName + "ConfigVersion.cmake"
+ property string packageName: product.targetName
+
+ additionalProductTypes: ["Exporter.cmake.package"]
+
+ Rule {
+ multiplex: true
+ requiresInputs: false
+
+ auxiliaryInputs: {
+ if (product.type.includes("staticlibrary"))
+ return ["staticlibrary"];
+ if (product.type.includes("dynamiclibrary"))
+ return ["dynamiclibrary"];
+ }
+
+ Artifact {
+ filePath: product.Exporter.cmake.configFileName
+ fileTags: ["Exporter.cmake.package", "Exporter.cmake.configFile"]
+ }
+ Artifact {
+ filePath: product.Exporter.cmake.versionFileName
+ fileTags: ["Exporter.cmake.package", "Exporter.cmake.versionFile"]
+ }
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ cmd.description = "generate cmake package files";
+ cmd.sourceCode = function() {
+ HelperFunctions.writeConfigFile(project, product, outputs);
+ HelperFunctions.writeVersionFile(product, outputs);
+ }
+ return [cmd];
+ }
+ }
+}
diff --git a/share/qbs/modules/Exporter/exporter.js b/share/qbs/modules/Exporter/exporter.js
new file mode 100644
index 000000000..65a632ac8
--- /dev/null
+++ b/share/qbs/modules/Exporter/exporter.js
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of the Qbs.
+**
+** 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.
+**
+****************************************************************************/
+
+function getPrefixToStrip(project, product, propName, value)
+{
+ function checkValuePrefix(forbiddenPrefix, prefixDescription)
+ {
+ if (value.startsWith(forbiddenPrefix)) {
+ throw "Value '" + value + "' for exported property '" + propName + "' in product '"
+ + product.name + "' points into " + prefixDescription + ".\n"
+ + "Did you forget to set the prefixMapping property in an Export item?";
+ }
+ }
+
+ // Catch user oversights: Paths that point into the project source or build directories
+ // make no sense in the module.
+ if (!value.startsWith(product.qbs.installRoot)) {
+ checkValuePrefix(project.buildDirectory, "project build directory");
+ checkValuePrefix(project.sourceDirectory, "project source directory");
+ }
+
+ // Adapt file paths pointing into the install dir, that is, make them relative to the
+ // module file for relocatability. We accept them with or without the install root.
+ // The latter form will typically be a result of applying the prefixMapping property,
+ // while the first one could be an untransformed path, for instance if the project
+ // file is written in such a way that include paths are picked up from the installed
+ // location rather than the source directory.
+ var result;
+ var fullInstallPrefix = FileInfo.joinPaths(product.qbs.installRoot, product.qbs.installPrefix);
+ if (fullInstallPrefix.length > 1 && value.startsWith(fullInstallPrefix)) {
+ result = fullInstallPrefix;
+ } else {
+ var installPrefix = FileInfo.joinPaths("/", product.qbs.installPrefix);
+ if (installPrefix.length > 1 && value.startsWith(installPrefix))
+ result = installPrefix;
+ }
+ return result;
+}
diff --git a/share/qbs/modules/Exporter/pkgconfig/pkgconfig.js b/share/qbs/modules/Exporter/pkgconfig/pkgconfig.js
index a3109d61d..50bba536c 100644
--- a/share/qbs/modules/Exporter/pkgconfig/pkgconfig.js
+++ b/share/qbs/modules/Exporter/pkgconfig/pkgconfig.js
@@ -33,7 +33,7 @@ var ModUtils = require("qbs.ModUtils");
function quote(value)
{
- if (value.contains(" ") || value.contains("'") || value.contains('"')) {
+ if (value.includes(" ") || value.includes("'") || value.includes('"')) {
return '"' + value.replace(/(["'\\])/g, "\\$1") + '"';
}
return value;
@@ -44,9 +44,9 @@ function writeEntry(product, file, key, propertyName, required, additionalValues
var value = product.Exporter.pkgconfig[propertyName];
if (additionalValues && additionalValues.length > 0)
value = (value || []).concat(additionalValues);
- var valueIsNotEmpty = value && (!Array.isArray(value) || value.length > 0);
+ var valueIsNotEmpty = value && (!(value instanceof Array) || value.length > 0);
if (valueIsNotEmpty) {
- if (Array.isArray(value))
+ if (value instanceof Array)
value = value.join(' ');
file.writeLine(key + ": " + value);
} else if (required) {
@@ -83,7 +83,7 @@ function collectAutodetectedData(topLevelProduct)
|| (value.length > installPrefix.length && value[installPrefix.length] !== '/')) {
return quotedValue;
}
- return quotedValue.replace(product.qbs.installPrefix, "${prefix}");
+ return quotedValue.replace(topLevelProduct.qbs.installPrefix, "${prefix}");
}
function transformedValue(product, moduleName, propertyName)
@@ -92,7 +92,7 @@ function collectAutodetectedData(topLevelProduct)
var value = transformFunc
? eval("(" + transformFunc + ")(product, moduleName, propertyName, originalValue)")
: originalValue;
- if (Array.isArray(value))
+ if (value instanceof Array)
value.forEach(function(v, i, a) { a[i] = quoteAndPrefixify(v); });
else if (value)
value = quoteAndPrefixify(value);
@@ -105,12 +105,12 @@ function collectAutodetectedData(topLevelProduct)
var libArtifacts;
var isProduct = !productOrModule.present;
var considerDynamicLibs = !isProduct || (productOrModule.type
- && productOrModule.type.contains("dynamiclibrary"));
+ && productOrModule.type.includes("dynamiclibrary"));
if (considerDynamicLibs) {
libArtifacts = productOrModule.artifacts.dynamiclibrary;
} else {
var considerStaticLibs = !isProduct || (productOrModule.type
- && productOrModule.type.contains("staticlibrary"));
+ && productOrModule.type.includes("staticlibrary"));
if (considerStaticLibs)
libArtifacts = productOrModule.artifacts.staticlibrary;
}
@@ -186,7 +186,7 @@ function collectAutodetectedData(topLevelProduct)
exportedDepNames.push(exportedDeps[i].name);
for (i = 0; i < (productOrModule.dependencies || []).length; ++i) {
var dep = productOrModule.dependencies[i];
- if (exportedDepNames.contains(dep.name))
+ if (exportedDepNames.includes(dep.name))
continue;
privateDeps.push(dep);
}
@@ -197,22 +197,22 @@ function collectAutodetectedData(topLevelProduct)
var depHasPkgConfig = dep.Exporter && dep.Exporter.pkgconfig;
if (depHasPkgConfig) {
var entry = FileInfo.completeBaseName(dep.Exporter.pkgconfig.fileName);
- if (excludedDeps.contains(entry))
+ if (excludedDeps.includes(entry))
return;
- if (isPrivateDep && !data.requiresPrivate.contains(entry)
- && !explicitRequiresPrivate.contains(entry)) {
+ if (isPrivateDep && !data.requiresPrivate.includes(entry)
+ && !explicitRequiresPrivate.includes(entry)) {
data.requiresPrivate.push(entry);
}
- if (!isPrivateDep && !data.requires.contains(entry)
- && !explicitRequires.contains(entry)) {
+ if (!isPrivateDep && !data.requires.includes(entry)
+ && !explicitRequires.includes(entry)) {
data.requires.push(entry);
}
} else {
- if (excludedDeps.contains(dep.name))
+ if (excludedDeps.includes(dep.name))
return;
- if (isPrivateDep && explicitRequiresPrivate.contains(dep.name))
+ if (isPrivateDep && explicitRequiresPrivate.includes(dep.name))
return;
- if (!isPrivateDep && explicitRequires.contains(dep.name))
+ if (!isPrivateDep && explicitRequires.includes(dep.name))
return;
collectAutodetectedDataRecursive(dep, isPrivateDep);
}
diff --git a/share/qbs/modules/Exporter/pkgconfig/pkgconfig.qbs b/share/qbs/modules/Exporter/pkgconfig/pkgconfig.qbs
index 8cc55f885..feb0e017c 100644
--- a/share/qbs/modules/Exporter/pkgconfig/pkgconfig.qbs
+++ b/share/qbs/modules/Exporter/pkgconfig/pkgconfig.qbs
@@ -34,9 +34,9 @@ Module {
auxiliaryInputs: {
if (!autoDetect)
return undefined;
- if (product.type.contains("staticlibrary"))
+ if (product.type.includes("staticlibrary"))
return ["staticlibrary"];
- if (product.type.contains("dynamiclibrary"))
+ if (product.type.includes("dynamiclibrary"))
return ["dynamiclibrary"];
}
@@ -46,7 +46,7 @@ Module {
}
prepare: {
var cmd = new JavaScriptCommand();
- cmd.description = "Creating " + output.fileName;
+ cmd.description = "creating " + output.fileName;
cmd.sourceCode = function() {
var f = new TextFile(output.filePath, TextFile.WriteOnly);
if (product.Exporter.pkgconfig._usePrefix)
diff --git a/share/qbs/modules/Exporter/qbs/qbsexporter.js b/share/qbs/modules/Exporter/qbs/qbsexporter.js
index 16408174b..145474a4b 100644
--- a/share/qbs/modules/Exporter/qbs/qbsexporter.js
+++ b/share/qbs/modules/Exporter/qbs/qbsexporter.js
@@ -30,6 +30,7 @@
var FileInfo = require("qbs.FileInfo");
var ModUtils = require("qbs.ModUtils");
+var ExporterHelpers = require("../exporter.js");
function tagListToString(tagList)
{
@@ -74,7 +75,7 @@ function writeTargetArtifactGroups(product, output, moduleFile)
var tag = product.Exporter.qbs._artifactTypes[i];
var artifactsForTag = product.artifacts[tag] || [];
for (var j = 0; j < artifactsForTag.length; ++j) {
- if (!relevantArtifacts.contains(artifactsForTag[j]))
+ if (!relevantArtifacts.includes(artifactsForTag[j]))
relevantArtifacts.push(artifactsForTag[j]);
}
}
@@ -82,7 +83,7 @@ function writeTargetArtifactGroups(product, output, moduleFile)
var artifactCount = relevantArtifacts ? relevantArtifacts.length : 0;
for (i = 0; i < artifactCount; ++i) {
var artifact = relevantArtifacts[i];
- if (!artifact.fileTags.contains("installable"))
+ if (!artifact.fileTags.includes("installable"))
continue;
// Put all artifacts with the same set of file tags into the same group, so we don't
@@ -102,18 +103,9 @@ function writeTargetArtifactGroups(product, output, moduleFile)
}
}
-function checkValuePrefix(name, value, forbiddenPrefix, prefixDescription)
-{
- if (value.startsWith(forbiddenPrefix)) {
- throw "Value '" + value + "' for exported property '" + name + "' in product '"
- + product.name + "' points into " + prefixDescription + ".\n"
- + "Did you forget to set the prefixMapping property in an Export item?";
- }
-}
-
function stringifyValue(project, product, moduleInstallDir, prop, value)
{
- if (Array.isArray(value)) {
+ if (value instanceof Array) {
var repr = "[";
for (var i = 0; i < value.length; ++i) {
repr += stringifyValue(project, product, moduleInstallDir, prop, value[i]) + ", ";
@@ -128,29 +120,9 @@ function stringifyValue(project, product, moduleInstallDir, prop, value)
return value;
}
- // Catch user oversights: Paths that point into the project source or build directories
- // make no sense in the module.
- if (!value.startsWith(product.qbs.installRoot)) {
- checkValuePrefix(prop.name, value, project.buildDirectory, "project build directory");
- checkValuePrefix(prop.name, value, project.sourceDirectory, "project source directory");
- }
-
- // Adapt file paths pointing into the install dir, that is, make them relative to the
- // module file for relocatability. We accept them with or without the install root.
- // The latter form will typically be a result of applying the prefixMapping property,
- // while the first one could be an untransformed path, for instance if the project
- // file is written in such a way that include paths are picked up from the installed
- // location rather than the source directory.
- var valuePrefixToStrip;
- var fullInstallPrefix = FileInfo.joinPaths(product.qbs.installRoot, product.qbs.installPrefix);
- if (fullInstallPrefix.length > 1 && value.startsWith(fullInstallPrefix)) {
- valuePrefixToStrip = fullInstallPrefix;
- } else {
- var installPrefix = FileInfo.joinPaths("/", product.qbs.installPrefix);
- if (installPrefix.length > 1 && value.startsWith(installPrefix))
- valuePrefixToStrip = installPrefix;
- }
+ var valuePrefixToStrip = ExporterHelpers.getPrefixToStrip(project, product, prop.name, value);
if (valuePrefixToStrip) {
+ var fullInstallPrefix = FileInfo.joinPaths(product.qbs.installRoot, product.qbs.installPrefix);
var deployedModuleInstallDir = moduleInstallDir.slice(fullInstallPrefix.length);
return "FileInfo.cleanPath(FileInfo.joinPaths(path, FileInfo.relativePath("
+ JSON.stringify(deployedModuleInstallDir) + ", "
@@ -172,14 +144,14 @@ function writeProperty(project, product, moduleInstallDir, prop, indentation, co
var moduleName;
if (isModuleProperty) {
moduleName = prop.name.slice(0, separatorIndex);
- if ((product.Exporter.qbs.excludedDependencies || []).contains(moduleName))
+ if ((product.Exporter.qbs.excludedDependencies || []).includes(moduleName))
return;
}
line += prop.name + ": ";
// We emit the literal value, unless the source code clearly refers to values from inside the
// original project, in which case the evaluated value is used.
- if (considerValue && /(project|product)\./.test(prop.sourceCode)) {
+ if (considerValue && /(project|product|exportingProduct)\./.test(prop.sourceCode)) {
var value;
if (isModuleProperty) {
var propertyName = prop.name.slice(separatorIndex + 1);
@@ -244,7 +216,7 @@ function isExcludedDependency(product, childItem)
for (var i = 0; i < childItem.properties.length; ++i) {
var prop = childItem.properties[i];
var unquotedRhs = prop.sourceCode.slice(1, -1);
- if (prop.name === "name" && product.Exporter.qbs.excludedDependencies.contains(unquotedRhs))
+ if (prop.name === "name" && product.Exporter.qbs.excludedDependencies.includes(unquotedRhs))
return true;
}
return false;
@@ -264,9 +236,9 @@ function writeImportStatements(product, moduleFile)
var imports = product.exports.imports;
// We potentially use FileInfo ourselves when transforming paths in stringifyValue().
- if (!imports.contains("import qbs.FileInfo"))
+ if (!imports.includes("import qbs.FileInfo"))
imports.push("import qbs.FileInfo");
- for (var i = 0; i < product.exports.imports.length; ++i)
- moduleFile.writeLine(product.exports.imports[i]);
+ for (var i = 0; i < imports.length; ++i)
+ moduleFile.writeLine(imports[i]);
}
diff --git a/share/qbs/modules/Exporter/qbs/qbsexporter.qbs b/share/qbs/modules/Exporter/qbs/qbsexporter.qbs
index 861483ef0..1e7cb02d5 100644
--- a/share/qbs/modules/Exporter/qbs/qbsexporter.qbs
+++ b/share/qbs/modules/Exporter/qbs/qbsexporter.qbs
@@ -59,10 +59,9 @@ Module {
}
prepare: {
var cmd = new JavaScriptCommand();
- cmd.description = "Creating " + output.fileName;
+ cmd.description = "creating " + output.fileName;
cmd.sourceCode = function() {
var f = new TextFile(output.filePath, TextFile.WriteOnly);
- f.writeLine("import qbs");
HelperFunctions.writeImportStatements(product, f);
f.writeLine("\nModule {");
HelperFunctions.writeModuleProperties(project, product, output, f);
diff --git a/share/qbs/modules/Sanitizers/address/asan.qbs b/share/qbs/modules/Sanitizers/address/asan.qbs
new file mode 100644
index 000000000..9d8f5b97e
--- /dev/null
+++ b/share/qbs/modules/Sanitizers/address/asan.qbs
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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.Utilities
+
+Module {
+ Depends { name: "cpp" }
+
+ property bool enabled: true
+ readonly property bool _supported: qbs.toolchain.includes("gcc")
+ || qbs.toolchain.includes("clang-cl")
+ || (qbs.toolchain.includes("msvc")
+ && Utilities.versionCompare(cpp.compilerVersion, "19.28.29500.0") >= 0)
+ readonly property bool _enabled: enabled && _supported
+
+ property string detectUseAfterReturn: "always"
+ PropertyOptions {
+ name: "detectUseAfterReturn"
+ description: "Whether to detect problems with stack use after return from a function"
+ allowedValues: ["never", "runtime", "always"]
+ }
+
+ property bool detectUseAfterScope: true
+
+ cpp.driverFlags: {
+ var flags = [];
+ if (!_enabled)
+ return flags;
+ if (qbs.toolchain.includes("msvc") && !qbs.toolchain.includes("clang-cl")) {
+ flags.push("/fsanitize=address");
+ if (detectUseAfterReturn !== "never")
+ flags.push("/fsanitize-address-use-after-return");
+ return flags;
+ }
+ flags.push("-fsanitize=address", "-fno-omit-frame-pointer");
+ if (detectUseAfterScope)
+ flags.push("-fsanitize-address-use-after-scope");
+ if (detectUseAfterReturn) {
+ if (qbs.toolchain.includes("llvm")) {
+ var minVersion = qbs.toolchain.contains("xcode") ? "14" : "13";
+ if (Utilities.versionCompare(cpp.compilerVersion, minVersion) >= 0)
+ flags.push("-fsanitize-address-use-after-return=" + detectUseAfterReturn);
+ } else if (detectUseAfterReturn === "never") {
+ flags.push("--param", "asan-use-after-return=0");
+ }
+ }
+ return flags;
+ }
+}
diff --git a/share/qbs/modules/archiver/archiver.qbs b/share/qbs/modules/archiver/archiver.qbs
index 6ae53dd37..069e76717 100644
--- a/share/qbs/modules/archiver/archiver.qbs
+++ b/share/qbs/modules/archiver/archiver.qbs
@@ -30,6 +30,7 @@
import qbs.Environment
import qbs.File
+import qbs.Host
import qbs.FileInfo
import qbs.Probes
@@ -53,7 +54,7 @@ Module {
names: ["7z"]
platformSearchPaths: {
var paths = base;
- if (qbs.hostOS.contains("windows")) {
+ if (Host.os().includes("windows")) {
var env32 = Environment.getEnv("PROGRAMFILES(X86)");
var env64 = Environment.getEnv("PROGRAMFILES");
if (env64 === env32 && env64.endsWith(" (x86)"))
@@ -211,7 +212,7 @@ Module {
args.push("-0");
} else {
compression = compression === "bz2" ? "bzip2" : compression;
- if (["store", "deflate", "bzip2"].contains(compression))
+ if (["store", "deflate", "bzip2"].includes(compression))
args.push("-Z", compression);
if (compressionLevel)
@@ -220,7 +221,7 @@ Module {
args.push("-r", output.filePath, ".", "-i@" + input.filePath);
args = args.concat(product.moduleProperty("archiver", "flags"));
- } else if (["tar", "zip", "jar"].contains(binaryName)) {
+ } else if (["tar", "zip", "jar"].includes(binaryName)) {
throw binaryName + ": unrecognized archive type: '" + type + "'";
} else if (binaryName) {
throw "unrecognized archive tool: '" + binaryName + "'";
@@ -229,7 +230,7 @@ Module {
}
var archiverCommand = new Command(binary, args);
- archiverCommand.description = "Creating archive file " + output.fileName;
+ archiverCommand.description = "creating archive file " + output.fileName;
archiverCommand.highlight = "linker";
archiverCommand.workingDirectory
= product.moduleProperty("archiver", "workingDirectory");
diff --git a/share/qbs/modules/bundle/BundleModule.qbs b/share/qbs/modules/bundle/BundleModule.qbs
index 1e83dc458..f640fd55f 100644
--- a/share/qbs/modules/bundle/BundleModule.qbs
+++ b/share/qbs/modules/bundle/BundleModule.qbs
@@ -33,25 +33,29 @@ import qbs.DarwinTools
import qbs.Environment
import qbs.File
import qbs.FileInfo
+import qbs.Host
import qbs.ModUtils
import qbs.PropertyList
import qbs.TextFile
import qbs.Utilities
import "bundle.js" as Bundle
+import "../codesign/codesign.js" as Codesign
Module {
Depends { name: "xcode"; required: false; }
+ Depends { name: "codesign"; required: false; }
Probe {
id: bundleSettingsProbe
- condition: qbs.targetOS.contains("darwin")
+ condition: qbs.targetOS.includes("darwin")
property string xcodeDeveloperPath: xcode.developerPath
property var xcodeArchSettings: xcode._architectureSettings
property string productTypeIdentifier: _productTypeIdentifier
- property bool useXcodeBuildSpecs: _useXcodeBuildSpecs
- property bool isMacOs: qbs.targetOS.contains("macos")
+ property bool useXcodeBuildSpecs: !useBuiltinXcodeBuildSpecs
+ property bool isMacOs: qbs.targetOS.includes("macos")
property bool xcodePresent: xcode.present
+ property string xcodeVersion: xcode.version
// Note that we include several settings pointing to properties which reference the output
// of this probe (WRAPPER_NAME, WRAPPER_EXTENSION, etc.). This is to ensure that derived
@@ -68,8 +72,11 @@ Module {
"PRODUCT_NAME": product.targetName,
"LOCAL_APPS_DIR": Environment.getEnv("HOME") + "/Applications",
"LOCAL_LIBRARY_DIR": Environment.getEnv("HOME") + "/Library",
+ // actually, this is cpp.targetAbi, but XCode does not set it for non-simulator builds
+ // while Qbs set it to "macho".
+ "LLVM_TARGET_TRIPLE_SUFFIX": qbs.targetOS.includes("simulator") ? "-simulator" : "",
"SWIFT_PLATFORM_TARGET_PREFIX": isMacOs ? "macos"
- : qbs.targetOS.contains("ios") ? "ios" : "",
+ : qbs.targetOS.includes("ios") ? "ios" : "",
"TARGET_BUILD_DIR": product.buildDirectory,
"WRAPPER_NAME": bundleName,
"WRAPPER_EXTENSION": extension
@@ -80,15 +87,14 @@ Module {
property var productTypeIdentifierChain: []
configure: {
- var specsPath = path;
+ var specsPaths = [path];
var specsSeparator = "-";
if (xcodeDeveloperPath && useXcodeBuildSpecs) {
- specsPath = xcodeDeveloperPath
- + "/Platforms/MacOSX.platform/Developer/Library/Xcode/Specifications";
+ specsPaths = Bundle.macOSSpecsPaths(xcodeVersion, xcodeDeveloperPath);
specsSeparator = " ";
}
- var reader = new Bundle.XcodeBuildSpecsReader(specsPath,
+ var reader = new Bundle.XcodeBuildSpecsReader(specsPaths,
specsSeparator,
additionalSettings,
!isMacOs);
@@ -112,7 +118,7 @@ Module {
additionalProductTypes: !(product.multiplexed || product.aggregate)
|| !product.multiplexConfigurationId ? ["bundle.content"] : []
- property bool isBundle: !product.consoleApplication && qbs.targetOS.contains("darwin")
+ property bool isBundle: !product.consoleApplication && qbs.targetOS.includes("darwin")
readonly property bool isShallow: bundleSettingsProbe.xcodeSettings["SHALLOW_BUNDLE"] === "YES"
@@ -146,7 +152,7 @@ Module {
property var infoPlist
property bool processInfoPlist: true
property bool embedInfoPlist: product.consoleApplication && !isBundle
- property string infoPlistFormat: qbs.targetOS.contains("macos") ? "same-as-input" : "binary1"
+ property string infoPlistFormat: qbs.targetOS.includes("macos") ? "same-as-input" : "binary1"
property string localizedResourcesFolderSuffix: ".lproj"
@@ -181,13 +187,20 @@ Module {
readonly property string unlocalizedResourcesFolderPath: bundleSettingsProbe.xcodeSettings["UNLOCALIZED_RESOURCES_FOLDER_PATH"]
readonly property string versionsFolderPath: bundleSettingsProbe.xcodeSettings["VERSIONS_FOLDER_PATH"]
+ property bool useBuiltinXcodeBuildSpecs: !_useXcodeBuildSpecs // true to use ONLY the qbs build specs
+
// private properties
property string _productTypeIdentifier: Bundle.productTypeIdentifier(product.type)
property stringList _productTypeIdentifierChain: bundleSettingsProbe.productTypeIdentifierChain
- property bool _useXcodeBuildSpecs: true // false to use ONLY the qbs build specs
+ readonly property path _developerPath: xcode.developerPath
+ readonly property path _platformInfoPlist: xcode.platformInfoPlist
+ readonly property path _sdkSettingsPlist: xcode.sdkSettingsPlist
+ readonly property path _toolchainInfoPlist: xcode.toolchainInfoPlist
+
+ property bool _useXcodeBuildSpecs: true // TODO: remove in 1.25
- readonly property var extraEnv: ({
+ property var extraEnv: ({
"PRODUCT_BUNDLE_IDENTIFIER": identifier
})
@@ -219,7 +232,7 @@ Module {
}
validate: {
- if (!qbs.targetOS.contains("darwin"))
+ if (!qbs.targetOS.includes("darwin"))
return;
if (!bundleSettingsProbe.found) {
var error = "Bundle product type " + _productTypeIdentifier + " is not supported.";
@@ -265,7 +278,7 @@ Module {
}
Rule {
- condition: qbs.targetOS.contains("darwin")
+ condition: qbs.targetOS.includes("darwin")
multiplex: true
requiresInputs: false // TODO: The resources property should probably be a tag instead.
inputs: ["infoplist", "partial_infoplist"]
@@ -273,8 +286,8 @@ Module {
outputFileTags: ["bundle.input", "aggregate_infoplist"]
outputArtifacts: {
var artifacts = [];
- var embed = ModUtils.moduleProperty(product, "embedInfoPlist");
- if (ModUtils.moduleProperty(product, "isBundle") || embed) {
+ var embed = product.bundle.embedInfoPlist;
+ if (product.bundle.isBundle || embed) {
artifacts.push({
filePath: FileInfo.joinPaths(
product.destinationDirectory, product.name + "-Info.plist"),
@@ -282,7 +295,7 @@ Module {
bundle: {
_bundleFilePath: FileInfo.joinPaths(
product.destinationDirectory,
- ModUtils.moduleProperty(product, "infoPlistPath")),
+ product.bundle.infoPlistPath),
}
});
}
@@ -293,20 +306,21 @@ Module {
var cmd = new JavaScriptCommand();
cmd.description = "generating Info.plist for " + product.name;
cmd.highlight = "codegen";
- cmd.infoPlist = ModUtils.moduleProperty(product, "infoPlist") || {};
- cmd.processInfoPlist = ModUtils.moduleProperty(product, "processInfoPlist");
- cmd.infoPlistFormat = ModUtils.moduleProperty(product, "infoPlistFormat");
- cmd.extraEnv = ModUtils.moduleProperty(product, "extraEnv");
- cmd.qmakeEnv = ModUtils.moduleProperty(product, "qmakeEnv");
+ cmd.infoPlist = product.bundle.infoPlist || {};
+ cmd.processInfoPlist = product.bundle.processInfoPlist;
+ cmd.infoPlistFormat = product.bundle.infoPlistFormat;
+ cmd.extraEnv = product.bundle.extraEnv;
+ cmd.qmakeEnv = product.bundle.qmakeEnv;
+ // TODO: bundle module should know nothing about cpp module
cmd.buildEnv = product.moduleProperty("cpp", "buildEnv");
- cmd.developerPath = product.moduleProperty("xcode", "developerPath");
- cmd.platformInfoPlist = product.moduleProperty("xcode", "platformInfoPlist");
- cmd.sdkSettingsPlist = product.moduleProperty("xcode", "sdkSettingsPlist");
- cmd.toolchainInfoPlist = product.moduleProperty("xcode", "toolchainInfoPlist");
+ cmd.developerPath = product.bundle._developerPath;
+ cmd.platformInfoPlist = product.bundle._platformInfoPlist;
+ cmd.sdkSettingsPlist = product.bundle._sdkSettingsPlist;
+ cmd.toolchainInfoPlist = product.bundle._toolchainInfoPlist;
- cmd.osBuildVersion = product.moduleProperty("qbs", "hostOSBuildVersion");
+ cmd.osBuildVersion = product.qbs.hostOSBuildVersion;
cmd.sourceCode = function() {
var plist, process, key, i;
@@ -335,7 +349,7 @@ Module {
if (processInfoPlist) {
// Add default values to the aggregate plist if the corresponding keys
// for those values are not already present
- var defaultValues = ModUtils.moduleProperty(product, "defaultInfoPlist");
+ var defaultValues = product.bundle.defaultInfoPlist;
for (key in defaultValues) {
if (defaultValues.hasOwnProperty(key) && !(key in aggregatePlist))
aggregatePlist[key] = defaultValues[key];
@@ -447,7 +461,7 @@ Module {
infoPlistFormat = "xml1";
var validFormats = [ "xml1", "binary1", "json" ];
- if (!validFormats.contains(infoPlistFormat))
+ if (!validFormats.includes(infoPlistFormat))
throw("Invalid Info.plist format " + infoPlistFormat + ". " +
"Must be in [xml1, binary1, json].");
@@ -465,18 +479,18 @@ Module {
}
Rule {
- condition: qbs.targetOS.contains("darwin")
+ condition: qbs.targetOS.includes("darwin")
multiplex: true
inputs: ["aggregate_infoplist"]
outputFileTags: ["bundle.input", "pkginfo"]
outputArtifacts: {
var artifacts = [];
- if (ModUtils.moduleProperty(product, "isBundle") && ModUtils.moduleProperty(product, "generatePackageInfo")) {
+ if (product.bundle.isBundle && product.bundle.generatePackageInfo) {
artifacts.push({
filePath: FileInfo.joinPaths(product.destinationDirectory, "PkgInfo"),
fileTags: ["bundle.input", "pkginfo"],
- bundle: { _bundleFilePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "pkgInfoPath")) }
+ bundle: { _bundleFilePath: FileInfo.joinPaths(product.destinationDirectory, product.bundle.pkgInfoPath) }
});
}
return artifacts;
@@ -506,13 +520,13 @@ Module {
}
Rule {
- condition: qbs.targetOS.contains("darwin")
+ condition: qbs.targetOS.includes("darwin")
multiplex: true
inputs: ["bundle.input",
"aggregate_infoplist", "pkginfo", "hpp",
- "icns", "xcent",
+ "icns", "codesign.xcent",
"compiled_ibdoc", "compiled_assetcatalog",
- "xcode.provisioningprofile.main"]
+ "codesign.embedded_provisioningprofile"]
// Make sure the inputs of this rule are only those rules which produce outputs compatible
// with the type of the bundle being produced.
@@ -523,15 +537,16 @@ Module {
"bundle.symlink.headers", "bundle.symlink.private-headers",
"bundle.symlink.resources", "bundle.symlink.executable",
"bundle.symlink.version", "bundle.hpp", "bundle.resource",
- "bundle.provisioningprofile", "bundle.content.copied", "bundle.application-executable"]
+ "bundle.provisioningprofile", "bundle.content.copied", "bundle.application-executable",
+ "bundle.code-signature"]
outputArtifacts: {
var i, artifacts = [];
- if (ModUtils.moduleProperty(product, "isBundle")) {
+ if (product.bundle.isBundle) {
for (i in inputs["bundle.input"]) {
- var fp = inputs["bundle.input"][i].moduleProperty("bundle", "_bundleFilePath");
+ var fp = inputs["bundle.input"][i].bundle._bundleFilePath;
if (!fp)
throw("Artifact " + inputs["bundle.input"][i].filePath + " has no associated bundle file path");
- var extraTags = inputs["bundle.input"][i].fileTags.contains("application")
+ var extraTags = inputs["bundle.input"][i].fileTags.includes("application")
? ["bundle.application-executable"] : [];
artifacts.push({
filePath: fp,
@@ -539,24 +554,23 @@ Module {
});
}
- for (i in inputs["xcode.provisioningprofile.main"]) {
- var ext = inputs["xcode.provisioningprofile.main"][i].fileName.split('.')[1];
+ var provprofiles = inputs["codesign.embedded_provisioningprofile"];
+ for (i in provprofiles) {
artifacts.push({
filePath: FileInfo.joinPaths(product.destinationDirectory,
- ModUtils.moduleProperty(product,
- "contentsFolderPath"),
- "embedded." + ext),
+ product.bundle.contentsFolderPath,
+ provprofiles[i].fileName),
fileTags: ["bundle.provisioningprofile", "bundle.content"]
});
}
- var packageType = ModUtils.moduleProperty(product, "packageType");
- var isShallow = ModUtils.moduleProperty(product, "isShallow");
+ var packageType = product.bundle.packageType;
+ var isShallow = product.bundle.isShallow;
if (packageType === "FMWK" && !isShallow) {
- var publicHeaders = ModUtils.moduleProperty(product, "publicHeaders");
+ var publicHeaders = product.bundle.publicHeaders;
if (publicHeaders && publicHeaders.length) {
artifacts.push({
- filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "bundleName"), "Headers"),
+ filePath: FileInfo.joinPaths(product.destinationDirectory, product.bundle.bundleName, "Headers"),
fileTags: ["bundle.symlink.headers", "bundle.content"]
});
}
@@ -564,23 +578,23 @@ Module {
var privateHeaders = ModUtils.moduleProperty(product, "privateHeaders");
if (privateHeaders && privateHeaders.length) {
artifacts.push({
- filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "bundleName"), "PrivateHeaders"),
+ filePath: FileInfo.joinPaths(product.destinationDirectory, product.bundle.bundleName, "PrivateHeaders"),
fileTags: ["bundle.symlink.private-headers", "bundle.content"]
});
}
artifacts.push({
- filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "bundleName"), "Resources"),
+ filePath: FileInfo.joinPaths(product.destinationDirectory, product.bundle.bundleName, "Resources"),
fileTags: ["bundle.symlink.resources", "bundle.content"]
});
artifacts.push({
- filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "bundleName"), product.targetName),
+ filePath: FileInfo.joinPaths(product.destinationDirectory, product.bundle.bundleName, product.targetName),
fileTags: ["bundle.symlink.executable", "bundle.content"]
});
artifacts.push({
- filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "versionsFolderPath"), "Current"),
+ filePath: FileInfo.joinPaths(product.destinationDirectory, product.bundle.versionsFolderPath, "Current"),
fileTags: ["bundle.symlink.version", "bundle.content"]
});
}
@@ -597,7 +611,7 @@ Module {
}
}
- sources = ModUtils.moduleProperty(product, "resources");
+ sources = product.bundle.resources;
for (i in sources) {
destination = BundleTools.destinationDirectoryForResource(product, {baseDir: FileInfo.path(sources[i]), fileName: FileInfo.fileName(sources[i])});
artifacts.push({
@@ -608,16 +622,24 @@ Module {
var wrapperPath = FileInfo.joinPaths(
product.destinationDirectory,
- ModUtils.moduleProperty(product, "bundleName"));
+ product.bundle.bundleName);
for (var i = 0; i < artifacts.length; ++i)
artifacts[i].bundle = { wrapperPath: wrapperPath };
+
+ if (Host.os().includes("darwin") && product.codesign
+ && product.codesign.enableCodeSigning) {
+ artifacts.push({
+ filePath: FileInfo.joinPaths(product.bundle.contentsFolderPath, "_CodeSignature/CodeResources"),
+ fileTags: ["bundle.code-signature", "bundle.content"]
+ });
+ }
}
return artifacts;
}
prepare: {
var i, cmd, commands = [];
- var packageType = ModUtils.moduleProperty(product, "packageType");
+ var packageType = product.bundle.packageType;
var bundleType = "bundle";
if (packageType === "APPL")
@@ -625,19 +647,8 @@ Module {
if (packageType === "FMWK")
bundleType = "framework";
- var bundles = outputs.bundle;
- for (i in bundles) {
- cmd = new Command("mkdir", ["-p", bundles[i].filePath]);
- cmd.description = "creating " + bundleType + " " + product.targetName;
- commands.push(cmd);
-
- cmd = new Command("touch", ["-c", bundles[i].filePath]);
- cmd.silent = true;
- commands.push(cmd);
- }
-
// Product is unbundled
- if (commands.length === 0) {
+ if (!product.bundle.isBundle) {
cmd = new JavaScriptCommand();
cmd.silent = true;
cmd.sourceCode = function () { };
@@ -646,7 +657,7 @@ Module {
var symlinks = outputs["bundle.symlink.version"];
for (i in symlinks) {
- cmd = new Command("ln", ["-sfn", ModUtils.moduleProperty(product, "frameworkVersion"),
+ cmd = new Command("ln", ["-sfn", product.bundle.frameworkVersion,
symlinks[i].filePath]);
cmd.silent = true;
commands.push(cmd);
@@ -693,8 +704,8 @@ Module {
}
var bundleInputs = sortedArtifactList(inputs["bundle.input"], function (a, b) {
- return a.moduleProperty("bundle", "_bundleFilePath").localeCompare(
- b.moduleProperty("bundle", "_bundleFilePath"));
+ return a.bundle._bundleFilePath.localeCompare(
+ b.bundle._bundleFilePath);
});
var bundleContents = sortedArtifactList(outputs["bundle.content.copied"]);
for (i in bundleContents) {
@@ -708,24 +719,27 @@ Module {
commands.push(cmd);
}
- var provisioningProfiles = outputs["bundle.provisioningprofile"];
- for (i in provisioningProfiles) {
- cmd = new JavaScriptCommand();
- cmd.description = "copying provisioning profile";
- cmd.highlight = "filegen";
- cmd.source = inputs["xcode.provisioningprofile.main"][i].filePath;
- cmd.destination = provisioningProfiles[i].filePath;
- cmd.sourceCode = function() {
- File.copy(source, destination);
- };
+ cmd = new JavaScriptCommand();
+ cmd.description = "copying provisioning profile";
+ cmd.highlight = "filegen";
+ cmd.sources = (inputs["codesign.embedded_provisioningprofile"] || [])
+ .map(function(artifact) { return artifact.filePath; });
+ cmd.destination = (outputs["bundle.provisioningprofile"] || [])
+ .map(function(artifact) { return artifact.filePath; });
+ cmd.sourceCode = function() {
+ var i;
+ for (var i in sources) {
+ File.copy(sources[i], destination[i]);
+ }
+ };
+ if (cmd.sources && cmd.sources.length)
commands.push(cmd);
- }
cmd = new JavaScriptCommand();
cmd.description = "copying public headers";
cmd.highlight = "filegen";
- cmd.sources = ModUtils.moduleProperty(product, "publicHeaders");
- cmd.destination = FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "publicHeadersFolderPath"));
+ cmd.sources = product.bundle.publicHeaders;
+ cmd.destination = FileInfo.joinPaths(product.destinationDirectory, product.bundle.publicHeadersFolderPath);
cmd.sourceCode = function() {
var i;
for (var i in sources) {
@@ -738,8 +752,8 @@ Module {
cmd = new JavaScriptCommand();
cmd.description = "copying private headers";
cmd.highlight = "filegen";
- cmd.sources = ModUtils.moduleProperty(product, "privateHeaders");
- cmd.destination = FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "privateHeadersFolderPath"));
+ cmd.sources = product.bundle.privateHeaders;
+ cmd.destination = FileInfo.joinPaths(product.destinationDirectory, product.bundle.privateHeadersFolderPath);
cmd.sourceCode = function() {
var i;
for (var i in sources) {
@@ -752,7 +766,7 @@ Module {
cmd = new JavaScriptCommand();
cmd.description = "copying resources";
cmd.highlight = "filegen";
- cmd.sources = ModUtils.moduleProperty(product, "resources");
+ cmd.sources = product.bundle.resources;
cmd.sourceCode = function() {
var i;
for (var i in sources) {
@@ -763,45 +777,18 @@ Module {
if (cmd.sources && cmd.sources.length)
commands.push(cmd);
- if (product.moduleProperty("qbs", "hostOS").contains("darwin")) {
- for (i in bundles) {
- var actualSigningIdentity = product.moduleProperty("xcode", "actualSigningIdentity");
- var codesignDisplayName = product.moduleProperty("xcode", "actualSigningIdentityDisplayName");
- if (actualSigningIdentity) {
- // If this is a framework, we need to sign its versioned directory
- var subpath = "";
- var frameworkVersion = ModUtils.moduleProperty(product, "frameworkVersion");
- if (frameworkVersion) {
- subpath = ModUtils.moduleProperty(product, "contentsFolderPath");
- subpath = subpath.substring(subpath.indexOf(ModUtils.moduleProperty("qbs", "pathSeparator")));
- }
-
- var args = product.moduleProperty("xcode", "codesignFlags") || [];
- args.push("--force");
- args.push("--sign", actualSigningIdentity);
- args = args.concat(DarwinTools._codeSignTimestampFlags(product));
-
- for (var j in inputs.xcent) {
- args.push("--entitlements", inputs.xcent[j].filePath);
- break; // there should only be one
- }
- args.push(bundles[i].filePath + subpath);
-
- cmd = new Command(product.moduleProperty("xcode", "codesignPath"), args);
- cmd.description = "codesign "
- + ModUtils.moduleProperty(product, "bundleName")
- + " using " + codesignDisplayName
- + " (" + actualSigningIdentity + ")";
- commands.push(cmd);
- }
-
- if (bundleType === "application"
- && product.moduleProperty("qbs", "targetOS").contains("macos")) {
- cmd = new Command(ModUtils.moduleProperty(product, "lsregisterPath"),
- ["-f", bundles[i].filePath]);
- cmd.description = "register " + ModUtils.moduleProperty(product, "bundleName");
- commands.push(cmd);
- }
+ if (product.qbs.hostOS.includes("darwin")) {
+ Array.prototype.push.apply(commands, Codesign.prepareSign(
+ project, product, inputs, outputs, input, output));
+
+ if (bundleType === "application"
+ && product.qbs.targetOS.includes("macos")) {
+ var bundlePath = FileInfo.joinPaths(
+ product.destinationDirectory, product.bundle.bundleName);
+ cmd = new Command(product.bundle.lsregisterPath,
+ ["-f", bundlePath]);
+ cmd.description = "registering " + product.bundle.bundleName;
+ commands.push(cmd);
}
}
diff --git a/share/qbs/modules/bundle/MacOSX-Package-Types.xcspec b/share/qbs/modules/bundle/MacOSX-Package-Types.xcspec
index b36353fc7..23f094641 100644
--- a/share/qbs/modules/bundle/MacOSX-Package-Types.xcspec
+++ b/share/qbs/modules/bundle/MacOSX-Package-Types.xcspec
@@ -1,462 +1,533 @@
-[
- {
- "DefaultBuildSettings" : {
- "EXECUTABLE_PATH" : "$(EXECUTABLE_NAME)",
- "EXECUTABLE_PREFIX" : "",
- "EXECUTABLE_SUFFIX" : "",
- "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)"
- },
- "Identifier" : "com.apple.package-type.mach-o-executable",
- "Type" : "PackageType",
- "Name" : "Mach-O Executable",
- "Description" : "Mach-O executable",
- "ProductReference" : {
- "FileType" : "compiled.mach-o.executable",
- "Name" : "$(EXECUTABLE_NAME)",
- "IsLaunchable" : "YES"
- }
- },
- {
- "DefaultBuildSettings" : {
- "EXECUTABLE_PATH" : "$(EXECUTABLE_NAME)",
- "EXECUTABLE_PREFIX" : "",
- "EXECUTABLE_SUFFIX" : "",
- "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)"
- },
- "Identifier" : "com.apple.package-type.mach-o-objfile",
- "Type" : "PackageType",
- "Name" : "Mach-O Object File",
- "Description" : "Mach-O Object File",
- "ProductReference" : {
- "FileType" : "compiled.mach-o.objfile",
- "Name" : "$(EXECUTABLE_NAME)",
- "IsLaunchable" : "NO"
- }
- },
- {
- "DefaultBuildSettings" : {
- "EXECUTABLE_PATH" : "$(EXECUTABLE_NAME)",
- "EXECUTABLE_PREFIX" : "",
- "EXECUTABLE_SUFFIX" : "",
- "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)"
- },
- "Identifier" : "com.apple.package-type.mach-o-dylib",
- "Type" : "PackageType",
- "Name" : "Mach-O Dynamic Library",
- "Description" : "Mach-O dynamic library",
- "ProductReference" : {
- "FileType" : "compiled.mach-o.dylib",
- "Name" : "$(EXECUTABLE_NAME)",
- "IsLaunchable" : "NO"
- }
- },
- {
- "DefaultBuildSettings" : {
- "EXECUTABLE_PATH" : "$(EXECUTABLE_NAME)",
- "EXECUTABLE_PREFIX" : "lib",
- "EXECUTABLE_SUFFIX" : ".a",
- "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)"
- },
- "Identifier" : "com.apple.package-type.static-library",
- "Type" : "PackageType",
- "Name" : "Mach-O Static Library",
- "Description" : "Mach-O static library",
- "ProductReference" : {
- "FileType" : "archive.ar",
- "Name" : "$(EXECUTABLE_NAME)",
- "IsLaunchable" : "NO"
- }
- },
- {
- "DefaultBuildSettings" : {
- "EXECUTABLE_PATH" : "$(EXECUTABLE_NAME)",
- "EXECUTABLE_PREFIX" : "",
- "EXECUTABLE_SUFFIX" : ".dylib",
- "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)"
- },
- "Identifier" : "com.apple.package-type.mach-o-bundle",
- "Type" : "PackageType",
- "Name" : "Mach-O Loadable",
- "Description" : "Mach-O loadable",
- "ProductReference" : {
- "FileType" : "compiled.mach-o.bundle",
- "Name" : "$(EXECUTABLE_NAME)",
- "IsLaunchable" : "NO"
- }
- },
- {
- "DefaultBuildSettings" : {
- "PUBLIC_HEADERS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/Headers",
- "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)",
- "EXECUTABLE_PREFIX" : "",
- "PLUGINS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/PlugIns",
- "DOCUMENTATION_FOLDER_PATH" : "$(LOCALIZED_RESOURCES_FOLDER_PATH)\/Documentation",
- "EXECUTABLES_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/Executables",
- "INFOSTRINGS_PATH" : "$(LOCALIZED_RESOURCES_FOLDER_PATH)\/InfoPlist.strings",
- "INFOPLIST_PATH" : "$(CONTENTS_FOLDER_PATH)\/Info.plist",
- "EXECUTABLE_SUFFIX" : "",
- "VERSIONPLIST_PATH" : "$(CONTENTS_FOLDER_PATH)\/version.plist",
- "SHARED_SUPPORT_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/SharedSupport",
- "EXECUTABLE_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/MacOS",
- "PBDEVELOPMENTPLIST_PATH" : "$(CONTENTS_FOLDER_PATH)\/pbdevelopment.plist",
- "FRAMEWORKS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/Frameworks",
- "LOCALIZED_RESOURCES_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/$(DEVELOPMENT_LANGUAGE).lproj",
- "SCRIPTS_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/Scripts",
- "WRAPPER_PREFIX" : "",
- "PRIVATE_HEADERS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/PrivateHeaders",
- "CONTENTS_FOLDER_PATH" : "$(WRAPPER_NAME)\/Contents",
- "WRAPPER_NAME" : "$(WRAPPER_PREFIX)$(PRODUCT_NAME)$(WRAPPER_SUFFIX)",
- "PKGINFO_PATH" : "$(CONTENTS_FOLDER_PATH)\/PkgInfo",
- "EXECUTABLE_PATH" : "$(EXECUTABLE_FOLDER_PATH)\/$(EXECUTABLE_NAME)",
- "UNLOCALIZED_RESOURCES_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/Resources",
- "JAVA_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/Java",
- "SHARED_FRAMEWORKS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/SharedFrameworks",
- "WRAPPER_SUFFIX" : ".bundle"
- },
- "Identifier" : "com.apple.package-type.wrapper",
- "Type" : "PackageType",
- "Name" : "Wrapper",
- "Description" : "Wrapper",
- "ProductReference" : {
- "FileType" : "wrapper.cfbundle",
- "Name" : "$(WRAPPER_NAME)",
- "IsLaunchable" : "NO"
- }
- },
- {
- "ProductReference" : {
- "FileType" : "wrapper.cfbundle",
- "Name" : "$(WRAPPER_NAME)",
- "IsLaunchable" : "NO"
- },
- "DefaultBuildSettings" : {
- "CONTENTS_FOLDER_PATH" : "$(WRAPPER_NAME)",
- "UNLOCALIZED_RESOURCES_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)",
- "SHALLOW_BUNDLE" : "YES",
- "EXECUTABLE_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)"
- },
- "Type" : "PackageType",
- "BasedOn" : "com.apple.package-type.wrapper",
- "Name" : "Wrapper (Shallow)",
- "Identifier" : "com.apple.package-type.wrapper.shallow",
- "Description" : "Shallow Wrapper"
- },
- {
- "ProductReference" : {
- "FileType" : "wrapper.application",
- "Name" : "$(WRAPPER_NAME)",
- "IsLaunchable" : "YES"
- },
- "DefaultBuildSettings" : {
- "GENERATE_PKGINFO_FILE" : "YES"
- },
- "Type" : "PackageType",
- "BasedOn" : "com.apple.package-type.wrapper",
- "Name" : "Application Wrapper",
- "Identifier" : "com.apple.package-type.wrapper.application",
- "Description" : "Application Wrapper"
- },
- {
- "ProductReference" : {
- "FileType" : "wrapper.application",
- "Name" : "$(WRAPPER_NAME)",
- "IsLaunchable" : "YES"
- },
- "DefaultBuildSettings" : {
- "UNLOCALIZED_RESOURCES_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)",
- "SHALLOW_BUNDLE" : "YES",
- "GENERATE_PKGINFO_FILE" : "YES"
- },
- "Type" : "PackageType",
- "BasedOn" : "com.apple.package-type.wrapper.shallow",
- "Name" : "Application Wrapper (Shallow)",
- "Identifier" : "com.apple.package-type.wrapper.application.shallow",
- "Description" : "Shallow Application Wrapper"
- },
- {
- "ProductReference" : {
- "FileType" : "wrapper.cfbundle",
- "Name" : "$(WRAPPER_NAME)",
- "IsLaunchable" : "NO"
- },
- "DefaultBuildSettings" : {
- "PRIVATE_HEADERS_FOLDER_PATH" : "$(KEXT_FRAMEWORK)\/Contents\/PrivateHeaders\/$(KEXT_FAMILY_NAME)",
- "PUBLIC_HEADERS_FOLDER_PATH" : "$(KEXT_FRAMEWORK)\/Contents\/Headers\/$(KEXT_FAMILY_NAME)"
+/**
+ MacOSX Package Types.xcspec
+
+ Copyright (c) 1999-2015 Apple Inc. All rights reserved.
+
+ Package type specifications in the Mac OS X platform.
+*/
+(
+ // Mach-O executable
+ { Type = PackageType;
+ Identifier = com.apple.package-type.mach-o-executable;
+ Name = "Mach-O Executable";
+ Description = "Mach-O executable";
+ DefaultBuildSettings = {
+ EXECUTABLE_PREFIX = "";
+ EXECUTABLE_SUFFIX = "";
+ EXECUTABLE_NAME = "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)";
+ EXECUTABLE_PATH = "$(EXECUTABLE_NAME)";
+ };
+ ProductReference = {
+ FileType = compiled.mach-o.executable;
+ Name = "$(EXECUTABLE_NAME)";
+ IsLaunchable = YES;
+ };
},
- "Type" : "PackageType",
- "BasedOn" : "com.apple.package-type.wrapper",
- "Name" : "Kernel Extension Wrapper",
- "Identifier" : "com.apple.package-type.wrapper.kernel-extension",
- "Description" : "Kernel Extension Wrapper"
- },
- {
- "ProductReference" : {
- "FileType" : "wrapper.cfbundle",
- "Name" : "$(WRAPPER_NAME)",
- "IsLaunchable" : "NO"
+
+ // Mach-O object file
+ { Type = PackageType;
+ Identifier = com.apple.package-type.mach-o-objfile;
+ Name = "Mach-O Object File";
+ Description = "Mach-O Object File";
+ DefaultBuildSettings = {
+ EXECUTABLE_PREFIX = "";
+ EXECUTABLE_SUFFIX = "";
+ EXECUTABLE_NAME = "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)";
+ EXECUTABLE_PATH = "$(EXECUTABLE_NAME)";
+ };
+ ProductReference = {
+ FileType = compiled.mach-o.objfile;
+ Name = "$(EXECUTABLE_NAME)";
+ IsLaunchable = NO;
+ };
},
- "DefaultBuildSettings" : {
- "PRIVATE_HEADERS_FOLDER_PATH" : "$(KEXT_FRAMEWORK)\/Contents\/PrivateHeaders\/$(KEXT_FAMILY_NAME)",
- "PUBLIC_HEADERS_FOLDER_PATH" : "$(KEXT_FRAMEWORK)\/Contents\/Headers\/$(KEXT_FAMILY_NAME)",
- "SHALLOW_BUNDLE" : "YES"
+
+ // Mach-O dynamic library
+ { Type = PackageType;
+ Identifier = com.apple.package-type.mach-o-dylib;
+ Name = "Mach-O Dynamic Library";
+ Description = "Mach-O dynamic library";
+ DefaultBuildSettings = {
+ EXECUTABLE_PREFIX = "";
+ EXECUTABLE_SUFFIX = "";
+ EXECUTABLE_NAME = "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)";
+ EXECUTABLE_PATH = "$(EXECUTABLE_NAME)";
+ };
+ ProductReference = {
+ FileType = compiled.mach-o.dylib;
+ Name = "$(EXECUTABLE_NAME)";
+ IsLaunchable = NO;
+ };
},
- "Type" : "PackageType",
- "BasedOn" : "com.apple.package-type.wrapper.shallow",
- "Name" : "Kernel Extension Wrapper (Shallow)",
- "Identifier" : "com.apple.package-type.wrapper.kernel-extension.shallow",
- "Description" : "Shallow Kernel Extension Wrapper"
- },
- {
- "DefaultBuildSettings" : {
- "PUBLIC_HEADERS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/Headers",
- "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)",
- "EXECUTABLE_PREFIX" : "",
- "PLUGINS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/PlugIns",
- "DOCUMENTATION_FOLDER_PATH" : "$(LOCALIZED_RESOURCES_FOLDER_PATH)\/Documentation",
- "EXECUTABLES_FOLDER_PATH" : "$(LOCALIZED_RESOURCES_FOLDER_PATH)",
- "INFOPLIST_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/Info.plist",
- "EXECUTABLE_SUFFIX" : "",
- "INFOPLISTSTRINGS_PATH" : "$(LOCALIZED_RESOURCES_FOLDER_PATH)\/InfoPlist.strings",
- "VERSIONPLIST_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/version.plist",
- "SHARED_SUPPORT_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)",
- "EXECUTABLE_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)",
- "PBDEVELOPMENTPLIST_PATH" : "$(CONTENTS_FOLDER_PATH)\/pbdevelopment.plist",
- "VERSIONS_FOLDER_PATH" : "$(WRAPPER_NAME)\/Versions",
- "FRAMEWORKS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/Frameworks",
- "CODESIGNING_FOLDER_PATH" : "$(TARGET_BUILD_DIR)\/$(CONTENTS_FOLDER_PATH)",
- "LOCALIZED_RESOURCES_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/$(DEVELOPMENT_LANGUAGE).lproj",
- "SCRIPTS_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/Scripts",
- "WRAPPER_PREFIX" : "",
- "PRIVATE_HEADERS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/PrivateHeaders",
- "CURRENT_VERSION" : "Current",
- "PKGINFO_PATH" : "$(WRAPPER_NAME)\/PkgInfo",
- "WRAPPER_NAME" : "$(WRAPPER_PREFIX)$(PRODUCT_NAME)$(WRAPPER_SUFFIX)",
- "CONTENTS_FOLDER_PATH" : "$(VERSIONS_FOLDER_PATH)\/$(FRAMEWORK_VERSION)",
- "EXECUTABLE_PATH" : "$(EXECUTABLE_FOLDER_PATH)\/$(EXECUTABLE_NAME)",
- "UNLOCALIZED_RESOURCES_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/Resources",
- "JAVA_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/Java",
- "SHARED_FRAMEWORKS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)\/SharedFrameworks",
- "WRAPPER_SUFFIX" : ".framework"
+
+ // Static library ('ar' archive containing .o files)
+ { Type = PackageType;
+ Identifier = com.apple.package-type.static-library;
+ Name = "Mach-O Static Library";
+ Description = "Mach-O static library";
+ DefaultBuildSettings = {
+ EXECUTABLE_PREFIX = "lib";
+ EXECUTABLE_SUFFIX = ".a";
+ EXECUTABLE_NAME = "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)";
+ EXECUTABLE_PATH = "$(EXECUTABLE_NAME)";
+ };
+ ProductReference = {
+ FileType = archive.ar;
+ Name = "$(EXECUTABLE_NAME)";
+ IsLaunchable = NO;
+ };
},
- "Identifier" : "com.apple.package-type.wrapper.framework",
- "Type" : "PackageType",
- "Name" : "Framework Wrapper",
- "Description" : "Framework wrapper",
- "ProductReference" : {
- "FileType" : "wrapper.framework",
- "Name" : "$(WRAPPER_NAME)",
- "IsLaunchable" : "NO"
- }
- },
- {
- "ProductReference" : {
- "FileType" : "wrapper.framework.static",
- "Name" : "$(WRAPPER_NAME)",
- "IsLaunchable" : "NO"
+
+ // Mach-O bundle (not related to a CFBundle)
+ { Type = PackageType;
+ Identifier = com.apple.package-type.mach-o-bundle;
+ Name = "Mach-O Loadable";
+ Description = "Mach-O loadable";
+ DefaultBuildSettings = {
+ EXECUTABLE_PREFIX = "";
+ EXECUTABLE_SUFFIX = ".dylib";
+ EXECUTABLE_NAME = "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)";
+ EXECUTABLE_PATH = "$(EXECUTABLE_NAME)";
+ };
+ ProductReference = {
+ FileType = compiled.mach-o.bundle;
+ Name = "$(EXECUTABLE_NAME)";
+ IsLaunchable = NO;
+ };
},
- "DefaultBuildSettings" : {
- "EXECUTABLE_SUFFIX" : "",
- "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)",
- "EXECUTABLE_PREFIX" : ""
+
+ // CFBundle wrapper
+ { Type = PackageType;
+ Identifier = com.apple.package-type.wrapper;
+ Name = "Wrapper";
+ Description = "Wrapper";
+ DefaultBuildSettings = {
+ PRODUCT_BUNDLE_PACKAGE_TYPE = "BNDL";
+ WRAPPER_PREFIX = "";
+ WRAPPER_SUFFIX = ".bundle";
+ WRAPPER_NAME = "$(WRAPPER_PREFIX)$(PRODUCT_NAME)$(WRAPPER_SUFFIX)";
+ CONTENTS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH_SHALLOW_BUNDLE_$(SHALLOW_BUNDLE))";
+ EXECUTABLE_PREFIX = "";
+ EXECUTABLE_SUFFIX = "";
+ EXECUTABLE_NAME = "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_VARIANT_SUFFIX)$(EXECUTABLE_SUFFIX)";
+ EXECUTABLE_FOLDER_PATH = "$(EXECUTABLE_FOLDER_PATH_SHALLOW_BUNDLE_$(SHALLOW_BUNDLE))";
+ EXECUTABLE_PATH = "$(EXECUTABLE_FOLDER_PATH)/$(EXECUTABLE_NAME)";
+ INFOPLIST_PATH = "$(CONTENTS_FOLDER_PATH)/Info.plist";
+ INFOSTRINGS_PATH = "$(LOCALIZED_RESOURCES_FOLDER_PATH)/InfoPlist.strings";
+ PKGINFO_PATH = "$(CONTENTS_FOLDER_PATH)/PkgInfo";
+ PBDEVELOPMENTPLIST_PATH = "$(CONTENTS_FOLDER_PATH)/pbdevelopment.plist";
+ VERSIONPLIST_PATH = "$(CONTENTS_FOLDER_PATH)/version.plist";
+ PUBLIC_HEADERS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)/Headers";
+ PRIVATE_HEADERS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)/PrivateHeaders";
+ EXECUTABLES_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)/Executables"; // Not the same as EXECUTABLE_FOLDER_PATH
+ FRAMEWORKS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)/Frameworks";
+ SHARED_FRAMEWORKS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)/SharedFrameworks";
+ SHARED_SUPPORT_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)/SharedSupport";
+ UNLOCALIZED_RESOURCES_FOLDER_PATH = "$(UNLOCALIZED_RESOURCES_FOLDER_PATH_SHALLOW_BUNDLE_$(SHALLOW_BUNDLE))";
+ LOCALIZED_RESOURCES_FOLDER_PATH = "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/$(DEVELOPMENT_LANGUAGE).lproj";
+ DOCUMENTATION_FOLDER_PATH = "$(LOCALIZED_RESOURCES_FOLDER_PATH)/Documentation";
+ MODULES_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)/Modules";
+ PLUGINS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)/PlugIns";
+ SCRIPTS_FOLDER_PATH = "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/Scripts";
+ JAVA_FOLDER_PATH = "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/Java";
+ SYSTEM_EXTENSIONS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)/Library/SystemExtensions";
+
+ // Settings specific to deep bundles (macOS)
+ CONTENTS_FOLDER_PATH_SHALLOW_BUNDLE_NO = "$(WRAPPER_NAME)/Contents";
+ EXECUTABLE_FOLDER_PATH_SHALLOW_BUNDLE_NO = "$(CONTENTS_FOLDER_PATH)/MacOS";
+ UNLOCALIZED_RESOURCES_FOLDER_PATH_SHALLOW_BUNDLE_NO = "$(CONTENTS_FOLDER_PATH)/Resources";
+
+ // Settings specific to shallow bundles (iOS, DriverKit on any OS)
+ CONTENTS_FOLDER_PATH_SHALLOW_BUNDLE_YES = "$(WRAPPER_NAME)";
+ EXECUTABLE_FOLDER_PATH_SHALLOW_BUNDLE_YES = "$(CONTENTS_FOLDER_PATH)";
+ UNLOCALIZED_RESOURCES_FOLDER_PATH_SHALLOW_BUNDLE_YES = "$(CONTENTS_FOLDER_PATH)";
+
+ // DriverKit should always use shallow bundles
+ SHALLOW_BUNDLE = "$(SHALLOW_BUNDLE_$(SWIFT_PLATFORM_TARGET_PREFIX))";
+ SHALLOW_BUNDLE_ = YES;
+ SHALLOW_BUNDLE_macos = NO;
+ SHALLOW_BUNDLE_ios = NO; // for macCatalyst
+ SHALLOW_BUNDLE_driverkit = YES;
+ };
+ ProductReference = {
+ FileType = wrapper.cfbundle;
+ Name = "$(WRAPPER_NAME)";
+ IsLaunchable = NO;
+ };
},
- "Type" : "PackageType",
- "BasedOn" : "com.apple.package-type.wrapper.framework",
- "Name" : "Mach-O Static Framework",
- "Identifier" : "com.apple.package-type.wrapper.framework.static",
- "Description" : "Mach-O static framework"
- },
- {
- "ProductReference" : {
- "FileType" : "wrapper.framework",
- "Name" : "$(WRAPPER_NAME)",
- "IsLaunchable" : "NO"
+
+ // Shallow CFBundle wrapper
+ { Type = PackageType;
+ Identifier = com.apple.package-type.wrapper.shallow;
+ BasedOn = com.apple.package-type.wrapper;
+ Name = "Wrapper (Shallow)";
+ Description = "Shallow Wrapper";
+ DefaultBuildSettings = {
+ SHALLOW_BUNDLE = YES;
+ };
+ ProductReference = {
+ FileType = wrapper.cfbundle;
+ Name = "$(WRAPPER_NAME)";
+ IsLaunchable = NO;
+ };
},
- "DefaultBuildSettings" : {
- "UNLOCALIZED_RESOURCES_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)",
- "CONTENTS_FOLDER_PATH" : "$(WRAPPER_NAME)",
- "SHALLOW_BUNDLE" : "YES",
- "VERSIONS_FOLDER_PATH" : "$(WRAPPER_NAME)"
+
+ // Application wrapper
+ { Type = PackageType;
+ Identifier = com.apple.package-type.wrapper.application;
+ BasedOn = com.apple.package-type.wrapper;
+ Name = "Application Wrapper";
+ Description = "Application Wrapper";
+ DefaultBuildSettings = {
+ PRODUCT_BUNDLE_PACKAGE_TYPE = "APPL";
+ GENERATE_PKGINFO_FILE = YES;
+ };
+ ProductReference = {
+ FileType = wrapper.application;
+ Name = "$(WRAPPER_NAME)";
+ IsLaunchable = YES;
+ };
},
- "Type" : "PackageType",
- "BasedOn" : "com.apple.package-type.wrapper.framework",
- "Name" : "Shallow Framework Wrapper",
- "Identifier" : "com.apple.package-type.wrapper.framework.shallow",
- "Description" : "Shallow framework wrapper"
- },
- {
- "ProductReference" : {
- "FileType" : "wrapper.cfbundle",
- "Name" : "$(WRAPPER_NAME)",
- "IsLaunchable" : "NO"
+
+ // Shallow Application wrapper
+ { Type = PackageType;
+ Identifier = com.apple.package-type.wrapper.application.shallow;
+ BasedOn = com.apple.package-type.wrapper.shallow;
+ Name = "Application Wrapper (Shallow)";
+ Description = "Shallow Application Wrapper";
+ DefaultBuildSettings = {
+ PRODUCT_BUNDLE_PACKAGE_TYPE = "APPL";
+ GENERATE_PKGINFO_FILE = YES;
+ SHALLOW_BUNDLE = YES;
+ };
+ ProductReference = {
+ FileType = wrapper.application;
+ Name = "$(WRAPPER_NAME)";
+ IsLaunchable = YES;
+ };
},
- "DefaultBuildSettings" : {
- "WRAPPER_SUFFIX" : "xctest"
+
+ // System extension wrapper
+ {
+ Type = PackageType;
+ Identifier = com.apple.package-type.wrapper.system-extension;
+ BasedOn = com.apple.package-type.wrapper;
+ Name = "System Extension Wrapper";
+ Description = "System Extension Wrapper";
+ DefaultBuildSettings = {
+ PRODUCT_BUNDLE_PACKAGE_TYPE = "SYSX";
+ };
+ ProductReference = {
+ FileType = wrapper.system-extension;
+ Name = "$(WRAPPER_NAME)";
+ IsLaunchable = NO;
+ };
},
- "Type" : "PackageType",
- "BasedOn" : "com.apple.package-type.wrapper",
- "Name" : "Unit Test Bundle",
- "Identifier" : "com.apple.package-type.bundle.unit-test",
- "Description" : "Unit Test Bundle"
- },
- {
- "ProductReference" : {
- "FileType" : "wrapper.cfbundle",
- "Name" : "$(WRAPPER_NAME)",
- "IsLaunchable" : "NO"
+
+ // Driver extension wrapper
+ {
+ Type = PackageType;
+ Identifier = com.apple.package-type.wrapper.driver-extension;
+ BasedOn = com.apple.package-type.wrapper.system-extension;
+ Name = "Driver Extension Wrapper";
+ Description = "Driver Extension Wrapper";
+ DefaultBuildSettings = {
+ PRODUCT_BUNDLE_PACKAGE_TYPE = "DEXT";
+ };
+ ProductReference = {
+ FileType = wrapper.driver-extension;
+ Name = "$(WRAPPER_NAME)";
+ IsLaunchable = NO;
+ };
},
- "DefaultBuildSettings" : {
- "WRAPPER_SUFFIX" : "octest"
+
+ // Kernel extension wrapper
+ { Type = PackageType;
+ Identifier = com.apple.package-type.wrapper.kernel-extension;
+ BasedOn = com.apple.package-type.wrapper;
+ Name = "Kernel Extension Wrapper";
+ Description = "Kernel Extension Wrapper";
+ DefaultBuildSettings = {
+ PRODUCT_BUNDLE_PACKAGE_TYPE = "KEXT";
+ PUBLIC_HEADERS_FOLDER_PATH = "$(KEXT_FRAMEWORK)/Contents/Headers/$(KEXT_FAMILY_NAME)";
+ PRIVATE_HEADERS_FOLDER_PATH = "$(KEXT_FRAMEWORK)/Contents/PrivateHeaders/$(KEXT_FAMILY_NAME)";
+ };
+ ProductReference = {
+ FileType = wrapper.cfbundle;
+ Name = "$(WRAPPER_NAME)";
+ IsLaunchable = NO;
+ };
},
- "Type" : "PackageType",
- "BasedOn" : "com.apple.package-type.wrapper",
- "Name" : "OCUnit Test Bundle",
- "Identifier" : "com.apple.package-type.bundle.ocunit-test",
- "Description" : "OCUnit Test Bundle"
- },
- {
- "ProductReference" : {
- "FileType" : "folder",
- "Name" : "$(WRAPPER_NAME)",
- "IsLaunchable" : "NO"
+
+ // Shallow Kernel extension wrapper
+ { Type = PackageType;
+ Identifier = com.apple.package-type.wrapper.kernel-extension.shallow;
+ BasedOn = com.apple.package-type.wrapper.shallow;
+ Name = "Kernel Extension Wrapper (Shallow)";
+ Description = "Shallow Kernel Extension Wrapper";
+ DefaultBuildSettings = {
+ PRODUCT_BUNDLE_PACKAGE_TYPE = "KEXT";
+ PUBLIC_HEADERS_FOLDER_PATH = "$(KEXT_FRAMEWORK)/Contents/Headers/$(KEXT_FAMILY_NAME)";
+ PRIVATE_HEADERS_FOLDER_PATH = "$(KEXT_FRAMEWORK)/Contents/PrivateHeaders/$(KEXT_FAMILY_NAME)";
+ SHALLOW_BUNDLE = YES;
+ };
+ ProductReference = {
+ FileType = wrapper.cfbundle;
+ Name = "$(WRAPPER_NAME)";
+ IsLaunchable = NO;
+ };
},
- "DefaultBuildSettings" : {
- "EXECUTABLE_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)",
- "JAVA_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)",
- "INFOSTRINGS_PATH" : "$(LOCALIZED_RESOURCES_FOLDER_PATH)\/ContentInfo.strings",
- "INFOPLIST_PATH" : "$(WRAPPER_NAME)\/ContentInfo.plist",
- "WRAPPER_SUFFIX" : "",
- "UNLOCALIZED_RESOURCES_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)",
- "DOCUMENTATION_FOLDER_PATH" : "$(LOCALIZED_RESOURCES_FOLDER_PATH)",
- "EXECUTABLES_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)",
- "LOCALIZED_RESOURCES_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)\/$(DEVELOPMENT_LANGUAGE).lproj",
- "PLUGINS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)",
- "PUBLIC_HEADERS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)",
- "SHARED_SUPPORT_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)",
- "SHARED_FRAMEWORKS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)",
- "PRIVATE_HEADERS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)",
- "SCRIPTS_FOLDER_PATH" : "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)",
- "FRAMEWORKS_FOLDER_PATH" : "$(CONTENTS_FOLDER_PATH)"
+
+ // Framework wrapper
+ { Type = PackageType;
+ Identifier = com.apple.package-type.wrapper.framework;
+ BasedOn = com.apple.package-type.wrapper;
+ Name = "Framework Wrapper";
+ Description = "Framework wrapper";
+ DefaultBuildSettings = {
+ PRODUCT_BUNDLE_PACKAGE_TYPE = "FMWK";
+ WRAPPER_SUFFIX = ".framework";
+ VERSIONS_FOLDER_PATH = "$(VERSIONS_FOLDER_PATH_SHALLOW_BUNDLE_$(SHALLOW_BUNDLE))";
+ CURRENT_VERSION = "Current";
+ INFOPLIST_PATH = "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/Info.plist";
+ PKGINFO_PATH = "$(WRAPPER_NAME)/PkgInfo";
+ VERSIONPLIST_PATH = "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/version.plist";
+ EXECUTABLES_FOLDER_PATH = "$(LOCALIZED_RESOURCES_FOLDER_PATH)"; // Not the same as EXECUTABLE_FOLDER_PATH
+ SHARED_SUPPORT_FOLDER_PATH = "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)";
+ CODESIGNING_FOLDER_PATH = "$(TARGET_BUILD_DIR)/$(CONTENTS_FOLDER_PATH)";
+
+ // Settings specific to deep bundles (macOS)
+ VERSIONS_FOLDER_PATH_SHALLOW_BUNDLE_NO = "$(WRAPPER_NAME)/Versions";
+ CONTENTS_FOLDER_PATH_SHALLOW_BUNDLE_NO = "$(VERSIONS_FOLDER_PATH)/$(FRAMEWORK_VERSION)";
+ EXECUTABLE_FOLDER_PATH_SHALLOW_BUNDLE_NO = "$(CONTENTS_FOLDER_PATH)";
+
+ // Settings specific to shallow bundles (iOS, DriverKit on any OS)
+ VERSIONS_FOLDER_PATH_SHALLOW_BUNDLE_YES = "$(WRAPPER_NAME)";
+ };
+ ProductReference = {
+ FileType = wrapper.framework;
+ Name = "$(WRAPPER_NAME)";
+ IsLaunchable = NO;
+ };
},
- "Type" : "PackageType",
- "BasedOn" : "com.apple.package-type.wrapper",
- "Name" : "In-App Purchase Content",
- "Identifier" : "com.apple.package-type.in-app-purchase-content",
- "Description" : "In-App Purchase Content"
- },
- {
- "ProductReference" : {
- "FileType" : "wrapper.xpc-service",
- "Name" : "$(WRAPPER_NAME)",
- "IsLaunchable" : "NO"
+
+ // Static framework wrapper (like a framework, except that it contains a libX.a instead of a dylib)
+ { Type = PackageType;
+ Identifier = com.apple.package-type.wrapper.framework.static;
+ Name = "Mach-O Static Framework";
+ Description = "Mach-O static framework";
+ BasedOn = com.apple.package-type.wrapper.framework;
+ DefaultBuildSettings = {
+ };
+ ProductReference = {
+ FileType = wrapper.framework.static;
+ Name = "$(WRAPPER_NAME)";
+ IsLaunchable = NO;
+ };
},
- "DefaultBuildSettings" : {
- "WRAPPER_SUFFIX" : ".xpc"
+
+ // Shallow Framework Package
+ { Type = PackageType;
+ Identifier = com.apple.package-type.wrapper.framework.shallow;
+ Name = "Shallow Framework Wrapper";
+ Description = "Shallow framework wrapper";
+ BasedOn = com.apple.package-type.wrapper.framework;
+ DefaultBuildSettings = {
+ SHALLOW_BUNDLE = YES;
+ };
+ ProductReference = {
+ FileType = wrapper.framework;
+ Name = "$(WRAPPER_NAME)";
+ IsLaunchable = NO;
+ };
},
- "Type" : "PackageType",
- "BasedOn" : "com.apple.package-type.wrapper",
- "Name" : "XPC Service",
- "Identifier" : "com.apple.package-type.xpc-service",
- "Description" : "XPC Service"
- },
- {
- "ProductReference" : {
- "FileType" : "wrapper.app-extension",
- "Name" : "$(WRAPPER_NAME)",
- "IsLaunchable" : "NO"
+
+ // Unit Test Bundle wrapper
+ { Type = PackageType;
+ Identifier = com.apple.package-type.bundle.unit-test;
+ BasedOn = com.apple.package-type.wrapper;
+ Name = "Unit Test Bundle";
+ Description = "Unit Test Bundle";
+ DefaultBuildSettings = {
+ WRAPPER_SUFFIX = "xctest";
+ };
+ ProductReference = {
+ FileType = wrapper.cfbundle;
+ Name = "$(WRAPPER_NAME)";
+ IsLaunchable = NO;
+ };
},
- "DefaultBuildSettings" : {
- "WRAPPER_SUFFIX" : ".pluginkit"
+
+ // Legacy OCUnit Test Bundle wrapper
+ { Type = PackageType;
+ Identifier = com.apple.package-type.bundle.ocunit-test;
+ BasedOn = com.apple.package-type.wrapper;
+ Name = "OCUnit Test Bundle";
+ Description = "OCUnit Test Bundle";
+ DefaultBuildSettings = {
+ WRAPPER_SUFFIX = "octest";
+ };
+ ProductReference = {
+ FileType = wrapper.cfbundle;
+ Name = "$(WRAPPER_NAME)";
+ IsLaunchable = NO;
+ };
},
- "Type" : "PackageType",
- "BasedOn" : "com.apple.package-type.xpc-service",
- "Name" : "PlugInKit PlugIn",
- "Identifier" : "com.apple.package-type.pluginkit-plugin",
- "Description" : "PlugInKit PlugIn"
- },
- {
- "ProductReference" : {
- "FileType" : "wrapper.app-extension",
- "Name" : "$(WRAPPER_NAME)",
- "IsLaunchable" : "NO"
+
+ // In-app Purchase Content wrapper
+ { Type = PackageType;
+ Identifier = com.apple.package-type.in-app-purchase-content;
+ BasedOn = com.apple.package-type.wrapper;
+ Name = "In-App Purchase Content";
+ Description = "In-App Purchase Content";
+ DefaultBuildSettings = {
+ PRODUCT_BUNDLE_PACKAGE_TYPE = "";
+ WRAPPER_SUFFIX = "";
+ EXECUTABLE_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)";
+ INFOPLIST_PATH = "$(WRAPPER_NAME)/ContentInfo.plist";
+ INFOSTRINGS_PATH = "$(LOCALIZED_RESOURCES_FOLDER_PATH)/ContentInfo.strings";
+ PUBLIC_HEADERS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)";
+ PRIVATE_HEADERS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)";
+ EXECUTABLES_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)";
+ FRAMEWORKS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)";
+ SHARED_FRAMEWORKS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)";
+ SHARED_SUPPORT_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)";
+ UNLOCALIZED_RESOURCES_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)";
+ LOCALIZED_RESOURCES_FOLDER_PATH = "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/$(DEVELOPMENT_LANGUAGE).lproj";
+ DOCUMENTATION_FOLDER_PATH = "$(LOCALIZED_RESOURCES_FOLDER_PATH)";
+ MODULES_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)";
+ PLUGINS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)";
+ SCRIPTS_FOLDER_PATH = "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)";
+ JAVA_FOLDER_PATH = "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)";
+ };
+ ProductReference = {
+ FileType = folder;
+ Name = "$(WRAPPER_NAME)";
+ IsLaunchable = NO;
+ };
},
- "DefaultBuildSettings" : {
- "WRAPPER_SUFFIX" : ".appex"
+
+ // XPC Service wrapper
+ { Type = PackageType;
+ Identifier = com.apple.package-type.xpc-service;
+ BasedOn = com.apple.package-type.wrapper;
+ Name = "XPC Service";
+ Description = "XPC Service";
+ DefaultBuildSettings = {
+ PRODUCT_BUNDLE_PACKAGE_TYPE = "XPC!";
+ WRAPPER_SUFFIX = ".xpc";
+ };
+ ProductReference = {
+ FileType = wrapper.xpc-service;
+ Name = "$(WRAPPER_NAME)";
+ IsLaunchable = NO;
+ };
},
- "Type" : "PackageType",
- "BasedOn" : "com.apple.package-type.pluginkit-plugin",
- "Name" : "App Extension",
- "Identifier" : "com.apple.package-type.app-extension",
- "Description" : "App Extension"
- },
- {
- "ProductReference" : {
- "FileType" : "wrapper.spotlight-importer",
- "Name" : "$(WRAPPER_NAME)",
- "IsLaunchable" : "NO"
+
+ // PlugInKit PlugIn wrapper
+ { Type = PackageType;
+ Identifier = com.apple.package-type.pluginkit-plugin;
+ BasedOn = com.apple.package-type.xpc-service;
+ Name = "PlugInKit PlugIn";
+ Description = "PlugInKit PlugIn";
+ DefaultBuildSettings = {
+ WRAPPER_SUFFIX = ".pluginkit";
+ };
+ ProductReference = {
+ FileType = wrapper.app-extension;
+ Name = "$(WRAPPER_NAME)";
+ IsLaunchable = NO;
+ };
},
- "DefaultBuildSettings" : {
+
+ // App Extension wrapper
+ { Type = PackageType;
+ Identifier = com.apple.package-type.app-extension;
+ BasedOn = com.apple.package-type.pluginkit-plugin;
+ Name = "App Extension";
+ Description = "App Extension";
+ DefaultBuildSettings = {
+ WRAPPER_SUFFIX = ".appex";
+ };
+ ProductReference = {
+ FileType = wrapper.app-extension;
+ Name = "$(WRAPPER_NAME)";
+ IsLaunchable = NO;
+ };
},
- "Type" : "PackageType",
- "BasedOn" : "com.apple.package-type.wrapper",
- "Name" : "Spotlight Importer",
- "Identifier" : "com.apple.package-type.spotlight-importer",
- "Description" : "Spotlight Importer"
- },
- {
- "DefaultBuildSettings" : {
- "EXECUTABLE_PATH" : "$(EXECUTABLE_NAME)",
- "JAVA_MAKE_ZIPFILE" : "NO",
- "JAVA_ARCHIVE_CLASSES" : "YES",
- "EXECUTABLE_PREFIX" : "",
- "EXECUTABLE_SUFFIX" : ".jar",
- "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_SUFFIX)"
+
+ // Spotlight Importer wrapper
+ { Type = PackageType;
+ Identifier = com.apple.package-type.spotlight-importer;
+ BasedOn = com.apple.package-type.wrapper;
+ Name = "Spotlight Importer";
+ Description = "Spotlight Importer";
+ DefaultBuildSettings = {
+ };
+ ProductReference = {
+ FileType = wrapper.spotlight-importer;
+ Name = "$(WRAPPER_NAME)";
+ IsLaunchable = NO;
+ };
},
- "Identifier" : "com.apple.package-type.jarfile",
- "Type" : "PackageType",
- "Name" : "Jar File",
- "Description" : "Jar file",
- "ProductReference" : {
- "FileType" : "archive.jar",
- "Name" : "$(EXECUTABLE_NAME)",
- "IsLaunchable" : "NO"
- }
- },
- {
- "DefaultBuildSettings" : {
- "EXECUTABLE_PATH" : "$(EXECUTABLE_NAME)",
- "JAVA_MAKE_ZIPFILE" : "YES",
- "JAVA_ARCHIVE_CLASSES" : "YES",
- "EXECUTABLE_PREFIX" : "",
- "EXECUTABLE_SUFFIX" : ".zip",
- "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_SUFFIX)"
+
+ // Jar file
+ { Type = PackageType;
+ Identifier = com.apple.package-type.jarfile;
+ Name = "Jar File";
+ Description = "Jar file";
+ DefaultBuildSettings = {
+ EXECUTABLE_PREFIX = "";
+ EXECUTABLE_SUFFIX = ".jar";
+ EXECUTABLE_NAME = "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_SUFFIX)";
+ EXECUTABLE_PATH = "$(EXECUTABLE_NAME)";
+ JAVA_ARCHIVE_CLASSES = YES;
+ JAVA_MAKE_ZIPFILE = NO;
+ };
+ ProductReference = {
+ FileType = archive.jar;
+ Name = "$(EXECUTABLE_NAME)";
+ IsLaunchable = NO;
+ };
},
- "Identifier" : "com.apple.package-type.zipfile",
- "Type" : "PackageType",
- "Name" : "Zip File",
- "Description" : "Zip file",
- "ProductReference" : {
- "FileType" : "archive.zip",
- "Name" : "$(EXECUTABLE_NAME)",
- "IsLaunchable" : "NO"
- }
- },
- {
- "DefaultBuildSettings" : {
- "EXECUTABLE_PATH" : "$(EXECUTABLE_NAME)",
- "JAVA_ARCHIVE_CLASSES" : "NO",
- "EXECUTABLE_PREFIX" : "",
- "EXECUTABLE_SUFFIX" : "",
- "EXECUTABLE_NAME" : "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_SUFFIX)"
+
+ // Zip file
+ { Type = PackageType;
+ Identifier = com.apple.package-type.zipfile;
+ Name = "Zip File";
+ Description = "Zip file";
+ DefaultBuildSettings = {
+ EXECUTABLE_PREFIX = "";
+ EXECUTABLE_SUFFIX = ".zip";
+ EXECUTABLE_NAME = "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_SUFFIX)";
+ EXECUTABLE_PATH = "$(EXECUTABLE_NAME)";
+ JAVA_ARCHIVE_CLASSES = YES;
+ JAVA_MAKE_ZIPFILE = YES;
+ };
+ ProductReference = {
+ FileType = archive.zip;
+ Name = "$(EXECUTABLE_NAME)";
+ IsLaunchable = NO;
+ };
},
- "Identifier" : "com.apple.package-type.javaclassfolder",
- "Type" : "PackageType",
- "Name" : "Class Folder",
- "Description" : "Class folder",
- "ProductReference" : {
- "FileType" : "wrapper.java-classfolder",
- "Name" : "$(EXECUTABLE_NAME)",
- "IsLaunchable" : "NO"
- }
- }
-]
+
+ // Java class folder
+ { Type = PackageType;
+ Identifier = com.apple.package-type.javaclassfolder;
+ Name = "Class Folder";
+ Description = "Class folder";
+ DefaultBuildSettings = {
+ EXECUTABLE_PREFIX = "";
+ EXECUTABLE_SUFFIX = "";
+ EXECUTABLE_NAME = "$(EXECUTABLE_PREFIX)$(PRODUCT_NAME)$(EXECUTABLE_SUFFIX)";
+ EXECUTABLE_PATH = "$(EXECUTABLE_NAME)";
+ JAVA_ARCHIVE_CLASSES = NO;
+ };
+ ProductReference = {
+ FileType = wrapper.java-classfolder;
+ Name = "$(EXECUTABLE_NAME)";
+ IsLaunchable = NO;
+ };
+ },
+)
diff --git a/share/qbs/modules/bundle/MacOSX-Product-Types.xcspec b/share/qbs/modules/bundle/MacOSX-Product-Types.xcspec
index 8d8450869..bc1d087d6 100644
--- a/share/qbs/modules/bundle/MacOSX-Product-Types.xcspec
+++ b/share/qbs/modules/bundle/MacOSX-Product-Types.xcspec
@@ -1,590 +1,803 @@
-[
- {
- "IconNamePrefix" : "TargetExecutable",
- "DefaultBuildProperties" : {
- "REZ_EXECUTABLE" : "YES",
- "FULL_PRODUCT_NAME" : "$(EXECUTABLE_NAME)",
- "LIBRARY_FLAG_NOSPACE" : "YES",
- "FRAMEWORK_FLAG_PREFIX" : "-framework",
- "INSTALL_PATH" : "\/usr\/local\/bin",
- "GCC_INLINES_ARE_PRIVATE_EXTERN" : "YES",
- "GCC_DYNAMIC_NO_PIC" : "NO",
- "GCC_SYMBOLS_PRIVATE_EXTERN" : "YES",
- "CODE_SIGNING_ALLOWED" : "YES",
- "STRIP_STYLE" : "all",
- "EXECUTABLE_PREFIX" : "",
- "MACH_O_TYPE" : "mh_execute",
- "EXECUTABLE_SUFFIX" : "",
- "LIBRARY_FLAG_PREFIX" : "-l"
+//
+// MacOSX Product Types.xcspec
+//
+// Copyright © 1999-2020 Apple Inc. All rights reserved.
+//
+// Product type specifications in the macOS platform.
+//
+(
+ //
+ // Single-file product types
+ //
+
+ // Tool (normal Unix command-line executable)
+ { Type = ProductType;
+ Identifier = com.apple.product-type.tool;
+ Class = PBXToolProductType;
+ Name = "Command-line Tool";
+ Description = "Standalone command-line tool";
+ IconNamePrefix = "TargetExecutable";
+ DefaultTargetName = "Command-line Tool";
+ DefaultBuildProperties = {
+ FULL_PRODUCT_NAME = "$(EXECUTABLE_NAME)";
+ MACH_O_TYPE = "mh_execute";
+ EXECUTABLE_PREFIX = "";
+ EXECUTABLE_SUFFIX = "";
+ REZ_EXECUTABLE = YES;
+ INSTALL_PATH = "/usr/local/bin";
+ FRAMEWORK_FLAG_PREFIX = "-framework";
+ LIBRARY_FLAG_PREFIX = "-l";
+ LIBRARY_FLAG_NOSPACE = YES;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_SYMBOLS_PRIVATE_EXTERN = YES;
+ GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
+ STRIP_STYLE = "all";
+ CODE_SIGNING_ALLOWED = YES;
+ };
+ PackageTypes = (
+ com.apple.package-type.mach-o-executable // default
+ );
+ WantsSigningEditing = YES;
+ WantsBundleIdentifierEditing = YES;
},
- "PackageTypes" : [
- "com.apple.package-type.mach-o-executable"
- ],
- "Type" : "ProductType",
- "DefaultTargetName" : "Command-line Tool",
- "Name" : "Command-line Tool",
- "Identifier" : "com.apple.product-type.tool",
- "Description" : "Standalone command-line tool",
- "Class" : "PBXToolProductType"
- },
- {
- "IconNamePrefix" : "TargetExecutable",
- "IsJava" : "YES",
- "PackageTypes" : [
- "com.apple.package-type.jarfile",
- "com.apple.package-type.zipfile",
- "com.apple.package-type.javaclassfolder"
- ],
- "Type" : "ProductType",
- "DefaultTargetName" : "Java Command-line Tool",
- "Name" : "Java Command-line Tool",
- "Identifier" : "com.apple.product-type.tool.java",
- "Description" : "Java Command-line tool",
- "DefaultBuildProperties" : {
- "REZ_EXECUTABLE" : "YES",
- "INSTALL_PATH" : "\/usr\/local\/bin",
- "FULL_PRODUCT_NAME" : "$(EXECUTABLE_NAME)"
- }
- },
- {
- "IconNamePrefix" : "TargetPlugin",
- "DefaultBuildProperties" : {
- "DEAD_CODE_STRIPPING" : "NO",
- "REZ_EXECUTABLE" : "YES",
- "LINK_WITH_STANDARD_LIBRARIES" : "NO",
- "FULL_PRODUCT_NAME" : "$(EXECUTABLE_NAME)",
- "LIBRARY_FLAG_NOSPACE" : "YES",
- "FRAMEWORK_FLAG_PREFIX" : "-framework",
- "INSTALL_PATH" : "$(HOME)\/Objects",
- "SKIP_INSTALL" : "YES",
- "GCC_INLINES_ARE_PRIVATE_EXTERN" : "YES",
- "KEEP_PRIVATE_EXTERNS" : "YES",
- "EXECUTABLE_EXTENSION" : "o",
- "PUBLIC_HEADERS_FOLDER_PATH" : "\/usr\/local\/include",
- "MACH_O_TYPE" : "mh_object",
- "EXECUTABLE_SUFFIX" : ".$(EXECUTABLE_EXTENSION)",
- "LIBRARY_FLAG_PREFIX" : "-l",
- "PRIVATE_HEADERS_FOLDER_PATH" : "\/usr\/local\/include",
- "STRIP_STYLE" : "debugging"
+
+ // Java tool
+ { Type = ProductType;
+ Identifier = com.apple.product-type.tool.java;
+ Name = "Java Command-line Tool";
+ Description = "Java Command-line tool";
+ IconNamePrefix = "TargetExecutable";
+ DefaultTargetName = "Java Command-line Tool";
+ DefaultBuildProperties = {
+ FULL_PRODUCT_NAME = "$(EXECUTABLE_NAME)";
+ REZ_EXECUTABLE = YES;
+ INSTALL_PATH = "/usr/local/bin";
+ };
+ IsJava = YES;
+ PackageTypes = (
+ com.apple.package-type.jarfile, // default
+ com.apple.package-type.zipfile,
+ com.apple.package-type.javaclassfolder
+ );
},
- "PackageTypes" : [
- "com.apple.package-type.mach-o-objfile"
- ],
- "Type" : "ProductType",
- "DefaultTargetName" : "Object File",
- "Name" : "Object File",
- "Identifier" : "com.apple.product-type.objfile",
- "Description" : "Object File",
- "Class" : "XCStandaloneExecutableProductType"
- },
- {
- "IconNamePrefix" : "TargetLibrary",
- "DefaultBuildProperties" : {
- "LIBRARY_FLAG_PREFIX" : "-l",
- "STRIP_STYLE" : "debugging",
- "REZ_EXECUTABLE" : "YES",
- "FULL_PRODUCT_NAME" : "$(EXECUTABLE_NAME)",
- "LD_DYLIB_INSTALL_NAME" : "$(DYLIB_INSTALL_NAME_BASE:standardizepath)\/$(EXECUTABLE_PATH)",
- "DYLIB_COMPATIBILITY_VERSION" : "1",
- "INSTALL_PATH" : "\/usr\/local\/lib",
- "FRAMEWORK_FLAG_PREFIX" : "-framework",
- "LIBRARY_FLAG_NOSPACE" : "YES",
- "GCC_INLINES_ARE_PRIVATE_EXTERN" : "YES",
- "CODE_SIGNING_ALLOWED" : "YES",
- "CODE_SIGNING_REQUIRED" : "NO",
- "EXECUTABLE_EXTENSION" : "dylib",
- "PUBLIC_HEADERS_FOLDER_PATH" : "\/usr\/local\/include",
- "DYLIB_INSTALL_NAME_BASE" : "$(INSTALL_PATH)",
- "EXECUTABLE_SUFFIX" : ".$(EXECUTABLE_EXTENSION)",
- "PRIVATE_HEADERS_FOLDER_PATH" : "\/usr\/local\/include",
- "MACH_O_TYPE" : "mh_dylib",
- "DYLIB_CURRENT_VERSION" : "1"
+
+ // Object file
+ { Type = ProductType;
+ Identifier = com.apple.product-type.objfile;
+ Class = XCStandaloneExecutableProductType;
+ Name = "Object File";
+ Description = "Object File";
+ IconNamePrefix = "TargetPlugin";
+ DefaultTargetName = "Object File";
+ DefaultBuildProperties = {
+ FULL_PRODUCT_NAME = "$(EXECUTABLE_NAME)";
+ MACH_O_TYPE = "mh_object";
+ LINK_WITH_STANDARD_LIBRARIES = NO;
+ REZ_EXECUTABLE = YES;
+ EXECUTABLE_SUFFIX = ".$(EXECUTABLE_EXTENSION)";
+ EXECUTABLE_EXTENSION = "o";
+ PUBLIC_HEADERS_FOLDER_PATH = "/usr/local/include";
+ PRIVATE_HEADERS_FOLDER_PATH = "/usr/local/include";
+ INSTALL_PATH = "$(HOME)/Objects";
+ FRAMEWORK_FLAG_PREFIX = "-framework";
+ LIBRARY_FLAG_PREFIX = "-l";
+ LIBRARY_FLAG_NOSPACE = YES;
+ SKIP_INSTALL = YES;
+ STRIP_STYLE = "debugging";
+ GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
+ KEEP_PRIVATE_EXTERNS = YES;
+ DEAD_CODE_STRIPPING = NO;
+ };
+ PackageTypes = (
+ com.apple.package-type.mach-o-objfile // default
+ );
},
- "PackageTypes" : [
- "com.apple.package-type.mach-o-dylib"
- ],
- "Type" : "ProductType",
- "DefaultTargetName" : "Dynamic Library",
- "Name" : "Dynamic Library",
- "Identifier" : "com.apple.product-type.library.dynamic",
- "Description" : "Dynamic library",
- "Class" : "PBXDynamicLibraryProductType"
- },
- {
- "IconNamePrefix" : "TargetLibrary",
- "DefaultBuildProperties" : {
- "STRIP_STYLE" : "debugging",
- "CLANG_ENABLE_MODULE_DEBUGGING" : "NO",
- "REZ_EXECUTABLE" : "YES",
- "FULL_PRODUCT_NAME" : "$(EXECUTABLE_NAME)",
- "LIBRARY_FLAG_NOSPACE" : "YES",
- "FRAMEWORK_FLAG_PREFIX" : "-framework",
- "INSTALL_PATH" : "\/usr\/local\/lib",
- "EXECUTABLE_EXTENSION" : "a",
- "EXECUTABLE_PREFIX" : "lib",
- "PUBLIC_HEADERS_FOLDER_PATH" : "\/usr\/local\/include",
- "EXECUTABLE_SUFFIX" : ".$(EXECUTABLE_EXTENSION)",
- "LIBRARY_FLAG_PREFIX" : "-l",
- "PRIVATE_HEADERS_FOLDER_PATH" : "\/usr\/local\/include",
- "MACH_O_TYPE" : "staticlib"
+
+ // Dynamic library
+ { Type = ProductType;
+ Identifier = com.apple.product-type.library.dynamic;
+ Class = PBXDynamicLibraryProductType;
+ Name = "Dynamic Library";
+ Description = "Dynamic library";
+ IconNamePrefix = "TargetLibrary";
+ DefaultTargetName = "Dynamic Library";
+ DefaultBuildProperties = {
+ FULL_PRODUCT_NAME = "$(EXECUTABLE_NAME)";
+ MACH_O_TYPE = "mh_dylib";
+ REZ_EXECUTABLE = YES;
+ EXECUTABLE_SUFFIX = ".$(EXECUTABLE_EXTENSION)";
+ EXECUTABLE_EXTENSION = "dylib";
+ PUBLIC_HEADERS_FOLDER_PATH = "/usr/local/include";
+ PRIVATE_HEADERS_FOLDER_PATH = "/usr/local/include";
+ INSTALL_PATH = "/usr/local/lib";
+ DYLIB_INSTALL_NAME_BASE = "$(INSTALL_PATH)";
+ LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
+ DYLIB_COMPATIBILITY_VERSION = "1";
+ DYLIB_CURRENT_VERSION = "1";
+ FRAMEWORK_FLAG_PREFIX = "-framework";
+ LIBRARY_FLAG_PREFIX = "-l";
+ LIBRARY_FLAG_NOSPACE = YES;
+ STRIP_STYLE = "debugging";
+ GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
+ CODE_SIGNING_ALLOWED = YES;
+ CODE_SIGNING_REQUIRED = NO;
+ };
+ PackageTypes = (
+ com.apple.package-type.mach-o-dylib // default
+ );
},
- "AlwaysPerformSeparateStrip" : "YES",
- "PackageTypes" : [
- "com.apple.package-type.static-library"
- ],
- "Type" : "ProductType",
- "DefaultTargetName" : "Static Library",
- "Name" : "Static Library",
- "Identifier" : "com.apple.product-type.library.static",
- "Description" : "Static library",
- "Class" : "PBXStaticLibraryProductType"
- },
- {
- "IconNamePrefix" : "TargetPlugin",
- "IsJava" : "YES",
- "PackageTypes" : [
- "com.apple.package-type.jarfile",
- "com.apple.package-type.zipfile",
- "com.apple.package-type.javaclassfolder"
- ],
- "Type" : "ProductType",
- "DefaultTargetName" : "Java Library",
- "Name" : "Java Library",
- "Identifier" : "com.apple.product-type.library.java.archive",
- "Description" : "Java library packaged as a Jar file, Zip file, or class folder",
- "DefaultBuildProperties" : {
- "INSTALL_PATH" : "\/usr\/local\/lib",
- "FULL_PRODUCT_NAME" : "$(PRODUCT_NAME)"
- }
- },
- {
- "HasInfoPlistStrings" : "YES",
- "Description" : "Generic bundle",
- "HasInfoPlist" : "YES",
- "Name" : "Bundle",
- "Class" : "PBXBundleProductType",
- "DefaultTargetName" : "Bundle",
- "DefaultBuildProperties" : {
- "LIBRARY_FLAG_NOSPACE" : "YES",
- "WRAPPER_NAME" : "$(WRAPPER_PREFIX)$(PRODUCT_NAME)$(WRAPPER_SUFFIX)",
- "FRAMEWORK_FLAG_PREFIX" : "-framework",
- "GCC_INLINES_ARE_PRIVATE_EXTERN" : "YES",
- "WRAPPER_SUFFIX" : ".$(WRAPPER_EXTENSION)",
- "FULL_PRODUCT_NAME" : "$(WRAPPER_NAME)",
- "WRAPPER_EXTENSION" : "bundle",
- "CODE_SIGNING_ALLOWED" : "YES",
- "WRAPPER_PREFIX" : "",
- "STRIP_STYLE" : "non-global",
- "MACH_O_TYPE" : "mh_bundle",
- "LIBRARY_FLAG_PREFIX" : "-l"
+
+ // Static library
+ { Type = ProductType;
+ Identifier = com.apple.product-type.library.static;
+ Class = PBXStaticLibraryProductType;
+ Name = "Static Library";
+ Description = "Static library";
+ IconNamePrefix = "TargetLibrary";
+ DefaultTargetName = "Static Library";
+ DefaultBuildProperties = {
+ FULL_PRODUCT_NAME = "$(EXECUTABLE_NAME)";
+ MACH_O_TYPE = "staticlib";
+ REZ_EXECUTABLE = YES;
+ EXECUTABLE_PREFIX = "lib";
+ EXECUTABLE_SUFFIX = ".$(EXECUTABLE_EXTENSION)";
+ EXECUTABLE_EXTENSION = "a";
+ PUBLIC_HEADERS_FOLDER_PATH = "/usr/local/include";
+ PRIVATE_HEADERS_FOLDER_PATH = "/usr/local/include";
+ INSTALL_PATH = "/usr/local/lib";
+ FRAMEWORK_FLAG_PREFIX = "-framework";
+ LIBRARY_FLAG_PREFIX = "-l";
+ LIBRARY_FLAG_NOSPACE = YES;
+ STRIP_STYLE = "debugging";
+ CLANG_ENABLE_MODULE_DEBUGGING = NO;
+ CODE_SIGNING_ALLOWED = NO;
+ };
+ AlwaysPerformSeparateStrip = YES;
+ PackageTypes = (
+ com.apple.package-type.static-library // default
+ );
},
- "PackageTypes" : [
- "com.apple.package-type.wrapper",
- "com.apple.package-type.wrapper.shallow"
- ],
- "IsWrapper" : "YES",
- "Type" : "ProductType",
- "Identifier" : "com.apple.product-type.bundle",
- "IconNamePrefix" : "TargetPlugin"
- },
- {
- "PackageTypes" : [
- "com.apple.package-type.wrapper.shallow"
- ],
- "Type" : "ProductType",
- "BasedOn" : "com.apple.product-type.bundle",
- "Name" : "Bundle (Shallow)",
- "Identifier" : "com.apple.product-type.bundle.shallow",
- "Description" : "Bundle (Shallow)",
- "Class" : "PBXBundleProductType"
- },
- {
- "Description" : "Application",
- "Class" : "PBXApplicationProductType",
- "Name" : "Application",
- "RunpathSearchPathForEmbeddedFrameworks" : "@executable_path\/..\/Frameworks",
- "ValidateEmbeddedBinaries" : "YES",
- "ProvisioningProfileSupported" : "YES",
- "DefaultTargetName" : "Application",
- "DefaultBuildProperties" : {
- "INSTALL_PATH" : "$(LOCAL_APPS_DIR)",
- "WRAPPER_EXTENSION" : "app",
- "GCC_DYNAMIC_NO_PIC" : "NO",
- "STRIP_STYLE" : "all",
- "CODE_SIGNING_ALLOWED" : "YES",
- "GCC_INLINES_ARE_PRIVATE_EXTERN" : "YES",
- "WRAPPER_SUFFIX" : ".$(WRAPPER_EXTENSION)",
- "GCC_SYMBOLS_PRIVATE_EXTERN" : "YES",
- "MACH_O_TYPE" : "mh_execute"
+
+ // Java library (jar or zip file)
+ { Type = ProductType;
+ Identifier = com.apple.product-type.library.java.archive;
+ Name = "Java Library";
+ Description = "Java library packaged as a Jar file, Zip file, or class folder";
+ IconNamePrefix = "TargetPlugin";
+ DefaultTargetName = "Java Library";
+ DefaultBuildProperties = {
+ FULL_PRODUCT_NAME = "$(PRODUCT_NAME)";
+ INSTALL_PATH = "/usr/local/lib";
+ };
+ IsJava = YES;
+ PackageTypes = (
+ com.apple.package-type.jarfile, // default
+ com.apple.package-type.zipfile,
+ com.apple.package-type.javaclassfolder
+ );
},
- "BasedOn" : "com.apple.product-type.bundle",
- "ProvisioningProfileRequired" : "NO",
- "PackageTypes" : [
- "com.apple.package-type.wrapper.application"
- ],
- "Type" : "ProductType",
- "CanEmbedCompilerSanitizerLibraries" : "YES",
- "Identifier" : "com.apple.product-type.application",
- "IconNamePrefix" : "TargetApp"
- },
- {
- "PackageTypes" : [
- "com.apple.package-type.wrapper.application.shallow"
- ],
- "Type" : "ProductType",
- "BasedOn" : "com.apple.product-type.application",
- "Name" : "Application (Shallow Bundle)",
- "Identifier" : "com.apple.product-type.application.shallow",
- "Description" : "Application (Shallow Bundle)",
- "Class" : "PBXApplicationProductType"
- },
- {
- "DefaultBuildProperties" : {
- "PKGINFO_PATH" : "",
- "INFOPLIST_PATH" : ""
+
+
+ //
+ // Wrapper product types
+ //
+
+ // Bundle
+ { Type = ProductType;
+ Identifier = com.apple.product-type.bundle;
+ Class = PBXBundleProductType;
+ Name = "Bundle";
+ Description = "Generic bundle";
+ IconNamePrefix = "TargetPlugin";
+ DefaultTargetName = "Bundle";
+ DefaultBuildProperties = {
+ FULL_PRODUCT_NAME = "$(WRAPPER_NAME)";
+ MACH_O_TYPE = "mh_bundle";
+ WRAPPER_PREFIX = "";
+ WRAPPER_SUFFIX = ".$(WRAPPER_EXTENSION)";
+ WRAPPER_EXTENSION = "bundle";
+ WRAPPER_NAME = "$(WRAPPER_PREFIX)$(PRODUCT_NAME)$(WRAPPER_SUFFIX)";
+ FRAMEWORK_FLAG_PREFIX = "-framework";
+ LIBRARY_FLAG_PREFIX = "-l";
+ LIBRARY_FLAG_NOSPACE = YES;
+ STRIP_STYLE = "non-global";
+ GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
+ CODE_SIGNING_ALLOWED = YES;
+ };
+ PackageTypes = (
+ com.apple.package-type.wrapper, // default
+ com.apple.package-type.wrapper.shallow // Not clear if this is needed in the presence of the Shallow Bundle product type below.
+ );
+ IsWrapper = YES;
+ HasInfoPlist = YES;
+ HasInfoPlistStrings = YES;
+ WantsBundleIdentifierEditing = YES;
+ WantsSigningEditing = YES;
},
- "IsJava" : "YES",
- "Type" : "ProductType",
- "BasedOn" : "com.apple.product-type.application",
- "Name" : "Java Application",
- "Identifier" : "com.apple.product-type.application.java",
- "Description" : "Java Application",
- "DefaultTargetName" : "Java Application"
- },
- {
- "IconNamePrefix" : "TargetFramework",
- "DefaultTargetName" : "Framework",
- "DefaultBuildProperties" : {
- "CODE_SIGNING_REQUIRES_TEAM" : "YES",
- "LD_DYLIB_INSTALL_NAME" : "$(DYLIB_INSTALL_NAME_BASE:standardizepath)\/$(EXECUTABLE_PATH)",
- "CODE_SIGNING_REQUIRED" : "NO",
- "CODE_SIGNING_ALLOWED" : "YES",
- "INSTALL_PATH" : "$(LOCAL_LIBRARY_DIR)\/Frameworks",
- "WRAPPER_SUFFIX" : ".$(WRAPPER_EXTENSION)",
- "WRAPPER_EXTENSION" : "framework",
- "FRAMEWORK_VERSION" : "A",
- "ENTITLEMENTS_REQUIRED" : "NO",
- "STRIP_STYLE" : "debugging",
- "DYLIB_INSTALL_NAME_BASE" : "$(INSTALL_PATH)",
- "MACH_O_TYPE" : "mh_dylib"
+
+ // Shallow Bundle Product
+ { Type = ProductType;
+ Identifier = com.apple.product-type.bundle.shallow;
+ BasedOn = com.apple.product-type.bundle;
+ Class = PBXBundleProductType;
+ Name = "Bundle (Shallow)";
+ Description = "Bundle (Shallow)";
+ PackageTypes = (
+ com.apple.package-type.wrapper.shallow
+ );
},
- "PackageTypes" : [
- "com.apple.package-type.wrapper.framework"
- ],
- "Type" : "ProductType",
- "BasedOn" : "com.apple.product-type.bundle",
- "Name" : "Framework",
- "Identifier" : "com.apple.product-type.framework",
- "Description" : "Framework",
- "Class" : "PBXFrameworkProductType"
- },
- {
- "PackageTypes" : [
- "com.apple.package-type.wrapper.framework.shallow"
- ],
- "Type" : "ProductType",
- "BasedOn" : "com.apple.product-type.framework",
- "Name" : "Framework (Shallow Bundle)",
- "Identifier" : "com.apple.product-type.framework.shallow",
- "Description" : "Framework (Shallow Bundle)",
- "Class" : "PBXFrameworkProductType"
- },
- {
- "IconNamePrefix" : "TargetFramework",
- "DefaultTargetName" : "Static Framework",
- "DefaultBuildProperties" : {
- "WRAPPER_EXTENSION" : "framework",
- "DYLIB_INSTALL_NAME_BASE" : "",
- "CODE_SIGNING_ALLOWED" : "NO",
- "FRAMEWORK_VERSION" : "A",
- "LD_DYLIB_INSTALL_NAME" : "",
- "GCC_INLINES_ARE_PRIVATE_EXTERN" : "NO",
- "INSTALL_PATH" : "$(LOCAL_LIBRARY_DIR)\/Frameworks",
- "WRAPPER_SUFFIX" : ".$(WRAPPER_EXTENSION)",
- "MACH_O_TYPE" : "staticlib"
+
+ // Application
+ { Type = ProductType;
+ Identifier = com.apple.product-type.application;
+ BasedOn = com.apple.product-type.bundle;
+ Class = PBXApplicationProductType;
+ Name = "Application";
+ Description = "Application";
+ IconNamePrefix = "TargetApp";
+ DefaultTargetName = "Application";
+ DefaultBuildProperties = {
+ MACH_O_TYPE = "mh_execute";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_SYMBOLS_PRIVATE_EXTERN = YES;
+ GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
+ WRAPPER_SUFFIX = ".$(WRAPPER_EXTENSION)";
+ WRAPPER_EXTENSION = "app";
+ INSTALL_PATH = "$(LOCAL_APPS_DIR)";
+ STRIP_STYLE = "all";
+ CODE_SIGNING_ALLOWED = YES;
+ LD_RUNPATH_SEARCH_PATHS = "$(LD_RUNPATH_SEARCH_PATHS_$(IS_MACCATALYST))";
+ LD_RUNPATH_SEARCH_PATHS_YES = ( "@loader_path/../Frameworks", );
+ };
+ PackageTypes = (
+ com.apple.package-type.wrapper.application // default
+ );
+
+ /** Product type validation hooks */
+ Validation = {
+
+ // Checks - a dictionary of checks that are perform just prior to building the product
+ // Each dictionary key is the "XCPropertyMacroExpression" to evaluate
+ // The dictionary value contains the error message to display if the condition evaluates to false.
+ Checks = {
+ // This is intentially empty as currently all of the checks are done in-code for this particular application type. However, we enable the plubmbing for the validation tool spec infrastructure to be called to avoid any further hacks in pbxbuild or xcbuild. This is to enable rdar://problem/45590882.
+ };
+
+ // Determines if the legacy build system has support for this validation hook. This is a workaround for enabling additional validation in xcbuild (specifically for rdar://problem/45590882), which does not have the same plugin restriction that is imposed on pbxbuild's implementation of the validation hooks.
+ EnabledForLegacyBuildSystem = NO;
+
+ // ValidationToolSpec - the identifier of the tool (script) to run after a target is constructed.
+ ValidationToolSpec = "com.apple.build-tools.platform.validate";
+ };
+ CanEmbedCompilerSanitizerLibraries = YES;
+ RunpathSearchPathForEmbeddedFrameworks = "@executable_path/../Frameworks";
+ ValidateEmbeddedBinaries = YES;
+ ProvisioningProfileSupported = YES;
+ ProvisioningProfileRequired = NO;
+ WantsBundleIdentifierEditing = YES;
+ WantsSigningEditing = YES;
},
- "AlwaysPerformSeparateStrip" : "YES",
- "PackageTypes" : [
- "com.apple.package-type.wrapper.framework.static"
- ],
- "Type" : "ProductType",
- "BasedOn" : "com.apple.product-type.framework",
- "Name" : "Static Framework",
- "Identifier" : "com.apple.product-type.framework.static",
- "Description" : "Static Framework",
- "Class" : "XCStaticFrameworkProductType"
- },
- {
- "DefaultTargetName" : "Kernel Extension",
- "DefaultBuildProperties" : {
- "GCC_ENABLE_BUILTIN_FUNCTIONS" : "NO",
- "MODULE_START" : "0",
- "PRIVATE_HEADERS_FOLDER_PATH" : "$(KEXT_FRAMEWORK)\/Contents\/PrivateHeaders\/$(KEXT_FAMILY_NAME)",
- "WRAPPER_SUFFIX" : ".$(WRAPPER_EXTENSION)",
- "MACH_O_TYPE" : "mh_execute",
- "GCC_ENABLE_KERNEL_DEVELOPMENT" : "YES",
- "PRODUCT_TYPE_CPLUSPLUSFLAGS" : "$(inherited) $(KEXT_CPLUSPLUSFLAGS)",
- "MODULE_STOP" : "0",
- "GCC_ENABLE_FLOATING_POINT_LIBRARY_CALLS" : "YES",
- "GCC_PRODUCT_TYPE_PREPROCESSOR_DEFINITIONS" : "$(inherited) KERNEL KERNEL_PRIVATE DRIVER_PRIVATE APPLE NeXT",
- "GCC_DISABLE_STATIC_FUNCTION_INLINING" : "YES",
- "ENABLE_APPLE_KEXT_CODE_GENERATION" : "YES",
- "CODE_SIGNING_ALLOWED" : "YES",
- "GCC_FORCE_CPU_SUBTYPE_ALL" : "YES",
- "PRODUCT_SPECIFIC_LDFLAGS" : "$(inherited) $(KEXT_LDFLAGS)",
- "WRAPPER_EXTENSION" : "kext",
- "KERNEL_EXTENSION_HEADER_SEARCH_PATHS" : "$(KERNEL_FRAMEWORK)\/PrivateHeaders $(KERNEL_FRAMEWORK_HEADERS)",
- "GCC_INLINES_ARE_PRIVATE_EXTERN" : "NO",
- "PRODUCT_TYPE_CFLAGS" : "$(inherited) $(KEXT_CFLAGS)",
- "KEXT_FRAMEWORK_NAME" : "Kernel",
- "GCC_NO_COMMON_BLOCKS" : "YES",
- "GCC_ENABLE_PASCAL_STRINGS" : "NO",
- "PUBLIC_HEADERS_FOLDER_PATH" : "$(KEXT_FRAMEWORK)\/Contents\/Headers\/$(KEXT_FAMILY_NAME)",
- "GCC_ENABLE_FUNCTION_INLINING" : "YES",
- "KERNEL_FRAMEWORK_HEADERS" : "$(KERNEL_FRAMEWORK)\/Headers",
- "KEXT_FAMILY_NAME" : "family",
- "KEXT_FRAMEWORK" : "$(SYSTEM_LIBRARY_DIR)\/Frameworks\/$(KEXT_FRAMEWORK_NAME).framework",
- "GCC_ENABLE_CPP_EXCEPTIONS" : "NO",
- "GCC_ENABLE_CPP_RTTI" : "NO",
- "MODULE_NAME" : "com.company.driver.modulename",
- "GCC_USE_STANDARD_INCLUDE_SEARCHING" : "NO",
- "KERNEL_FRAMEWORK" : "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)\/Frameworks\/Kernel.framework",
- "MODULE_VERSION" : "1.0",
- "INSTALL_PATH" : "$(DEFAULT_KEXT_INSTALL_PATH)",
- "PRODUCT_TYPE_HEADER_SEARCH_PATHS" : "$(inherited) $(KERNEL_EXTENSION_HEADER_SEARCH_PATHS)",
- "GCC_CHECK_RETURN_VALUE_OF_OPERATOR_NEW" : "YES",
- "STRIP_STYLE" : "debugging"
+
+ // Shallow Application Product
+ { Type = ProductType;
+ Identifier = com.apple.product-type.application.shallow;
+ BasedOn = com.apple.product-type.application;
+ Class = PBXApplicationProductType; // see radar 5604879, this shouldn't be necesary
+ Name = "Application (Shallow Bundle)";
+ Description = "Application (Shallow Bundle)";
+ PackageTypes = (
+ com.apple.package-type.wrapper.application.shallow
+ );
},
- "PackageTypes" : [
- "com.apple.package-type.wrapper.kernel-extension",
- "com.apple.package-type.wrapper.kernel-extension.shallow"
- ],
- "Type" : "ProductType",
- "BasedOn" : "com.apple.product-type.bundle",
- "Name" : "Kernel Extension",
- "Identifier" : "com.apple.product-type.kernel-extension",
- "Description" : "Kernel extension",
- "Class" : "XCKernelExtensionProductType"
- },
- {
- "DefaultBuildProperties" : {
+ // Java Application
+ { Type = ProductType;
+ Identifier = com.apple.product-type.application.java;
+ BasedOn = com.apple.product-type.application;
+ Name = "Java Application";
+ Description = "Java Application";
+ DefaultTargetName = "Java Application";
+ DefaultBuildProperties = {
+ INFOPLIST_PATH = "";
+ PKGINFO_PATH = "";
+ };
+ IsJava = YES;
},
- "PackageTypes" : [
- "com.apple.package-type.wrapper.kernel-extension.shallow"
- ],
- "Type" : "ProductType",
- "BasedOn" : "com.apple.product-type.kernel-extension",
- "Name" : "Kernel Extension (Shallow)",
- "Identifier" : "com.apple.product-type.kernel-extension.shallow",
- "Description" : "Kernel extension (shallow)",
- "Class" : "XCKernelExtensionProductType"
- },
- {
- "DefaultTargetName" : "IOKit Kernel Extension",
- "DefaultBuildProperties" : {
- "CODE_SIGNING_ALLOWED" : "YES"
+
+ // Framework
+ { Type = ProductType;
+ Identifier = com.apple.product-type.framework;
+ BasedOn = com.apple.product-type.bundle;
+ Class = PBXFrameworkProductType;
+ Name = "Framework";
+ Description = "Framework";
+ IconNamePrefix = "TargetFramework";
+ DefaultTargetName = "Framework";
+ DefaultBuildProperties = {
+ MACH_O_TYPE = "mh_dylib";
+ FRAMEWORK_VERSION = "A";
+ WRAPPER_SUFFIX = ".$(WRAPPER_EXTENSION)";
+ WRAPPER_EXTENSION = "framework";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ DYLIB_INSTALL_NAME_BASE = "$(INSTALL_PATH)";
+ LD_DYLIB_INSTALL_NAME = "$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)";
+ STRIP_STYLE = "debugging";
+ CODE_SIGNING_ALLOWED = YES;
+ CODE_SIGNING_REQUIRED = NO;
+ ENTITLEMENTS_REQUIRED = NO;
+ CODE_SIGNING_REQUIRES_TEAM = YES;
+ };
+ PackageTypes = (
+ com.apple.package-type.wrapper.framework // default
+ );
},
- "PackageTypes" : [
- "com.apple.package-type.wrapper.kernel-extension",
- "com.apple.package-type.wrapper.kernel-extension.shallow"
- ],
- "Type" : "ProductType",
- "BasedOn" : "com.apple.product-type.kernel-extension",
- "Name" : "IOKit Kernel Extension",
- "Identifier" : "com.apple.product-type.kernel-extension.iokit",
- "Description" : "IOKit Kernel extension",
- "Class" : "XCKernelExtensionProductType"
- },
- {
- "DefaultTargetName" : "IOKit Kernel Extension (Shallow)",
- "DefaultBuildProperties" : {
+ // Shallow Framework Product
+ { Type = ProductType;
+ Identifier = com.apple.product-type.framework.shallow;
+ BasedOn = com.apple.product-type.framework;
+ Class = PBXFrameworkProductType;
+ Name = "Framework (Shallow Bundle)";
+ Description = "Framework (Shallow Bundle)";
+ PackageTypes = (
+ com.apple.package-type.wrapper.framework.shallow
+ );
},
- "PackageTypes" : [
- "com.apple.package-type.wrapper.kernel-extension.shallow"
- ],
- "Type" : "ProductType",
- "BasedOn" : "com.apple.product-type.kernel-extension",
- "Name" : "IOKit Kernel Extension (Shallow)",
- "Identifier" : "com.apple.product-type.kernel-extension.iokit.shallow",
- "Description" : "IOKit Kernel extension (Shallow)",
- "Class" : "XCKernelExtensionProductType"
- },
- {
- "DefaultBuildProperties" : {
- "TEST_FRAMEWORK_SEARCH_PATHS" : [
- "$(inherited)",
- "$(PLATFORM_DIR)\/Developer\/Library\/Frameworks"
- ],
- "PRODUCT_SPECIFIC_LDFLAGS" : "-framework XCTest",
- "WRAPPER_EXTENSION" : "xctest",
- "PRODUCT_TYPE_FRAMEWORK_SEARCH_PATHS" : "$(TEST_FRAMEWORK_SEARCH_PATHS)"
+
+ // Static framework
+ { Type = ProductType;
+ Identifier = com.apple.product-type.framework.static;
+ BasedOn = com.apple.product-type.framework;
+ Class = XCStaticFrameworkProductType;
+ Name = "Static Framework";
+ Description = "Static Framework";
+ IconNamePrefix = "TargetFramework";
+ DefaultTargetName = "Static Framework";
+ DefaultBuildProperties = {
+ MACH_O_TYPE = "staticlib";
+ FRAMEWORK_VERSION = "A";
+ WRAPPER_SUFFIX = ".$(WRAPPER_EXTENSION)";
+ WRAPPER_EXTENSION = "framework";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ DYLIB_INSTALL_NAME_BASE = "";
+ LD_DYLIB_INSTALL_NAME = "";
+ GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
+ CODE_SIGNING_ALLOWED = NO;
+ };
+ AlwaysPerformSeparateStrip = YES;
+ PackageTypes = (
+ com.apple.package-type.wrapper.framework.static // default
+ );
},
- "PackageTypes" : [
- "com.apple.package-type.bundle.unit-test"
- ],
- "CanEmbedCompilerSanitizerLibraries" : "YES",
- "IsUnitTest" : "YES",
- "Type" : "ProductType",
- "BasedOn" : "com.apple.product-type.bundle",
- "Name" : "Unit Test Bundle",
- "Identifier" : "com.apple.product-type.bundle.unit-test",
- "Description" : "Unit Test Bundle",
- "Class" : "PBXXCTestBundleProductType"
- },
- {
- "DefaultBuildProperties" : {
- "TEST_FRAMEWORK_SEARCH_PATHS" : [
- "$(inherited)",
- "$(PLATFORM_DIR)\/Developer\/Library\/Frameworks"
- ],
- "PRODUCT_SPECIFIC_LDFLAGS" : "-framework XCTest",
- "WRAPPER_EXTENSION" : "xctest",
- "USES_XCTRUNNER" : "YES",
- "PRODUCT_TYPE_FRAMEWORK_SEARCH_PATHS" : "$(TEST_FRAMEWORK_SEARCH_PATHS)"
+
+ // System extension
+ { Type = ProductType;
+ Identifier = com.apple.product-type.system-extension;
+ BasedOn = com.apple.product-type.bundle;
+ Name = "DriverKit Driver";
+ Description = "DriverKit driver";
+ DefaultTargetName = "DriverKit Driver";
+ DefaultBuildProperties = {
+ MACH_O_TYPE = "mh_execute";
+ WRAPPER_SUFFIX = ".$(WRAPPER_EXTENSION)";
+ WRAPPER_EXTENSION = "systemextension";
+
+ PRODUCT_NAME = "$(PRODUCT_BUNDLE_IDENTIFIER)";
+ };
+ PackageTypes = (
+ com.apple.package-type.wrapper.system-extension,
+ );
+ ProvisioningProfileSupported = YES;
+ ProvisioningProfileRequired = NO;
},
- "PackageTypes" : [
- "com.apple.package-type.bundle.unit-test"
- ],
- "ProvisioningProfileSupported" : "YES",
- "IsUITest" : "YES",
- "Type" : "ProductType",
- "BasedOn" : "com.apple.product-type.bundle.unit-test",
- "Name" : "UI Testing Bundle",
- "Identifier" : "com.apple.product-type.bundle.ui-testing",
- "Description" : "UI Testing Bundle",
- "Class" : "PBXXCTestBundleProductType"
- },
- {
- "DefaultBuildProperties" : {
- "WRAPPER_EXTENSION" : "octest"
+
+ // DriverKit driver
+ { Type = ProductType;
+ Identifier = com.apple.product-type.driver-extension;
+ BasedOn = com.apple.product-type.system-extension;
+ Name = "DriverKit Driver";
+ Description = "DriverKit driver";
+ DefaultTargetName = "DriverKit Driver";
+ DefaultBuildProperties = {
+ SDKROOT = "driverkit";
+ MACH_O_TYPE = "mh_execute";
+ WRAPPER_SUFFIX = ".$(WRAPPER_EXTENSION)";
+ WRAPPER_EXTENSION = "dext";
+ INSTALL_PATH = "$(DEFAULT_DEXT_INSTALL_PATH)";
+ STRIP_STYLE = "debugging";
+
+ DEXT_FRAMEWORK_NAME = "DriverKit";
+ DEXT_FRAMEWORK = "$(SYSTEM_LIBRARY_DIR)/Frameworks/$(DEXT_FRAMEWORK_NAME).framework";
+
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+
+ PRODUCT_NAME = "$(PRODUCT_BUNDLE_IDENTIFIER)";
+ PRODUCT_TYPE_HEADER_SEARCH_PATHS = "$(inherited) $(IIG_HEADERS_DIR)";
+ };
+ DefaultEntitlements = {
+ "com.apple.developer.driverkit" = YES;
+ };
+ PackageTypes = (
+ com.apple.package-type.wrapper.driver-extension,
+ );
},
- "PackageTypes" : [
- "com.apple.package-type.bundle.ocunit-test"
- ],
- "IsUnitTest" : "YES",
- "Type" : "ProductType",
- "BasedOn" : "com.apple.product-type.bundle",
- "Name" : "OCUnit Test Bundle",
- "Identifier" : "com.apple.product-type.bundle.ocunit-test",
- "Description" : "OCUnit Test Bundle",
- "Class" : "PBXBundleProductType"
- },
- {
- "HasInfoPlistStrings" : "NO",
- "PackageTypes" : [
- "com.apple.package-type.in-app-purchase-content"
- ],
- "HasInfoPlist" : "YES",
- "IsWrapper" : "YES",
- "Type" : "ProductType",
- "DefaultBuildProperties" : {
- "FULL_PRODUCT_NAME" : "$(WRAPPER_NAME)"
+
+ // Kernel Extension
+ { Type = ProductType;
+ Identifier = com.apple.product-type.kernel-extension;
+ BasedOn = com.apple.product-type.bundle;
+ Class = XCKernelExtensionProductType;
+ Name = "Kernel Extension";
+ Description = "Kernel extension";
+ DefaultTargetName = "Kernel Extension";
+ DefaultBuildProperties = {
+ MACH_O_TYPE = "mh_execute";
+ WRAPPER_SUFFIX = ".$(WRAPPER_EXTENSION)";
+ WRAPPER_EXTENSION = "kext";
+ INSTALL_PATH = "$(DEFAULT_KEXT_INSTALL_PATH)";
+ STRIP_STYLE = "debugging";
+
+ KEXT_FRAMEWORK_NAME = "Kernel";
+ KEXT_FRAMEWORK = "$(SYSTEM_LIBRARY_DIR)/Frameworks/$(KEXT_FRAMEWORK_NAME).framework";
+ KEXT_FAMILY_NAME = "family";
+ PUBLIC_HEADERS_FOLDER_PATH = "$(KEXT_FRAMEWORK)/Contents/Headers/$(KEXT_FAMILY_NAME)";
+ PRIVATE_HEADERS_FOLDER_PATH = "$(KEXT_FRAMEWORK)/Contents/PrivateHeaders/$(KEXT_FAMILY_NAME)";
+ MODULE_NAME = "com.company.driver.modulename";
+ MODULE_VERSION = "1.0";
+ MODULE_START = "0";
+ MODULE_STOP = "0";
+
+ ENABLE_APPLE_KEXT_CODE_GENERATION = YES; // -fapple-kext
+ GCC_ENABLE_KERNEL_DEVELOPMENT = YES; // -mkernel
+
+ GCC_USE_STANDARD_INCLUDE_SEARCHING = NO; // -nostdinc
+ GCC_ENABLE_PASCAL_STRINGS = NO; // Disables -fpascal-strings
+ GCC_FORCE_CPU_SUBTYPE_ALL = YES; // -force_cpusubtype_ALL
+ GCC_CHECK_RETURN_VALUE_OF_OPERATOR_NEW = YES; // -fcheck-new
+ GCC_INLINES_ARE_PRIVATE_EXTERN = NO; // -fvisibility-inlines-hidden
+ GCC_ENABLE_BUILTIN_FUNCTIONS = NO; // -fno-builtin
+ GCC_NO_COMMON_BLOCKS = YES; // -fno-common
+ GCC_ENABLE_CPP_EXCEPTIONS = NO; // -fno-exceptions
+ GCC_ENABLE_CPP_RTTI = NO; // -fno-rtti
+
+ // Supposedly these two flags are the default in GCC, but they're provided here for compatibility with older Xcode versions.
+ GCC_ENABLE_FUNCTION_INLINING = YES; // -finline
+ GCC_DISABLE_STATIC_FUNCTION_INLINING = YES; // -fno-keep-inline-functions
+
+ // Per-product-type settings.
+ // The KERNEL_*** settings are defined differently for some SDKs, so we continue to use them for compatibility reasons.
+ KERNEL_FRAMEWORK = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/Kernel.framework";
+ KERNEL_FRAMEWORK_HEADERS = "$(KERNEL_FRAMEWORK)/Headers";
+ KERNEL_EXTENSION_HEADER_SEARCH_PATHS = "$(KERNEL_FRAMEWORK)/PrivateHeaders $(KERNEL_FRAMEWORK_HEADERS)";
+ // These settings are reserved for use by product types.
+ GCC_PRODUCT_TYPE_PREPROCESSOR_DEFINITIONS = "$(inherited) KERNEL KERNEL_PRIVATE DRIVER_PRIVATE APPLE NeXT";
+ PRODUCT_TYPE_CFLAGS = "$(inherited) $(KEXT_CFLAGS)";
+ PRODUCT_TYPE_CPLUSPLUSFLAGS = "$(inherited) $(KEXT_CPLUSPLUSFLAGS)";
+ PRODUCT_SPECIFIC_LDFLAGS = "$(inherited) $(KEXT_LDFLAGS)";
+ PRODUCT_TYPE_HEADER_SEARCH_PATHS = "$(inherited) $(KERNEL_EXTENSION_HEADER_SEARCH_PATHS)";
+
+ CODE_SIGNING_ALLOWED = YES;
+
+ ARCHS_STANDARD = "arm64e x86_64";
+ ARCHS_STANDARD_64_BIT = "$(ARCHS_STANDARD)";
+ ARCHS_STANDARD_INCLUDING_64_BIT = "$(ARCHS_STANDARD)";
+ };
+ PackageTypes = (
+ com.apple.package-type.wrapper.kernel-extension, // Default
+ com.apple.package-type.wrapper.kernel-extension.shallow,
+ );
+ },
+
+ // Shallow Kernel Extension
+ {
+ Type = ProductType;
+ Identifier = com.apple.product-type.kernel-extension.shallow;
+ BasedOn = com.apple.product-type.kernel-extension;
+ Class = XCKernelExtensionProductType;
+ Name = "Kernel Extension (Shallow)";
+ Description = "Kernel extension (shallow)";
+ DefaultBuildProperties = {
+ // None yet
+ };
+ PackageTypes = (
+ com.apple.package-type.wrapper.kernel-extension.shallow,
+ );
+ },
+
+ // IOKit Kernel Extension
+ { Type = ProductType;
+ Identifier = com.apple.product-type.kernel-extension.iokit;
+ BasedOn = com.apple.product-type.kernel-extension;
+ Class = XCKernelExtensionProductType;
+ Name = "IOKit Kernel Extension";
+ Description = "IOKit Kernel extension";
+ DefaultTargetName = "IOKit Kernel Extension";
+ DefaultBuildProperties = {
+ CODE_SIGNING_ALLOWED = YES;
+ };
+ PackageTypes = (
+ com.apple.package-type.wrapper.kernel-extension, // Default
+ com.apple.package-type.wrapper.kernel-extension.shallow,
+ );
+ },
+
+ // Shallow IOKit Kernel Extension
+ { Type = ProductType;
+ Identifier = com.apple.product-type.kernel-extension.iokit.shallow;
+ BasedOn = com.apple.product-type.kernel-extension;
+ Class = XCKernelExtensionProductType;
+ Name = "IOKit Kernel Extension (Shallow)";
+ Description = "IOKit Kernel extension (Shallow)";
+ DefaultTargetName = "IOKit Kernel Extension (Shallow)";
+ DefaultBuildProperties = {
+ // None yet
+ };
+ PackageTypes = (
+ com.apple.package-type.wrapper.kernel-extension.shallow,
+ );
+ },
+
+ // Unit Test Bundle
+ { Type = ProductType;
+ Identifier = com.apple.product-type.bundle.unit-test;
+ BasedOn = com.apple.product-type.bundle;
+ Class = PBXXCTestBundleProductType;
+ Name = "Unit Test Bundle";
+ Description = "Unit Test Bundle";
+ DefaultBuildProperties = {
+ WRAPPER_EXTENSION = "xctest";
+ ENABLE_TESTING_SEARCH_PATHS = YES;
+ PRODUCT_SPECIFIC_LDFLAGS = "-framework XCTest";
+ XCTRUNNER_PATH = "$(XCTRUNNER_PATH$(TEST_BUILD_STYLE))";
+ LD_RUNPATH_SEARCH_PATHS = "$(LD_RUNPATH_SEARCH_PATHS_$(IS_MACCATALYST))";
+ LD_RUNPATH_SEARCH_PATHS_YES = (
+ "@loader_path/../Frameworks",
+ "@executable_path/../Frameworks",
+ );
+ };
+ PackageTypes = (
+ com.apple.package-type.bundle.unit-test
+ );
+ CanEmbedCompilerSanitizerLibraries = YES;
+ IsUnitTest = YES;
+ WantsBundleIdentifierEditing = NO;
+ },
+
+ // UI Testing Bundle
+ { Type = ProductType;
+ Identifier = com.apple.product-type.bundle.ui-testing;
+ BasedOn = com.apple.product-type.bundle.unit-test;
+ Class = PBXXCTestBundleProductType;
+ Name = "UI Testing Bundle";
+ Description = "UI Testing Bundle";
+ DefaultBuildProperties = {
+ USES_XCTRUNNER = "YES";
+ };
+ PackageTypes = (
+ com.apple.package-type.bundle.unit-test
+ );
+ ProvisioningProfileSupported = YES;
+ IsUITest = YES;
+ InfoPlistAdditions = {
+ XCTContainsUITests = YES;
+ };
+ WantsBundleIdentifierEditing = NO;
},
- "Name" : "In-App Purchase Content",
- "Identifier" : "com.apple.product-type.in-app-purchase-content",
- "Description" : "In-App Purchase Content",
- "Class" : "PBXBundleProductType"
- },
- {
- "IconNamePrefix" : "XPCService",
- "DefaultTargetName" : "XPC Service",
- "CanEmbedCompilerSanitizerLibraries" : "YES",
- "DefaultBuildProperties" : {
- "MACH_O_TYPE" : "mh_execute",
- "WRAPPER_EXTENSION" : "xpc"
+
+ // Legacy OCUnit Test Bundle
+ { Type = ProductType;
+ Identifier = com.apple.product-type.bundle.ocunit-test;
+ BasedOn = com.apple.product-type.bundle;
+ Class = PBXBundleProductType;
+ Name = "OCUnit Test Bundle";
+ Description = "OCUnit Test Bundle";
+ DefaultBuildProperties = {
+ WRAPPER_EXTENSION = "octest";
+ };
+ PackageTypes = (
+ com.apple.package-type.bundle.ocunit-test
+ );
+ IsUnitTest = YES;
+ },
+
+ // In-App Purchase Content
+ { Type = ProductType;
+ Identifier = com.apple.product-type.in-app-purchase-content;
+ Class = PBXBundleProductType;
+ Name = "In-App Purchase Content";
+ Description = "In-App Purchase Content";
+ DefaultBuildProperties = {
+ CODE_SIGNING_ALLOWED = NO;
+ FULL_PRODUCT_NAME = "$(WRAPPER_NAME)";
+ };
+ PackageTypes = (
+ com.apple.package-type.in-app-purchase-content, // default
+ );
+ IsWrapper = YES;
+ HasInfoPlist = YES;
+ HasInfoPlistStrings = NO;
+ },
+
+ // XPC Service
+ {
+ Type = ProductType;
+ Identifier = "com.apple.product-type.xpc-service";
+ BasedOn = "com.apple.product-type.bundle";
+ Class = PBXBundleProductType;
+ Name = "XPC Service";
+ Description = "XPC Service";
+ IconNamePrefix = XPCService;
+ DefaultTargetName = "XPC Service";
+ CanEmbedCompilerSanitizerLibraries = YES;
+ "DefaultBuildProperties" = {
+ "MACH_O_TYPE" = "mh_execute";
+ WRAPPER_EXTENSION = "xpc";
+ LD_RUNPATH_SEARCH_PATHS = "$(LD_RUNPATH_SEARCH_PATHS_$(IS_MACCATALYST)_$(_BOOL_$(SKIP_INSTALL)))";
+ LD_RUNPATH_SEARCH_PATHS_YES_YES = (
+ "@loader_path/../Frameworks",
+ "@loader_path/../../../../Frameworks",
+ );
+ LD_RUNPATH_SEARCH_PATHS_YES_NO = ( "@loader_path/../Frameworks", );
+ };
+ PackageTypes = (
+ "com.apple.package-type.xpc-service",
+ );
+ ProvisioningProfileSupported = YES;
+ ProvisioningProfileRequired = NO;
+ WantsBundleIdentifierEditing = YES;
+ WantsSigningEditing = YES;
+ },
+
+ // PlugIn-Kit PlugIn
+ {
+ Type = ProductType;
+ Identifier = "com.apple.product-type.pluginkit-plugin";
+ BasedOn = "com.apple.product-type.xpc-service";
+ Class = PBXBundleProductType;
+ Name = "PlugInKit PlugIn";
+ Description = "PlugInKit PlugIn";
+ IconNamePrefix = XPCService;
+ DefaultTargetName = "PlugInKit PlugIn";
+ "DefaultBuildProperties" = {
+ "PRODUCT_SPECIFIC_LDFLAGS" = "$(SDKROOT)/System/Library/PrivateFrameworks/PlugInKit.framework/PlugInKit";
+ WRAPPER_EXTENSION = "pluginkit";
+ };
+ PackageTypes = (
+ "com.apple.package-type.pluginkit-plugin",
+ );
},
- "PackageTypes" : [
- "com.apple.package-type.xpc-service"
- ],
- "Type" : "ProductType",
- "BasedOn" : "com.apple.product-type.bundle",
- "Name" : "XPC Service",
- "Identifier" : "com.apple.product-type.xpc-service",
- "Description" : "XPC Service",
- "Class" : "PBXBundleProductType"
- },
- {
- "IconNamePrefix" : "XPCService",
- "DefaultTargetName" : "PlugInKit PlugIn",
- "DefaultBuildProperties" : {
- "WRAPPER_EXTENSION" : "pluginkit",
- "PRODUCT_SPECIFIC_LDFLAGS" : "$(SDKROOT)\/System\/Library\/PrivateFrameworks\/PlugInKit.framework\/PlugInKit"
+
+ // App Extension
+ {
+ Type = ProductType;
+ Identifier = "com.apple.product-type.app-extension";
+ BasedOn = "com.apple.product-type.pluginkit-plugin";
+ Class = PBXBundleProductType;
+ Name = "App Extension";
+ Description = "App Extension";
+ IconNamePrefix = AppExtension;
+ DefaultTargetName = "App Extension";
+ "DefaultBuildProperties" = {
+ "CODE_SIGNING_ALLOWED" = YES;
+ "APPLICATION_EXTENSION_API_ONLY" = YES;
+ "PRODUCT_SPECIFIC_LDFLAGS" = "-e _NSExtensionMain";
+ WRAPPER_EXTENSION = "appex";
+ };
+ PackageTypes = (
+ "com.apple.package-type.app-extension",
+ );
+ ProvisioningProfileSupported = YES;
+ ProvisioningProfileRequired = NO;
+ WantsBundleIdentifierEditing = YES;
+ WantsSigningEditing = YES;
},
- "PackageTypes" : [
- "com.apple.package-type.pluginkit-plugin"
- ],
- "Type" : "ProductType",
- "BasedOn" : "com.apple.product-type.xpc-service",
- "Name" : "PlugInKit PlugIn",
- "Identifier" : "com.apple.product-type.pluginkit-plugin",
- "Description" : "PlugInKit PlugIn",
- "Class" : "PBXBundleProductType"
- },
- {
- "Description" : "App Extension",
- "Class" : "PBXBundleProductType",
- "Name" : "App Extension",
- "ProvisioningProfileSupported" : "YES",
- "DefaultTargetName" : "App Extension",
- "DefaultBuildProperties" : {
- "APPLICATION_EXTENSION_API_ONLY" : "YES",
- "PRODUCT_SPECIFIC_LDFLAGS" : "-e _NSExtensionMain",
- "WRAPPER_EXTENSION" : "appex",
- "CODE_SIGNING_ALLOWED" : "YES"
+
+ // Xcode Extension
+ {
+ Type = ProductType;
+ Identifier = "com.apple.product-type.xcode-extension";
+ BasedOn = "com.apple.product-type.app-extension";
+ Name = "Xcode Extension";
+ Description = "Xcode Extension";
+ IconNamePrefix = XcodeExtension;
+ DefaultTargetName = "Xcode Extension";
+ "DefaultBuildProperties" = {
+ "CODE_SIGNING_ALLOWED" = YES;
+ "APPLICATION_EXTENSION_API_ONLY" = YES;
+ "PRODUCT_SPECIFIC_LDFLAGS" = "-e _XCExtensionMain -lXcodeExtension";
+ "PRODUCT_TYPE_FRAMEWORK_SEARCH_PATHS" = (
+ "$(inherited)",
+ "$(DEVELOPER_FRAMEWORKS_DIR)",
+ );
+ "PRODUCT_TYPE_LIBRARY_SEARCH_PATHS" = (
+ "$(inherited)",
+ "$(DEVELOPER_USR_DIR)/lib",
+ );
+ LD_RUNPATH_SEARCH_PATHS = (
+ "@loader_path/../Frameworks",
+ );
+ WRAPPER_EXTENSION = "appex";
+ };
+ PackageTypes = (
+ "com.apple.package-type.app-extension",
+ );
+ ProvisioningProfileSupported = YES;
+ ProvisioningProfileRequired = NO;
+ WantsBundleIdentifierEditing = YES;
+ WantsSigningEditing = YES;
},
- "BasedOn" : "com.apple.product-type.pluginkit-plugin",
- "ProvisioningProfileRequired" : "NO",
- "PackageTypes" : [
- "com.apple.package-type.app-extension"
- ],
- "Type" : "ProductType",
- "Identifier" : "com.apple.product-type.app-extension",
- "IconNamePrefix" : "AppExtension"
- },
- {
- "Description" : "Xcode Extension",
- "Class" : "PBXBundleProductType",
- "Name" : "Xcode Extension",
- "ProvisioningProfileSupported" : "YES",
- "DefaultTargetName" : "Xcode Extension",
- "DefaultBuildProperties" : {
- "APPLICATION_EXTENSION_API_ONLY" : "YES",
- "PRODUCT_SPECIFIC_LDFLAGS" : "-e _XCExtensionMain -lXcodeExtension -weak_framework XcodeKit",
- "PRODUCT_TYPE_LIBRARY_SEARCH_PATHS" : [
- "$(inherited)",
- "$(DEVELOPER_USR_DIR)\/lib"
- ],
- "CODE_SIGNING_ALLOWED" : "YES",
- "WRAPPER_EXTENSION" : "appex",
- "PRODUCT_TYPE_FRAMEWORK_SEARCH_PATHS" : [
- "$(inherited)",
- "$(DEVELOPER_FRAMEWORKS_DIR)"
- ]
+
+ // Spotlight Importer
+ {
+ Type = ProductType;
+ Identifier = "com.apple.product-type.spotlight-importer";
+ BasedOn = "com.apple.product-type.bundle";
+ Class = PBXBundleProductType;
+ Name = "Spotlight Importer";
+ Description = "Spotlight Importer";
+ DefaultTargetName = "Spotlight";
+ "DefaultBuildProperties" = {
+ "CODE_SIGNING_ALLOWED" = YES;
+ };
+ PackageTypes = (
+ "com.apple.package-type.spotlight-importer",
+ );
},
- "BasedOn" : "com.apple.product-type.app-extension",
- "ProvisioningProfileRequired" : "NO",
- "PackageTypes" : [
- "com.apple.package-type.app-extension"
- ],
- "Type" : "ProductType",
- "Identifier" : "com.apple.product-type.xcode-extension",
- "IconNamePrefix" : "XcodeExtension"
- },
- {
- "DefaultTargetName" : "Spotlight",
- "DefaultBuildProperties" : {
- "CODE_SIGNING_ALLOWED" : "YES"
+
+ // Copied from iOS specs to aid in build system diagnostic support.
+ // Later, we should put these in some central place.
+ {
+ Type = ProductType;
+ Identifier = "com.apple.product-type.app-extension.messages";
+ BasedOn = "com.apple.product-type.app-extension";
+ },
+
+ {
+ Type = ProductType;
+ Identifier = "com.apple.product-type.app-extension.messages-sticker-pack";
+ BasedOn = "com.apple.product-type.app-extension";
+ IsCapabilitiesUnsupported = YES;
+ WantsSimpleTargetEditing = YES;
+ DefaultBuildProperties = {
+ MESSAGES_APPLICATION_EXTENSION_PRODUCT_BINARY_SOURCE_PATH = "$(PLATFORM_DIR)/Library/Application Support/MessagesApplicationExtensionStub/MessagesApplicationExtensionStub";
+ ASSETCATALOG_COMPILER_INCLUDE_STICKER_CONTENT = YES;
+ ASSETCATALOG_COMPILER_TARGET_STICKERS_ICON_ROLE = "extension";
+ ASSETCATALOG_COMPILER_STICKER_PACK_IDENTIFIER_PREFIX = "$(PRODUCT_BUNDLE_IDENTIFIER).sticker-pack.";
+ };
+ AllowedBuildPhases = (
+ "com.apple.buildphase.resources",
+ "com.apple.buildphase.shell-script",
+ );
+ InfoPlistAdditions = {
+ LSApplicationIsStickerProvider = YES;
+ };
+ },
+
+ {
+ Type = ProductType;
+ Identifier = "com.apple.product-type.application.on-demand-install-capable";
+ BasedOn = "com.apple.product-type.application";
+ Name = "App Clip";
+ Description = "App Clip";
+ DefaultBuildProperties = {
+ ENABLE_ON_DEMAND_RESOURCES = NO;
+ ASSETCATALOG_COMPILER_STANDALONE_ICON_BEHAVIOR = none; // Don't include standalone icons to keep size down
+ PRODUCT_SPECIFIC_LDFLAGS = "$(inherited) -framework AppClip";
+ SKIP_INSTALL = YES;
+ };
+ DefaultEntitlements = {
+ "com.apple.developer.on-demand-install-capable" = YES;
+ };
+ SupportsOnDemandResources = NO;
+ IsEmbeddable = YES;
+ BuildPhaseInjectionsWhenEmbedding = (
+ {
+ BuildPhase = "CopyFiles";
+ Name = "Embed App Clips";
+ RunOnlyForDeploymentPostprocessing = NO;
+ DstSubFolderSpec = 16;
+ DstPath = "$(CONTENTS_FOLDER_PATH)/AppClips";
+ }
+ );
},
- "PackageTypes" : [
- "com.apple.package-type.spotlight-importer"
- ],
- "Type" : "ProductType",
- "BasedOn" : "com.apple.product-type.bundle",
- "Name" : "Spotlight Importer",
- "Identifier" : "com.apple.product-type.spotlight-importer",
- "Description" : "Spotlight Importer",
- "Class" : "PBXBundleProductType"
- }
-]
+)
diff --git a/share/qbs/modules/bundle/bundle.js b/share/qbs/modules/bundle/bundle.js
index 2354d88b5..cf765f7be 100644
--- a/share/qbs/modules/bundle/bundle.js
+++ b/share/qbs/modules/bundle/bundle.js
@@ -28,9 +28,12 @@
**
****************************************************************************/
+var File = require("qbs.File");
+var FileInfo = require("qbs.FileInfo");
var DarwinTools = require("qbs.DarwinTools");
var ModUtils = require("qbs.ModUtils");
var Process = require("qbs.Process");
+var Utilities = require("qbs.Utilities");
// HACK: Workaround until the PropertyList extension is supported cross-platform
var TextFile = require("qbs.TextFile");
@@ -80,14 +83,14 @@ var _productTypeIdentifiers = {
function productTypeIdentifier(productType) {
for (var k in _productTypeIdentifiers) {
- if (productType.contains(k))
+ if (productType.includes(k))
return _productTypeIdentifiers[k];
}
return "com.apple.package-type.wrapper";
}
function excludedAuxiliaryInputs(project, product) {
- var chain = product.moduleProperty("bundle", "_productTypeIdentifierChain");
+ var chain = product.bundle._productTypeIdentifierChain;
var bestPossibleType;
for (var i = chain.length - 1; i >= 0; --i) {
switch (chain[i]) {
@@ -147,27 +150,77 @@ function _assign(target, source) {
}
}
+function macOSSpecsPaths(version, developerPath) {
+ var result = [];
+ if (Utilities.versionCompare(version, "15.3") >= 0) {
+ result.push(FileInfo.joinPaths(
+ developerPath, "..", "SharedFrameworks", "XCBuild.framework", "PlugIns",
+ "XCBBuildService.bundle", "Contents", "PlugIns", "XCBSpecifications.ideplugin",
+ "Contents", "Resources"));
+ }
+ if (Utilities.versionCompare(version, "14.3") >= 0) {
+ result.push(FileInfo.joinPaths(
+ developerPath, "Library", "Xcode", "Plug-ins", "XCBSpecifications.ideplugin",
+ "Contents", "Resources"));
+ } else if (Utilities.versionCompare(version, "12.5") >= 0) {
+ result.push(FileInfo.joinPaths(
+ developerPath, "..", "PlugIns", "XCBSpecifications.ideplugin",
+ "Contents", "Resources"));
+ } else if (Utilities.versionCompare(version, "12") >= 0) {
+ result.push(FileInfo.joinPaths(
+ developerPath, "Platforms", "MacOSX.platform", "Developer", "Library", "Xcode",
+ "PrivatePlugIns", "IDEOSXSupportCore.ideplugin", "Contents", "Resources"));
+ } else {
+ result.push(FileInfo.joinPaths(
+ developerPath, "Platforms", "MacOSX.platform", "Developer", "Library", "Xcode",
+ "Specifications"));
+ }
+ return result;
+}
+
var XcodeBuildSpecsReader = (function () {
- function XcodeBuildSpecsReader(specsPath, separator, additionalSettings, useShallowBundles) {
+ function XcodeBuildSpecsReader(specsPaths, separator, additionalSettings, useShallowBundles) {
this._additionalSettings = additionalSettings;
this._useShallowBundles = useShallowBundles;
- var i;
- var plist = new PropertyList2();
- var plist2 = new PropertyList2();
- try {
- plist.readFromFile(specsPath + ["/MacOSX", "Package", "Types.xcspec"].join(separator));
- plist2.readFromFile(specsPath + ["/MacOSX", "Product", "Types.xcspec"].join(separator));
- this._packageTypes = plist.toObject();
- this._productTypes = plist2.toObject();
- this._types = {};
- for (i = 0; i < this._packageTypes.length; ++i)
- this._types[this._packageTypes[i]["Identifier"]] = this._packageTypes[i];
- for (i = 0; i < this._productTypes.length; ++i)
- this._types[this._productTypes[i]["Identifier"]] = this._productTypes[i];
- } finally {
- plist.clear();
- plist2.clear();
+
+ this._packageTypes = [];
+ this._productTypes = [];
+
+ var i, j;
+ for (i = 0; i < specsPaths.length; ++i) {
+ var specsPath = specsPaths[i];
+ var names = ["", "Darwin", "MacOSX"];
+ for (j = 0; j < names.length; ++j) {
+ var name = names[j];
+ var plist = new PropertyList2();
+ var plist2 = new PropertyList2();
+ try
+ {
+ var plistName = [name, "Package", "Types.xcspec"].join(name ? separator : "");
+ var plistName2 = [name, "Product", "Types.xcspec"].join(name ? separator : "");
+ var plistPath = FileInfo.joinPaths(specsPath, plistName);
+ var plistPath2 = FileInfo.joinPaths(specsPath, plistName2);
+ if (File.exists(plistPath)) {
+ plist.readFromFile(plistPath);
+ this._packageTypes = this._packageTypes.concat(plist.toObject());
+ }
+ if (File.exists(plistPath2)) {
+ plist2.readFromFile(plistPath2);
+ this._productTypes = this._productTypes.concat(plist2.toObject());
+ }
+ } finally {
+ plist.clear();
+ plist2.clear();
+ }
+ }
}
+
+ this._types = {};
+ for (i = 0; i < this._packageTypes.length; ++i)
+ this._types[this._packageTypes[i]["Identifier"]] = this._packageTypes[i];
+ for (i = 0; i < this._productTypes.length; ++i)
+ this._types[this._productTypes[i]["Identifier"]] = this._productTypes[i];
+
}
XcodeBuildSpecsReader.prototype.productTypeIdentifierChain = function (typeIdentifier) {
var ids = [typeIdentifier];
@@ -266,7 +319,8 @@ var XcodeBuildSpecsReader = (function () {
};
XcodeBuildSpecsReader.prototype.expandedSetting = function (typeIdentifier, baseSettings,
settingName) {
- var obj = baseSettings || {};
+ var obj = {};
+ _assign(obj, baseSettings); // todo: copy recursively
obj = _assign(obj, this.settings(typeIdentifier, true));
if (obj) {
for (var x in this._additionalSettings) {
@@ -278,7 +332,7 @@ var XcodeBuildSpecsReader = (function () {
var original;
while (original !== setting) {
original = setting;
- setting = DarwinTools.expandPlistEnvironmentVariables({ key: setting }, obj, true)["key"];
+ setting = DarwinTools.expandPlistEnvironmentVariables({ key: setting }, obj, false)["key"];
}
return setting;
}
diff --git a/share/qbs/modules/capnproto/capnproto.js b/share/qbs/modules/capnproto/capnproto.js
new file mode 100644
index 000000000..64464f42c
--- /dev/null
+++ b/share/qbs/modules/capnproto/capnproto.js
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** 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.
+**
+****************************************************************************/
+
+var File = require("qbs.File");
+var FileInfo = require("qbs.FileInfo");
+var Utilities = require("qbs.Utilities");
+
+function validateCompiler(name, path) {
+ if (!File.exists(path))
+ throw "Cannot find executable '" + name + "'. Please set the compilerPath "
+ + "property or make sure the compiler is found in PATH";
+}
+
+function validatePlugin(name, path) {
+ if (!name)
+ throw "pluginName is not set";
+ if (!File.exists(path))
+ throw "Cannot find plugin '" + name + "'. Please set the pluginPath "
+ + "property or make sure the plugin is found in PATH";
+}
+
+function getOutputDir(module, input) {
+ var outputDir = module.outputDir;
+ var importPaths = module.importPaths;
+ if (importPaths.length !== 0) {
+ var canonicalInput = File.canonicalFilePath(FileInfo.path(input.filePath));
+ for (var i = 0; i < importPaths.length; ++i) {
+ var path = File.canonicalFilePath(importPaths[i]);
+
+ if (canonicalInput.startsWith(path)) {
+ return outputDir + "/" + FileInfo.relativePath(path, canonicalInput);
+ }
+ }
+ }
+ return outputDir;
+}
+
+function artifact(outputDir, input, tag, suffix) {
+ return {
+ fileTags: [tag],
+ filePath: FileInfo.joinPaths(outputDir, FileInfo.baseName(input.fileName) + suffix),
+ cpp: {
+ includePaths: [].concat(input.cpp.includePaths, outputDir),
+ warningLevel: "none",
+ }
+ };
+}
+
+function doPrepare(module, product, input, outputs, lang)
+{
+ var outputDir = FileInfo.path(outputs["cpp"][0].filePath);
+
+ var args = [];
+ args.push("--output=" + module.pluginPath + ":" + outputDir);
+ args.push("--src-prefix=" + FileInfo.path(input.filePath));
+
+ var importPaths = module.importPaths;
+ importPaths.forEach(function(path) {
+ if (!FileInfo.isAbsolutePath(path))
+ path = FileInfo.joinPaths(product.sourceDirectory, path);
+ args.push("--import-path", path);
+ });
+
+ args.push(input.filePath);
+
+ var cmd = new Command(module.compilerPath, args);
+ cmd.highlight = "codegen";
+ cmd.description = "generating " + lang + " files for " + input.fileName;
+ return [cmd];
+}
diff --git a/share/qbs/modules/capnproto/capnprotobase.qbs b/share/qbs/modules/capnproto/capnprotobase.qbs
new file mode 100644
index 000000000..916e53a51
--- /dev/null
+++ b/share/qbs/modules/capnproto/capnprotobase.qbs
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** 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.FileInfo
+import qbs.Probes
+import "capnproto.js" as HelperFunctions
+
+Module {
+ property string compilerName: "capnpc"
+ property string compilerPath: compilerProbe.filePath
+
+ property string pluginName
+ property string pluginPath: pluginProbe.filePath
+
+ property pathList importPaths: []
+
+ property string outputDir: product.buildDirectory + "/capnp"
+
+ property var _searchPaths
+
+ Probes.BinaryProbe {
+ id: compilerProbe
+ names: compilerName ? [compilerName] : []
+ searchPaths: _searchPaths
+ }
+
+ Probes.BinaryProbe {
+ id: pluginProbe
+ names: pluginName ? [pluginName] : []
+ searchPaths: _searchPaths
+ }
+
+ FileTagger {
+ patterns: ["*.capnp"]
+ fileTags: ["capnproto.input"];
+ }
+
+ validate: {
+ HelperFunctions.validateCompiler(compilerName, compilerPath);
+ HelperFunctions.validatePlugin(pluginName, pluginPath);
+ }
+}
diff --git a/share/qbs/modules/capnproto/cpp/capnprotocpp.qbs b/share/qbs/modules/capnproto/cpp/capnprotocpp.qbs
new file mode 100644
index 000000000..83192b7de
--- /dev/null
+++ b/share/qbs/modules/capnproto/cpp/capnprotocpp.qbs
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** 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 "../capnprotobase.qbs" as CapnProtoBase
+import "../capnproto.js" as HelperFunctions
+
+CapnProtoBase {
+ property bool useRpc: false
+
+ Depends { name: "cpp" }
+ Depends { name: "capnp" }
+ Depends { name: "capnp-rpc"; condition: useRpc }
+
+ pluginName: "capnpc-c++"
+ version: capnp.version
+ _searchPaths: capnp.hostBinDirs
+
+ cpp.systemIncludePaths: outputDir
+ cpp.cxxLanguageVersion: "c++14"
+
+ Rule {
+ inputs: ["capnproto.input"]
+ outputFileTags: ["hpp", "cpp"]
+ outputArtifacts: {
+ var outputDir = HelperFunctions.getOutputDir(input.capnproto.cpp, input);
+ var result = [
+ HelperFunctions.artifact(outputDir, input, "hpp", ".capnp.h"),
+ HelperFunctions.artifact(outputDir, input, "cpp", ".capnp.c++")
+ ];
+ return result;
+ }
+
+ prepare: {
+ var result = HelperFunctions.doPrepare(
+ input.capnproto.cpp, product, input, outputs, "cpp");
+ return result;
+ }
+ }
+}
diff --git a/share/qbs/modules/cli/CLIModule.qbs b/share/qbs/modules/cli/CLIModule.qbs
index d0ca120ef..3b12284ed 100644
--- a/share/qbs/modules/cli/CLIModule.qbs
+++ b/share/qbs/modules/cli/CLIModule.qbs
@@ -1,12 +1,13 @@
// base for Common Language Infrastructure modules
import qbs.FileInfo
+import qbs.Host
import qbs.ModUtils
import "cli.js" as CLI
Module {
- Depends { name: "bundle"; condition: qbs.targetOS.contains("darwin") }
+ Depends { name: "bundle"; condition: qbs.targetOS.includes("darwin") }
Properties {
- condition: qbs.targetOS.contains("darwin")
+ condition: qbs.targetOS.includes("darwin")
bundle.isBundle: false
}
@@ -87,8 +88,8 @@ Module {
}
setupBuildEnvironment: {
- var v = new ModUtils.EnvironmentVariable("PATH", product.qbs.pathListSeparator,
- product.qbs.hostOS.contains("windows"));
+ var v = new ModUtils.EnvironmentVariable("PATH", FileInfo.pathListSeparator(),
+ Host.os().includes("windows"));
v.prepend(product.cli.toolchainInstallPath);
v.set();
}
@@ -115,9 +116,7 @@ Module {
"debugInfoSuffix"))
}
- prepare: {
- return CLI.prepareCompiler(product, inputs, outputs.application[0]);
- }
+ prepare: CLI.prepareCompiler(product, inputs, outputs.application[0])
}
Rule {
@@ -142,9 +141,7 @@ Module {
"debugInfoSuffix"))
}
- prepare: {
- return CLI.prepareCompiler(product, inputs, outputs.dynamiclibrary[0]);
- }
+ prepare: CLI.prepareCompiler(product, inputs, outputs.dynamiclibrary[0])
}
Rule {
@@ -169,9 +166,7 @@ Module {
"debugInfoSuffix"))
}
- prepare: {
- return CLI.prepareCompiler(product, inputs, outputs["cli.netmodule"][0]);
- }
+ prepare: CLI.prepareCompiler(product, inputs, outputs["cli.netmodule"][0])
}
Rule {
diff --git a/share/qbs/modules/cli/cli.js b/share/qbs/modules/cli/cli.js
index 38833ac51..faa812201 100644
--- a/share/qbs/modules/cli/cli.js
+++ b/share/qbs/modules/cli/cli.js
@@ -59,16 +59,16 @@ function prepareCompiler(product, inputs, output) {
"cli.fsharp": fsharpCompilerPath
};
- var pathFunction = product.moduleProperty("qbs", "hostOS").contains("windows")
+ var pathFunction = product.moduleProperty("qbs", "hostOS").includes("windows")
? FileInfo.toWindowsSeparators
: function (path) { return path; };
var outputDescription = "assembly";
- if (output.fileTags.contains("application")) {
+ if (output.fileTags.includes("application")) {
args.push("/target:" + (product.consoleApplication === false ? "winexe" : "exe"));
- } else if (output.fileTags.contains("dynamiclibrary")) {
+ } else if (output.fileTags.includes("dynamiclibrary")) {
args.push("/target:library");
- } else if (output.fileTags.contains("cli.netmodule")) {
+ } else if (output.fileTags.includes("cli.netmodule")) {
args.push("/target:module");
outputDescription = "netmodule";
}
@@ -77,7 +77,7 @@ function prepareCompiler(product, inputs, output) {
var keys = Object.keys(inputs);
var language;
for (i in keys) {
- if (Object.keys(compilers).contains(keys[i])) {
+ if (Object.keys(compilers).includes(keys[i])) {
if (language)
throw("You cannot compile source files in more than one CLI language into a single " + outputDescription + ".");
language = keys[i];
diff --git a/share/qbs/modules/cli/mono.qbs b/share/qbs/modules/cli/mono.qbs
index f04956a5e..f16387dd7 100644
--- a/share/qbs/modules/cli/mono.qbs
+++ b/share/qbs/modules/cli/mono.qbs
@@ -1,8 +1,9 @@
import qbs.File
+import qbs.Host
import qbs.Probes
CLIModule {
- condition: qbs.toolchain && qbs.toolchain.contains("mono")
+ condition: qbs.toolchain && qbs.toolchain.includes("mono")
debugInfoSuffix: ".mdb"
csharpCompilerName: "mcs"
@@ -14,9 +15,9 @@ CLIModule {
names: ["mono"]
platformSearchPaths: {
var paths = [];
- if (qbs.hostOS.contains("macos"))
+ if (Host.os().includes("macos"))
paths.push("/Library/Frameworks/Mono.framework/Commands");
- if (qbs.hostOS.contains("unix"))
+ if (Host.os().includes("unix"))
paths.push("/usr/bin");
return paths;
}
diff --git a/share/qbs/modules/cli/windows-dotnet.qbs b/share/qbs/modules/cli/windows-dotnet.qbs
index 6fde50b85..a4d27c207 100644
--- a/share/qbs/modules/cli/windows-dotnet.qbs
+++ b/share/qbs/modules/cli/windows-dotnet.qbs
@@ -1,7 +1,7 @@
import qbs.Utilities
CLIModule {
- condition: qbs.toolchain && qbs.toolchain.contains("dotnet")
+ condition: qbs.toolchain && qbs.toolchain.includes("dotnet")
debugInfoSuffix: ".pdb"
csharpCompilerName: "csc"
diff --git a/share/qbs/modules/codesign/CodeSignModule.qbs b/share/qbs/modules/codesign/CodeSignModule.qbs
new file mode 100644
index 000000000..6db35c85c
--- /dev/null
+++ b/share/qbs/modules/codesign/CodeSignModule.qbs
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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.File
+import qbs.FileInfo
+import "codesign.js" as CodeSign
+
+Module {
+ condition: false
+
+ property bool enableCodeSigning: false
+
+ property string codesignName
+ property string codesignPath: codesignName
+ property stringList codesignFlags
+
+ property string signingTimestamp
+ PropertyOptions {
+ name: "signingTimestamp"
+ description: "URL of the RFC 3161 time stamp server."
+ }
+
+ property bool _canSignArtifacts: false // whether can sign individual actifacts
+}
diff --git a/share/qbs/modules/codesign/android.qbs b/share/qbs/modules/codesign/android.qbs
new file mode 100644
index 000000000..b1811dcfd
--- /dev/null
+++ b/share/qbs/modules/codesign/android.qbs
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 Raphaël Cotty <raphael.cotty@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of the Qbs.
+**
+** 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.Environment
+import qbs.File
+import qbs.FileInfo
+import qbs.Host
+import qbs.ModUtils
+import qbs.Probes
+import "codesign.js" as CodeSign
+
+CodeSignModule {
+ condition: qbs.targetOS.includes("android")
+ priority: 1
+ enableCodeSigning: true
+
+ property bool useApksigner: true
+ property path apksignerFilePath
+
+ Probes.JdkProbe {
+ id: jdk
+ environmentPaths: (jdkPath ? [jdkPath] : []).concat(base)
+ }
+ property string jdkPath: jdk.path
+ property string jarsignerFilePath: FileInfo.joinPaths(jdkPath, "bin", jarsignerName)
+ property string jarsignerName: "jarsigner"
+ property string keytoolFilePath: FileInfo.joinPaths(jdkPath, "bin", keytoolName)
+ property string keytoolName: "keytool"
+
+ property string debugKeystorePath: FileInfo.joinPaths(
+ Environment.getEnv(Host.os().includes("windows")
+ ? "USERPROFILE" : "HOME"),
+ ".android", "debug.keystore")
+ readonly property string debugKeystorePassword: "android"
+ readonly property string debugPassword: "android"
+ readonly property string debugKeyAlias: "androiddebugkey"
+
+ property string keystorePath: debugKeystorePath
+ property string keystorePassword: debugKeystorePassword
+ property string keyPassword: debugPassword
+ property string keyAlias: debugKeyAlias
+
+ // Private property set by the Android.sdk module
+ property string _packageName
+
+ Rule {
+ condition: useApksigner
+ inputs: ["android.package_unsigned"]
+ Artifact {
+ filePath: product.codesign._packageName
+ fileTags: "android.package"
+ }
+ prepare: CodeSign.signApkPackage.apply(this, arguments)
+ }
+
+ Rule {
+ condition: !useApksigner
+ inputs: ["android.package_unsigned"]
+ Artifact {
+ filePath: product.codesign._packageName
+ fileTags: "android.package"
+ }
+ prepare: CodeSign.signAabPackage.apply(this, arguments)
+ }
+
+ validate: {
+ // Typically there is a debug keystore in ~/.android/debug.keystore which gets created
+ // by the native build tools the first time a build is done. However, we don't want to
+ // create it ourselves, because writing to a location outside the qbs build directory is
+ // both polluting and has the potential for race conditions. So we'll instruct the user what
+ // to do.
+ if (keystorePath === debugKeystorePath && !File.exists(debugKeystorePath)) {
+ throw ModUtils.ModuleError("Could not find an Android debug keystore at " +
+ codesign.debugKeystorePath + ". " +
+ "If you are developing for Android on this machine for the first time and " +
+ "have never built an application using the native Gradle / Android Studio " +
+ "tooling, this is normal. You must create the debug keystore now using the " +
+ "following command, in order to continue:\n\n" +
+ CodeSign.createDebugKeyStoreCommandString(codesign.keytoolFilePath,
+ codesign.debugKeystorePath,
+ codesign.debugKeystorePassword,
+ codesign.debugPassword,
+ codesign.debugKeyAlias) +
+ "\n\n" +
+ "See the following URL for more information: " +
+ "https://developer.android.com/studio/publish/app-signing.html#debug-mode");
+ }
+ }
+}
diff --git a/share/qbs/modules/codesign/apple.qbs b/share/qbs/modules/codesign/apple.qbs
new file mode 100644
index 000000000..0d1335d92
--- /dev/null
+++ b/share/qbs/modules/codesign/apple.qbs
@@ -0,0 +1,387 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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.BundleTools
+import qbs.DarwinTools
+import qbs.Environment
+import qbs.File
+import qbs.FileInfo
+import qbs.Host
+import qbs.ModUtils
+import qbs.PropertyList
+import qbs.Probes
+import qbs.Utilities
+import "codesign.js" as CodeSign
+import "../xcode/xcode.js" as XcodeUtils
+
+CodeSignModule {
+ Depends { name: "xcode"; required: qbs.toolchain && qbs.toolchain.includes("xcode") }
+
+ Probes.BinaryProbe {
+ id: codesignProbe
+ names: [codesignName]
+ }
+
+ condition: Host.os().includes("macos") && qbs.targetOS.includes("darwin")
+ priority: 0
+
+ enableCodeSigning: _codeSigningRequired
+
+ codesignName: "codesign"
+ codesignPath: codesignProbe.filePath
+
+ _canSignArtifacts: true
+
+ property string signingType: {
+ if (_adHocCodeSigningAllowed)
+ return "ad-hoc";
+ if (_codeSigningAllowed)
+ return "app-store";
+ }
+
+ PropertyOptions {
+ name: "signingType"
+ allowedValues: ["app-store", "apple-id", "ad-hoc"]
+ }
+
+ property string signingIdentity: {
+ if (signingType === "ad-hoc") // only useful on macOS
+ return "-";
+
+ var isDebug = qbs.buildVariant !== "release";
+
+ if (qbs.targetOS.includes("ios") || qbs.targetOS.includes("tvos")
+ || qbs.targetOS.includes("watchos")) {
+ switch (signingType) {
+ case "app-store":
+ return isDebug ? "iPhone Developer" : "iPhone Distribution";
+ }
+ }
+
+ if (qbs.targetOS.includes("macos")) {
+ switch (signingType) {
+ case "app-store":
+ return isDebug ? "Mac Developer" : "3rd Party Mac Developer Application";
+ case "apple-id":
+ return "Developer ID Application";
+ }
+ }
+ }
+
+ signingTimestamp: "none"
+
+ property string provisioningProfile
+ PropertyOptions {
+ name: "provisioningProfile"
+ description: "Name or UUID of the provisioning profile to embed in the application; " +
+ "typically left blank to allow automatic provisioning"
+ }
+
+ property string teamIdentifier
+ PropertyOptions {
+ name: "teamIdentifier"
+ description: "Name or identifier of the development team whose identities will be used; " +
+ "typically left blank unless signed into multiple development teams"
+ }
+
+ property path provisioningProfilesPath: "~/Library/MobileDevice/Provisioning Profiles"
+
+ readonly property var _actualSigningIdentity: {
+ if (signingIdentity === "-") {
+ return {
+ SHA1: signingIdentity,
+ subjectInfo: { CN: "ad hoc" }
+ }
+ }
+
+ var identities = CodeSign.findSigningIdentities(signingIdentity, teamIdentifier);
+ if (identities && Object.keys(identities).length > 1) {
+ throw "Multiple codesigning identities (i.e. certificate and private key pairs) " +
+ "matching '" + signingIdentity + "' were found." +
+ CodeSign.humanReadableIdentitySummary(identities);
+ }
+
+ for (var i in identities)
+ return identities[i];
+ }
+
+ // Allowed for macOS
+ readonly property bool _adHocCodeSigningAllowed:
+ XcodeUtils.boolFromSdkOrPlatform("AD_HOC_CODE_SIGNING_ALLOWED",
+ xcode._sdkProps, xcode._platformProps, true)
+
+ // Allowed for all device platforms (not simulators)
+ readonly property bool _codeSigningAllowed:
+ XcodeUtils.boolFromSdkOrPlatform("CODE_SIGNING_ALLOWED",
+ xcode._sdkProps, xcode._platformProps, true)
+
+ // Required for tvOS, iOS, and watchOS (not simulators)
+ property bool _codeSigningRequired: {
+ // allow to override value from Xcode so tests do not require signing
+ var envRequired = Environment.getEnv("QBS_AUTOTEST_CODE_SIGNING_REQUIRED");
+ if (envRequired)
+ return envRequired === "1";
+ return XcodeUtils.boolFromSdkOrPlatform("CODE_SIGNING_REQUIRED",
+ xcode._sdkProps, xcode._platformProps, false)
+ }
+
+ // Required for tvOS, iOS, and watchOS (not simulators)
+ readonly property bool _entitlementsRequired:
+ XcodeUtils.boolFromSdkOrPlatform("ENTITLEMENTS_REQUIRED",
+ xcode._sdkProps, xcode._platformProps, false)
+
+ readonly property bool _provisioningProfileAllowed:
+ product.bundle
+ && product.bundle.isBundle
+ && product.type.includes("application")
+ && xcode.platformType !== "simulator"
+
+ // Required for tvOS, iOS, and watchOS (not simulators)
+ // PROVISIONING_PROFILE_REQUIRED is specified only in Embedded-Device.xcspec in the
+ // IDEiOSSupportCore IDE plugin, so we'll just write out the logic here manually
+ readonly property bool _provisioningProfileRequired:
+ _provisioningProfileAllowed && !qbs.targetOS.includes("macos")
+
+ // Not used on simulator platforms either but provisioning profiles aren't used there anyways
+ readonly property string _provisioningProfilePlatform: {
+ if (qbs.targetOS.includes("macos"))
+ return "OSX";
+ if (qbs.targetOS.includes("ios") || qbs.targetOS.includes("watchos"))
+ return "iOS";
+ if (qbs.targetOS.includes("tvos"))
+ return "tvOS";
+ }
+
+ readonly property string _embeddedProfileName:
+ (xcode._platformProps || {})["EMBEDDED_PROFILE_NAME"] || "embedded.mobileprovision"
+
+ setupBuildEnvironment: {
+ var prefixes = product.xcode ? [
+ product.xcode.platformPath + "/Developer",
+ product.xcode.toolchainPath,
+ product.xcode.developerPath
+ ] : [];
+ for (var i = 0; i < prefixes.length; ++i) {
+ var codesign_allocate = prefixes[i] + "/usr/bin/codesign_allocate";
+ if (File.exists(codesign_allocate)) {
+ var v = new ModUtils.EnvironmentVariable("CODESIGN_ALLOCATE");
+ v.value = codesign_allocate;
+ v.set();
+ break;
+ }
+ }
+ }
+
+ Group {
+ name: "Provisioning Profiles"
+ prefix: codesign.provisioningProfilesPath + "/"
+ files: ["*.mobileprovision", "*.provisionprofile"]
+ }
+
+ FileTagger {
+ fileTags: ["codesign.entitlements"]
+ patterns: ["*.entitlements"]
+ }
+
+ FileTagger {
+ fileTags: ["codesign.provisioningprofile"]
+ patterns: ["*.mobileprovision", "*.provisionprofile"]
+ }
+
+ Rule {
+ multiplex: true
+ condition: product.codesign.enableCodeSigning &&
+ product.codesign._provisioningProfileAllowed
+ inputs: ["codesign.provisioningprofile"]
+
+ outputFileTags: ["codesign.embedded_provisioningprofile"]
+ outputArtifacts: {
+ var artifacts = [];
+ var provisioningProfiles = (inputs["codesign.provisioningprofile"] || [])
+ .map(function (a) { return a.filePath; });
+ var bestProfile = CodeSign.findBestProvisioningProfile(product, provisioningProfiles);
+ var uuid = product.provisioningProfile;
+ if (bestProfile) {
+ artifacts.push({
+ filePath: FileInfo.joinPaths(product.destinationDirectory,
+ product.codesign._embeddedProfileName),
+ fileTags: ["codesign.embedded_provisioningprofile"],
+ codesign: {
+ _provisioningProfileFilePath: bestProfile.filePath,
+ _provisioningProfileData: JSON.stringify(bestProfile.data),
+ }
+ });
+ } else if (uuid) {
+ throw "Your build settings specify a provisioning profile with the UUID '"
+ + uuid + "', however, no such provisioning profile was found.";
+ } else if (product._provisioningProfileRequired) {
+ var hasProfiles = !!((inputs["codesign.provisioningprofile"] || []).length);
+ var teamIdentifier = product.teamIdentifier;
+ var codeSignIdentity = product.signingIdentity;
+ if (hasProfiles) {
+ if (codeSignIdentity) {
+ console.warn("No provisioning profiles matching the bundle identifier '"
+ + product.bundle.identifier
+ + "' were found.");
+ } else {
+ console.warn("No provisioning profiles matching an applicable signing "
+ + "identity were found.");
+ }
+ } else {
+ if (codeSignIdentity) {
+ if (teamIdentifier) {
+ console.warn("No provisioning profiles with a valid signing identity "
+ + "(i.e. certificate and private key pair) matching the "
+ + "team ID '" + teamIdentifier + "' were found.")
+ } else {
+ console.warn("No provisioning profiles with a valid signing identity "
+ + "(i.e. certificate and private key pair) were found.");
+ }
+ } else {
+ console.warn("No non-expired provisioning profiles were found.");
+ }
+ }
+ }
+ return artifacts;
+ }
+
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ var data = JSON.parse(output.codesign._provisioningProfileData);
+ cmd.source = output.codesign._provisioningProfileFilePath;
+ cmd.destination = output.filePath;
+ cmd.description = "using provisioning profile " + data.Name + " (" + data.UUID + ")";
+ cmd.highlight = "filegen";
+ cmd.sourceCode = function() {
+ File.copy(source, destination);
+ };
+ return [cmd];
+ }
+ }
+
+ Rule {
+ multiplex: true
+ condition: product.codesign.enableCodeSigning
+ inputs: ["codesign.entitlements", "codesign.embedded_provisioningprofile"]
+
+ Artifact {
+ filePath: FileInfo.joinPaths(product.destinationDirectory,
+ product.targetName + ".xcent")
+ fileTags: ["codesign.xcent"]
+ }
+
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ cmd.description = "generating entitlements";
+ cmd.highlight = "codegen";
+ cmd.bundleIdentifier = product.bundle.identifier;
+ cmd.signingEntitlements = (inputs["codesign.entitlements"] || [])
+ .map(function (a) { return a.filePath; });
+ cmd.provisioningProfiles = (inputs["codesign.embedded_provisioningprofile"] || [])
+ .map(function (a) { return a.filePath; });
+ cmd.platformPath = product.xcode ? product.xcode.platformPath : undefined;
+ cmd.sdkPath = product.xcode ? product.xcode.sdkPath : undefined;
+ cmd.sourceCode = function() {
+ var i;
+ var provData = {};
+ var provisionProfiles = inputs["codesign.embedded_provisioningprofile"];
+ for (i in provisionProfiles) {
+ var plist = new PropertyList();
+ try {
+ plist.readFromData(Utilities.smimeMessageContent(
+ provisionProfiles[i].filePath));
+ provData = plist.toObject();
+ } finally {
+ plist.clear();
+ }
+ }
+
+ var aggregateEntitlements = {};
+
+ // Start building up an aggregate entitlements plist from the files in the SDKs,
+ // which contain placeholders in the same manner as Info.plist
+ function entitlementsFileContents(path) {
+ return File.exists(path) ? BundleTools.infoPlistContents(path) : undefined;
+ }
+ var entitlementsSources = [];
+ if (platformPath) {
+ entitlementsSources.push(
+ entitlementsFileContents(
+ FileInfo.joinPaths(platformPath, "Entitlements.plist")));
+ }
+ if (sdkPath) {
+ entitlementsSources.push(
+ entitlementsFileContents(
+ FileInfo.joinPaths(sdkPath, "Entitlements.plist")));
+ }
+
+ for (i = 0; i < signingEntitlements.length; ++i) {
+ entitlementsSources.push(entitlementsFileContents(signingEntitlements[i]));
+ }
+
+ for (i = 0; i < entitlementsSources.length; ++i) {
+ var contents = entitlementsSources[i];
+ for (var key in contents) {
+ if (contents.hasOwnProperty(key))
+ aggregateEntitlements[key] = contents[key];
+ }
+ }
+
+ contents = provData["Entitlements"];
+ for (key in contents) {
+ if (contents.hasOwnProperty(key) && !aggregateEntitlements.hasOwnProperty(key))
+ aggregateEntitlements[key] = contents[key];
+ }
+
+ // Expand entitlements variables with data from the provisioning profile
+ var env = {
+ "AppIdentifierPrefix": (provData["ApplicationIdentifierPrefix"] || "") + ".",
+ "CFBundleIdentifier": bundleIdentifier
+ };
+ DarwinTools.expandPlistEnvironmentVariables(aggregateEntitlements, env, true);
+
+ // Anything with an undefined or otherwise empty value should be removed
+ // Only JSON-formatted plists can have null values, other formats error out
+ // This also follows Xcode behavior
+ DarwinTools.cleanPropertyList(aggregateEntitlements);
+
+ var plist = new PropertyList();
+ try {
+ plist.readFromObject(aggregateEntitlements);
+ plist.writeToFile(outputs["codesign.xcent"][0].filePath, "xml1");
+ } finally {
+ plist.clear();
+ }
+ };
+ return [cmd];
+ }
+ }
+}
diff --git a/share/qbs/modules/codesign/codesign.js b/share/qbs/modules/codesign/codesign.js
new file mode 100644
index 000000000..482225ea2
--- /dev/null
+++ b/share/qbs/modules/codesign/codesign.js
@@ -0,0 +1,493 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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.
+**
+****************************************************************************/
+
+var File = require("qbs.File");
+var FileInfo = require("qbs.FileInfo");
+var PathTools = require("qbs.PathTools");
+var Process = require("qbs.Process");
+var PropertyList = require("qbs.PropertyList");
+var Utilities = require("qbs.Utilities");
+
+function findSigningIdentities(searchString, team) {
+ if (!searchString)
+ return {};
+ var identities = Utilities.signingIdentities();
+ var matchedIdentities = {};
+ for (var key in identities) {
+ var identity = identities[key];
+ if (team && ![identity.subjectInfo.O, identity.subjectInfo.OU].includes(team))
+ continue;
+ if (searchString === key
+ || (identity.subjectInfo.CN && identity.subjectInfo.CN.startsWith(searchString))) {
+ matchedIdentities[key] = identity;
+ }
+ }
+ return matchedIdentities;
+}
+
+function humanReadableIdentitySummary(identities) {
+ return "\n\t" + Object.keys(identities).map(function (key) {
+ return identities[key].subjectInfo.CN
+ + " in team "
+ + identities[key].subjectInfo.O
+ + " (" + identities[key].subjectInfo.OU + ")";
+ }).join("\n\t");
+}
+
+/**
+ * Returns the best provisioning profile for code signing a binary with the given parameters.
+ * Ideally, this should behave identically as Xcode but the algorithm is not documented
+ * \l{https://developer.apple.com/library/ios/qa/qa1814/_index.html}{Automatic Provisioning}
+ */
+function findBestProvisioningProfile(product, files) {
+ var actualSigningIdentity = product.codesign._actualSigningIdentity || {};
+ var teamIdentifier = product.codesign.teamIdentifier;
+ var bundleIdentifier = product.bundle.identifier;
+ var targetOS = product.qbs.targetOS;
+ var buildVariant = product.qbs.buildVariant;
+ var query = product.codesign.provisioningProfile;
+ var profilePlatform = product.codesign._provisioningProfilePlatform;
+
+ // Read all provisioning profiles on disk into plist objects in memory
+ var profiles = files.map(function(filePath) {
+ var plist = new PropertyList();
+ try {
+ plist.readFromData(Utilities.smimeMessageContent(filePath));
+ return {
+ data: plist.toObject(),
+ filePath: filePath
+ };
+ } finally {
+ plist.clear();
+ }
+ });
+
+ // Do a simple search by matching UUID or Name
+ if (query) {
+ for (var i = 0; i < profiles.length; ++i) {
+ var obj = profiles[i];
+ if (obj.data && (obj.data.UUID === query || obj.data.Name === query))
+ return obj;
+ }
+
+ // If we asked for a specific provisioning profile, don't select one automatically
+ return undefined;
+ }
+
+ // Provisioning profiles are not normally used with ad-hoc code signing or non-apps
+ // We do these checks down here only for the automatic selection but not above because
+ // if the user explicitly selects a provisioning profile it should be used no matter what
+ if (actualSigningIdentity.SHA1 === "-" || !product.type.includes("application"))
+ return undefined;
+
+ // Filter out any provisioning profiles we know to be unsuitable from the start
+ profiles = profiles.filter(function (profile) {
+ var data = profile.data;
+
+ if (actualSigningIdentity.subjectInfo) {
+ var certCommonNames = (data["DeveloperCertificates"] || []).map(function (cert) {
+ return Utilities.certificateInfo(cert).subjectInfo.CN;
+ });
+ if (!certCommonNames.includes(actualSigningIdentity.subjectInfo.CN)) {
+ console.log("Skipping provisioning profile with no matching certificate names for '"
+ + actualSigningIdentity.subjectInfo.CN
+ + "' (found " + certCommonNames.join(", ") + "): "
+ + profile.filePath);
+ return false;
+ }
+ }
+
+ var platforms = data["Platform"] || [];
+ if (platforms.length > 0 && profilePlatform && !platforms.includes(profilePlatform)) {
+ console.log("Skipping provisioning profile for platform " + platforms.join(", ")
+ + " (current platform " + profilePlatform + ")"
+ + ": " + profile.filePath);
+ return false;
+ }
+
+ if (teamIdentifier
+ && !data["TeamIdentifier"].includes(teamIdentifier)
+ && data["TeamName"] !== teamIdentifier) {
+ console.log("Skipping provisioning profile for team " + data["TeamIdentifier"]
+ + " (" + data["TeamName"] + ") (current team " + teamIdentifier + ")"
+ + ": " + profile.filePath);
+ return false;
+ }
+
+ if (Date.parse(data["ExpirationDate"]) <= Date.now()) {
+ console.log("Skipping expired provisioning profile: " + profile.filePath);
+ return false;
+ }
+
+ // Filter development vs distribution profiles;
+ // though the certificate common names check should have been sufficient
+ var isDebug = buildVariant === "debug";
+ if (data["Entitlements"]["get-task-allow"] !== isDebug) {
+ console.log("Skipping provisioning profile for wrong debug mode: " + profile.filePath);
+ return false;
+ }
+
+ var prefix = data["ApplicationIdentifierPrefix"];
+ var fullAppId = data["Entitlements"]["application-identifier"];
+ if ([prefix, bundleIdentifier].join(".") !== fullAppId
+ && [prefix, "*"].join(".") !== fullAppId) {
+ console.log("Skipping provisioning profile not matching full ("
+ + [prefix, bundleIdentifier].join(".") + ") or wildcard ("
+ + [prefix, "*"].join(".") + ") app ID (found " + fullAppId + "): "
+ + profile.filePath);
+ return false;
+ }
+
+ return true;
+ });
+
+ // Sort by expiration date - sooner expiration dates come last
+ profiles.sort(function(profileA, profileB) {
+ var expA = Date.parse(profileA.data["ExpirationDate"]);
+ var expB = Date.parse(profileB.data["ExpirationDate"]);
+ if (expA < expB)
+ return -1;
+ if (expA > expB)
+ return 1;
+ return 0;
+ });
+
+ // Sort by application identifier - wildcard profiles come last
+ profiles.sort(function(profileA, profileB) {
+ var idA = profileA.data["Entitlements"]["application-identifier"];
+ var idB = profileB.data["Entitlements"]["application-identifier"];
+ if (!idA.endsWith(".*") && idB.endsWith(".*"))
+ return -1;
+ if (idA.endsWith(".*") && !idB.endsWith(".*"))
+ return 1;
+ return 0;
+ });
+
+ if (profiles.length) {
+ console.log("Automatic provisioning using profile "
+ + profiles[0].data.UUID
+ + " ("
+ + profiles[0].data.TeamName
+ + " - "
+ + profiles[0].data.Name
+ + ") in product "
+ + product.name);
+ return profiles[0];
+ }
+}
+
+/**
+ * Finds out the search paths for the `signtool.exe` utility supplied with
+ * the Windows SDK's.
+ */
+function findBestSignToolSearchPaths(arch) {
+ var searchPaths = [];
+ var keys = [
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows",
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Microsoft SDKs\\Windows"
+ ];
+ for (var keyIndex = 0; keyIndex < keys.length; ++keyIndex) {
+ var re = /^v([0-9]+)\.([0-9]+)$/;
+ var groups = Utilities.nativeSettingGroups(keys[keyIndex]).filter(function(version) {
+ return version.match(re);
+ });
+
+ groups.sort(function(a, b) {
+ return Utilities.versionCompare(b.substring(1), a.substring(1));
+ });
+
+ function addSearchPath(searchPath) {
+ if (File.exists(searchPath) && !searchPaths.includes(searchPath)) {
+ searchPaths.push(searchPath);
+ return true;
+ }
+ return false;
+ }
+
+ for (var groupIndex = 0; groupIndex < groups.length; ++groupIndex) {
+ var fullKey = keys[keyIndex] + "\\" + groups[groupIndex];
+ var fullVersion = Utilities.getNativeSetting(fullKey, "ProductVersion");
+ if (fullVersion) {
+ var installRoot = FileInfo.cleanPath(
+ Utilities.getNativeSetting(fullKey, "InstallationFolder"));
+ if (installRoot) {
+ // Try to add the architecture-independent path at first.
+ var searchPath = FileInfo.joinPaths(installRoot, "App Certification Kit");
+ if (!addSearchPath(searchPath)) {
+ // Try to add the architecture-dependent paths at second.
+ var binSearchPath = FileInfo.joinPaths(installRoot, "bin/" + fullVersion);
+ if (!File.exists(binSearchPath)) {
+ binSearchPath += ".0";
+ if (!File.exists(binSearchPath))
+ continue;
+ }
+
+ function kitsArchitectureSubDirectory(arch) {
+ if (arch === "x86")
+ return "x86";
+ else if (arch === "x86_64")
+ return "x64";
+ else if (arch.startsWith("arm64"))
+ return "arm64";
+ else if (arch.startsWith("arm"))
+ return "arm";
+ }
+
+ var archDir = kitsArchitectureSubDirectory(arch);
+ searchPath = FileInfo.joinPaths(binSearchPath, archDir);
+ addSearchPath(searchPath);
+ }
+ }
+ }
+ }
+ }
+
+ return searchPaths;
+}
+
+function prepareSign(project, product, inputs, outputs, input, output) {
+ var cmd, cmds = [];
+
+ if (!product.codesign.enableCodeSigning)
+ return cmds;
+
+ var isBundle = "bundle.content" in outputs;
+
+ var artifacts = [];
+ if (isBundle) {
+ artifacts = [{
+ filePath: FileInfo.joinPaths(product.destinationDirectory, product.bundle.bundleName),
+ fileName: product.bundle.bundleName
+ }];
+ } else {
+ artifacts = outputs["codesign.signed_artifact"];
+ }
+ var isProductBundle = product.bundle && product.bundle.isBundle;
+ var shouldSignArtifact = !isProductBundle || isBundle;
+
+ var enableCodeSigning = product.codesign.enableCodeSigning;
+ if (enableCodeSigning) {
+ var actualSigningIdentity = product.codesign._actualSigningIdentity;
+ if (!actualSigningIdentity) {
+ throw "No codesigning identities (i.e. certificate and private key pairs) matching “"
+ + product.codesign.signingIdentity + "” were found.";
+ }
+
+ // If this is a framework, we need to sign its versioned directory
+ var subpath = "";
+ if (isBundle) {
+ var isFramework = product.bundle.packageType === "FMWK";
+ if (isFramework) {
+ subpath = product.bundle.contentsFolderPath;
+ subpath = subpath.substring(product.bundle.bundleName.length);
+ }
+ }
+
+ // The codesign tool behaves weirdly. It can sign a bundle with a single artifact, but if
+ // say debug build variant is present, it starts complaining that it is not signed.
+ // We could always sign everything, but again, in case of a framework (but not in case of
+ // app or loadable bundle), codesign produces a warning that artifact is already signed.
+ // So, we skip signing the release artifact and only sign if other build variants present.
+ if (!shouldSignArtifact && artifacts.length == 1) {
+ artifacts = [];
+ }
+ for (var i = 0; i < artifacts.length; ++i) {
+ if (!shouldSignArtifact
+ && artifacts[i].qbs && artifacts[i].qbs.buildVariant === "release") {
+ continue;
+ }
+ var outputFilePath = artifacts[i].filePath;
+ var outputFileName = artifacts[i].fileName;
+
+ var args = ["--force", "--sign", actualSigningIdentity.SHA1];
+
+ // If signingTimestamp is undefined or empty, do not specify the flag at all -
+ // this uses the system-specific default behavior
+ var signingTimestamp = product.codesign.signingTimestamp;
+ if (signingTimestamp) {
+ // If signingTimestamp is an empty string, specify the flag but do
+ // not specify a value - this uses a default Apple-provided server
+ var flag = "--timestamp";
+ if (signingTimestamp)
+ flag += "=" + signingTimestamp;
+ args.push(flag);
+ }
+
+ for (var j in inputs["codesign.xcent"]) {
+ args.push("--entitlements", inputs["codesign.xcent"][j].filePath);
+ break; // there should only be one
+ }
+
+ args = args.concat(product.codesign.codesignFlags || []);
+
+ args.push(outputFilePath + subpath);
+ cmd = new Command(product.codesign.codesignPath, args);
+ cmd.description = "codesign " + outputFileName
+ + " (" + actualSigningIdentity.subjectInfo.CN + ")";
+ cmd.outputFilePath = outputFilePath;
+ cmd.stderrFilterFunction = function(stderr) {
+ return stderr.replace(outputFilePath + ": replacing existing signature\n", "");
+ };
+ cmds.push(cmd);
+ }
+ }
+
+ if (isBundle) {
+ cmd = new Command("touch", ["-c", outputFilePath]);
+ cmd.silent = true;
+ cmds.push(cmd);
+ }
+
+ return cmds;
+}
+
+function signApkPackage(project, product, inputs, outputs, input, output, explicitlyDependsOn) {
+ var apkInput = inputs["android.package_unsigned"][0];
+ var apkOutput = outputs["android.package"][0];
+ var cmd;
+ if (product.codesign.enableCodeSigning) {
+ var args = ["sign",
+ "--ks", product.codesign.keystorePath,
+ "--ks-pass", "pass:" + product.codesign.keystorePassword,
+ "--ks-key-alias", product.codesign.keyAlias,
+ "--key-pass", "pass:" + product.codesign.keyPassword,
+ "--out", apkOutput.filePath,
+ apkInput.filePath];
+ cmd = new Command(product.codesign.apksignerFilePath, args);
+ cmd.description = "signing " + apkOutput.fileName;
+ } else {
+ cmd = new JavaScriptCommand();
+ cmd.description = "copying without signing " + apkOutput.fileName;
+ cmd.source = apkInput.filePath;
+ cmd.target = apkOutput.filePath;
+ cmd.silent = true;
+ cmd.sourceCode = function() {
+ // If enableCodeSigning is changed to false without any change to unsigned package then
+ // the copy won't happen because of timestamps. So the target file needs file needs to
+ // be removed to avoid it.
+ File.remove(target);
+ File.copy(source, target);
+ }
+ }
+ return cmd;
+}
+
+function signAabPackage(project, product, inputs, outputs, input, output, explicitlyDependsOn) {
+ var aabInput = inputs["android.package_unsigned"][0];
+ var aabOutput = outputs["android.package"][0];
+ var cmd;
+ if (product.codesign.enableCodeSigning) {
+ args = ["-sigalg", "SHA1withRSA", "-digestalg", "SHA1",
+ "-keystore", product.codesign.keystorePath,
+ "-storepass", product.codesign.keystorePassword,
+ "-keypass", product.codesign.keyPassword,
+ "-signedjar", aabOutput.filePath,
+ aabInput.filePath,
+ product.codesign.keyAlias];
+ cmd = new Command(product.codesign.jarsignerFilePath, args);
+ cmd.description = "signing " + aabOutput.fileName;
+ } else {
+ cmd = new JavaScriptCommand();
+ cmd.description = "copying without signing " + aabOutput.fileName;
+ cmd.source = aabInput.filePath;
+ cmd.target = aabOutput.filePath;
+ cmd.silent = true;
+ cmd.sourceCode = function() {
+ // If enableCodeSigning is changed to false without any change to unsigned package then
+ // the copy won't happen because of timestamps. So the target file needs file needs to
+ // be removed to avoid it.
+ File.remove(target);
+ File.copy(source, target);
+ }
+ }
+ return cmd;
+}
+
+function createDebugKeyStoreCommandString(keytoolFilePath, keystoreFilePath, keystorePassword,
+ keyPassword, keyAlias) {
+ var args = ["-genkey", "-keystore", keystoreFilePath, "-alias", keyAlias,
+ "-storepass", keystorePassword, "-keypass", keyPassword, "-keyalg", "RSA",
+ "-keysize", "2048", "-validity", "10000", "-dname",
+ "CN=Android Debug,O=Android,C=US"];
+ return Process.shellQuote(keytoolFilePath, args);
+}
+
+function prepareSigntool(project, product, inputs, outputs, input, output) {
+ var cmd, cmds = [];
+
+ if (!product.codesign.enableCodeSigning)
+ return cmds;
+
+ var args = ["sign"];
+
+ var subjectName = product.codesign.subjectName;
+ if (subjectName)
+ args.push("/n", subjectName);
+
+ var rootSubjectName = product.codesign.rootSubjectName;
+ if (rootSubjectName)
+ args.push("/r", rootSubjectName);
+
+ var hashAlgorithm = product.codesign.hashAlgorithm;
+ if (hashAlgorithm)
+ args.push("/fd", hashAlgorithm);
+
+ var signingTimestamp = product.codesign.signingTimestamp;
+ if (signingTimestamp)
+ args.push("/tr", signingTimestamp);
+
+ var timestampAlgorithm = product.codesign.timestampAlgorithm;
+ if (timestampAlgorithm)
+ args.push("/td", timestampAlgorithm);
+
+ var certificatePath = product.codesign.certificatePath;
+ if (certificatePath)
+ args.push("/f", certificatePath);
+
+ var certificatePassword = product.codesign.certificatePassword;
+ if (certificatePassword)
+ args.push("/p", certificatePassword);
+
+ var crossCertificatePath = product.codesign.crossCertificatePath;
+ if (crossCertificatePath)
+ args.push("/ac", crossCertificatePath);
+
+ args = args.concat(product.codesign.codesignFlags || []);
+
+ var outputArtifact = outputs["codesign.signed_artifact"][0];
+ args.push(outputArtifact.filePath);
+
+ cmd = new Command(product.codesign.codesignPath, args);
+ cmd.description = "signing " + outputArtifact.fileName;
+ cmd.highlight = "linker";
+ cmds.push(cmd);
+ return cmds;
+}
diff --git a/share/qbs/modules/codesign/noop.qbs b/share/qbs/modules/codesign/noop.qbs
new file mode 100644
index 000000000..d8c75eabc
--- /dev/null
+++ b/share/qbs/modules/codesign/noop.qbs
@@ -0,0 +1,35 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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.
+**
+****************************************************************************/
+
+CodeSignModule {
+ condition: true
+ priority: -100
+}
diff --git a/share/qbs/modules/codesign/signtool.qbs b/share/qbs/modules/codesign/signtool.qbs
new file mode 100644
index 000000000..111f0a307
--- /dev/null
+++ b/share/qbs/modules/codesign/signtool.qbs
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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.File
+import qbs.Host
+import qbs.ModUtils
+import qbs.Probes
+import "codesign.js" as CODESIGN
+
+CodeSignModule {
+ condition: qbs.targetOS.includes("windows")
+ && Host.os().includes("windows")
+ && qbs.toolchain.includes("msvc")
+
+ _canSignArtifacts: true
+
+ Probes.BinaryProbe {
+ id: signtoolProbe
+ names: [codesignName]
+ searchPaths: CODESIGN.findBestSignToolSearchPaths(Host.architecture())
+ }
+
+ codesignName: "signtool"
+ codesignPath: signtoolProbe.filePath
+
+ property string subjectName
+ PropertyOptions {
+ name: "subjectName"
+ description: "Name of the subject of the signing certificate."
+ }
+
+ property string rootSubjectName
+ PropertyOptions {
+ name: "rootSubjectName"
+ description: "Name of the subject of the root certificate that the signing " +
+ "certificate must chain to."
+ }
+
+ property string hashAlgorithm
+ PropertyOptions {
+ name: "hashAlgorithm"
+ description: "Name of the hash algorithm used on the signing certificate."
+ allowedValues: ["sha1", "sha256", "sha384", "sha512"]
+ }
+
+ property string timestampAlgorithm
+ PropertyOptions {
+ name: "timestampAlgorithm"
+ description: "Name of the timestamp algorithm."
+ allowedValues: ["sha1", "sha256"]
+ }
+
+ property path certificatePath
+ PropertyOptions {
+ name: "certificatePath"
+ description: "Path to the signing certificate PFX file."
+ }
+
+ property string certificatePassword
+ PropertyOptions {
+ name: "certificatePassword"
+ description: "Password to use when opening a certificate PFX file."
+ }
+
+ property path crossCertificatePath
+ PropertyOptions {
+ name: "crossCertificatePath"
+ description: "Path to the additional certificate CER file."
+ }
+
+ validate: {
+ if (enableCodeSigning && !File.exists(codesignPath)) {
+ throw ModUtils.ModuleError("Could not find 'signtool' utility");
+ }
+ }
+}
diff --git a/share/qbs/modules/cpp/CppModule.qbs b/share/qbs/modules/cpp/CppModule.qbs
index bdd6d2750..bd1eaa242 100644
--- a/share/qbs/modules/cpp/CppModule.qbs
+++ b/share/qbs/modules/cpp/CppModule.qbs
@@ -29,10 +29,11 @@
****************************************************************************/
// base for Cpp modules
+import qbs.FileInfo
import qbs.ModUtils
import qbs.Utilities
import qbs.WindowsUtils
-
+import "cpp.js" as Cpp
import "setuprunenv.js" as SetupRunEnv
Module {
@@ -128,7 +129,7 @@ Module {
defaults will be used."
}
- property string minimumAndroidVersion
+ property string minimumAndroidVersion // not used, undocumented
PropertyOptions {
name: "minimumAndroidVersion"
description: "a version number in the format [major].[minor] indicating the earliest \
@@ -136,7 +137,7 @@ Module {
version which is then written to AndroidManifest.xml."
}
- property string maximumAndroidVersion
+ property string maximumAndroidVersion // not used, undocumented
PropertyOptions {
name: "maximumAndroidVersion"
description: "a version number in the format [major].[minor] indicating the latest \
@@ -145,6 +146,12 @@ Module {
be set."
}
+ property string toolchainInstallPath
+ PropertyOptions {
+ name: "toolchainInstallPath"
+ description: "a path to the directory where the toolchain executable files are located."
+ }
+
property pathList includePaths
property pathList systemIncludePaths
property pathList distributionIncludePaths
@@ -173,12 +180,19 @@ Module {
property string executablePrefix: ""
property string staticLibrarySuffix: ""
property string dynamicLibrarySuffix: ""
+ property string archSuffix: ""
property string loadableModuleSuffix: ""
property string executableSuffix: ""
property string debugInfoSuffix: ""
property string debugInfoBundleSuffix: ""
property string variantSuffix: ""
property string dynamicLibraryImportSuffix: ".lib"
+ property string objectSuffix: ".o"
+ property string linkerMapSuffix: ".map"
+ property string compilerListingSuffix: ".lst"
+ property string assemblerListingSuffix: ".lst"
+ property string resourceSuffix: ".res"
+ property string precompiledHeaderSuffix
property bool createSymlinks: true
property stringList dynamicLibraries // list of names, will be linked with -lname
property stringList staticLibraries // list of static library files
@@ -193,6 +207,33 @@ Module {
property bool discardUnusedData
property bool removeDuplicateLibraries: true
+ property string defineFlag
+ property string includeFlag
+ property string systemIncludeFlag
+ property string preincludeFlag
+ property string libraryDependencyFlag
+ property string libraryPathFlag
+ property string linkerScriptFlag
+
+ property stringList knownArchitectures: []
+ property var toolchainDetails
+ property string compilerExtension: FileInfo.executableSuffix()
+
+ property string linkerMode: "automatic"
+ PropertyOptions {
+ name: "linkerMode"
+ allowedValues: ["automatic", "manual"]
+ description: "Controls whether to automatically use an appropriate compiler frontend "
+ + "in place of the system linker when linking binaries. The default is \"automatic\", "
+ + "which chooses either the C++ compiler, C compiler, or system linker specified by "
+ + "the linkerName/linkerPath properties, depending on the type of object files "
+ + "present on the linker command line. \"manual\" allows you to explicitly specify "
+ + "the linker using the linkerName/linkerPath properties, and allows linker flags "
+ + "passed to the linkerFlags and platformLinkerFlags properties to be escaped "
+ + "manually (using -Wl or -Xlinker) instead of automatically based on the selected "
+ + "linker."
+ }
+
property stringList assemblerFlags
PropertyOptions {
name: "assemblerFlags"
@@ -299,14 +340,12 @@ Module {
property stringList cLanguageVersion
PropertyOptions {
name: "cLanguageVersion"
- allowedValues: ["c89", "c99", "c11"]
description: "The version of the C standard with which the code must comply."
}
property stringList cxxLanguageVersion
PropertyOptions {
name: "cxxLanguageVersion"
- allowedValues: ["c++98", "c++11", "c++14", "c++17"]
description: "The version of the C++ standard with which the code must comply."
}
@@ -369,13 +408,14 @@ Module {
property bool combineObjcSources: false
property bool combineObjcxxSources: false
+ // Those are set internally by different cpp module implementations
property stringList targetAssemblerFlags
property stringList targetDriverFlags
property stringList targetLinkerFlags
property bool _skipAllChecks: false // Internal
- property bool validateTargetTriple: true
+ property bool validateTargetTriple: true // undocumented
// TODO: The following four rules could use a convenience base item if rule properties
// were available in Artifact items and prepare scripts.
@@ -508,6 +548,13 @@ Module {
return '"' + a + '"'; }).join(", ")
+ ". See https://docs.microsoft.com/en-us/windows/desktop/SysInfo/operating-system-version");
}
+
+ if (knownArchitectures && knownArchitectures.length > 0) {
+ var isSupported = Cpp.supportsArchitecture(qbs.architecture, knownArchitectures);
+ if (!isSupported) {
+ throw ModUtils.ModuleError("Unsupported architecture: '" + qbs.architecture + "'");
+ }
+ }
}
}
diff --git a/share/qbs/modules/cpp/DarwinGCC.qbs b/share/qbs/modules/cpp/DarwinGCC.qbs
index 9332603ec..e20973acc 100644
--- a/share/qbs/modules/cpp/DarwinGCC.qbs
+++ b/share/qbs/modules/cpp/DarwinGCC.qbs
@@ -43,7 +43,7 @@ import "gcc.js" as Gcc
UnixGCC {
condition: false
- Depends { name: "xcode"; required: qbs.toolchain && qbs.toolchain.contains("xcode") }
+ Depends { name: "xcode"; required: qbs.toolchain && qbs.toolchain.includes("xcode") }
Probes.BinaryProbe {
id: lipoProbe
@@ -76,7 +76,7 @@ UnixGCC {
dynamicLibrarySuffix: ".dylib"
Properties {
- condition: product.multiplexByQbsProperties.contains("buildVariants")
+ condition: product.multiplexByQbsProperties.includes("buildVariants")
&& qbs.buildVariants && qbs.buildVariants.length > 1
&& (!product.aggregate || !!product.multiplexConfigurationId)
&& qbs.buildVariant !== "release"
@@ -98,7 +98,7 @@ UnixGCC {
setupBuildEnvironment: {
for (var key in product.cpp.buildEnv) {
- v = new ModUtils.EnvironmentVariable(key);
+ var v = new ModUtils.EnvironmentVariable(key);
v.value = product.cpp.buildEnv[key];
v.set();
}
@@ -107,32 +107,42 @@ UnixGCC {
property var defaultInfoPlist: {
var dict = {};
- if (qbs.targetOS.contains("macos")) {
+ if (qbs.targetOS.includes("macos")) {
dict["NSPrincipalClass"] = "NSApplication"; // needed for Retina display support
+ // QBS-1670: set this flag by default to avoid extensive GPU usage
+ dict["NSSupportsAutomaticGraphicsSwitching"] = true;
+
if (minimumMacosVersion)
dict["LSMinimumSystemVersion"] = minimumMacosVersion;
}
+ if (qbs.targetOS.includes("ios") && minimumIosVersion)
+ dict["MinimumOSVersion"] = minimumIosVersion;
+ else if (qbs.targetOS.includes("tvos") && minimumTvosVersion)
+ dict["MinimumOSVersion"] = minimumTvosVersion;
+ else if (qbs.targetOS.includes("watchos") && minimumWatchosVersion)
+ dict["MinimumOSVersion"] = minimumWatchosVersion;
+
if (qbs.targetOS.containsAny(["ios", "tvos"])) {
dict["LSRequiresIPhoneOS"] = true;
if (xcode.platformType === "device") {
- if (qbs.targetOS.contains("ios")) {
+ if (qbs.targetOS.includes("ios")) {
if (qbs.architecture === "arm64")
dict["UIRequiredDeviceCapabilities"] = ["arm64"];
else
dict["UIRequiredDeviceCapabilities"] = ["armv7"];
}
- if (qbs.targetOS.contains("tvos"))
+ if (qbs.targetOS.includes("tvos"))
dict["UIRequiredDeviceCapabilities"] = ["arm64"];
}
}
if (xcode.present) {
var targetDevices = DarwinTools.targetedDeviceFamily(xcode.targetDevices);
- if (qbs.targetOS.contains("ios"))
+ if (qbs.targetOS.includes("ios"))
dict["UIDeviceFamily"] = targetDevices;
if (qbs.targetOS.containsAny(["ios", "watchos"])) {
@@ -143,13 +153,13 @@ UnixGCC {
"UIInterfaceOrientationLandscapeRight"
];
- if (targetDevices.contains("ipad"))
+ if (targetDevices.includes("ipad"))
dict["UISupportedInterfaceOrientations~ipad"] = orientations;
- if (targetDevices.contains("watch"))
+ if (targetDevices.includes("watch"))
dict["UISupportedInterfaceOrientations"] = orientations.slice(0, 2);
- if (targetDevices.contains("iphone")) {
+ if (targetDevices.includes("iphone")) {
orientations.splice(1, 1);
dict["UISupportedInterfaceOrientations"] = orientations;
}
@@ -189,13 +199,13 @@ UnixGCC {
// Set the corresponding environment variable even if the minimum OS version is undefined,
// because this indicates the default deployment target for that OS
- if (qbs.targetOS.contains("ios") && minimumIosVersion)
+ if (qbs.targetOS.includes("ios") && minimumIosVersion)
env["IPHONEOS_DEPLOYMENT_TARGET"] = minimumIosVersion;
- if (qbs.targetOS.contains("macos") && minimumMacosVersion)
+ if (qbs.targetOS.includes("macos") && minimumMacosVersion)
env["MACOSX_DEPLOYMENT_TARGET"] = minimumMacosVersion;
- if (qbs.targetOS.contains("watchos") && minimumWatchosVersion)
+ if (qbs.targetOS.includes("watchos") && minimumWatchosVersion)
env["WATCHOS_DEPLOYMENT_TARGET"] = minimumWatchosVersion;
- if (qbs.targetOS.contains("tvos") && minimumTvosVersion)
+ if (qbs.targetOS.includes("tvos") && minimumTvosVersion)
env["TVOS_DEPLOYMENT_TARGET"] = minimumTvosVersion;
if (xcode.present)
@@ -208,7 +218,7 @@ UnixGCC {
property string minimumDarwinVersionCompilerFlag
property string minimumDarwinVersionLinkerFlag
- property bool libcxxAvailable: qbs.toolchain.contains("clang") && cxxLanguageVersion !== "c++98"
+ property bool libcxxAvailable: qbs.toolchain.includes("clang") && cxxLanguageVersion !== "c++98"
Rule {
condition: enableAggregationRules
@@ -216,7 +226,8 @@ UnixGCC {
multiplex: true
outputFileTags: ["bundle.input", "application", "primary", "debuginfo_app",
- "debuginfo_bundle", "bundle.variant_symlink", "debuginfo_plist"]
+ "debuginfo_bundle", "bundle.variant_symlink", "debuginfo_plist",
+ "codesign.signed_artifact"]
outputArtifacts: Darwin.lipoOutputArtifacts(product, inputs, "application", "app")
prepare: Darwin.prepareLipo.apply(Darwin, arguments)
@@ -227,7 +238,8 @@ UnixGCC {
inputsFromDependencies: ["loadablemodule"]
multiplex: true
- outputFileTags: ["bundle.input", "loadablemodule", "primary", "debuginfo_loadablemodule"]
+ outputFileTags: ["bundle.input", "loadablemodule", "primary", "debuginfo_loadablemodule",
+ "debuginfo_bundle", "debuginfo_plist", "codesign.signed_artifact"]
outputArtifacts: Darwin.lipoOutputArtifacts(product, inputs, "loadablemodule",
"loadablemodule")
@@ -241,7 +253,7 @@ UnixGCC {
outputFileTags: ["bundle.input", "dynamiclibrary", "dynamiclibrary_symbols", "primary",
"debuginfo_dll","debuginfo_bundle","bundle.variant_symlink",
- "debuginfo_plist"]
+ "debuginfo_plist", "codesign.signed_artifact"]
outputArtifacts: Darwin.lipoOutputArtifacts(product, inputs, "dynamiclibrary", "dll")
prepare: Darwin.prepareLipo.apply(Darwin, arguments)
@@ -252,14 +264,14 @@ UnixGCC {
inputsFromDependencies: ["staticlibrary"]
multiplex: true
- outputFileTags: ["bundle.input", "staticlibrary", "primary"]
+ outputFileTags: ["bundle.input", "staticlibrary", "primary", "codesign.signed_artifact"]
outputArtifacts: Darwin.lipoOutputArtifacts(product, inputs, "staticlibrary")
prepare: Darwin.prepareLipo.apply(Darwin, arguments)
}
Rule {
- condition: qbs.targetOS.contains("darwin")
+ condition: qbs.targetOS.includes("darwin")
multiplex: true
Artifact {
diff --git a/share/qbs/modules/cpp/GenericGCC.qbs b/share/qbs/modules/cpp/GenericGCC.qbs
index 63d5db7b8..f84028940 100644
--- a/share/qbs/modules/cpp/GenericGCC.qbs
+++ b/share/qbs/modules/cpp/GenericGCC.qbs
@@ -30,6 +30,7 @@
import qbs.File
import qbs.FileInfo
+import qbs.Host
import qbs.ModUtils
import qbs.PathTools
import qbs.Probes
@@ -38,12 +39,15 @@ import qbs.TextFile
import qbs.Utilities
import qbs.UnixUtils
import qbs.WindowsUtils
+import 'cpp.js' as Cpp
import 'gcc.js' as Gcc
CppModule {
- condition: qbs.toolchain && qbs.toolchain.contains("gcc")
+ condition: qbs.toolchain && qbs.toolchain.includes("gcc")
priority: -100
+ Depends { name: "codesign" }
+
Probes.GccBinaryProbe {
id: compilerPathProbe
condition: !toolchainInstallPath && !_skipAllChecks
@@ -114,9 +118,14 @@ CppModule {
compilerFrameworkPaths: gccProbe.frameworkPaths
compilerLibraryPaths: gccProbe.libraryPaths
- property bool compilerHasTargetOption: qbs.toolchain.contains("clang")
+ staticLibraryPrefix: "lib"
+ staticLibrarySuffix: ".a"
+
+ precompiledHeaderSuffix: ".gch"
+
+ property bool compilerHasTargetOption: qbs.toolchain.includes("clang")
&& Utilities.versionCompare(compilerVersion, "3.1") >= 0
- property bool assemblerHasTargetOption: qbs.toolchain.contains("xcode")
+ property bool assemblerHasTargetOption: qbs.toolchain.includes("xcode")
&& Utilities.versionCompare(compilerVersion, "7") >= 0
property string target: targetArch
? [targetArch, targetVendor, targetSystem, targetAbi].join("-")
@@ -131,8 +140,7 @@ CppModule {
property string toolchainPrefix: compilerPathProbe.found
? compilerPathProbe.tcPrefix
: undefined
- property string toolchainInstallPath: compilerPathProbe.found ? compilerPathProbe.path
- : undefined
+ toolchainInstallPath: compilerPathProbe.found ? compilerPathProbe.path : undefined
property string binutilsPath: binutilsProbe.found ? binutilsProbe.path : toolchainInstallPath
assemblerName: 'as' + compilerExtension
@@ -148,21 +156,6 @@ CppModule {
property string syslibroot: sysroot
property stringList sysrootFlags: sysroot ? ["--sysroot=" + sysroot] : []
- property string linkerMode: "automatic"
- PropertyOptions {
- name: "linkerMode"
- allowedValues: ["automatic", "manual"]
- description: "Controls whether to automatically use an appropriate compiler frontend "
- + "in place of the system linker when linking binaries. The default is \"automatic\", "
- + "which chooses either the C++ compiler, C compiler, or system linker specified by "
- + "the linkerName/linkerPath properties, depending on the type of object files "
- + "present on the linker command line. \"manual\" allows you to explicitly specify "
- + "the linker using the linkerName/linkerPath properties, and allows linker flags "
- + "passed to the linkerFlags and platformLinkerFlags properties to be escaped "
- + "manually (using -Wl or -Xlinker) instead of automatically based on the selected "
- + "linker."
- }
-
property string exportedSymbolsCheckMode: "ignore-undefined"
PropertyOptions {
name: "exportedSymbolsCheckMode"
@@ -177,7 +170,7 @@ CppModule {
property string linkerVariant
PropertyOptions {
name: "linkerVariant"
- allowedValues: ["bfd", "gold", "lld"]
+ allowedValues: ["bfd", "gold", "lld", "mold"]
description: "Allows to specify the linker variant. Maps to gcc's and clang's -fuse-ld "
+ "option."
}
@@ -189,10 +182,9 @@ CppModule {
property string toolchainPathPrefix: Gcc.pathPrefix(toolchainInstallPath, toolchainPrefix)
property string binutilsPathPrefix: Gcc.pathPrefix(binutilsPath, toolchainPrefix)
- property string compilerExtension: qbs.hostOS.contains("windows") ? ".exe" : ""
- property string cCompilerName: (qbs.toolchain.contains("clang") ? "clang" : "gcc")
+ property string cCompilerName: (qbs.toolchain.includes("clang") ? "clang" : "gcc")
+ compilerExtension
- property string cxxCompilerName: (qbs.toolchain.contains("clang") ? "clang++" : "g++")
+ property string cxxCompilerName: (qbs.toolchain.includes("clang") ? "clang++" : "g++")
+ compilerExtension
compilerPathByLanguage: ({
@@ -216,13 +208,22 @@ CppModule {
property stringList dsymutilFlags
property bool alwaysUseLipo: false
- property string includeFlag: "-I"
- property string systemIncludeFlag: "-isystem"
+ defineFlag: "-D"
+ includeFlag: "-I"
+ systemIncludeFlag: "-isystem"
+ preincludeFlag: "-include"
+ libraryPathFlag: "-L"
+ linkerScriptFlag: "-T"
readonly property bool shouldCreateSymlinks: {
- return createSymlinks && internalVersion && ["macho", "elf"].contains(cpp.imageFormat);
+ return createSymlinks && internalVersion && ["macho", "elf"].includes(imageFormat);
}
+ readonly property bool shouldSignArtifacts: codesign._canSignArtifacts
+ && codesign.enableCodeSigning
+ // codesigning is done during the lipo step
+ && !product.multiplexed
+
property string internalVersion: {
if (product.version === undefined)
return undefined;
@@ -250,18 +251,18 @@ CppModule {
property var buildEnv: {
var env = {};
- if (qbs.toolchain.contains("mingw"))
- env.PATH = [toolchainInstallPath]; // For libwinpthread etc
+ if (qbs.toolchain.includes("mingw"))
+ env.PATH = toolchainInstallPath; // For libwinpthread etc
return env;
}
exceptionHandlingModel: {
- if (qbs.toolchain.contains("mingw")) {
+ if (qbs.toolchain.includes("mingw")) {
// https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html claims
// __USING_SJLJ_EXCEPTIONS__ is defined as 1 when using SJLJ exceptions, but there don't
// seem to be defines for the other models, so use the presence of the DLLs for now.
var prefix = toolchainInstallPath;
- if (!qbs.hostOS.contains("windows"))
+ if (!Host.os().includes("windows"))
prefix = FileInfo.joinPaths(toolchainInstallPath, "..", "lib", "gcc",
toolchainPrefix,
[compilerVersionMajor, compilerVersionMinor].join("."));
@@ -313,7 +314,7 @@ CppModule {
if (gccProbe.targetPlatform) {
// Can't differentiate Darwin OSes at the compiler level alone
if (gccProbe.targetPlatform === "darwin"
- ? !qbs.targetOS.contains("darwin")
+ ? !qbs.targetOS.includes("darwin")
: qbs.targetPlatform !== gccProbe.targetPlatform)
isWrongTriple = true;
} else if (qbs.targetPlatform) {
@@ -350,7 +351,7 @@ CppModule {
var validateFlagsFunction = function (value) {
if (value) {
for (var i = 0; i < value.length; ++i) {
- if (["-target", "-triple", "-arch"].contains(value[i]))
+ if (["-target", "-triple", "-arch"].includes(value[i]))
return false;
}
}
@@ -400,28 +401,33 @@ CppModule {
condition: product.cpp.shouldLink
multiplex: true
inputs: {
- var tags = ["obj", "linkerscript", "versionscript"];
+ var tags = ["obj", "res", "linkerscript", "versionscript"];
if (product.bundle && product.bundle.embedInfoPlist
- && product.qbs.targetOS.contains("darwin")) {
+ && product.qbs.targetOS.includes("darwin")) {
tags.push("aggregate_infoplist");
}
return tags;
}
inputsFromDependencies: ["dynamiclibrary_symbols", "staticlibrary", "dynamiclibrary_import"]
- outputFileTags: [
- "bundle.input",
- "dynamiclibrary", "dynamiclibrary_symlink", "dynamiclibrary_symbols", "debuginfo_dll",
- "debuginfo_bundle","dynamiclibrary_import", "debuginfo_plist",
- ]
+ outputFileTags: {
+ var tags = ["bundle.input", "dynamiclibrary", "dynamiclibrary_symlink",
+ "dynamiclibrary_symbols", "debuginfo_dll", "debuginfo_bundle",
+ "dynamiclibrary_import", "debuginfo_plist"];
+ if (shouldSignArtifacts)
+ tags.push("codesign.signed_artifact");
+ return tags;
+ }
outputArtifacts: {
var artifacts = [{
- filePath: product.destinationDirectory + "/"
- + PathTools.dynamicLibraryFilePath(product),
- fileTags: ["bundle.input", "dynamiclibrary"],
+ filePath: FileInfo.joinPaths(product.destinationDirectory,
+ PathTools.dynamicLibraryFilePath(product)),
+ fileTags: ["bundle.input", "dynamiclibrary"]
+ .concat(product.cpp.shouldSignArtifacts
+ ? ["codesign.signed_artifact"] : []),
bundle: {
- _bundleFilePath: product.destinationDirectory + "/"
- + PathTools.bundleExecutableFilePath(product)
+ _bundleFilePath: FileInfo.joinPaths(product.destinationDirectory,
+ PathTools.bundleExecutableFilePath(product))
}
}];
if (product.cpp.imageFormat === "pe") {
@@ -445,9 +451,9 @@ CppModule {
var maxVersionParts = product.cpp.internalVersion ? 3 : 1;
for (var i = 0; i < maxVersionParts; ++i) {
var symlink = {
- filePath: product.destinationDirectory + "/"
- + PathTools.dynamicLibraryFilePath(product, undefined, undefined,
- i),
+ filePath: FileInfo.joinPaths(product.destinationDirectory,
+ PathTools.dynamicLibraryFilePath(
+ product, undefined, undefined, i)),
fileTags: ["dynamiclibrary_symlink"]
};
if (i > 0 && artifacts[i-1].filePath == symlink.filePath)
@@ -460,16 +466,14 @@ CppModule {
return artifacts;
}
- prepare: {
- return Gcc.prepareLinker.apply(Gcc, arguments);
- }
+ prepare: Gcc.prepareLinker.apply(Gcc, arguments)
}
Rule {
name: "staticLibraryLinker"
condition: product.cpp.shouldLink
multiplex: true
- inputs: ["obj", "linkerscript"]
+ inputs: ["obj", "res", "linkerscript"]
inputsFromDependencies: ["dynamiclibrary_symbols", "dynamiclibrary_import", "staticlibrary"]
outputFileTags: ["bundle.input", "staticlibrary", "c_staticlibrary", "cpp_staticlibrary"]
@@ -479,9 +483,9 @@ CppModule {
var objCount = objs ? objs.length : 0;
for (var i = 0; i < objCount; ++i) {
var ft = objs[i].fileTags;
- if (ft.contains("c_obj"))
+ if (ft.includes("c_obj"))
tags.push("c_staticlibrary");
- if (ft.contains("cpp_obj"))
+ if (ft.includes("cpp_obj"))
tags.push("cpp_staticlibrary");
}
return [{
@@ -499,6 +503,8 @@ CppModule {
var args = ['rcs', output.filePath];
for (var i in inputs.obj)
args.push(inputs.obj[i].filePath);
+ for (var i in inputs.res)
+ args.push(inputs.res[i].filePath);
var cmd = new Command(product.cpp.archiverPath, args);
cmd.description = 'creating ' + output.fileName;
cmd.highlight = 'linker'
@@ -513,22 +519,29 @@ CppModule {
condition: product.cpp.shouldLink
multiplex: true
inputs: {
- var tags = ["obj", "linkerscript"];
+ var tags = ["obj", "res", "linkerscript"];
if (product.bundle && product.bundle.embedInfoPlist
- && product.qbs.targetOS.contains("darwin")) {
+ && product.qbs.targetOS.includes("darwin")) {
tags.push("aggregate_infoplist");
}
return tags;
}
inputsFromDependencies: ["dynamiclibrary_symbols", "dynamiclibrary_import", "staticlibrary"]
- outputFileTags: ["bundle.input", "loadablemodule", "debuginfo_loadablemodule",
- "debuginfo_bundle","debuginfo_plist"]
+ outputFileTags: {
+ var tags = ["bundle.input", "loadablemodule", "debuginfo_loadablemodule",
+ "debuginfo_bundle", "debuginfo_plist"];
+ if (shouldSignArtifacts)
+ tags.push("codesign.signed_artifact");
+ return tags;
+ }
outputArtifacts: {
var app = {
filePath: FileInfo.joinPaths(product.destinationDirectory,
PathTools.loadableModuleFilePath(product)),
- fileTags: ["bundle.input", "loadablemodule"],
+ fileTags: ["bundle.input", "loadablemodule"]
+ .concat(product.cpp.shouldSignArtifacts
+ ? ["codesign.signed_artifact"] : []),
bundle: {
_bundleFilePath: FileInfo.joinPaths(product.destinationDirectory,
PathTools.bundleExecutableFilePath(product))
@@ -541,9 +554,7 @@ CppModule {
return artifacts;
}
- prepare: {
- return Gcc.prepareLinker.apply(Gcc, arguments);
- }
+ prepare: Gcc.prepareLinker.apply(Gcc, arguments)
}
Rule {
@@ -551,22 +562,30 @@ CppModule {
condition: product.cpp.shouldLink
multiplex: true
inputs: {
- var tags = ["obj", "linkerscript"];
+ var tags = ["obj", "res", "linkerscript"];
if (product.bundle && product.bundle.embedInfoPlist
- && product.qbs.targetOS.contains("darwin")) {
+ && product.qbs.targetOS.includes("darwin")) {
tags.push("aggregate_infoplist");
}
return tags;
}
inputsFromDependencies: ["dynamiclibrary_symbols", "dynamiclibrary_import", "staticlibrary"]
- outputFileTags: ["bundle.input", "application", "debuginfo_app","debuginfo_bundle",
- "debuginfo_plist", "mem_map"]
+ outputFileTags: {
+ var tags = ["bundle.input", "application", "debuginfo_app", "debuginfo_bundle",
+ "debuginfo_plist"];
+ if (shouldSignArtifacts)
+ tags.push("codesign.signed_artifact");
+ if (generateLinkerMapFile)
+ tags.push("mem_map");
+ return tags;
+ }
outputArtifacts: {
var app = {
filePath: FileInfo.joinPaths(product.destinationDirectory,
PathTools.applicationFilePath(product)),
- fileTags: ["bundle.input", "application"],
+ fileTags: ["bundle.input", "application"].concat(
+ product.cpp.shouldSignArtifacts ? ["codesign.signed_artifact"] : []),
bundle: {
_bundleFilePath: FileInfo.joinPaths(product.destinationDirectory,
PathTools.bundleExecutableFilePath(product))
@@ -578,16 +597,14 @@ CppModule {
if (product.cpp.generateLinkerMapFile) {
artifacts.push({
filePath: FileInfo.joinPaths(product.destinationDirectory,
- product.targetName + ".map"),
+ product.targetName + product.cpp.linkerMapSuffix),
fileTags: ["mem_map"]
});
}
return artifacts;
}
- prepare: {
- return Gcc.prepareLinker.apply(Gcc, arguments);
- }
+ prepare: Gcc.prepareLinker.apply(Gcc, arguments)
}
Rule {
@@ -595,94 +612,53 @@ CppModule {
inputs: ["cpp", "c", "objcpp", "objc", "asm_cpp"]
auxiliaryInputs: ["hpp"]
explicitlyDependsOn: ["c_pch", "cpp_pch", "objc_pch", "objcpp_pch"]
-
- outputFileTags: ["obj", "c_obj", "cpp_obj", "intermediate_obj"]
- outputArtifacts: {
- var tags;
- if (input.fileTags.contains("cpp_intermediate_object"))
- tags = ["intermediate_obj"];
- else
- tags = ["obj"];
- if (inputs.c || inputs.objc)
- tags.push("c_obj");
- if (inputs.cpp || inputs.objcpp)
- tags.push("cpp_obj");
- return [{
- fileTags: tags,
- filePath: FileInfo.joinPaths(Utilities.getHash(input.baseDir),
- input.fileName + ".o")
- }];
- }
-
- prepare: {
- return Gcc.prepareCompiler.apply(Gcc, arguments);
- }
+ outputFileTags: Cpp.compilerOutputTags(false).concat(["c_obj", "cpp_obj"])
+ outputArtifacts: Cpp.compilerOutputArtifacts(input, inputs)
+ prepare: Gcc.prepareCompiler.apply(Gcc, arguments)
}
Rule {
name: "assembler"
inputs: ["asm"]
-
- Artifact {
- fileTags: ["obj"]
- filePath: FileInfo.joinPaths(Utilities.getHash(input.baseDir), input.fileName + ".o")
- }
-
- prepare: {
- return Gcc.prepareAssembler.apply(Gcc, arguments);
- }
+ outputFileTags: Cpp.assemblerOutputTags(false)
+ outputArtifacts: Cpp.assemblerOutputArtifacts(input)
+ prepare: Gcc.prepareAssembler.apply(Gcc, arguments)
}
Rule {
condition: useCPrecompiledHeader
inputs: ["c_pch_src"]
auxiliaryInputs: ["hpp"]
- Artifact {
- filePath: product.name + "_c.gch"
- fileTags: ["c_pch"]
- }
- prepare: {
- return Gcc.prepareCompiler.apply(Gcc, arguments);
- }
+ outputFileTags: Cpp.precompiledHeaderOutputTags("c", false)
+ outputArtifacts: Cpp.precompiledHeaderOutputArtifacts(input, product, "c", false)
+ prepare: Gcc.prepareCompiler.apply(Gcc, arguments)
}
Rule {
condition: useCxxPrecompiledHeader
inputs: ["cpp_pch_src"]
auxiliaryInputs: ["hpp"]
- Artifact {
- filePath: product.name + "_cpp.gch"
- fileTags: ["cpp_pch"]
- }
- prepare: {
- return Gcc.prepareCompiler.apply(Gcc, arguments);
- }
+ outputFileTags: Cpp.precompiledHeaderOutputTags("cpp", false)
+ outputArtifacts: Cpp.precompiledHeaderOutputArtifacts(input, product, "cpp", false)
+ prepare: Gcc.prepareCompiler.apply(Gcc, arguments)
}
Rule {
condition: useObjcPrecompiledHeader
inputs: ["objc_pch_src"]
auxiliaryInputs: ["hpp"]
- Artifact {
- filePath: product.name + "_objc.gch"
- fileTags: ["objc_pch"]
- }
- prepare: {
- return Gcc.prepareCompiler.apply(Gcc, arguments);
- }
+ outputFileTags: Cpp.precompiledHeaderOutputTags("objc", false)
+ outputArtifacts: Cpp.precompiledHeaderOutputArtifacts(input, product, "objc", false)
+ prepare: Gcc.prepareCompiler.apply(Gcc, arguments)
}
Rule {
condition: useObjcxxPrecompiledHeader
inputs: ["objcpp_pch_src"]
auxiliaryInputs: ["hpp"]
- Artifact {
- filePath: product.name + "_objcpp.gch"
- fileTags: ["objcpp_pch"]
- }
- prepare: {
- return Gcc.prepareCompiler.apply(Gcc, arguments);
- }
+ outputFileTags: Cpp.precompiledHeaderOutputTags("objcpp", false)
+ outputArtifacts: Cpp.precompiledHeaderOutputArtifacts(input, product, "objcpp", false)
+ prepare: Gcc.prepareCompiler.apply(Gcc, arguments)
}
FileTagger {
diff --git a/share/qbs/modules/cpp/LinuxGCC.qbs b/share/qbs/modules/cpp/LinuxGCC.qbs
index 14fb0a7e9..4b594a0aa 100644
--- a/share/qbs/modules/cpp/LinuxGCC.qbs
+++ b/share/qbs/modules/cpp/LinuxGCC.qbs
@@ -28,11 +28,12 @@
**
****************************************************************************/
+import qbs.Host
import qbs.Process
UnixGCC {
- condition: qbs.targetOS.contains('linux') &&
- qbs.toolchain && qbs.toolchain.contains('gcc')
+ condition: qbs.targetOS.includes('linux') &&
+ qbs.toolchain && qbs.toolchain.includes('gcc')
priority: 1
targetVendor: "pc"
@@ -41,7 +42,7 @@ UnixGCC {
Probe {
id: runPathsProbe
- condition: !_skipAllChecks && qbs.targetPlatform === qbs.hostPlatform
+ condition: !_skipAllChecks && qbs.targetPlatform === Host.platform()
property stringList systemRunPaths: []
configure: {
var paths = [];
diff --git a/share/qbs/modules/cpp/MingwBaseModule.qbs b/share/qbs/modules/cpp/MingwBaseModule.qbs
index 60ad28b08..c9cfe9bd8 100644
--- a/share/qbs/modules/cpp/MingwBaseModule.qbs
+++ b/share/qbs/modules/cpp/MingwBaseModule.qbs
@@ -37,8 +37,6 @@ import "setuprunenv.js" as SetupRunEnv
GenericGCC {
condition: false
- staticLibraryPrefix: "lib"
- staticLibrarySuffix: ".a"
dynamicLibrarySuffix: ".dll"
executableSuffix: ".exe"
debugInfoSuffix: ".debug"
@@ -46,9 +44,10 @@ GenericGCC {
windowsApiCharacterSet: "unicode"
platformDefines: base.concat(WindowsUtils.characterSetDefines(windowsApiCharacterSet))
.concat("WIN32")
+ runtimeLibrary: "dynamic"
Properties {
- condition: product.multiplexByQbsProperties.contains("buildVariants")
+ condition: product.multiplexByQbsProperties.includes("buildVariants")
&& qbs.buildVariants && qbs.buildVariants.length > 1
&& qbs.buildVariant !== "release"
&& product.type.containsAny(["staticlibrary", "dynamiclibrary"])
@@ -97,9 +96,9 @@ GenericGCC {
var tf;
try {
tf = new TextFile(outputFilePath, TextFile.WriteOnly);
- if (productType.contains("application"))
+ if (productType.includes("application"))
tf.write("1 "); // CREATEPROCESS_MANIFEST_RESOURCE_ID
- else if (productType.contains("dynamiclibrary"))
+ else if (productType.includes("dynamiclibrary"))
tf.write("2 "); // ISOLATIONAWARE_MANIFEST_RESOURCE_ID
tf.write("24 "); // RT_MANIFEST
tf.writeLine(Utilities.cStringQuote(inputFilePath));
diff --git a/share/qbs/modules/cpp/UnixGCC.qbs b/share/qbs/modules/cpp/UnixGCC.qbs
index e5b99cd98..6f377c5c8 100644
--- a/share/qbs/modules/cpp/UnixGCC.qbs
+++ b/share/qbs/modules/cpp/UnixGCC.qbs
@@ -31,14 +31,12 @@
import qbs.File
GenericGCC {
- condition: qbs.toolchain && qbs.toolchain.contains("gcc")
- && qbs.targetOS && qbs.targetOS.contains("unix")
+ condition: qbs.toolchain && qbs.toolchain.includes("gcc")
+ && qbs.targetOS.includes("unix")
priority: -50
- staticLibraryPrefix: "lib"
dynamicLibraryPrefix: "lib"
loadableModulePrefix: "lib"
- staticLibrarySuffix: ".a"
dynamicLibrarySuffix: ".so"
debugInfoSuffix: ".debug"
imageFormat: "elf"
diff --git a/share/qbs/modules/cpp/android-gcc.qbs b/share/qbs/modules/cpp/android-gcc.qbs
index 3e44f4ff3..7c45d3c6b 100644
--- a/share/qbs/modules/cpp/android-gcc.qbs
+++ b/share/qbs/modules/cpp/android-gcc.qbs
@@ -39,25 +39,36 @@ import 'gcc.js' as Gcc
LinuxGCC {
Depends { name: "Android.ndk" }
- condition: qbs.targetOS.contains("android") && qbs.toolchain && qbs.toolchain.contains("llvm")
+ condition: qbs.targetOS.includes("android") && qbs.toolchain && qbs.toolchain.includes("llvm")
priority: 2
- rpaths: [rpathOrigin]
+ rpaths: []
+ // toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android
cxxLanguageVersion: "c++14"
- property string cxxStlBaseDir: FileInfo.joinPaths(Android.ndk.ndkDir, "sources", "cxx-stl")
- property string stlBaseDir: FileInfo.joinPaths(cxxStlBaseDir, "llvm-libc++")
- property string stlLibsDir: {
- if (stlBaseDir)
- return FileInfo.joinPaths(stlBaseDir, "libs", Android.ndk.abi);
- return undefined;
+ property string archLibsDir: {
+ switch (qbs.architecture) {
+ case "arm64":
+ return "aarch64";
+ case "armv7a":
+ return "arm";
+ case "x86_64":
+ return qbs.architecture;
+ case "x86":
+ return "i686";
+ }
}
+ property string targetDir: "android" + (["armeabi", "armeabi-v7a"].includes(Android.ndk.abi) ? "eabi" : "")
+ property string triple: [archLibsDir, targetSystem, targetDir].join("-")
+ property string libsDir: FileInfo.joinPaths(sysroot, "usr", "lib", triple);
- property string sharedStlFilePath: (stlLibsDir && Android.ndk.appStl.endsWith("_shared"))
- ? FileInfo.joinPaths(stlLibsDir, dynamicLibraryPrefix + Android.ndk.appStl + dynamicLibrarySuffix)
+ property string sharedStlFilePath: (libsDir && Android.ndk.appStl.endsWith("_shared"))
+ ? FileInfo.joinPaths(libsDir, dynamicLibraryPrefix + Android.ndk.appStl + dynamicLibrarySuffix)
: undefined
- property string staticStlFilePath: (stlLibsDir && Android.ndk.appStl.endsWith("_static"))
- ? FileInfo.joinPaths(stlLibsDir, NdkUtils.stlFilePath(staticLibraryPrefix, Android.ndk, staticLibrarySuffix))
+ property string staticStlFilePath: (libsDir && Android.ndk.appStl.endsWith("_static"))
+ ? FileInfo.joinPaths(libsDir, Android.ndk.platformVersion,
+ NdkUtils.stlFileName(staticLibraryPrefix, Android.ndk,
+ staticLibrarySuffix))
: undefined
Group {
@@ -67,15 +78,6 @@ LinuxGCC {
fileTags: "android.stl"
}
- Group {
- name: "gdbserver"
- condition: qbs.buildVariant !== "release" && product.cpp.shouldLink
- files: FileInfo.joinPaths(Android.ndk.ndkDir, "prebuilt",
- "android-" + NdkUtils.abiNameToDirName(Android.ndk.abi),
- "gdbserver", "gdbserver")
- fileTags: "android.gdbserver"
- }
-
toolchainInstallPath: FileInfo.joinPaths(Android.ndk.ndkDir, "toolchains",
"llvm", "prebuilt",
Android.ndk.hostArch, "bin")
@@ -83,11 +85,10 @@ LinuxGCC {
property string toolchainTriple: [targetAbi === "androideabi" ? "arm" : targetArch,
targetSystem, targetAbi].join("-")
+ internalVersion: undefined
toolchainPrefix: undefined
machineType: {
- if (Android.ndk.abi === "armeabi")
- return "armv5te";
if (Android.ndk.abi === "armeabi-v7a")
return "armv7-a";
}
@@ -99,59 +100,43 @@ LinuxGCC {
commonCompilerFlags: NdkUtils.commonCompilerFlags(qbs.toolchain, qbs.buildVariant, Android.ndk)
- linkerFlags: NdkUtils.commonLinkerFlags(Android.ndk.abi);
+ linkerFlags: NdkUtils.commonLinkerFlags(Android.ndk);
driverLinkerFlags: {
- var flags = ["-fuse-ld=lld", "-Wl,--exclude-libs,libgcc.a", "-Wl,--exclude-libs,libatomic.a", "-nostdlib++"];
- if (Android.ndk.appStl.startsWith("c++") && Android.ndk.abi === "armeabi-v7a")
- flags = flags.concat(["-Wl,--exclude-libs,libunwind.a"]);
+ var flags = ["-fuse-ld=lld", "-Wl,--exclude-libs,libgcc.a", "-nostdlib++"];
+ // See https://android.googlesource.com/platform/ndk/+/ndk-release-r21/docs/BuildSystemMaintainers.md#Unwinding
+ if (Android.ndk.abi === "armeabi-v7a") {
+ flags = flags.concat(["-Wl,--exclude-libs,libgcc_real.a"]);
+ if (Android.ndk.appStl.startsWith("c++"))
+ flags = flags.concat(["-Wl,--exclude-libs,libunwind.a"]);
+ }
return flags;
}
platformDriverFlags: ["-fdata-sections", "-ffunction-sections", "-funwind-tables",
"-fstack-protector-strong", "-no-canonical-prefixes"]
- libraryPaths: {
- var prefix = FileInfo.joinPaths(sysroot, "usr");
- var paths = [];
- if (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(FileInfo.joinPaths(stlLibsDir, NdkUtils.stlFilePath(dynamicLibraryPrefix, Android.ndk, dynamicLibrarySuffix)));
+ libs.push(FileInfo.joinPaths(libsDir, Android.ndk.platformVersion,
+ NdkUtils.stlFileName(dynamicLibraryPrefix, Android.ndk,
+ dynamicLibrarySuffix)));
return libs;
}
staticLibraries: staticStlFilePath
- systemIncludePaths: {
- 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"];
- // Might be superseded by an -mandroid-version or similar Clang compiler flag in future
- list.push("__ANDROID_API__=" + Android.ndk.platformVersion);
- return list;
- }
+ // When using ndk r19c, llvm doesn't add sysroot/usr/include/c++/v1 to the path
+ // But it works starting with ndk r20b
+ systemIncludePaths: (Utilities.versionCompare(Android.ndk.version, "20") < 0) ?
+ FileInfo.joinPaths(sysroot, "usr", "include", "c++", "v1") : []
+
+ defines: ["ANDROID", "__ANDROID__"]
binutilsPath: FileInfo.joinPaths(Android.ndk.ndkDir, "toolchains", "llvm", "prebuilt",
Android.ndk.hostArch, "bin");
binutilsPathPrefix: FileInfo.joinPaths(binutilsPath, "llvm-")
- syslibroot: FileInfo.joinPaths(Android.ndk.ndkDir, "platforms",
- Android.ndk.platform, "arch-"
- + NdkUtils.abiNameToDirName(Android.ndk.abi))
- sysroot: FileInfo.joinPaths(Android.ndk.ndkDir, "sysroot")
+ sysroot: FileInfo.joinPaths(Android.ndk.ndkDir, "toolchains", "llvm", "prebuilt",
+ Android.ndk.hostArch, "sysroot")
targetArch: {
switch (qbs.architecture) {
@@ -168,9 +153,10 @@ LinuxGCC {
}
}
- targetVendor: "none"
+ target: [targetArch, targetSystem, targetAbi].join("-")
targetSystem: "linux"
- targetAbi: "android" + (["armeabi", "armeabi-v7a"].contains(Android.ndk.abi) ? "eabi" : "")
+ targetAbi: "android" + (["armeabi", "armeabi-v7a"].includes(Android.ndk.abi) ? "eabi" : "") +
+ Android.ndk.platformVersion
endianness: "little"
@@ -182,9 +168,9 @@ LinuxGCC {
fileTags: "android.nativelibrary"
}
prepare: {
- var stripArgs = ["--strip-unneeded", "-o", output.filePath, input.filePath];
+ var stripArgs = ["--strip-all", "-o", output.filePath, input.filePath];
var stripCmd = new Command(product.cpp.stripPath, stripArgs);
- stripCmd.description = "Stripping unneeded symbols from " + input.fileName;
+ stripCmd.description = "stripping unneeded symbols from " + input.fileName;
return stripCmd;
}
}
diff --git a/share/qbs/modules/cpp/cosmic.js b/share/qbs/modules/cpp/cosmic.js
new file mode 100644
index 000000000..4979f33f7
--- /dev/null
+++ b/share/qbs/modules/cpp/cosmic.js
@@ -0,0 +1,443 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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.
+**
+****************************************************************************/
+
+var Cpp = require("cpp.js");
+var Environment = require("qbs.Environment");
+var File = require("qbs.File");
+var FileInfo = require("qbs.FileInfo");
+var ModUtils = require("qbs.ModUtils");
+var Process = require("qbs.Process");
+var TemporaryDir = require("qbs.TemporaryDir");
+var TextFile = require("qbs.TextFile");
+
+function toolchainDetails(qbs) {
+ var architecture = qbs.architecture;
+ if (architecture.startsWith("arm")) {
+ return {
+ "executableSuffix": ".cxm",
+ "staticLibrarySuffix": ".cxm",
+ "assemblerName": "cacorm",
+ "compilerName": "cxcorm"
+ };
+ } else if (architecture === "stm8") {
+ return {
+ "executableSuffix": ".sm8",
+ "staticLibrarySuffix": ".sm8",
+ "assemblerName": "castm8",
+ "compilerName": "cxstm8"
+ };
+ } else if (architecture === "hcs8") {
+ return {
+ "executableSuffix": ".h08",
+ "staticLibrarySuffix": ".h08",
+ "assemblerName": "ca6808",
+ "compilerName": "cx6808"
+ };
+ } else if (architecture === "hcs12") {
+ return {
+ "executableSuffix": ".h12",
+ "staticLibrarySuffix": ".h12",
+ "assemblerName": "ca6812",
+ "compilerName": "cx6812"
+ };
+ } else if (architecture === "m68k") {
+ return {
+ "executableSuffix": ".332",
+ "staticLibrarySuffix": ".332",
+ "assemblerName": "ca332",
+ "compilerName": "cx332"
+ };
+ }
+}
+
+function guessArchitecture(compilerFilePath) {
+ var baseName = FileInfo.baseName(compilerFilePath);
+ if (baseName === "cxcorm")
+ return "arm";
+ else if (baseName === "cxstm8")
+ return "stm8";
+ else if (baseName === "cx6808")
+ return "hcs8";
+ else if (baseName === "cx6812")
+ return "hcs12";
+ else if (baseName === "cx332")
+ return "m68k";
+}
+
+function dumpMacros(compilerFilePath) {
+ // Note: The COSMIC compiler does not support the predefined
+ // macros dumping. So, we do it with the following trick, where we try
+ // to create and compile a special temporary file and to parse the console
+ // output with the own magic pattern: (""|"key"|"value"|"").
+
+ var outputDirectory = new TemporaryDir();
+ var outputFilePath = FileInfo.fromNativeSeparators(FileInfo.joinPaths(outputDirectory.path(),
+ "dump-macros.c"));
+ var outputFile = new TextFile(outputFilePath, TextFile.WriteOnly);
+ outputFile.writeLine("#define VALUE_TO_STRING(x) #x");
+ outputFile.writeLine("#define VALUE(x) VALUE_TO_STRING(x)");
+ outputFile.writeLine("#define VAR_NAME_VALUE(var) #var VALUE(var)");
+ // The COSMIC compiler defines only one pre-defined macro
+ // (at least nothing is said about other macros in the documentation).
+ var keys = ["__CSMC__"];
+ for (var i in keys) {
+ var key = keys[i];
+ outputFile.writeLine("#if defined (" + key + ")");
+ outputFile.writeLine("#pragma message (VAR_NAME_VALUE(" + key + "))");
+ outputFile.writeLine("#endif");
+ }
+ outputFile.close();
+
+ var process = new Process();
+ process.exec(compilerFilePath, [outputFilePath], false);
+ File.remove(outputFilePath);
+
+ var map = {};
+ // COSMIC compiler use the errors output!
+ process.readStdErr().trim().split(/\r?\n/g).map(function(line) {
+ var match = line.match(/^#message \("(.+)" "(.+)"\)$/);
+ if (match)
+ map[match[1]] = match[2];
+ });
+ return map;
+}
+
+function dumpVersion(compilerFilePath) {
+ var p = new Process();
+ p.exec(compilerFilePath, ["-vers"]);
+ // COSMIC compiler use the errors output!
+ var output = p.readStdErr();
+ var match = output.match(/^COSMIC.+V(\d+)\.?(\d+)\.?(\*|\d+)?/);
+ if (match) {
+ var major = match[1] ? parseInt(match[1], 10) : 0;
+ var minor = match[2] ? parseInt(match[2], 10) : 0;
+ var patch = match[3] ? parseInt(match[3], 10) : 0;
+ return { major: major, minor: minor, patch: patch };
+ }
+}
+
+function guessEndianness(architecture) {
+ // There is no mention of supported endianness in the cosmic compiler.
+ return "big";
+}
+
+function dumpDefaultPaths(compilerFilePath, architecture) {
+ var rootPath = FileInfo.path(compilerFilePath);
+ var includePath;
+ var includePaths = [];
+ if (architecture.startsWith("arm")) {
+ includePath = FileInfo.joinPaths(rootPath, "hcorm");
+ if (File.exists(includePath))
+ includePaths.push(includePath);
+ } else if (architecture === "stm8") {
+ includePath = FileInfo.joinPaths(rootPath, "hstm8");
+ if (File.exists(includePath))
+ includePaths.push(includePath);
+ } else if (architecture === "hcs8") {
+ includePath = FileInfo.joinPaths(rootPath, "h6808");
+ if (File.exists(includePath))
+ includePaths.push(includePath);
+ } else if (architecture === "hcs12") {
+ includePath = FileInfo.joinPaths(rootPath, "h6812");
+ if (File.exists(includePath))
+ includePaths.push(includePath);
+ } else if (architecture === "m68k") {
+ includePath = FileInfo.joinPaths(rootPath, "h332");
+ if (File.exists(includePath))
+ includePaths.push(includePath);
+ }
+
+ var libraryPaths = [];
+ var libraryPath = FileInfo.joinPaths(rootPath, "lib");
+ if (File.exists(libraryPath))
+ libraryPaths.push(libraryPath);
+
+ return {
+ "includePaths": includePaths,
+ "libraryPaths": libraryPaths,
+ }
+}
+
+function compilerFlags(project, product, input, outputs, explicitlyDependsOn) {
+ var args = [];
+
+ // Up to 128 include files.
+ args = args.concat(Cpp.collectPreincludePathsArguments(input));
+
+ // Defines.
+ args = args.concat(Cpp.collectDefinesArguments(input));
+
+ // Up to 128 include paths.
+ args = args.concat(Cpp.collectIncludePathsArguments(input));
+ args = args.concat(Cpp.collectSystemIncludePathsArguments(input));
+
+ // Debug information flags.
+ if (input.cpp.debugInformation)
+ args.push("+debug");
+
+ var architecture = input.qbs.architecture;
+ var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(outputs.obj[0].fileTags));
+
+ // Warning level flags.
+ switch (input.cpp.warningLevel) {
+ case "none":
+ // Disabled by default.
+ break;
+ case "all":
+ // Highest warning level.
+ args.push("-pw7");
+ break;
+ }
+
+ // C language version flags.
+ if (tag === "c") {
+ var knownValues = ["c99"];
+ var cLanguageVersion = Cpp.languageVersion(
+ input.cpp.cLanguageVersion, knownValues, "C");
+ switch (cLanguageVersion) {
+ case "c99":
+ args.push("-p", "c99");
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Objects output directory.
+ args.push("-co", FileInfo.path(outputs.obj[0].filePath));
+
+ // Listing files generation flag.
+ if (input.cpp.generateCompilerListingFiles) {
+ // Enable listings.
+ args.push("-l");
+ // Listings output directory.
+ args.push("-cl", FileInfo.path(outputs.lst[0].filePath));
+ }
+
+ // Misc flags.
+ args = args.concat(Cpp.collectMiscCompilerArguments(input, tag),
+ Cpp.collectMiscDriverArguments(product));
+
+ // Input.
+ args.push(input.filePath);
+ return args;
+}
+
+function assemblerFlags(project, product, input, outputs, explicitlyDependsOn) {
+ var args = [];
+
+ // Up to 128 include paths.
+ args = args.concat(Cpp.collectIncludePathsArguments(input));
+ args = args.concat(Cpp.collectSystemIncludePathsArguments(input));
+
+ // Debug information flags.
+ if (input.cpp.debugInformation)
+ args.push("-xx");
+
+ // Misc flags.
+ args = args.concat(Cpp.collectMiscAssemblerArguments(input, "asm"));
+
+ // Listing files generation flag.
+ if (input.cpp.generateAssemblerListingFiles) {
+ args.push("-l");
+ args.push("+l", outputs.lst[0].filePath);
+ }
+
+ // Objects output file path.
+ args.push("-o", outputs.obj[0].filePath);
+
+ // Input.
+ args.push(input.filePath);
+ return args;
+}
+
+function linkerFlags(project, product, inputs, outputs) {
+ var args = [];
+
+ // Library paths.
+ args = args.concat(Cpp.collectLibraryPaths(product).map(function(path) {
+ // It is workaround to use the relative paths avoids a strange linking
+ // errors. Maybe it is related to the limitations on the length of the
+ // command arguments, or on the length of the paths.
+ return product.cpp.libraryPathFlag + Cpp.relativePath(product.buildDirectory, path);
+ }));
+
+ // Output.
+ args.push("-o", outputs.application[0].filePath);
+
+ // Map file generation flag.
+ if (product.cpp.generateLinkerMapFile)
+ args.push("-m", outputs.mem_map[0].filePath);
+
+ // Misc flags.
+ args = args.concat(Cpp.collectMiscEscapableLinkerArguments(product),
+ Cpp.collectMiscLinkerArguments(product),
+ Cpp.collectMiscDriverArguments(product));
+
+ // Linker scripts.
+ args = args.concat(Cpp.collectLinkerScriptPathsArguments(product, inputs));
+
+ // Input objects.
+ args = args.concat(Cpp.collectLinkerObjectPaths(inputs));
+
+ // Library dependencies (order has matters).
+ args = args.concat(Cpp.collectLibraryDependencies(product).map(function(dep) {
+ // It is workaround to use the relative paths avoids a strange linking
+ // errors. Maybe it is related to the limitations on the length of the
+ // command arguments, or on the length of the paths.
+ return Cpp.relativePath(product.buildDirectory, dep.filePath);
+ }));
+
+ return args;
+}
+
+function archiverFlags(project, product, inputs, outputs) {
+ var args = ["-cl"];
+
+ // Output.
+ args.push(outputs.staticlibrary[0].filePath);
+
+ // Input objects.
+ args = args.concat(Cpp.collectLinkerObjectPaths(inputs));
+ return args;
+}
+
+function createPath(fullPath) {
+ var cmd = new JavaScriptCommand();
+ cmd.fullPath = fullPath;
+ cmd.silent = true;
+ cmd.sourceCode = function() {
+ File.makePath(fullPath);
+ };
+ return cmd;
+}
+
+// It is a workaround to rename the generated object file to the desired name.
+// Reason is that the Cosmic compiler always generates the object files in the
+// format of 'module.o', but we expect it in flexible format, e.g. 'module.c.obj'
+// or 'module.c.o' depending on the cpp.objectSuffix property.
+function renameObjectFile(project, product, inputs, outputs, input, output) {
+ var object = outputs.obj[0];
+ var cmd = new JavaScriptCommand();
+ cmd.newObject = object.filePath;
+ cmd.oldObject = FileInfo.joinPaths(FileInfo.path(object.filePath),
+ object.baseName + ".o");
+ cmd.silent = true;
+ cmd.sourceCode = function() { File.move(oldObject, newObject); };
+ return cmd;
+}
+
+// It is a workaround to rename the generated listing file to the desired name.
+// Reason is that the Cosmic compiler always generates the listing files in the
+// format of 'module.ls', but we expect it in flexible format, e.g. 'module.c.lst'
+// or 'module.c.ls' depending on the cpp.compilerListingSuffix property.
+function renameListingFile(project, product, inputs, outputs, input, output) {
+ var listing = outputs.lst[0];
+ var cmd = new JavaScriptCommand();
+ cmd.newListing = listing.filePath;
+ cmd.oldListing = FileInfo.joinPaths(FileInfo.path(listing.filePath),
+ listing.baseName + ".ls");
+ cmd.silent = true;
+ cmd.sourceCode = function() { File.move(oldListing, newListing); };
+ return cmd;
+}
+
+function prepareCompiler(project, product, inputs, outputs, input, output, explicitlyDependsOn) {
+ var cmds = [];
+
+ // Create output objects path, because the Cosmic doesn't do it.
+ var cmd = createPath(FileInfo.path(outputs.obj[0].filePath));
+ cmds.push(cmd);
+
+ // Create output listing path, because the Cosmic doesn't do it.
+ if (input.cpp.generateCompilerListingFiles) {
+ cmd = createPath(FileInfo.path(outputs.lst[0].filePath));
+ cmds.push(cmd);
+ }
+
+ var args = compilerFlags(project, product, input, outputs, explicitlyDependsOn);
+ cmd = new Command(input.cpp.compilerPath, args);
+ cmd.workingDirectory = product.buildDirectory;
+ cmd.description = "compiling " + input.fileName;
+ cmd.highlight = "compiler";
+ cmd.jobPool = "compiler";
+ cmds.push(cmd);
+
+ cmds.push(renameObjectFile(project, product, inputs, outputs, input, output));
+
+ if (input.cpp.generateCompilerListingFiles)
+ cmds.push(renameListingFile(project, product, inputs, outputs, input, output));
+
+ return cmds;
+}
+
+function prepareAssembler(project, product, inputs, outputs, input, output, explicitlyDependsOn) {
+ var cmds = [];
+
+ // Create output objects path, because the Cosmic doesn't do it.
+ var cmd = createPath(FileInfo.path(outputs.obj[0].filePath));
+ cmds.push(cmd);
+
+ // Create output listing path, because the Cosmic doesn't do it.
+ if (input.cpp.generateCompilerListingFiles) {
+ cmd = createPath(FileInfo.path(outputs.lst[0].filePath));
+ cmds.push(cmd);
+ }
+
+ var args = assemblerFlags(project, product, input, outputs, explicitlyDependsOn);
+ cmd = new Command(input.cpp.assemblerPath, args);
+ cmd.workingDirectory = product.buildDirectory;
+ cmd.description = "assembling " + input.fileName;
+ cmd.highlight = "compiler";
+ cmd.jobPool = "assembler";
+ cmds.push(cmd);
+ return cmds;
+}
+
+function prepareLinker(project, product, inputs, outputs, input, output) {
+ var primaryOutput = outputs.application[0];
+ var args = linkerFlags(project, product, inputs, outputs);
+ var cmd = new Command(product.cpp.linkerPath, args);
+ cmd.workingDirectory = product.buildDirectory;
+ cmd.description = "linking " + primaryOutput.fileName;
+ cmd.highlight = "linker";
+ cmd.jobPool = "linker";
+ return [cmd];
+}
+
+function prepareArchiver(project, product, inputs, outputs, input, output) {
+ var args = archiverFlags(project, product, inputs, outputs);
+ var cmd = new Command(product.cpp.archiverPath, args);
+ cmd.workingDirectory = product.buildDirectory;
+ cmd.description = "creating " + output.fileName;
+ cmd.highlight = "linker";
+ cmd.jobPool = "linker";
+ return [cmd];
+}
diff --git a/share/qbs/modules/cpp/cosmic.qbs b/share/qbs/modules/cpp/cosmic.qbs
new file mode 100644
index 000000000..8bf0f22a3
--- /dev/null
+++ b/share/qbs/modules/cpp/cosmic.qbs
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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.File
+import qbs.FileInfo
+import qbs.PathTools
+import qbs.Probes
+import qbs.Utilities
+import "cosmic.js" as COSMIC
+import "cpp.js" as Cpp
+
+CppModule {
+ condition: qbs.toolchain && qbs.toolchain.includes("cosmic")
+
+ Probes.BinaryProbe {
+ id: compilerPathProbe
+ condition: !toolchainInstallPath && !_skipAllChecks
+ names: ["cxcorm"]
+ }
+
+ Probes.CosmicProbe {
+ id: cosmicProbe
+ condition: !_skipAllChecks
+ compilerFilePath: compilerPath
+ enableDefinesByLanguage: enableCompilerDefinesByLanguage
+ }
+
+ qbs.architecture: cosmicProbe.found ? cosmicProbe.architecture : original
+ qbs.targetPlatform: "none"
+
+ compilerVersionMajor: cosmicProbe.versionMajor
+ compilerVersionMinor: cosmicProbe.versionMinor
+ compilerVersionPatch: cosmicProbe.versionPatch
+ endianness: cosmicProbe.endianness
+
+ compilerDefinesByLanguage: cosmicProbe.compilerDefinesByLanguage
+ compilerIncludePaths: cosmicProbe.includePaths
+
+ toolchainInstallPath: compilerPathProbe.found ? compilerPathProbe.path : undefined
+
+ /* Work-around for QtCreator which expects these properties to exist. */
+ property string cCompilerName: compilerName
+ property string cxxCompilerName: compilerName
+
+ compilerName: toolchainDetails.compilerName + compilerExtension
+ compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName)
+
+ assemblerName: toolchainDetails.assemblerName + compilerExtension
+ assemblerPath: FileInfo.joinPaths(toolchainInstallPath, assemblerName)
+
+ linkerName: "clnk" + compilerExtension
+ linkerPath: FileInfo.joinPaths(toolchainInstallPath, linkerName)
+
+ property string archiverName: "clib" + compilerExtension
+ property string archiverPath: FileInfo.joinPaths(toolchainInstallPath, archiverName)
+
+ runtimeLibrary: "static"
+
+ staticLibrarySuffix: toolchainDetails.staticLibrarySuffix
+ executableSuffix: toolchainDetails.executableSuffix
+
+ imageFormat: "cosmic"
+
+ enableExceptions: false
+ enableRtti: false
+
+ defineFlag: "-d"
+ includeFlag: "-i"
+ systemIncludeFlag: "-i"
+ preincludeFlag: "-ph"
+ libraryDependencyFlag: ""
+ libraryPathFlag: "-l"
+ linkerScriptFlag: ""
+
+ toolchainDetails: COSMIC.toolchainDetails(qbs)
+
+ knownArchitectures: ["arm", "hcs12", "hcs8", "m68k", "stm8"]
+
+ Rule {
+ id: assembler
+ inputs: ["asm"]
+ outputFileTags: Cpp.assemblerOutputTags(generateAssemblerListingFiles)
+ outputArtifacts: Cpp.assemblerOutputArtifacts(input)
+ prepare: COSMIC.prepareAssembler.apply(COSMIC, arguments)
+ }
+
+ FileTagger {
+ patterns: ["*.s"]
+ fileTags: ["asm"]
+ }
+
+ Rule {
+ id: compiler
+ inputs: ["cpp", "c"]
+ auxiliaryInputs: ["hpp"]
+ outputFileTags: Cpp.compilerOutputTags(generateCompilerListingFiles)
+ outputArtifacts: Cpp.compilerOutputArtifacts(input)
+ prepare: COSMIC.prepareCompiler.apply(COSMIC, arguments)
+ }
+
+ Rule {
+ id: applicationLinker
+ multiplex: true
+ inputs: ["obj", "linkerscript"]
+ inputsFromDependencies: ["staticlibrary"]
+ outputFileTags: Cpp.applicationLinkerOutputTags(generateLinkerMapFile)
+ outputArtifacts: Cpp.applicationLinkerOutputArtifacts(product)
+ prepare: COSMIC.prepareLinker.apply(COSMIC, arguments)
+ }
+
+ Rule {
+ id: staticLibraryLinker
+ multiplex: true
+ inputs: ["obj"]
+ inputsFromDependencies: ["staticlibrary"]
+ outputFileTags: Cpp.staticLibraryLinkerOutputTags()
+ outputArtifacts: Cpp.staticLibraryLinkerOutputArtifacts(product)
+ prepare: COSMIC.prepareArchiver.apply(COSMIC, arguments)
+ }
+}
diff --git a/share/qbs/modules/cpp/cpp.js b/share/qbs/modules/cpp/cpp.js
index 0e440bdb0..9f907580a 100644
--- a/share/qbs/modules/cpp/cpp.js
+++ b/share/qbs/modules/cpp/cpp.js
@@ -28,6 +28,12 @@
**
****************************************************************************/
+var File = require("qbs.File");
+var FileInfo = require("qbs.FileInfo");
+var ModUtils = require("qbs.ModUtils");
+var PathTools = require("qbs.PathTools");
+var Utilities = require("qbs.Utilities");
+
function languageVersion(versionArray, knownValues, lang) {
if (!versionArray)
return undefined;
@@ -36,7 +42,7 @@ function languageVersion(versionArray, knownValues, lang) {
return versions[0];
for (var i = 0; i < knownValues.length; ++i) {
var candidate = knownValues[i];
- if (versions.contains(candidate))
+ if (versions.includes(candidate))
return candidate;
}
var version = versions[0];
@@ -44,3 +50,426 @@ function languageVersion(versionArray, knownValues, lang) {
+ "' from list of unknown " + lang + " version strings (" + versions + ")");
return version;
}
+
+function extractMacros(output, regexp) {
+ var m = {};
+ output.trim().split(/\r?\n/g).map(function(line) {
+ if (regexp) {
+ var match = regexp.exec(line);
+ if (!match)
+ return;
+ line = match[1];
+ }
+ var prefix = "#define ";
+ if (!line.startsWith(prefix))
+ return;
+ var index = line.indexOf(" ", prefix.length);
+ if (index !== -1)
+ m[line.substr(prefix.length, index - prefix.length)] = line.substr(index + 1);
+ });
+ return m;
+}
+
+function relativePath(baseDirectory, filePath) {
+ if (FileInfo.isAbsolutePath(filePath))
+ return FileInfo.relativePath(baseDirectory, filePath);
+ return filePath;
+}
+
+function assemblerOutputTags(needsListingFiles) {
+ var tags = ["obj"];
+ if (needsListingFiles)
+ tags.push("lst");
+ return tags;
+}
+
+function compilerOutputTags(needsListingFiles) {
+ var tags = ["obj", "intermediate_obj"];
+ if (needsListingFiles)
+ tags.push("lst");
+ return tags;
+}
+
+function applicationLinkerOutputTags(needsLinkerMapFile) {
+ var tags = ["application"];
+ if (needsLinkerMapFile)
+ tags.push("mem_map");
+ return tags;
+}
+
+function dynamicLibraryLinkerOutputTags() {
+ return ["dynamiclibrary", "dynamiclibrary_import"];
+}
+
+function staticLibraryLinkerOutputTags() {
+ return ["staticlibrary"];
+}
+
+function resourceCompilerOutputTags() {
+ return ["res"];
+}
+
+function precompiledHeaderOutputTags(lang, generateObjects) {
+ var tags = [lang + "_pch"];
+ if (generateObjects)
+ tags.push("obj");
+ return tags;
+};
+
+function assemblerOutputArtifacts(input) {
+ var artifacts = [];
+ artifacts.push({
+ fileTags: ["obj"],
+ filePath: FileInfo.joinPaths(Utilities.getHash(input.baseDir),
+ input.fileName + input.cpp.objectSuffix)
+ });
+ if (input.cpp.generateAssemblerListingFiles) {
+ artifacts.push({
+ fileTags: ["lst"],
+ filePath: FileInfo.joinPaths(Utilities.getHash(input.baseDir),
+ input.fileName + input.cpp.assemblerListingSuffix)
+ });
+ }
+ return artifacts;
+}
+
+function compilerOutputArtifacts(input, inputs) {
+ var objTags = input.fileTags.includes("cpp_intermediate_object")
+ ? ["intermediate_obj"]
+ : ["obj"];
+ if (inputs) {
+ if (inputs.c || inputs.objc)
+ objTags.push("c_obj");
+ if (inputs.cpp || inputs.objcpp)
+ objTags.push("cpp_obj");
+ }
+ var artifacts = [{
+ fileTags: objTags,
+ filePath: FileInfo.joinPaths(Utilities.getHash(input.baseDir),
+ input.fileName + input.cpp.objectSuffix)
+ }];
+ if (input.cpp.generateCompilerListingFiles) {
+ artifacts.push({
+ fileTags: ["lst"],
+ filePath: FileInfo.joinPaths(Utilities.getHash(input.baseDir),
+ input.fileName + input.cpp.compilerListingSuffix)
+ });
+ }
+ return artifacts;
+}
+
+function applicationLinkerOutputArtifacts(product) {
+ var artifacts = [{
+ fileTags: ["application"],
+ filePath: FileInfo.joinPaths(product.destinationDirectory,
+ PathTools.applicationFilePath(product))
+ }];
+ if (product.cpp.generateLinkerMapFile) {
+ artifacts.push({
+ fileTags: ["mem_map"],
+ filePath: FileInfo.joinPaths(product.destinationDirectory,
+ product.targetName + product.cpp.linkerMapSuffix)
+ });
+ }
+ return artifacts;
+}
+
+function dynamicLibraryLinkerOutputArtifacts(product) {
+ return [{
+ fileTags: ["dynamiclibrary"],
+ filePath: FileInfo.joinPaths(product.destinationDirectory,
+ PathTools.dynamicLibraryFilePath(product))
+ }, {
+ fileTags: ["dynamiclibrary_import"],
+ filePath: FileInfo.joinPaths(product.destinationDirectory,
+ PathTools.importLibraryFilePath(product)),
+ alwaysUpdated: false
+ }];
+}
+
+function staticLibraryLinkerOutputArtifacts(product) {
+ return [{
+ fileTags: ["staticlibrary"],
+ filePath: FileInfo.joinPaths(product.destinationDirectory,
+ PathTools.staticLibraryFilePath(product))
+ }];
+}
+
+function resourceCompilerOutputArtifacts(input) {
+ return [{
+ fileTags: ["res"],
+ filePath: FileInfo.joinPaths(Utilities.getHash(input.baseDir),
+ input.completeBaseName + input.cpp.resourceSuffix)
+ }];
+}
+
+function precompiledHeaderOutputArtifacts(input, product, lang, generateObjects) {
+ var artifacts = [{
+ fileTags: [lang + "_pch"],
+ filePath: product.name + "_" + lang + product.cpp.precompiledHeaderSuffix
+ }];
+ if (generateObjects) {
+ artifacts.push({
+ fileTags: ["obj"],
+ filePath: Utilities.getHash(input.completeBaseName)
+ + "_" + lang + input.cpp.objectSuffix
+ });
+ }
+ return artifacts;
+}
+
+function collectLibraryDependencies(product) {
+ var seen = {};
+ var seenObjectFiles = [];
+ var result = [];
+
+ function addFilePath(filePath, wholeArchive, productName) {
+ result.push({ filePath: filePath, wholeArchive: wholeArchive, productName: productName });
+ }
+
+ function addArtifactFilePaths(dep, artifacts) {
+ if (!artifacts)
+ return;
+ var artifactFilePaths = artifacts.map(function(a) { return a.filePath; });
+ var wholeArchive = dep.parameters.cpp && dep.parameters.cpp.linkWholeArchive;
+ var artifactsAreImportLibs = artifacts.length > 0
+ && artifacts[0].fileTags.includes("dynamiclibrary_import");
+ for (var i = 0; i < artifactFilePaths.length; ++i) {
+ addFilePath(artifactFilePaths[i], wholeArchive,
+ artifactsAreImportLibs ? dep.name : undefined);
+ }
+ }
+
+ function addExternalLibs(obj) {
+ if (!obj.cpp)
+ return;
+ function ensureArray(a) {
+ return (a instanceof Array) ? a : [];
+ }
+ function sanitizedModuleListProperty(obj, moduleName, propertyName) {
+ return ensureArray(ModUtils.sanitizedModuleProperty(obj, moduleName, propertyName));
+ }
+ function handleExternalLibraries(tag, libSuffix, objSuffix) {
+ var externalLibs = sanitizedModuleListProperty(obj, "cpp", tag) || [];
+ externalLibs.forEach(function(libName) {
+ var isObjectFile = objSuffix && libName.endsWith(objSuffix);
+ if (isObjectFile) {
+ if (seenObjectFiles.includes(libName))
+ return;
+ seenObjectFiles.push(libName);
+ }
+ if (!libName.endsWith(libSuffix) && !isObjectFile && !libName.startsWith('@'))
+ libName += libSuffix;
+ addFilePath(libName, false);
+ });
+ }
+ handleExternalLibraries("staticLibraries",
+ obj.moduleProperty("cpp", "staticLibrarySuffix"),
+ obj.moduleProperty("cpp", "objectSuffix"));
+ handleExternalLibraries("dynamicLibraries",
+ obj.moduleProperty("cpp", "dynamicLibraryImportSuffix"));
+ }
+
+ function traverse(dep) {
+ if (seen.hasOwnProperty(dep.name))
+ return;
+ if (dep.parameters.cpp && dep.parameters.cpp.link === false)
+ return;
+
+ var staticLibraryArtifacts = dep.artifacts["staticlibrary"];
+ var dynamicLibraryArtifacts = staticLibraryArtifacts
+ ? null : dep.artifacts["dynamiclibrary_import"];
+ if (staticLibraryArtifacts) {
+ seen[dep.name] = true;
+ dep.dependencies.forEach(traverse);
+ addArtifactFilePaths(dep, staticLibraryArtifacts);
+ addExternalLibs(dep);
+ } else if (dynamicLibraryArtifacts) {
+ seen[dep.name] = true;
+ addArtifactFilePaths(dep, dynamicLibraryArtifacts);
+ }
+ }
+
+ product.dependencies.forEach(traverse);
+ addExternalLibs(product);
+ return result;
+}
+
+function collectAbsoluteLibraryDependencyPaths(product) {
+ var paths = collectLibraryPaths(product);
+ var deps = collectLibraryDependencies(product);
+ return deps.map(function(dep) {
+ var filePath = dep.filePath;
+ if (FileInfo.isAbsolutePath(filePath))
+ return filePath;
+ for (var i = 0; i < paths.length; ++i) {
+ var fullPath = FileInfo.joinPaths(paths[i], filePath);
+ if (File.exists(fullPath))
+ return fullPath;
+ }
+ return filePath;
+ });
+}
+
+function collectDefines(input) {
+ var allDefines = [];
+ var platformDefines = input.cpp.platformDefines;
+ if (platformDefines)
+ allDefines = allDefines.uniqueConcat(platformDefines);
+ var defines = input.cpp.defines;
+ if (defines)
+ allDefines = allDefines.uniqueConcat(defines);
+ return allDefines;
+}
+
+function collectIncludePaths(input) {
+ var allIncludePaths = [];
+ var includePaths = input.cpp.includePaths;
+ if (includePaths)
+ allIncludePaths = allIncludePaths.uniqueConcat(includePaths);
+ var builtIns = input.cpp.compilerIncludePaths;
+ return allIncludePaths.filter(function(p) {
+ return !builtIns.includes(p);
+ });
+}
+
+function collectSystemIncludePaths(input) {
+ var allIncludePaths = [];
+ var systemIncludePaths = input.cpp.systemIncludePaths;
+ if (systemIncludePaths)
+ allIncludePaths = allIncludePaths.uniqueConcat(systemIncludePaths);
+ var distributionIncludePaths = input.cpp.distributionIncludePaths;
+ if (distributionIncludePaths)
+ allIncludePaths = allIncludePaths.uniqueConcat(distributionIncludePaths);
+ var builtIns = input.cpp.compilerIncludePaths;
+ return allIncludePaths.filter(function(p) {
+ return !builtIns.includes(p);
+ });
+}
+
+function collectPreincludePaths(input) {
+ return input.cpp.prefixHeaders;
+}
+
+function collectLibraryPaths(product) {
+ var allLibraryPaths = [];
+ var libraryPaths = product.cpp.libraryPaths;
+ if (libraryPaths)
+ allLibraryPaths = allLibraryPaths.uniqueConcat(libraryPaths);
+ var distributionLibraryPaths = product.cpp.distributionLibraryPaths;
+ if (distributionLibraryPaths)
+ allLibraryPaths = allLibraryPaths.uniqueConcat(distributionLibraryPaths);
+ return allLibraryPaths;
+}
+
+function collectLinkerScriptPaths(inputs) {
+ return inputs.linkerscript
+ ? inputs.linkerscript.map(function(script) { return script.filePath; })
+ : [];
+}
+
+function collectLinkerObjectPaths(inputs) {
+ return inputs.obj ? inputs.obj.map(function(obj) { return obj.filePath; }) : [];
+}
+
+function collectResourceObjectPaths(inputs) {
+ return inputs.res ? inputs.res.map(function(res) { return res.filePath; }) : [];
+}
+
+function collectLibraryDependenciesArguments(product) {
+ var deps = collectLibraryDependencies(product);
+ return deps.map(function(dep) { return product.cpp.libraryDependencyFlag + dep.filePath })
+}
+
+function collectDefinesArguments(input) {
+ var defines = collectDefines(input);
+ return defines.map(function(define) { return input.cpp.defineFlag + define });
+}
+
+function collectIncludePathsArguments(input) {
+ var paths = collectIncludePaths(input);
+ return paths.map(function(path) { return input.cpp.includeFlag + path });
+}
+
+function collectSystemIncludePathsArguments(input, flag) {
+ flag = (flag === undefined) ? input.cpp.systemIncludeFlag : flag;
+ var paths = collectSystemIncludePaths(input);
+ return paths.map(function(path) { return flag + path });
+}
+
+function collectPreincludePathsArguments(input, split) {
+ var paths = collectPreincludePaths(input);
+ if (split) {
+ var args = [];
+ for (var i = 0; i < paths.length; ++i)
+ args.push(input.cpp.preincludeFlag, paths[i]);
+ return args;
+ } else {
+ return paths.map(function(path) { return input.cpp.preincludeFlag + path });
+ }
+}
+
+function collectLibraryPathsArguments(product, flag) {
+ flag = (flag === undefined) ? product.cpp.libraryPathFlag : flag;
+ var paths = collectLibraryPaths(product);
+ return paths.map(function(path) { return flag + path });
+}
+
+function collectLinkerScriptPathsArguments(product, inputs, split, flag) {
+ flag = (flag === undefined) ? product.cpp.linkerScriptFlag : flag;
+ var paths = collectLinkerScriptPaths(inputs);
+ if (split) {
+ var args = [];
+ for (var i = 0; i < paths.length; ++i)
+ args.push(flag, paths[i]);
+ return args;
+ } else {
+ return paths.map(function(path) { return flag + path });
+ }
+}
+
+function collectLinkerObjectPathsArguments(product, inputs, flag) {
+ flag = (flag === undefined) ? "" : flag;
+ var paths = collectLinkerObjectPaths(product);
+ return paths.map(function(path) { return flag + path });
+}
+
+function collectMiscCompilerArguments(input, tag) {
+ return [].concat(ModUtils.moduleProperty(input, "platformFlags"),
+ ModUtils.moduleProperty(input, "flags"),
+ ModUtils.moduleProperty(input, "platformFlags", tag),
+ ModUtils.moduleProperty(input, "flags", tag));
+}
+
+function collectMiscAssemblerArguments(input, tag) {
+ return [].concat(ModUtils.moduleProperty(input, "platformFlags", tag),
+ ModUtils.moduleProperty(input, "flags", tag));
+}
+
+function collectMiscDriverArguments(config) {
+ return [].concat(ModUtils.moduleProperty(config, "platformDriverFlags"),
+ ModUtils.moduleProperty(config, "driverFlags"),
+ ModUtils.moduleProperty(config, "targetDriverFlags"));
+}
+
+function collectMiscLinkerArguments(product) {
+ return [].concat(ModUtils.moduleProperty(product, "driverLinkerFlags"));
+}
+
+function collectMiscEscapableLinkerArguments(product) {
+ return [].concat(ModUtils.moduleProperty(product, "platformLinkerFlags"),
+ ModUtils.moduleProperty(product, "linkerFlags"));
+}
+
+function supportsArchitecture(architecture, knownArchitectures) {
+ for (var i = 0; i < knownArchitectures.length; ++i) {
+ if (architecture.startsWith("arm")) {
+ if (architecture.startsWith(knownArchitectures[i]))
+ return true;
+ } else {
+ if (architecture === knownArchitectures[i])
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/share/qbs/modules/cpp/darwin.js b/share/qbs/modules/cpp/darwin.js
index 6373b57c4..0223c5ed3 100644
--- a/share/qbs/modules/cpp/darwin.js
+++ b/share/qbs/modules/cpp/darwin.js
@@ -28,6 +28,7 @@
**
****************************************************************************/
+var Codesign = require("../codesign/codesign.js");
var File = require("qbs.File");
var FileInfo = require("qbs.FileInfo");
var Gcc = require("./gcc.js");
@@ -72,7 +73,7 @@ function lipoOutputArtifacts(product, inputs, fileTag, debugSuffix) {
// approach for all bundle types.
var defaultVariant;
if (!buildVariants.some(function (x) { return x.name === "release"; })
- && product.multiplexByQbsProperties.contains("buildVariants")
+ && product.multiplexByQbsProperties.includes("buildVariants")
&& product.qbs.buildVariants && product.qbs.buildVariants.length > 1) {
var defaultBuildVariant = product.qbs.defaultBuildVariant;
buildVariants.map(function (variant) {
@@ -99,6 +100,9 @@ function lipoOutputArtifacts(product, inputs, fileTag, debugSuffix) {
else
tags.push(fileTag, "primary");
+ if (product.codesign.enableCodeSigning)
+ tags.push("codesign.signed_artifact");
+
return {
filePath: FileInfo.joinPaths(product.destinationDirectory,
PathTools.linkerOutputFilePath(fileTag, product,
@@ -133,7 +137,7 @@ function prepareLipo(project, product, inputs, outputs, input, output) {
for (var p in inputs)
inputs[p] = inputs[p].filter(function(inp) { return inp.product.name === product.name; });
var allInputs = [].concat.apply([], Object.keys(inputs).map(function (tag) {
- return ["application", "dynamiclibrary", "staticlibrary", "loadablemodule"].contains(tag)
+ return ["application", "dynamiclibrary", "staticlibrary", "loadablemodule"].includes(tag)
? inputs[tag] : [];
}));
@@ -168,26 +172,17 @@ function prepareLipo(project, product, inputs, outputs, input, output) {
commands.push(cmd);
}
- var debugInfo = outputs.debuginfo_app || outputs.debuginfo_dll
- || outputs.debuginfo_loadablemodule;
- if (debugInfo) {
- var dsymPath = debugInfo[0].filePath;
- if (outputs.debuginfo_bundle && outputs.debuginfo_bundle[0])
- dsymPath = outputs.debuginfo_bundle[0].filePath;
- var flags = ModUtils.moduleProperty(product, "dsymutilFlags") || [];
- cmd = new Command(ModUtils.moduleProperty(product, "dsymutilPath"), flags.concat([
- "-o", dsymPath
- ]).concat(outputs.primary.map(function (f) { return f.filePath; })));
- cmd.description = "generating dSYM for " + product.name;
- commands.push(cmd);
- }
+ commands = commands.concat(
+ Gcc.separateDebugInfoCommandsDarwin(product, outputs, outputs.primary));
- cmd = new Command(ModUtils.moduleProperty(product, "stripPath"),
- ["-S", outputs.primary[0].filePath]);
- cmd.silent = true;
- commands.push(cmd);
if (outputs.dynamiclibrary_symbols)
Array.prototype.push.apply(commands, Gcc.createSymbolCheckingCommands(product, outputs));
+
+ if (product.codesign.enableCodeSigning) {
+ Array.prototype.push.apply(
+ commands, Codesign.prepareSign(project, product, inputs, outputs, input, output));
+ }
+
return commands;
}
diff --git a/share/qbs/modules/cpp/dmc.js b/share/qbs/modules/cpp/dmc.js
new file mode 100644
index 000000000..ea7cd7bb5
--- /dev/null
+++ b/share/qbs/modules/cpp/dmc.js
@@ -0,0 +1,506 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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.
+**
+****************************************************************************/
+
+var Cpp = require("cpp.js");
+var Environment = require("qbs.Environment");
+var File = require("qbs.File");
+var FileInfo = require("qbs.FileInfo");
+var ModUtils = require("qbs.ModUtils");
+var Process = require("qbs.Process");
+var TemporaryDir = require("qbs.TemporaryDir");
+var TextFile = require("qbs.TextFile");
+var Utilities = require("qbs.Utilities");
+
+function targetFlags(platform, architecture, extender, consoleApp, type) {
+ if (platform === "dos") {
+ if (architecture === "x86_16") {
+ if (extender === "dosz")
+ return ["-mz"];
+ else if (extender === "dosr")
+ return ["-mr"];
+ return ["-mc"];
+ } else if (architecture === "x86") {
+ if (extender === "dosx")
+ return ["-mx"];
+ else if (extender === "dosp")
+ return ["-mp"];
+ }
+ } else if (platform === "windows") {
+ var flags = [];
+ if (architecture === "x86_16") {
+ flags.push("-ml");
+ if (type.includes("application") && !consoleApp)
+ flags.push("-WA");
+ else if (type.includes("dynamiclibrary"))
+ flags.push("-WD");
+ } else if (architecture === "x86") {
+ flags.push("-mn");
+ if (type.includes("application"))
+ flags.push("-WA");
+ else if (type.includes("dynamiclibrary"))
+ flags.push("-WD");
+ }
+ return flags;
+ }
+ return [];
+}
+
+function languageFlags(tag) {
+ if (tag === "cpp")
+ return ["-cpp"];
+ return [];
+}
+
+function dumpMacros(compilerPath, platform, architecture, extender, tag) {
+ // Note: The DMC compiler does not support the predefined/ macros dumping. So, we do it
+ // with the following trick, where we try to create and compile a special temporary file
+ // and to parse the console output with the own magic pattern: #define <key> <value>.
+
+ var outputDirectory = new TemporaryDir();
+ var outputFilePath = FileInfo.joinPaths(outputDirectory.path(), "dump-macros.c");
+ var outputFile = new TextFile(outputFilePath, TextFile.WriteOnly);
+ outputFile.writeLine("#define VALUE_TO_STRING(x) #x");
+ outputFile.writeLine("#define VALUE(x) VALUE_TO_STRING(x)");
+ outputFile.writeLine("#define VAR_NAME_VALUE(var) \"#define \" #var\" \"VALUE(var)");
+ // Declare all available pre-defined macros of DMC compiler.
+ var keys = [
+ // Prepare the DOS target macros.
+ "_MSDOS", "MSDOS",
+ // Prepare the OS/2 target macros.
+ "__OS2__",
+ // Prepare the Windows target macros.
+ "WIN32", "_WIN32", "__NT__",
+ // Prepare extended the 32 and 16 bit DOS target macros.
+ "DOS386", "DOS16RM",
+ // Prepare the memory model macros.
+ "M_I86", "_M_I86",
+ "_M_I86TM", "M_I86TM",
+ "_M_I86SM", "M_I86SM",
+ "_M_I86MM", "M_I86MM",
+ "_M_I86CM", "M_I86CM",
+ "_M_I86LM", "M_I86LM",
+ "_M_I86VM", "M_I86VM",
+ // Prepare 8086 macros.
+ "_M_I8086", "M_I8086",
+ // Prepare 286 macros.
+ "_M_I286", "M_I286",
+ // Prepare 32 bit macros.
+ "_M_IX86",
+ // Prepare compiler identification macros.
+ "__DMC__", "__DMC_VERSION_STRING__",
+ // Prepare common compiler macros.
+ "_CHAR_UNSIGNED", "_CHAR_EQ_UCHAR", "_DEBUG_TRACE", "_DLL",
+ "_ENABLE_ARRAYNEW", "_BOOL_DEFINED", "_WCHAR_T_DEFINED",
+ "_CPPRTTI", "_CPPUNWIND", "_MD", "_PUSHPOP_SUPPORTED",
+ "_STDCALL_SUPPORTED", "__INTSIZE", "__DEFALIGN", "_INTEGRAL_MAX_BITS",
+ "_WINDOWS", "_WINDLL", "__INLINE_8087", "__I86__", "__SMALL__",
+ "__MEDIUM__", "__COMPACT__", "__LARGE__", "__VCM__", "__FPCE__",
+ "__FPCE__IEEE__", "DEBUG",
+ // Prepare C99 and C++98 macros.
+ "__STDC__", "__STDC_HOSTED__", "__STDC_VERSION__", "__STDC_IEC_559__",
+ "__STDC_IEC_559_COMPLEX__", "__STDC_ISO_10646__", "__cplusplus"
+ ];
+ for (var i = 0; i < keys.length; ++i) {
+ var key = keys[i];
+ outputFile.writeLine("#if defined (" + key + ")");
+ outputFile.writeLine("#pragma message (VAR_NAME_VALUE(" + key + "))");
+ outputFile.writeLine("#endif");
+ }
+ outputFile.close();
+
+ var process = new Process();
+ process.setWorkingDirectory(outputDirectory.path());
+ var lang = languageFlags(tag);
+ var target = targetFlags(platform, architecture, extender, false, ["application"]);
+ var args = ["-c"].concat(lang, target, FileInfo.toWindowsSeparators(outputFilePath));
+ process.exec(compilerPath, args, false);
+ File.remove(outputFilePath);
+ var out = process.readStdOut();
+ return Cpp.extractMacros(out);
+}
+
+function dumpDefaultPaths(compilerFilePath, tag) {
+ var binPath = FileInfo.path(compilerFilePath);
+ var rootPath = FileInfo.path(binPath);
+ var includePaths = [];
+ var cppIncludePath = FileInfo.joinPaths(rootPath, "stlport/stlport");
+ if (File.exists(cppIncludePath))
+ includePaths.push(cppIncludePath);
+ var cIncludePath = FileInfo.joinPaths(rootPath, "include");
+ if (File.exists(cIncludePath))
+ includePaths.push(cIncludePath);
+
+ var libraryPaths = [];
+ var libraryPath = FileInfo.joinPaths(rootPath, "lib");
+ if (File.exists(libraryPath))
+ libraryPaths.push(libraryPath);
+
+ return {
+ "includePaths": includePaths,
+ "libraryPaths": libraryPaths,
+ }
+}
+
+function guessVersion(macros) {
+ var version = macros["__DMC__"];
+ return { major: parseInt(version / 100),
+ minor: parseInt(version % 100),
+ patch: 0 };
+}
+
+function effectiveLinkerPath(product) {
+ if (product.cpp.linkerMode === "automatic") {
+ var compilerPath = product.cpp.compilerPath;
+ if (compilerPath)
+ return compilerPath;
+ console.log("Found no C-language objects, choosing system linker for " + product.name);
+ }
+ return product.cpp.linkerPath;
+}
+
+function useCompilerDriverLinker(product) {
+ var linker = effectiveLinkerPath(product);
+ var compilers = product.cpp.compilerPathByLanguage;
+ if (compilers)
+ return linker === compilers["cpp"] || linker === compilers["c"];
+ return linker === product.cpp.compilerPath;
+}
+
+function depsOutputTags() {
+ return ["dep"];
+}
+
+function depsOutputArtifacts(input, product) {
+ return [{
+ fileTags: depsOutputTags(),
+ filePath: FileInfo.joinPaths(product.destinationDirectory,
+ input.baseName + ".dep")
+ }];
+}
+
+function compilerFlags(project, product, input, outputs, explicitlyDependsOn) {
+ var args = ["-c"];
+
+ var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(outputs.obj[0].fileTags));
+ args = args.concat(languageFlags(tag));
+ args = args.concat(targetFlags(product.qbs.targetPlatform, product.qbs.architecture,
+ product.cpp.extenderName, product.consoleApplication,
+ product.type));
+
+ // Input.
+ args.push(FileInfo.toWindowsSeparators(input.filePath));
+ // Output.
+ args.push("-o" + FileInfo.toWindowsSeparators(outputs.obj[0].filePath));
+ // Preinclude headers.
+ args = args.concat(Cpp.collectPreincludePaths(input).map(function(path) {
+ return input.cpp.preincludeFlag + FileInfo.toWindowsSeparators(path);
+ }));
+
+ // Defines.
+ args = args.concat(Cpp.collectDefinesArguments(input));
+
+ if (tag === "cpp") {
+ // We need to add the paths to the STL includes, because the DMC compiler does
+ // not handle it by default (because the STL libraries is a separate port).
+ var compilerIncludePaths = input.cpp.compilerIncludePaths || [];
+ args = args.concat(compilerIncludePaths.map(function(path) {
+ return input.cpp.includeFlag + FileInfo.toWindowsSeparators(path);
+ }));
+ }
+
+ // Other includes.
+ args = args.concat(Cpp.collectIncludePaths(input).map(function(path) {
+ return input.cpp.includeFlag + FileInfo.toWindowsSeparators(path);
+ }));
+ args = args.concat(Cpp.collectSystemIncludePaths(input).map(function(path) {
+ return input.cpp.systemIncludeFlag + FileInfo.toWindowsSeparators(path);
+ }));
+
+ // Debug information flags.
+ if (input.cpp.debugInformation)
+ args.push("-d");
+
+ // Optimization flags.
+ switch (input.cpp.optimization) {
+ case "small":
+ args.push("-o+space");
+ break;
+ case "fast":
+ args.push("-o+speed");
+ break;
+ case "none":
+ args.push("-o+none");
+ break;
+ }
+
+ // Warning level flags.
+ switch (input.cpp.warningLevel) {
+ case "none":
+ args.push("-w");
+ break;
+ case "all":
+ args.push("-w-");
+ break;
+ }
+ if (input.cpp.treatWarningsAsErrors)
+ args.push("-wx");
+
+ if (tag === "cpp") {
+ // Exceptions flag.
+ if (input.cpp.enableExceptions)
+ args.push("-Ae");
+
+ // RTTI flag.
+ var enableRtti = input.cpp.enableRtti;
+ if (input.cpp.enableRtti)
+ args.push("-Ar");
+ }
+
+ // Listing files generation flag.
+ if (input.cpp.generateCompilerListingFiles) {
+ // We need to use the relative path here, because the DMC compiler does not handle
+ // a long file path for this option.
+ var listingPath = Cpp.relativePath(product.buildDirectory, outputs.lst[0].filePath);
+ args.push("-l" + FileInfo.toWindowsSeparators(listingPath));
+ }
+
+ // Misc flags.
+ args = args.concat(Cpp.collectMiscCompilerArguments(input, tag),
+ Cpp.collectMiscDriverArguments(product));
+ return args;
+}
+
+function assemblerFlags(project, product, input, outputs, explicitlyDependsOn) {
+ var args = ["-c"];
+
+ // Input.
+ args.push(FileInfo.toWindowsSeparators(input.filePath));
+ // Output.
+ args.push("-o" + FileInfo.toWindowsSeparators(outputs.obj[0].filePath));
+ // Preinclude headers.
+ args = args.concat(Cpp.collectPreincludePaths(input).map(function(path) {
+ return input.cpp.preincludeFlag + FileInfo.toWindowsSeparators(path);
+ }));
+
+ // Defines.
+ args = args.concat(Cpp.collectDefinesArguments(input));
+
+ // Other includes.
+ args = args.concat(Cpp.collectIncludePaths(input).map(function(path) {
+ return input.cpp.includeFlag + FileInfo.toWindowsSeparators(path);
+ }));
+ args = args.concat(Cpp.collectSystemIncludePaths(input).map(function(path) {
+ return input.cpp.systemIncludeFlag + FileInfo.toWindowsSeparators(path);
+ }));
+
+ // Misc flags.
+ args = args.concat(Cpp.collectMiscAssemblerArguments(input, "asm"));
+ return args;
+}
+
+function linkerFlags(project, product, inputs, outputs) {
+ var args = [];
+
+ var useCompilerDriver = useCompilerDriverLinker(product);
+ if (useCompilerDriver) {
+ args = args.concat(targetFlags(product.qbs.targetPlatform, product.qbs.architecture,
+ product.cpp.extenderName, product.consoleApplication,
+ product.type));
+
+ // Input objects.
+ args = args.concat(Cpp.collectLinkerObjectPaths(inputs).map(function(path) {
+ return FileInfo.toWindowsSeparators(path);
+ }));
+
+ // Input resources.
+ args = args.concat(Cpp.collectResourceObjectPaths(inputs).map(function(path) {
+ return FileInfo.toWindowsSeparators(path);
+ }));
+
+ // Input libraries.
+ args = args.concat(Cpp.collectAbsoluteLibraryDependencyPaths(product).map(function(path) {
+ return FileInfo.toWindowsSeparators(path);
+ }));
+
+ // Output.
+ if (product.type.includes("application")) {
+ args.push("-o" + FileInfo.toWindowsSeparators(outputs.application[0].filePath));
+ args.push("-L/" + (product.cpp.generateLinkerMapFile ? "MAP" : "NOMAP"));
+ if (product.qbs.targetPlatform === "windows" && product.qbs.architecture === "x86")
+ args.push("-L/SUBSYSTEM:" + (product.consoleApplication ? "CONSOLE" : "WINDOWS"));
+ } else if (product.type.includes("dynamiclibrary")) {
+ args.push("-o" + FileInfo.toWindowsSeparators(outputs.dynamiclibrary[0].filePath));
+ if (product.qbs.targetPlatform === "windows" && product.qbs.architecture === "x86") {
+ args.push("kernel32.lib");
+ args.push("-L/IMPLIB:" + FileInfo.toWindowsSeparators(
+ outputs.dynamiclibrary_import[0].filePath));
+ }
+ }
+
+ if (product.cpp.debugInformation)
+ args.push("-L/DEBUG");
+
+ args.push("-L/NOLOGO", "-L/SILENT");
+ }
+
+ // Misc flags.
+ args = args.concat(Cpp.collectMiscEscapableLinkerArguments(product),
+ Cpp.collectMiscLinkerArguments(product),
+ Cpp.collectMiscDriverArguments(product));
+ return args;
+}
+
+function archiverFlags(project, product, inputs, outputs) {
+ var args = ["-c"];
+ // Output.
+ args.push(FileInfo.toWindowsSeparators(outputs.staticlibrary[0].filePath));
+ // Input objects.
+ args = args.concat(Cpp.collectLinkerObjectPaths(inputs).map(function(path) {
+ return FileInfo.toWindowsSeparators(path);
+ }));
+ return args;
+}
+
+function rccCompilerFlags(project, product, input, outputs) {
+ // Input.
+ var args = [FileInfo.toWindowsSeparators(input.filePath)];
+ // Output.
+ args.push("-o" + FileInfo.toWindowsSeparators(outputs.res[0].filePath));
+ // Bitness.
+ args.push("-32");
+
+ // Defines
+ args = args.concat(Cpp.collectDefinesArguments(input));
+
+ // Other includes.
+ args = args.concat(Cpp.collectIncludePaths(input).map(function(path) {
+ return input.cpp.includeFlag + FileInfo.toWindowsSeparators(path);
+ }));
+ args = args.concat(Cpp.collectSystemIncludePaths(input).map(function(path) {
+ return input.cpp.systemIncludeFlag + FileInfo.toWindowsSeparators(path);
+ }));
+ return args;
+}
+
+function buildLinkerMapFilePath(target, suffix) {
+ return FileInfo.joinPaths(FileInfo.path(target.filePath),
+ FileInfo.completeBaseName(target.fileName) + suffix);
+}
+
+// It is a workaround which removes the generated linker map file if it is disabled
+// by cpp.generateLinkerMapFile property. Reason is that the DMC compiler always
+// generates this file, and does not have an option to disable generation for a linker
+// map file. So, we can to remove a listing files only after the linking completes.
+function removeLinkerMapFile(project, product, inputs, outputs, input, output) {
+ var target = outputs.dynamiclibrary ? outputs.dynamiclibrary[0]
+ : outputs.application[0];
+ var cmd = new JavaScriptCommand();
+ cmd.mapFilePath = buildLinkerMapFilePath(target, ".map")
+ cmd.silent = true;
+ cmd.sourceCode = function() { File.remove(mapFilePath); };
+ return cmd;
+}
+
+// It is a workaround to rename the extension of the output linker map file to the
+// specified one, since the linker generates only files with the '.map' extension.
+function renameLinkerMapFile(project, product, inputs, outputs, input, output) {
+ var target = outputs.dynamiclibrary ? outputs.dynamiclibrary[0]
+ : outputs.application[0];
+ var cmd = new JavaScriptCommand();
+ cmd.newMapFilePath = buildLinkerMapFilePath(target, product.cpp.linkerMapSuffix);
+ cmd.oldMapFilePath = buildLinkerMapFilePath(target, ".map");
+ cmd.silent = true;
+ cmd.sourceCode = function() {
+ if (oldMapFilePath !== newMapFilePath)
+ File.move(oldMapFilePath, newMapFilePath);
+ };
+ return cmd;
+}
+
+function prepareCompiler(project, product, inputs, outputs, input, output, explicitlyDependsOn) {
+ var args = compilerFlags(project, product, input, outputs, explicitlyDependsOn);
+ var cmd = new Command(input.cpp.compilerPath, args);
+ cmd.workingDirectory = product.buildDirectory;
+ cmd.description = "compiling " + input.fileName;
+ cmd.highlight = "compiler";
+ cmd.jobPool = "compiler";
+ return [cmd];
+}
+
+function prepareAssembler(project, product, inputs, outputs, input, output, explicitlyDependsOn) {
+ var args = assemblerFlags(project, product, input, outputs, explicitlyDependsOn);
+ var cmd = new Command(input.cpp.assemblerPath, args);
+ cmd.workingDirectory = product.buildDirectory;
+ cmd.description = "compiling " + input.fileName;
+ cmd.highlight = "compiler";
+ cmd.jobPool = "assembler";
+ return [cmd];
+}
+
+function prepareLinker(project, product, inputs, outputs, input, output) {
+ var cmds = [];
+ var primaryOutput = outputs.dynamiclibrary ? outputs.dynamiclibrary[0]
+ : outputs.application[0];
+ var args = linkerFlags(project, product, inputs, outputs);
+ var linkerPath = effectiveLinkerPath(product);
+ var cmd = new Command(linkerPath, args);
+ cmd.workingDirectory = product.buildDirectory;
+ cmd.description = "linking " + primaryOutput.fileName;
+ cmd.highlight = "linker";
+ cmd.jobPool = "linker";
+ cmds.push(cmd);
+
+ if (product.cpp.generateLinkerMapFile)
+ cmds.push(renameLinkerMapFile(project, product, inputs, outputs, input, output));
+ else
+ cmds.push(removeLinkerMapFile(project, product, inputs, outputs, input, output));
+
+ return cmds;
+}
+
+function prepareArchiver(project, product, inputs, outputs, input, output) {
+ var args = archiverFlags(project, product, inputs, outputs);
+ var cmd = new Command(product.cpp.archiverPath, args);
+ cmd.workingDirectory = product.buildDirectory;
+ cmd.description = "creating " + output.fileName;
+ cmd.highlight = "linker";
+ cmd.jobPool = "linker";
+ return [cmd];
+}
+
+function prepareRccCompiler(project, product, inputs, outputs, input, output) {
+ var args = rccCompilerFlags(project, product, input, outputs);
+ var cmd = new Command(input.cpp.rccCompilerPath, args);
+ cmd.workingDirectory = product.buildDirectory;
+ cmd.description = "compiling " + input.fileName;
+ cmd.highlight = "compiler";
+ cmd.jobPool = "compiler";
+ return [cmd];
+}
diff --git a/share/qbs/modules/cpp/dmc.qbs b/share/qbs/modules/cpp/dmc.qbs
new file mode 100644
index 000000000..ac89550e8
--- /dev/null
+++ b/share/qbs/modules/cpp/dmc.qbs
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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.File
+import qbs.FileInfo
+import qbs.Host
+import qbs.PathTools
+import qbs.Probes
+import qbs.Utilities
+import "dmc.js" as DMC
+import "cpp.js" as Cpp
+
+CppModule {
+ condition: Host.os().includes("windows") && qbs.toolchain && qbs.toolchain.includes("dmc")
+
+ Probes.BinaryProbe {
+ id: compilerPathProbe
+ condition: !toolchainInstallPath && !_skipAllChecks
+ names: ["dmc"]
+ }
+
+ Probes.DmcProbe {
+ id: dmcProbe
+ condition: !_skipAllChecks
+ compilerFilePath: compilerPath
+ enableDefinesByLanguage: enableCompilerDefinesByLanguage
+ _targetPlatform: qbs.targetPlatform
+ _targetArchitecture: qbs.architecture
+ _targetExtender: extenderName
+ }
+
+ qbs.architecture: dmcProbe.found ? dmcProbe.architecture : original
+ qbs.targetPlatform: dmcProbe.found ? dmcProbe.targetPlatform : original
+
+ compilerVersionMajor: dmcProbe.versionMajor
+ compilerVersionMinor: dmcProbe.versionMinor
+ compilerVersionPatch: dmcProbe.versionPatch
+ endianness: "little"
+
+ compilerDefinesByLanguage: dmcProbe.compilerDefinesByLanguage
+ compilerIncludePaths: dmcProbe.includePaths
+
+ toolchainInstallPath: compilerPathProbe.found ? compilerPathProbe.path : undefined
+
+ /* Work-around for QtCreator which expects these properties to exist. */
+ property string cCompilerName: compilerName
+ property string cxxCompilerName: compilerName
+
+ compilerName: "dmc.exe"
+ compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName)
+
+ assemblerName: "dmc.exe"
+ assemblerPath: FileInfo.joinPaths(toolchainInstallPath, assemblerName)
+
+ linkerName: "link.exe"
+ linkerPath: FileInfo.joinPaths(toolchainInstallPath, linkerName)
+
+ property string archiverName: "lib.exe"
+ property string archiverPath: FileInfo.joinPaths(toolchainInstallPath, archiverName)
+ property string rccCompilerName: "rcc.exe"
+ property string rccCompilerPath: FileInfo.joinPaths(toolchainInstallPath, rccCompilerName)
+
+ property string extenderName
+ PropertyOptions {
+ name: "extenderName"
+ allowedValues: [undefined, "dosz", "dosr", "dosx", "dosp"]
+ description: "Specifies the DOS memory extender to compile with:\n"
+ + " - \"dosz\" is the ZPM 16 bit DOS Extender\n"
+ + " - \"dosr\" is the Rational 16 bit DOS Extender\n"
+ + " - \"dosx\" is the DOSX 32 bit DOS Extender\n"
+ + " - \"dosp\" is the Pharlap 32 bit DOS Extender\n"
+ ;
+ }
+
+ runtimeLibrary: "dynamic"
+
+ staticLibrarySuffix: ".lib"
+ dynamicLibrarySuffix: ".dll"
+ executableSuffix: ".exe"
+ objectSuffix: ".obj"
+
+ imageFormat: {
+ if (qbs.targetPlatform === "dos")
+ return "mz";
+ else if (qbs.targetPlatform === "windows")
+ return "pe";
+ }
+
+ defineFlag: "-D"
+ includeFlag: "-I"
+ systemIncludeFlag: "-I"
+ preincludeFlag: "-HI"
+ libraryPathFlag: "-L/packcode"
+
+ knownArchitectures: ["x86", "x86_16"]
+
+ Rule {
+ id: assembler
+ inputs: ["asm"]
+ outputFileTags: DMC.depsOutputTags().concat(
+ Cpp.assemblerOutputTags(generateAssemblerListingFiles))
+ outputArtifacts: DMC.depsOutputArtifacts(input, product).concat(
+ Cpp.assemblerOutputArtifacts(input))
+ prepare: DMC.prepareAssembler.apply(DMC, arguments)
+ }
+
+ FileTagger {
+ patterns: ["*.s", "*.asm"]
+ fileTags: ["asm"]
+ }
+
+ Rule {
+ id: compiler
+ inputs: ["cpp", "c"]
+ auxiliaryInputs: ["hpp"]
+ outputFileTags: DMC.depsOutputTags().concat(
+ Cpp.compilerOutputTags(generateCompilerListingFiles))
+ outputArtifacts: DMC.depsOutputArtifacts(input, product).concat(
+ Cpp.compilerOutputArtifacts(input))
+ prepare: DMC.prepareCompiler.apply(DMC, arguments)
+ }
+
+
+ Rule {
+ id: rccCompiler
+ inputs: ["rc"]
+ auxiliaryInputs: ["hpp"]
+ outputFileTags: Cpp.resourceCompilerOutputTags()
+ outputArtifacts: Cpp.resourceCompilerOutputArtifacts(input)
+ prepare: DMC.prepareRccCompiler.apply(DMC, arguments)
+ }
+
+ FileTagger {
+ patterns: ["*.rc"]
+ fileTags: ["rc"]
+ }
+
+ Rule {
+ id: applicationLinker
+ multiplex: true
+ inputs: ["obj", "res", "linkerscript"]
+ inputsFromDependencies: ["staticlibrary", "dynamiclibrary_import"]
+ outputFileTags: Cpp.applicationLinkerOutputTags(generateLinkerMapFile)
+ outputArtifacts: Cpp.applicationLinkerOutputArtifacts(product)
+ prepare: DMC.prepareLinker.apply(DMC, arguments)
+ }
+
+ Rule {
+ id: dynamicLibraryLinker
+ multiplex: true
+ inputs: ["obj", "res"]
+ inputsFromDependencies: ["staticlibrary", "dynamiclibrary_import"]
+ outputFileTags: Cpp.dynamicLibraryLinkerOutputTags()
+ outputArtifacts: Cpp.dynamicLibraryLinkerOutputArtifacts(product)
+ prepare: DMC.prepareLinker.apply(DMC, arguments)
+ }
+
+ Rule {
+ id: staticLibraryLinker
+ multiplex: true
+ inputs: ["obj"]
+ inputsFromDependencies: ["staticlibrary", "dynamiclibrary_import"]
+ outputFileTags: Cpp.staticLibraryLinkerOutputTags()
+ outputArtifacts: Cpp.staticLibraryLinkerOutputArtifacts(product)
+ prepare: DMC.prepareArchiver.apply(DMC, arguments)
+ }
+}
diff --git a/share/qbs/modules/cpp/freebsd-gcc.qbs b/share/qbs/modules/cpp/freebsd-gcc.qbs
index b5a4b89f3..e04ed7f2b 100644
--- a/share/qbs/modules/cpp/freebsd-gcc.qbs
+++ b/share/qbs/modules/cpp/freebsd-gcc.qbs
@@ -29,13 +29,14 @@
****************************************************************************/
import "freebsd.js" as FreeBSD
+import qbs.Host
UnixGCC {
- condition: qbs.targetOS && qbs.targetOS.contains("freebsd") &&
- qbs.toolchain && qbs.toolchain.contains("gcc")
+ condition: qbs.targetOS.includes("freebsd") &&
+ qbs.toolchain && qbs.toolchain.includes("gcc")
priority: 1
- targetSystem: "freebsd" + (qbs.hostOS.contains("freebsd") ? FreeBSD.hostKernelRelease() : "")
+ targetSystem: "freebsd" + (Host.os().includes("freebsd") ? FreeBSD.hostKernelRelease() : "")
distributionIncludePaths: ["/usr/local/include"]
distributionLibraryPaths: ["/usr/local/lib"]
diff --git a/share/qbs/modules/cpp/gcc.js b/share/qbs/modules/cpp/gcc.js
index 574fe769b..90f8fc933 100644
--- a/share/qbs/modules/cpp/gcc.js
+++ b/share/qbs/modules/cpp/gcc.js
@@ -28,9 +28,11 @@
**
****************************************************************************/
+var Codesign = require("../codesign/codesign.js");
var Cpp = require("cpp.js");
var File = require("qbs.File");
var FileInfo = require("qbs.FileInfo");
+var Host = require("qbs.Host");
var DarwinTools = require("qbs.DarwinTools");
var ModUtils = require("qbs.ModUtils");
var PathTools = require("qbs.PathTools");
@@ -76,6 +78,7 @@ function useCompilerDriverLinker(product, inputs) {
function collectLibraryDependencies(product, isDarwin) {
var publicDeps = {};
+ var privateDeps = {};
var objects = [];
var objectByFilePath = {};
var tagForLinkingAgainstSharedLib = product.cpp.imageFormat === "pe"
@@ -132,7 +135,7 @@ function collectLibraryDependencies(product, isDarwin) {
if (!obj.cpp)
return;
function ensureArray(a) {
- return Array.isArray(a) ? a : [];
+ return (a instanceof Array) ? a : [];
}
function sanitizedModuleListProperty(obj, moduleName, propertyName) {
return ensureArray(ModUtils.sanitizedModuleProperty(obj, moduleName, propertyName));
@@ -168,6 +171,8 @@ function collectLibraryDependencies(product, isDarwin) {
&& typeof dep.artifacts[tagForLinkingAgainstSharedLib] !== "undefined";
if (!isStaticLibrary && !isDynamicLibrary)
return;
+ if (isBelowIndirectDynamicLib && privateDeps[dep.name])
+ return;
var nextIsBelowIndirectDynamicLib = isBelowIndirectDynamicLib || isDynamicLibrary;
dep.dependencies.forEach(function(depdep) {
@@ -191,6 +196,7 @@ function collectLibraryDependencies(product, isDarwin) {
publicDeps[dep.name] = true;
} else {
addArtifactFilePaths(dep, tagForLinkingAgainstSharedLib, addPrivateFilePath);
+ privateDeps[dep.name] = true;
}
}
}
@@ -202,7 +208,6 @@ function collectLibraryDependencies(product, isDarwin) {
product.dependencies.forEach(traverseDirectDependency);
addExternalLibs(product);
- var seenRPathLinkDirs = {};
var result = { libraries: [], rpath_link: [] };
objects.forEach(
function (obj) {
@@ -213,10 +218,7 @@ function collectLibraryDependencies(product, isDarwin) {
framework: obj.framework });
} else {
var dirPath = FileInfo.path(obj.filePath);
- if (!seenRPathLinkDirs.hasOwnProperty(dirPath)) {
- seenRPathLinkDirs[dirPath] = true;
- result.rpath_link.push(dirPath);
- }
+ result.rpath_link.push(dirPath);
}
});
return result;
@@ -228,7 +230,7 @@ function escapeLinkerFlags(product, inputs, linkerFlags) {
if (useCompilerDriverLinker(product, inputs)) {
var sep = ",";
- var useXlinker = linkerFlags.some(function (f) { return f.contains(sep); });
+ var useXlinker = linkerFlags.some(function (f) { return f.includes(sep); });
if (useXlinker) {
// One or more linker arguments contain the separator character itself
// Use -Xlinker to handle these
@@ -245,7 +247,7 @@ function escapeLinkerFlags(product, inputs, linkerFlags) {
return xlinkerFlags;
}
- if (product.cpp.enableSuspiciousLinkerFlagWarnings && linkerFlags.contains("-Xlinker")) {
+ if (product.cpp.enableSuspiciousLinkerFlagWarnings && linkerFlags.includes("-Xlinker")) {
console.warn("Encountered -Xlinker linker flag escape sequence. This may cause the " +
"target to fail to link. Please do not escape these flags manually; " +
"qbs does that for you.");
@@ -260,9 +262,7 @@ function escapeLinkerFlags(product, inputs, linkerFlags) {
}
function linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPath) {
- var libraryPaths = product.cpp.libraryPaths;
- var distributionLibraryPaths = product.cpp.distributionLibraryPaths;
- var isDarwin = product.qbs.targetOS.contains("darwin");
+ var isDarwin = product.qbs.targetOS.includes("darwin");
var libraryDependencies = collectLibraryDependencies(product, isDarwin);
var frameworks = product.cpp.frameworks;
var weakFrameworks = product.cpp.weakFrameworks;
@@ -275,7 +275,7 @@ function linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPat
var escapableLinkerFlags = [];
- if (primaryOutput.fileTags.contains("dynamiclibrary")) {
+ if (primaryOutput.fileTags.includes("dynamiclibrary")) {
if (isDarwin) {
args.push((function () {
var tags = ["c", "cpp", "objc", "objcpp", "asm_cpp"];
@@ -300,7 +300,7 @@ function linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPat
}
}
- if (primaryOutput.fileTags.contains("loadablemodule"))
+ if (primaryOutput.fileTags.includes("loadablemodule"))
args.push(isDarwin ? "-bundle" : "-shared");
if (primaryOutput.fileTags.containsAny(["dynamiclibrary", "loadablemodule"])) {
@@ -323,7 +323,7 @@ function linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPat
var sysroot = product.cpp.syslibroot;
if (sysroot) {
- if (product.qbs.toolchain.contains("qcc"))
+ if (product.qbs.toolchain.includes("qcc"))
escapableLinkerFlags.push("--sysroot=" + sysroot);
else if (isDarwin)
escapableLinkerFlags.push("-syslibroot", sysroot);
@@ -340,7 +340,7 @@ function linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPat
function fixupRPath(rpath) {
// iOS, tvOS, watchOS, and others, are fine
- if (!product.qbs.targetOS.contains("macos"))
+ if (!product.qbs.targetOS.includes("macos"))
return rpath;
// ...as are newer versions of macOS
@@ -355,11 +355,12 @@ function linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPat
return rpath;
}
- if (!product.qbs.targetOS.contains("windows")) {
- function isNotSystemRunPath(p) {
- return !FileInfo.isAbsolutePath(p) || (!systemRunPaths.contains(p)
- && !canonicalSystemRunPaths.contains(File.canonicalFilePath(p)));
- };
+ function isNotSystemRunPath(p) {
+ return !FileInfo.isAbsolutePath(p) || (!systemRunPaths.includes(p)
+ && !canonicalSystemRunPaths.includes(File.canonicalFilePath(p)));
+ };
+
+ if (!product.qbs.targetOS.includes("windows")) {
for (i in rpaths) {
if (isNotSystemRunPath(rpaths[i]))
escapableLinkerFlags.push("-rpath", fixupRPath(rpaths[i]));
@@ -369,13 +370,16 @@ function linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPat
if (product.cpp.entryPoint)
escapableLinkerFlags.push("-e", product.cpp.entryPoint);
- if (product.qbs.toolchain.contains("mingw")) {
+ if (product.qbs.toolchain.includes("mingw")) {
if (product.consoleApplication !== undefined)
escapableLinkerFlags.push("-subsystem",
product.consoleApplication ? "console" : "windows");
var minimumWindowsVersion = product.cpp.minimumWindowsVersion;
if (minimumWindowsVersion) {
+ // workaround for QBS-1724, mingw seems to be broken
+ if (Utilities.versionCompare(minimumWindowsVersion, "6.2") > 0)
+ minimumWindowsVersion = "6.2";
var subsystemVersion = WindowsUtils.getWindowsVersionInFormat(minimumWindowsVersion, 'subsystem');
if (subsystemVersion) {
var major = subsystemVersion.split('.')[0];
@@ -397,23 +401,16 @@ function linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPat
var stdlib = isLinkingCppObjects
? product.cpp.cxxStandardLibrary
: undefined;
- if (stdlib && product.qbs.toolchain.contains("clang"))
+ if (stdlib && product.qbs.toolchain.includes("clang"))
args.push("-stdlib=" + stdlib);
// Flags for library search paths
- var allLibraryPaths = [];
- if (libraryPaths)
- allLibraryPaths = allLibraryPaths.uniqueConcat(libraryPaths);
- if (distributionLibraryPaths)
- allLibraryPaths = allLibraryPaths.uniqueConcat(distributionLibraryPaths);
- if (systemRunPaths.length > 0)
- allLibraryPaths = allLibraryPaths.filter(isNotSystemRunPath);
- args = args.concat(allLibraryPaths.map(function(path) { return '-L' + path }));
-
- var linkerScripts = inputs.linkerscript
- ? inputs.linkerscript.map(function(a) { return a.filePath; }) : [];
- Array.prototype.push.apply(escapableLinkerFlags, [].uniqueConcat(linkerScripts)
- .map(function(path) { return '-T' + path }));
+ var allLibraryPaths = Cpp.collectLibraryPaths(product);
+ var builtIns = product.cpp.compilerLibraryPaths
+ allLibraryPaths = allLibraryPaths.filter(function(p) { return !builtIns.includes(p); });
+ args = args.concat(allLibraryPaths.map(function(path) { return product.cpp.libraryPathFlag + path }));
+
+ escapableLinkerFlags = escapableLinkerFlags.concat(Cpp.collectLinkerScriptPathsArguments(product, inputs));
var versionScripts = inputs.versionscript
? inputs.versionscript.map(function(a) { return a.filePath; }) : [];
@@ -425,16 +422,15 @@ function linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPat
var useCompilerDriver = useCompilerDriverLinker(product, inputs);
args = args.concat(configFlags(product, useCompilerDriver));
- Array.prototype.push.apply(escapableLinkerFlags, product.cpp.platformLinkerFlags);
- Array.prototype.push.apply(escapableLinkerFlags, product.cpp.linkerFlags);
+ escapableLinkerFlags = escapableLinkerFlags.concat(Cpp.collectMiscEscapableLinkerArguments(product));
// Note: due to the QCC response files hack in prepareLinker(), at least one object file or
// library file must follow the output file path so that QCC has something to process before
// sending the rest of the arguments through the response file.
args.push("-o", primaryOutput.filePath);
- if (inputs.obj)
- args = args.concat(inputs.obj.map(function (obj) { return obj.filePath }));
+ args = args.concat(Cpp.collectLinkerObjectPaths(inputs));
+ args = args.concat(Cpp.collectResourceObjectPaths(inputs));
for (i in frameworks) {
frameworkExecutablePath = PathTools.frameworkExecutablePath(frameworks[i]);
@@ -479,9 +475,12 @@ function linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPat
var symbolLinkMode = dep.symbolLinkMode;
if (isDarwin && symbolLinkMode) {
- if (!["lazy", "reexport", "upward", "weak"].contains(symbolLinkMode))
+ if (!["lazy", "reexport", "upward", "weak"].includes(symbolLinkMode))
throw new Error("unknown value '" + symbolLinkMode + "' for cpp.symbolLinkMode");
+ }
+ var supportsLazyMode = Utilities.versionCompare(product.cpp.compilerVersion, "15.0.0") < 0;
+ if (isDarwin && symbolLinkMode && (symbolLinkMode !== "lazy" || supportsLazyMode)) {
if (FileInfo.isAbsolutePath(lib) || lib.startsWith('@'))
escapableLinkerFlags.push("-" + symbolLinkMode + "_library", lib);
else if (dep.framework)
@@ -535,9 +534,10 @@ function linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPat
var escapedLinkerFlags = escapeLinkerFlags(product, inputs, escapableLinkerFlags);
Array.prototype.push.apply(escapedLinkerFlags, args);
- var driverLinkerFlags = useCompilerDriver ? product.cpp.driverLinkerFlags : undefined;
- if (driverLinkerFlags)
- Array.prototype.push.apply(escapedLinkerFlags, driverLinkerFlags);
+ if (useCompilerDriver)
+ escapedLinkerFlags = escapedLinkerFlags.concat(Cpp.collectMiscLinkerArguments(product));
+ if (product.qbs.toolchain.includes("mingw") && product.cpp.runtimeLibrary === "static")
+ escapedLinkerFlags = ['-static-libgcc', '-static-libstdc++'].concat(escapedLinkerFlags);
return escapedLinkerFlags;
}
@@ -545,15 +545,12 @@ function linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPat
function configFlags(config, isDriver) {
var args = [];
- if (isDriver !== false) {
- args = args.concat(config.cpp.platformDriverFlags);
- args = args.concat(config.cpp.driverFlags);
- args = args.concat(config.cpp.targetDriverFlags);
- }
+ if (isDriver !== false)
+ args = args.concat(Cpp.collectMiscDriverArguments(config));
var frameworkPaths = config.cpp.frameworkPaths;
if (frameworkPaths)
- args = args.concat(frameworkPaths.map(function(path) { return '-F' + path }));
+ args = args.uniqueConcat(frameworkPaths.map(function(path) { return '-F' + path }));
var allSystemFrameworkPaths = [];
@@ -586,7 +583,7 @@ function languageTagFromFileExtension(toolchain, fileName) {
"s" : "asm",
"S" : "asm_cpp"
};
- if (!toolchain.contains("clang"))
+ if (!toolchain.includes("clang"))
m["sx"] = "asm_cpp"; // clang does NOT recognize .sx
return m[fileName.substring(i + 1)];
}
@@ -594,7 +591,7 @@ function languageTagFromFileExtension(toolchain, fileName) {
// Older versions of the QNX SDK have C and C++ compilers whose filenames differ only by case,
// which won't work in case insensitive environments like Win32+NTFS, HFS+ and APFS
function isLegacyQnxSdk(config) {
- return config.qbs.toolchain.contains("qcc") && config.qnx && !config.qnx.qnx7;
+ return config.qbs.toolchain.includes("qcc") && config.qnx && !config.qnx.qnx7;
}
function effectiveCompilerInfo(toolchain, input, output) {
@@ -602,7 +599,7 @@ function effectiveCompilerInfo(toolchain, input, output) {
var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(output.fileTags));
// Whether we're compiling a precompiled header or normal source file
- var pchOutput = output.fileTags.contains(tag + "_pch");
+ var pchOutput = output.fileTags.includes(tag + "_pch");
var compilerPathByLanguage = input.cpp.compilerPathByLanguage;
if (compilerPathByLanguage)
@@ -610,7 +607,7 @@ function effectiveCompilerInfo(toolchain, input, output) {
if (!compilerPath
|| tag !== languageTagFromFileExtension(toolchain, input.fileName)
|| isLegacyQnxSdk(input)) {
- if (input.qbs.toolchain.contains("qcc"))
+ if (input.qbs.toolchain.includes("qcc"))
language = qnxLangArgs(input, tag);
else
language = ["-x", languageName(tag) + (pchOutput ? '-header' : '')];
@@ -704,6 +701,22 @@ function standardFallbackValueOrDefault(toolchain, compilerVersion, languageVers
{"name": "gcc", "version": "4.7"}
]
},
+ "c17": {
+ "fallback": "c11",
+ "toolchains": [
+ {"name": "xcode", "version": "10.2"},
+ {"name": "clang", "version": "7.0"},
+ {"name": "gcc", "version": "8.1"}
+ ]
+ },
+ "c2x": {
+ "fallback": "c17",
+ "toolchains": [
+ {"name": "xcode", "version": "11.4"},
+ {"name": "clang", "version": "9.0"},
+ {"name": "gcc", "version": "9.0"}
+ ]
+ },
"c++14": {
"fallback": "c++1y",
"toolchains": [
@@ -723,9 +736,17 @@ function standardFallbackValueOrDefault(toolchain, compilerVersion, languageVers
"c++20": {
"fallback": "c++2a",
"toolchains": [
- {"name": "xcode"}, // not yet implemented
- {"name": "clang"}, // not yet implemented
- {"name": "gcc"} // not yet implemented
+ {"name": "xcode", "version": "12.5"},
+ {"name": "clang", "version": "11.0"},
+ {"name": "gcc", "version": "10.1"}
+ ]
+ },
+ "c++23": {
+ "fallback": "c++2b",
+ "toolchains": [
+ {"name": "xcode"},
+ {"name": "clang"},
+ {"name": "gcc"}
]
}
};
@@ -734,7 +755,7 @@ function standardFallbackValueOrDefault(toolchain, compilerVersion, languageVers
if (m) {
for (var idx = 0; idx < m.toolchains.length; ++idx) {
var tc = m.toolchains[idx];
- if (toolchain.contains(tc.name)) {
+ if (toolchain.includes(tc.name)) {
// If we found our toolchain and it doesn't yet support the language standard
// we're requesting, or we're using an older version that only supports the
// preliminary flag, use that.
@@ -754,16 +775,9 @@ function standardFallbackValueOrDefault(toolchain, compilerVersion, languageVers
function compilerFlags(project, product, input, output, explicitlyDependsOn) {
var i;
- var includePaths = input.cpp.includePaths;
- var systemIncludePaths = input.cpp.systemIncludePaths;
- var distributionIncludePaths = input.cpp.distributionIncludePaths;
-
- var platformDefines = input.cpp.platformDefines;
- var defines = input.cpp.defines;
-
// Determine which C-language we're compiling
var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(output.fileTags));
- if (!["c", "cpp", "objc", "objcpp", "asm_cpp"].contains(tag))
+ if (!["c", "cpp", "objc", "objcpp", "asm_cpp"].includes(tag))
throw ("unsupported source language: " + tag);
var compilerInfo = effectiveCompilerInfo(product.qbs.toolchain,
@@ -796,12 +810,12 @@ function compilerFlags(project, product, input, output, explicitlyDependsOn) {
args = args.concat(configFlags(input));
- if (!input.qbs.toolchain.contains("qcc"))
+ if (!input.qbs.toolchain.includes("qcc"))
args.push('-pipe');
if (input.cpp.enableReproducibleBuilds) {
var toolchain = product.qbs.toolchain;
- if (!toolchain.contains("clang")) {
+ if (!toolchain.includes("clang")) {
var hashString = FileInfo.relativePath(project.sourceDirectory, input.filePath);
var hash = Utilities.getHash(hashString);
args.push("-frandom-seed=0x" + hash.substring(0, 8));
@@ -809,8 +823,8 @@ function compilerFlags(project, product, input, output, explicitlyDependsOn) {
var major = product.cpp.compilerVersionMajor;
var minor = product.cpp.compilerVersionMinor;
- if ((toolchain.contains("clang") && (major > 3 || (major === 3 && minor >= 5))) ||
- (toolchain.contains("gcc") && (major > 4 || (major === 4 && minor >= 9)))) {
+ if ((toolchain.includes("clang") && (major > 3 || (major === 3 && minor >= 5))) ||
+ (toolchain.includes("gcc") && (major > 4 || (major === 4 && minor >= 9)))) {
args.push("-Wdate-time");
}
}
@@ -838,7 +852,7 @@ function compilerFlags(project, product, input, output, explicitlyDependsOn) {
}
var visibility = input.cpp.visibility;
- if (!product.qbs.toolchain.contains("mingw")) {
+ if (!product.qbs.toolchain.includes("mingw")) {
if (visibility === 'hidden' || visibility === 'minimal')
args.push('-fvisibility=hidden');
if ((visibility === 'hiddenInlines' || visibility === 'minimal') && tag === 'cpp')
@@ -851,62 +865,40 @@ function compilerFlags(project, product, input, output, explicitlyDependsOn) {
// Only push language arguments if we have to.
Array.prototype.push.apply(args, compilerInfo.language);
- args = args.concat(ModUtils.moduleProperty(input, 'platformFlags'),
- ModUtils.moduleProperty(input, 'flags'),
- ModUtils.moduleProperty(input, 'platformFlags', tag),
- ModUtils.moduleProperty(input, 'flags', tag));
+ args = args.concat(Cpp.collectMiscCompilerArguments(input, tag));
var pchTag = compilerInfo.tag + "_pch";
- var pchOutput = output.fileTags.contains(pchTag);
+ var pchOutput = output.fileTags.includes(pchTag);
var pchInputs = explicitlyDependsOn[pchTag];
if (!pchOutput && pchInputs && pchInputs.length === 1
&& ModUtils.moduleProperty(input, 'usePrecompiledHeader', tag)) {
var pchInput = pchInputs[0];
var pchFilePath = FileInfo.joinPaths(FileInfo.path(pchInput.filePath),
pchInput.completeBaseName);
- args.push('-include', pchFilePath);
+ args.push(input.cpp.preincludeFlag, pchFilePath);
}
- var prefixHeaders = input.cpp.prefixHeaders;
- for (i in prefixHeaders) {
- args.push('-include');
- args.push(prefixHeaders[i]);
- }
+ args = args.concat(Cpp.collectPreincludePathsArguments(input));
var positionIndependentCode = input.cpp.positionIndependentCode;
- if (positionIndependentCode && !product.qbs.targetOS.contains("windows"))
+ if (positionIndependentCode && !product.qbs.targetOS.includes("windows"))
args.push('-fPIC');
var cppFlags = input.cpp.cppFlags;
for (i in cppFlags)
args.push('-Wp,' + cppFlags[i])
- var allDefines = [];
- if (platformDefines)
- allDefines = allDefines.uniqueConcat(platformDefines);
- if (defines)
- allDefines = allDefines.uniqueConcat(defines);
- args = args.concat(allDefines.map(function(define) { return '-D' + define }));
- if (includePaths) {
- args = args.concat([].uniqueConcat(includePaths).map(function(path) {
- return input.cpp.includeFlag + path;
- }));
- }
-
- var allSystemIncludePaths = [];
- if (systemIncludePaths)
- allSystemIncludePaths = allSystemIncludePaths.uniqueConcat(systemIncludePaths);
- if (distributionIncludePaths)
- allSystemIncludePaths = allSystemIncludePaths.uniqueConcat(distributionIncludePaths);
- allSystemIncludePaths.forEach(function(v) { args.push(input.cpp.systemIncludeFlag, v); });
+ args = args.concat(Cpp.collectDefinesArguments(input));
+ args = args.concat(Cpp.collectIncludePathsArguments(input));
+ args = args.concat(Cpp.collectSystemIncludePathsArguments(input));
var minimumWindowsVersion = input.cpp.minimumWindowsVersion;
- if (minimumWindowsVersion && product.qbs.targetOS.contains("windows")) {
+ if (minimumWindowsVersion && product.qbs.targetOS.includes("windows")) {
var hexVersion = WindowsUtils.getWindowsVersionInFormat(minimumWindowsVersion, 'hex');
if (hexVersion) {
var versionDefs = [ 'WINVER', '_WIN32_WINNT', '_WIN32_WINDOWS' ];
for (i in versionDefs)
- args.push('-D' + versionDefs[i] + '=' + hexVersion);
+ args.push(input.cpp.defineFlag + versionDefs[i] + '=' + hexVersion);
}
}
@@ -914,11 +906,11 @@ function compilerFlags(project, product, input, output, explicitlyDependsOn) {
switch (tag) {
case "c":
case "objc":
- var knownValues = ["c11", "c99", "c90", "c89"];
+ var knownValues = ["c2x", "c17", "c11", "c99", "c90", "c89"];
return Cpp.languageVersion(input.cpp.cLanguageVersion, knownValues, "C");
case "cpp":
case "objcpp":
- knownValues = ["c++20", "c++2a", "c++17", "c++1z",
+ knownValues = ["c++23", "c++2b", "c++20", "c++2a", "c++17", "c++1z",
"c++14", "c++1y", "c++11", "c++0x",
"c++03", "c++98"];
return Cpp.languageVersion(input.cpp.cxxLanguageVersion, knownValues, "C++");
@@ -935,7 +927,7 @@ function compilerFlags(project, product, input, output, explicitlyDependsOn) {
if (tag === "cpp" || tag === "objcpp") {
var cxxStandardLibrary = product.cpp.cxxStandardLibrary;
- if (cxxStandardLibrary && product.qbs.toolchain.contains("clang")) {
+ if (cxxStandardLibrary && product.qbs.toolchain.includes("clang")) {
args.push("-stdlib=" + cxxStandardLibrary);
}
}
@@ -950,7 +942,7 @@ function additionalCompilerAndLinkerFlags(product) {
var args = []
var requireAppExtensionSafeApi = product.cpp.requireAppExtensionSafeApi;
- if (requireAppExtensionSafeApi !== undefined && product.qbs.targetOS.contains("darwin")) {
+ if (requireAppExtensionSafeApi !== undefined && product.qbs.targetOS.includes("darwin")) {
args.push(requireAppExtensionSafeApi ? "-fapplication-extension" : "-fno-application-extension");
}
@@ -976,10 +968,6 @@ function languageName(fileTag) {
function prepareAssembler(project, product, inputs, outputs, input, output) {
var assemblerPath = product.cpp.assemblerPath;
- var includePaths = input.cpp.includePaths;
- var systemIncludePaths = input.cpp.systemIncludePaths;
- var distributionIncludePaths = input.cpp.distributionIncludePaths;
-
var args = product.cpp.targetAssemblerFlags;
if (input.cpp.debugInformation)
@@ -989,18 +977,9 @@ function prepareAssembler(project, product, inputs, outputs, input, output) {
if (warnings === 'none')
args.push('-W');
- var tag = "asm";
- args = args.concat(ModUtils.moduleProperty(input, 'platformFlags', tag),
- ModUtils.moduleProperty(input, 'flags', tag));
-
- var allIncludePaths = [];
- if (includePaths)
- allIncludePaths = allIncludePaths.uniqueConcat(includePaths);
- if (systemIncludePaths)
- allIncludePaths = allIncludePaths.uniqueConcat(systemIncludePaths);
- if (distributionIncludePaths)
- allIncludePaths = allIncludePaths.uniqueConcat(distributionIncludePaths);
- args = args.concat(allIncludePaths.map(function(path) { return input.cpp.includeFlag + path }));
+ args = args.concat(Cpp.collectMiscAssemblerArguments(input, "asm"));
+ args = args.concat(Cpp.collectIncludePathsArguments(input));
+ args = args.concat(Cpp.collectSystemIncludePathsArguments(input, input.cpp.includeFlag));
args.push("-o", output.filePath);
args.push(input.filePath);
@@ -1014,7 +993,7 @@ function prepareAssembler(project, product, inputs, outputs, input, output) {
function compilerEnvVars(config, compilerInfo)
{
- if (config.qbs.toolchain.contains("qcc"))
+ if (config.qbs.toolchain.includes("qcc"))
return ["QCC_CONF_PATH"];
var list = ["CPATH", "TMPDIR"];
@@ -1026,15 +1005,15 @@ function compilerEnvVars(config, compilerInfo)
list.push("OBJC_INCLUDE_PATH");
else if (compilerInfo.tag === "objccpp")
list.push("OBJCPLUS_INCLUDE_PATH");
- if (config.qbs.targetOS.contains("macos"))
+ if (config.qbs.targetOS.includes("macos"))
list.push("MACOSX_DEPLOYMENT_TARGET");
- else if (config.qbs.targetOS.contains("ios"))
+ else if (config.qbs.targetOS.includes("ios"))
list.push("IPHONEOS_DEPLOYMENT_TARGET");
- else if (config.qbs.targetOS.contains("tvos"))
+ else if (config.qbs.targetOS.includes("tvos"))
list.push("TVOS_DEPLOYMENT_TARGET");
- else if (config.qbs.targetOS.contains("watchos"))
+ else if (config.qbs.targetOS.includes("watchos"))
list.push("WATCHOS_DEPLOYMENT_TARGET");
- if (config.qbs.toolchain.contains("clang")) {
+ if (config.qbs.toolchain.includes("clang")) {
list.push("TEMP", "TMP");
} else {
list.push("LANG", "LC_CTYPE", "LC_MESSAGES", "LC_ALL", "GCC_COMPARE_DEBUG",
@@ -1045,7 +1024,7 @@ function compilerEnvVars(config, compilerInfo)
function linkerEnvVars(config, inputs)
{
- if (config.qbs.toolchain.contains("clang") || config.qbs.toolchain.contains("qcc"))
+ if (config.qbs.toolchain.includes("clang") || config.qbs.toolchain.includes("qcc"))
return [];
var list = ["GNUTARGET", "LDEMULATION", "COLLECT_NO_DEMANGLE"];
if (useCompilerDriverLinker(config, inputs))
@@ -1055,7 +1034,7 @@ function linkerEnvVars(config, inputs)
function setResponseFileThreshold(command, product)
{
- if (product.qbs.targetOS.contains("windows") && product.qbs.hostOS.contains("windows"))
+ if (product.qbs.targetOS.includes("windows") && Host.os().includes("windows"))
command.responseFileThreshold = 10000;
}
@@ -1063,7 +1042,7 @@ function prepareCompiler(project, product, inputs, outputs, input, output, expli
var compilerInfo = effectiveCompilerInfo(product.qbs.toolchain,
input, output);
var compilerPath = compilerInfo.path;
- var pchOutput = output.fileTags.contains(compilerInfo.tag + "_pch");
+ var pchOutput = output.fileTags.includes(compilerInfo.tag + "_pch");
var args = compilerFlags(project, product, input, output, explicitlyDependsOn);
var wrapperArgsLength = 0;
@@ -1153,7 +1132,7 @@ function getSymbolInfo(product, inputFile)
// construct the list of defined symbols by subtracting.
var undefinedGlobalSymbols = collectStdoutLines(command, args.concat(["-u", inputFile]));
result.definedGlobalSymbols = result.allGlobalSymbols.filter(function(line) {
- return !undefinedGlobalSymbols.contains(line); });
+ return !undefinedGlobalSymbols.includes(line); });
result.success = true;
} catch (e) {
console.debug("Failed to collect symbols for shared library: nm command '"
@@ -1253,8 +1232,13 @@ function createSymbolCheckingCommands(product, outputs) {
oldSymbols = oldNmResult.allGlobalSymbols;
newSymbols = newNmResult.allGlobalSymbols;
} else {
- oldSymbols = oldNmResult.definedGlobalSymbols;
- newSymbols = newNmResult.definedGlobalSymbols;
+ var weakFilter = function(line) {
+ var symbolType = line.split(/\s+/)[1];
+ return symbolType != "v" && symbolType != "V"
+ && symbolType != "w" && symbolType != "W";
+ };
+ oldSymbols = oldNmResult.definedGlobalSymbols.filter(weakFilter);
+ newSymbols = newNmResult.definedGlobalSymbols.filter(weakFilter);
}
if (oldSymbols.length !== newSymbols.length) {
console.debug("List of relevant symbols differs for '" + libFilePath + "'.");
@@ -1281,6 +1265,59 @@ function createSymbolCheckingCommands(product, outputs) {
return commands;
}
+function separateDebugInfoCommands(product, outputs, primaryOutput) {
+ var commands = [];
+
+ var debugInfo = outputs.debuginfo_app || outputs.debuginfo_dll
+ || outputs.debuginfo_loadablemodule;
+
+ if (debugInfo) {
+ var objcopy = product.cpp.objcopyPath;
+
+ var cmd = new Command(objcopy, ["--only-keep-debug", primaryOutput.filePath,
+ debugInfo[0].filePath]);
+ cmd.silent = true;
+ commands.push(cmd);
+
+ cmd = new Command(objcopy, ["--strip-debug", primaryOutput.filePath]);
+ cmd.silent = true;
+ commands.push(cmd);
+
+ cmd = new Command(objcopy, ["--add-gnu-debuglink=" + debugInfo[0].filePath,
+ primaryOutput.filePath]);
+ cmd.silent = true;
+ commands.push(cmd);
+ }
+
+ return commands;
+}
+
+function separateDebugInfoCommandsDarwin(product, outputs, primaryOutputs) {
+ var commands = [];
+
+ var debugInfo = outputs.debuginfo_app || outputs.debuginfo_dll
+ || outputs.debuginfo_loadablemodule;
+ if (debugInfo) {
+ var dsymPath = debugInfo[0].filePath;
+ if (outputs.debuginfo_bundle && outputs.debuginfo_bundle[0])
+ dsymPath = outputs.debuginfo_bundle[0].filePath;
+
+ var flags = product.cpp.dsymutilFlags || [];
+ var files = primaryOutputs.map(function (f) { return f.filePath; });
+ var cmd = new Command(product.cpp.dsymutilPath,
+ flags.concat(["-o", dsymPath].concat(files)));
+ cmd.description = "generating dSYM for " + product.name;
+ commands.push(cmd);
+
+ // strip debug info
+ cmd = new Command(product.cpp.stripPath, ["-S"].concat(files));
+ cmd.silent = true;
+ commands.push(cmd);
+ }
+
+ return commands;
+}
+
function prepareLinker(project, product, inputs, outputs, input, output) {
var i, primaryOutput, cmd, commands = [];
@@ -1307,7 +1344,7 @@ function prepareLinker(project, product, inputs, outputs, input, output) {
var responseFileArgumentIndex = wrapperArgsLength;
// qcc doesn't properly handle response files, so we have to do it manually
- var useQnxResponseFileHack = product.qbs.toolchain.contains("qcc")
+ var useQnxResponseFileHack = product.qbs.toolchain.includes("qcc")
&& useCompilerDriverLinker(product, inputs);
if (useQnxResponseFileHack) {
// qcc needs to see at least one object/library file to think it has something to do,
@@ -1327,43 +1364,13 @@ function prepareLinker(project, product, inputs, outputs, input, output) {
setResponseFileThreshold(cmd, product);
commands.push(cmd);
- var debugInfo = outputs.debuginfo_app || outputs.debuginfo_dll
- || outputs.debuginfo_loadablemodule;
- if (debugInfo) {
- if (product.qbs.targetOS.contains("darwin")) {
- if (!product.aggregate) {
- var dsymPath = debugInfo[0].filePath;
- if (outputs.debuginfo_bundle && outputs.debuginfo_bundle[0])
- dsymPath = outputs.debuginfo_bundle[0].filePath;
- var flags = product.cpp.dsymutilFlags || [];
- cmd = new Command(product.cpp.dsymutilPath, flags.concat([
- "-o", dsymPath, primaryOutput.filePath
- ]));
- cmd.description = "generating dSYM for " + product.name;
- commands.push(cmd);
-
- cmd = new Command(product.cpp.stripPath,
- ["-S", primaryOutput.filePath]);
- cmd.silent = true;
- commands.push(cmd);
- }
- } else {
- var objcopy = product.cpp.objcopyPath;
-
- cmd = new Command(objcopy, ["--only-keep-debug", primaryOutput.filePath,
- debugInfo[0].filePath]);
- cmd.silent = true;
- commands.push(cmd);
-
- cmd = new Command(objcopy, ["--strip-debug", primaryOutput.filePath]);
- cmd.silent = true;
- commands.push(cmd);
-
- cmd = new Command(objcopy, ["--add-gnu-debuglink=" + debugInfo[0].filePath,
- primaryOutput.filePath]);
- cmd.silent = true;
- commands.push(cmd);
+ if (product.qbs.targetOS.includes("darwin")) {
+ if (!product.aggregate) {
+ commands = commands.concat(separateDebugInfoCommandsDarwin(
+ product, outputs, [primaryOutput]));
}
+ } else {
+ commands = commands.concat(separateDebugInfoCommands(product, outputs, primaryOutput));
}
if (outputs.dynamiclibrary) {
@@ -1383,27 +1390,9 @@ function prepareLinker(project, product, inputs, outputs, input, output) {
}
}
- if (product.xcode && product.bundle) {
- var actualSigningIdentity = product.xcode.actualSigningIdentity;
- var codesignDisplayName = product.xcode.actualSigningIdentityDisplayName;
- if (actualSigningIdentity && !product.bundle.isBundle) {
- args = product.xcode.codesignFlags || [];
- args.push("--force");
- args.push("--sign", actualSigningIdentity);
- args = args.concat(DarwinTools._codeSignTimestampFlags(product));
-
- for (var j in inputs.xcent) {
- args.push("--entitlements", inputs.xcent[j].filePath);
- break; // there should only be one
- }
- args.push(primaryOutput.filePath);
- cmd = new Command(product.xcode.codesignPath, args);
- cmd.description = "codesign "
- + primaryOutput.fileName
- + " using " + codesignDisplayName
- + " (" + actualSigningIdentity + ")";
- commands.push(cmd);
- }
+ if (product.cpp.shouldSignArtifacts) {
+ Array.prototype.push.apply(
+ commands, Codesign.prepareSign(project, product, inputs, outputs, input, output));
}
return commands;
@@ -1462,12 +1451,7 @@ function dumpMacros(env, compilerFilePath, args, nullDevice, tag) {
p.exec(compilerFilePath,
(args || []).concat(["-Wp,-dM", "-E", "-x", languageName(tag || "c") , nullDevice]),
true);
- var map = {};
- p.readStdOut().trim().split(/\r?\n/g).map(function (line) {
- var parts = line.split(" ", 3);
- map[parts[1]] = parts[2];
- });
- return map;
+ return Cpp.extractMacros(p.readStdOut());
} finally {
p.close();
}
@@ -1514,7 +1498,7 @@ function dumpDefaultPaths(env, compilerFilePath, args, nullDevice, pathListSepar
if (libraryPaths.length === 0)
libraryPaths.push(sysroot + "/lib", sysroot + "/usr/lib");
- if (frameworkPaths.length === 0 && targetOS.contains("darwin"))
+ if (frameworkPaths.length === 0 && targetOS.includes("darwin"))
frameworkPaths.push(sysroot + "/System/Library/Frameworks");
return {
@@ -1527,6 +1511,28 @@ function dumpDefaultPaths(env, compilerFilePath, args, nullDevice, pathListSepar
}
}
+function targetLinkerFlags(targetArch, targetOS) {
+ var linkerFlags = {
+ "windows": {
+ "i386": "i386pe",
+ "x86_64": "i386pep",
+ },
+ "freebsd": {
+ "i386": "elf_i386_fbsd",
+ "x86_64": "elf_x86_64_fbsd",
+ },
+ "other": {
+ "i386": "elf_i386",
+ "x86_64": "elf_x86_64",
+ }
+ };
+ if (targetOS.includes("windows"))
+ return linkerFlags["windows"][targetArch];
+ else if (targetOS.includes("freebsd"))
+ return linkerFlags["freebsd"][targetArch];
+ return linkerFlags["other"][targetArch];
+}
+
function targetFlags(tool, hasTargetOption, target, targetArch, machineType, targetOS) {
var args = [];
if (hasTargetOption) {
@@ -1539,8 +1545,8 @@ function targetFlags(tool, hasTargetOption, target, targetArch, machineType, tar
"x86_64": ["-m64"],
},
"linker": {
- "i386": ["-m", targetOS.contains("windows") ? "i386pe" : "elf_i386"],
- "x86_64": ["-m", targetOS.contains("windows") ? "i386pep" : "elf_x86_64"],
+ "i386": ["-m", targetLinkerFlags("i386", targetOS)],
+ "x86_64": ["-m", targetLinkerFlags("x86_64", targetOS)],
},
"assembler": {
"i386": ["--32"],
diff --git a/share/qbs/modules/cpp/iar.js b/share/qbs/modules/cpp/iar.js
index d51668095..ed58ac262 100644
--- a/share/qbs/modules/cpp/iar.js
+++ b/share/qbs/modules/cpp/iar.js
@@ -37,155 +37,342 @@ var Process = require("qbs.Process");
var TemporaryDir = require("qbs.TemporaryDir");
var TextFile = require("qbs.TextFile");
-function compilerName(qbs) {
- switch (qbs.architecture) {
- case "arm":
- return "iccarm";
- case "mcs51":
- return "icc8051";
- case "avr":
- return "iccavr";
- case "stm8":
- return "iccstm8";
- case "msp430":
- return "icc430";
- case "rl78":
- return "iccrl78";
- }
- throw "Unable to deduce compiler name for unsupported architecture: '"
- + qbs.architecture + "'";
+function supportXLinker(architecture) {
+ return architecture === "78k"
+ || architecture === "avr"
+ || architecture === "avr32"
+ || architecture === "cr16"
+ || architecture === "hcs12"
+ || architecture === "hcs8"
+ || architecture === "m16c"
+ || architecture === "m32c"
+ || architecture === "m68k"
+ || architecture === "mcs51"
+ || architecture === "msp430"
+ || architecture === "r32c"
+ || architecture === "v850";
}
-function assemblerName(qbs) {
- switch (qbs.architecture) {
- case "arm":
- return "iasmarm";
- case "rl78":
- return "iasmrl78";
- case "mcs51":
- return "a8051";
- case "avr":
- return "aavr";
- case "stm8":
- return "iasmstm8";
- case "msp430":
- return "a430";
- }
- throw "Unable to deduce assembler name for unsupported architecture: '"
- + qbs.architecture + "'";
+function supportILinker(architecture) {
+ return architecture.startsWith("arm")
+ || architecture === "rh850"
+ || architecture === "riscv"
+ || architecture === "rl78"
+ || architecture === "rx"
+ || architecture === "sh"
+ || architecture === "stm8";
}
-function linkerName(qbs) {
- switch (qbs.architecture) {
- case "arm":
- return "ilinkarm";
- case "stm8":
- return "ilinkstm8";
- case "rl78":
- return "ilinkrl78";
- case "mcs51":
- case "avr":
- case "msp430":
- return "xlink";
- }
- throw "Unable to deduce linker name for unsupported architecture: '"
- + qbs.architecture + "'";
+function supportXArchiver(architecture) {
+ return architecture === "78k"
+ || architecture === "avr"
+ || architecture === "avr32"
+ || architecture === "cr16"
+ || architecture === "hcs12"
+ || architecture === "hcs8"
+ || architecture === "m16c"
+ || architecture === "m32c"
+ || architecture === "m68k"
+ || architecture === "mcs51"
+ || architecture === "msp430"
+ || architecture === "r32c"
+ || architecture === "v850";
}
-function archiverName(qbs) {
- switch (qbs.architecture) {
- case "arm":
- case "stm8":
- case "rl78":
- return "iarchive";
- case "mcs51":
- case "avr":
- case "msp430":
- return "xlib";
- }
- throw "Unable to deduce archiver name for unsupported architecture: '"
- + qbs.architecture + "'";
+function supportIArchiver(architecture) {
+ return architecture.startsWith("arm")
+ || architecture === "rh850"
+ || architecture === "riscv"
+ || architecture === "rl78"
+ || architecture === "rx"
+ || architecture === "sh"
+ || architecture === "stm8";
}
-function staticLibrarySuffix(qbs) {
- switch (qbs.architecture) {
- case "arm":
- case "stm8":
- case "rl78":
- return ".a";
- case "mcs51":
- return ".r51";
- case "avr":
- return ".r90";
- case "msp430":
- return ".r43";
- }
- throw "Unable to deduce static library suffix for unsupported architecture: '"
- + qbs.architecture + "'";
+function supportXAssembler(architecture) {
+ return architecture.startsWith("arm")
+ || architecture === "78k"
+ || architecture === "avr"
+ || architecture === "hcs12"
+ || architecture === "m16c"
+ || architecture === "mcs51"
+ || architecture === "msp430"
+ || architecture === "m32c"
+ || architecture === "v850";
}
-function executableSuffix(qbs) {
- switch (qbs.architecture) {
- case "arm":
- case "stm8":
- case "rl78":
- return ".out";
- case "mcs51":
- return qbs.debugInformation ? ".d51" : ".a51";
- case "avr":
- return qbs.debugInformation ? ".d90" : ".a90";
- case "msp430":
- return qbs.debugInformation ? ".d43" : ".a43";
- }
- throw "Unable to deduce executable suffix for unsupported architecture: '"
- + qbs.architecture + "'";
+function supportIAssembler(architecture) {
+ return architecture === "avr32"
+ || architecture === "cr16"
+ || architecture === "hcs8"
+ || architecture === "r32c"
+ || architecture === "rh850"
+ || architecture === "riscv"
+ || architecture === "rl78"
+ || architecture === "rx"
+ || architecture === "sh"
+ || architecture === "stm8"
+ || architecture === "m68k";
}
-function objectSuffix(qbs) {
- switch (qbs.architecture) {
- case "arm":
- case "stm8":
- case "rl78":
- return ".o";
- case "mcs51":
- return ".r51";
+function supportEndianness(architecture) {
+ return architecture.startsWith("arm")
+ || architecture === "rx";
+}
+
+function supportCppExceptions(architecture) {
+ return architecture.startsWith("arm")
+ || architecture === "rh850"
+ || architecture === "riscv"
+ || architecture === "rl78"
+ || architecture === "rx";
+}
+
+function supportCppRtti(architecture) {
+ return architecture.startsWith("arm")
+ || architecture === "rh850"
+ || architecture === "riscv"
+ || architecture === "rl78"
+ || architecture === "rx";
+}
+
+function supportCppWarningAboutCStyleCast(architecture) {
+ return architecture.startsWith("arm")
+ || architecture === "avr"
+ || architecture === "avr32"
+ || architecture === "cr16"
+ || architecture === "mcs51"
+ || architecture === "msp430"
+ || architecture === "rh850"
+ || architecture === "rl78"
+ || architecture === "rx"
+ || architecture === "stm8"
+ || architecture === "v850";
+}
+
+function supportDeprecatedFeatureWarnings(architecture) {
+ return architecture.startsWith("arm")
+ || architecture === "avr"
+ || architecture === "cr16"
+ || architecture === "mcs51"
+ || architecture === "msp430"
+ || architecture === "rh850"
+ || architecture === "rl78"
+ || architecture === "rx"
+ || architecture === "stm8"
+ || architecture === "v850";
+}
+
+function supportCLanguageVersion(architecture) {
+ return architecture !== "78k";
+}
+
+function supportCppLanguage(compilerFilePath) {
+ var baseName = FileInfo.baseName(compilerFilePath);
+ return baseName !== "iccs08";
+}
+
+// It is a 'magic' IAR-specific target architecture code.
+function architectureCode(architecture) {
+ switch (architecture) {
+ case "78k":
+ return "26";
case "avr":
- return ".r90";
+ return "90";
+ case "avr32":
+ return "82";
+ case "mcs51":
+ return "51";
case "msp430":
- return ".r43";
+ return "43";
+ case "v850":
+ return "85";
+ case "m68k":
+ return "68";
+ case "m32c":
+ return "48";
+ case "r32c":
+ return "53";
+ case "m16c":
+ return "34";
+ case "cr16":
+ return "45";
+ case "hcs12":
+ return "12";
+ case "hcs8":
+ return "78";
+ case "rh850": case "riscv": case "rl78": case "rx": case "sh": case "stm8":
+ return "";
+ default:
+ if (architecture.startsWith("arm"))
+ return "";
+ break;
}
- throw "Unable to deduce object file suffix for unsupported architecture: '"
- + qbs.architecture + "'";
}
-function imageFormat(qbs) {
- switch (qbs.architecture) {
- case "arm":
- case "stm8":
- case "rl78":
- return "elf";
- case "mcs51":
- case "avr":
- case "msp430":
- return "ubrof";
+function toolchainDetails(qbs) {
+ var architecture = qbs.architecture;
+ var code = architectureCode(architecture);
+ var details = {};
+
+ if (supportXLinker(architecture)) {
+ details.libraryPathFlag = "-I";
+ details.linkerScriptFlag = "-f";
+ details.linkerName = "xlink";
+ details.linkerSilentFlag = "-S";
+ details.linkerMapFileFlag = "-l";
+ details.linkerEntryPointFlag = "-s";
+ } else if (supportILinker(architecture)) {
+ details.libraryPathFlag = "-L";
+ details.linkerScriptFlag = "--config";
+ details.linkerSilentFlag = "--silent";
+ details.linkerMapFileFlag = "--map";
+ details.linkerEntryPointFlag = "--entry";
+ details.linkerName = architecture.startsWith("arm")
+ ? "ilinkarm" : ("ilink" + architecture);
+ }
+
+ if (supportXArchiver(architecture))
+ details.archiverName = "xar";
+ else if (supportIArchiver(architecture))
+ details.archiverName = "iarchive";
+
+ var hasCode = (code !== "");
+ details.staticLibrarySuffix = hasCode ? (".r" + code) : ".a";
+ details.executableSuffix = hasCode
+ ? ((qbs.debugInformation) ? (".d" + code) : (".a" + code)) : ".out";
+ details.objectSuffix = hasCode ? (".r" + code) : ".o";
+ details.imageFormat = hasCode ? "ubrof" : "elf";
+
+ if (architecture.startsWith("arm")) {
+ details.compilerName = "iccarm";
+ details.assemblerName = "iasmarm";
+ } else if (architecture === "78k") {
+ details.compilerName = "icc78k";
+ details.assemblerName = "a78k";
+ } else if (architecture === "avr") {
+ details.compilerName = "iccavr";
+ details.assemblerName = "aavr";
+ } else if (architecture === "avr32") {
+ details.compilerName = "iccavr32";
+ details.assemblerName = "aavr32";
+ } else if (architecture === "cr16") {
+ details.compilerName = "icccr16c";
+ details.assemblerName = "acr16c";
+ } else if (architecture === "hcs12") {
+ details.compilerName = "icchcs12";
+ details.assemblerName = "ahcs12";
+ } else if (architecture === "hcs8") {
+ details.compilerName = "iccs08";
+ details.assemblerName = "as08";
+ } else if (architecture === "m16c") {
+ details.compilerName = "iccm16c";
+ details.assemblerName = "am16c";
+ } else if (architecture === "m32c") {
+ details.compilerName = "iccm32c";
+ details.assemblerName = "am32c";
+ } else if (architecture === "m68k") {
+ details.compilerName = "icccf";
+ details.assemblerName = "acf";
+ } else if (architecture === "mcs51") {
+ details.compilerName = "icc8051";
+ details.assemblerName = "a8051";
+ } else if (architecture === "msp430") {
+ details.compilerName = "icc430";
+ details.assemblerName = "a430";
+ } else if (architecture === "r32c") {
+ details.compilerName = "iccr32c";
+ details.assemblerName = "ar32c";
+ } else if (architecture === "rh850") {
+ details.compilerName = "iccrh850";
+ details.assemblerName = "iasmrh850";
+ } else if (architecture === "riscv") {
+ details.compilerName = "iccriscv";
+ details.assemblerName = "iasmriscv";
+ } else if (architecture === "rl78") {
+ details.compilerName = "iccrl78";
+ details.assemblerName = "iasmrl78";
+ } else if (architecture === "rx") {
+ details.compilerName = "iccrx";
+ details.assemblerName = "iasmrx";
+ } else if (architecture === "sh") {
+ details.compilerName = "iccsh";
+ details.assemblerName = "iasmsh";
+ } else if (architecture === "stm8") {
+ details.compilerName = "iccstm8";
+ details.assemblerName = "iasmstm8";
+ } else if (architecture === "v850") {
+ details.compilerName = "iccv850";
+ details.assemblerName = "av850";
}
- throw "Unable to deduce image format for unsupported architecture: '"
- + qbs.architecture + "'";
+
+ return details;
+}
+
+function guessArmArchitecture(core) {
+ var arch = "arm";
+ if (core === "__ARM4M__")
+ arch += "v4m";
+ else if (core === "__ARM4TM__")
+ arch += "v4tm";
+ else if (core === "__ARM5E__")
+ arch += "v5e";
+ else if (core === "__ARM5__")
+ arch += "v5";
+ else if (core === "__ARM6M__")
+ arch += "v6m";
+ else if (core === "__ARM6SM__")
+ arch += "v6sm";
+ else if (core === "__ARM6__")
+ arch += "v6";
+ else if (core === "__ARM7M__")
+ arch += "v7m";
+ else if (core === "__ARM7R__")
+ arch += "v7r";
+ return arch;
}
function guessArchitecture(macros) {
- if (macros["__ICCARM__"] === "1")
- return "arm";
+ if (macros["__ICC430__"] === "1")
+ return "msp430";
+ else if (macros["__ICC78K__"] === "1")
+ return "78k";
else if (macros["__ICC8051__"] === "1")
return "mcs51";
+ else if (macros["__ICCARM__"] === "1")
+ return guessArmArchitecture(macros["__CORE__"]);
+ else if (macros["__ICCAVR32__"] === "1")
+ return "avr32";
else if (macros["__ICCAVR__"] === "1")
return "avr";
- else if (macros["__ICCSTM8__"] === "1")
- return "stm8";
- else if (macros["__ICC430__"] === "1")
- return "msp430";
+ else if (macros["__ICCCF__"] === "1")
+ return "m68k";
+ else if (macros["__ICCCR16C__"] === "1")
+ return "cr16";
+ else if (macros["__ICCHCS12__"] === "1")
+ return "hcs12";
+ else if (macros["__ICCM16C__"] === "1")
+ return "m16c";
+ else if (macros["__ICCM32C__"] === "1")
+ return "m32c";
+ else if (macros["__ICCR32C__"] === "1")
+ return "r32c";
+ else if (macros["__ICCRH850__"] === "1")
+ return "rh850";
+ else if (macros["__ICCRISCV__"] === "1")
+ return "riscv";
else if (macros["__ICCRL78__"] === "1")
return "rl78";
+ else if (macros["__ICCRX__"] === "1")
+ return "rx";
+ else if (macros["__ICCS08__"] === "1")
+ return "hcs8";
+ else if (macros["__ICCSH__"] === "1")
+ return "sh";
+ else if (macros["__ICCSTM8__"] === "1")
+ return "stm8";
+ else if (macros["__ICCV850__"] === "1")
+ return "v850";
}
function guessEndianness(macros) {
@@ -194,24 +381,34 @@ function guessEndianness(macros) {
return "big"
}
-function guessVersion(macros, architecture)
-{
+function guessVersion(macros, architecture) {
var version = parseInt(macros["__VER__"], 10);
- switch (architecture) {
- case "arm":
+ if (architecture.startsWith("arm")) {
return { major: parseInt(version / 1000000),
minor: parseInt(version / 1000) % 1000,
- patch: parseInt(version) % 1000,
- found: true }
- case "mcs51":
- case "avr":
- case "stm8":
- case "msp430":
- case "rl78":
+ patch: parseInt(version) % 1000 }
+ } else if (architecture === "78k"
+ || architecture === "avr"
+ || architecture === "avr32"
+ || architecture === "cr16"
+ || architecture === "hcs12"
+ || architecture === "hcs8"
+ || architecture === "m16c"
+ || architecture === "m32c"
+ || architecture === "m68k"
+ || architecture === "mcs51"
+ || architecture === "msp430"
+ || architecture === "r32c"
+ || architecture === "rh850"
+ || architecture === "riscv"
+ || architecture === "rl78"
+ || architecture === "rx"
+ || architecture === "sh"
+ || architecture === "stm8"
+ || architecture === "v850") {
return { major: parseInt(version / 100),
minor: parseInt(version % 100),
- patch: 0,
- found: true }
+ patch: 0 }
}
}
@@ -219,16 +416,27 @@ function cppLanguageOption(compilerFilePath) {
var baseName = FileInfo.baseName(compilerFilePath);
switch (baseName) {
case "iccarm":
- case "rl78":
+ case "iccrh850":
+ case "iccriscv":
+ case "iccrl78":
+ case "iccrx":
return "--c++";
+ case "icc430":
+ case "icc78k":
case "icc8051":
case "iccavr":
+ case "iccavr32":
+ case "icccf":
+ case "icccr16c":
+ case "icchcs12":
+ case "iccm16c":
+ case "iccm32c":
+ case "iccr32c":
+ case "iccsh":
case "iccstm8":
- case "icc430":
+ case "iccv850":
return "--ec++";
}
- throw "Unable to deduce C++ language option for unsupported compiler: '"
- + FileInfo.toNativeSeparators(compilerFilePath) + "'";
}
function dumpMacros(compilerFilePath, tag) {
@@ -238,169 +446,65 @@ function dumpMacros(compilerFilePath, tag) {
var outFilePath = FileInfo.fromNativeSeparators(tempDir.path() + "/iar-macros.predef");
var args = [ inFilePath, "--predef_macros", outFilePath ];
- if (tag && tag === "cpp")
+ if (tag === "cpp" && supportCppLanguage(compilerFilePath))
args.push(cppLanguageOption(compilerFilePath));
var p = new Process();
+ p.setWorkingDirectory(tempDir.path());
p.exec(compilerFilePath, args, true);
var outFile = new TextFile(outFilePath, TextFile.ReadOnly);
- var map = {};
- outFile.readAll().trim().split(/\r?\n/g).map(function (line) {
- var parts = line.split(" ", 3);
- map[parts[1]] = parts[2];
- });
- return map;
+ return Cpp.extractMacros(outFile.readAll());
}
-function dumpDefaultPaths(compilerFilePath, tag) {
+function dumpCompilerIncludePaths(compilerFilePath, tag) {
+ // We can dump the compiler include paths using the undocumented `--IDE3` flag,
+ // e.g. which also is used in the IAR extension for the VSCode. In this case the
+ // compiler procuces the console output in the following format:
+ // `$$TOOL_BEGIN $$VERSION "3" $$INC_BEGIN $$FILEPATH "<path\\to\\directory>" $$TOOL_END`
+
var tempDir = new TemporaryDir();
var inFilePath = FileInfo.fromNativeSeparators(tempDir.path() + "/empty-source.c");
var inFile = new TextFile(inFilePath, TextFile.WriteOnly);
- var args = [ inFilePath, "--preinclude", "." ];
- if (tag === "cpp")
+ var args = ["--IDE3", inFilePath];
+ if (tag === "cpp" && supportCppLanguage(compilerFilePath))
args.push(cppLanguageOption(compilerFilePath));
+ var includePaths = [];
var p = new Process();
- // This process should return an error, don't throw
- // an error in this case.
+ p.setWorkingDirectory(tempDir.path());
+ // It is possible that the process can return an error code in case the
+ // compiler does not support the `--IDE3` flag. So, don't throw an error in this case.
p.exec(compilerFilePath, args, false);
- var output = p.readStdErr();
-
- var includePaths = [];
- var pass = 0;
- for (var pos = 0; pos < output.length; ++pos) {
- var searchIndex = output.indexOf("searched:", pos);
- if (searchIndex === -1)
- break;
- var startQuoteIndex = output.indexOf('"', searchIndex + 1);
- if (startQuoteIndex === -1)
- break;
- var endQuoteIndex = output.indexOf('"', startQuoteIndex + 1);
- if (endQuoteIndex === -1)
- break;
- pos = endQuoteIndex + 1;
-
- // Ignore the first path as it is not a compiler include path.
- ++pass;
- if (pass === 1)
- continue;
-
- var parts = output.substring(startQuoteIndex + 1, endQuoteIndex).split("\n");
- var includePath = "";
- for (var i in parts)
- includePath += parts[i].trim();
-
- includePaths.push(includePath);
- }
-
- return {
- "includePaths": includePaths
- };
-}
-
-function collectLibraryDependencies(product) {
- var seen = {};
- var result = [];
-
- function addFilePath(filePath) {
- result.push({ filePath: filePath });
- }
-
- function addArtifactFilePaths(dep, artifacts) {
- if (!artifacts)
- return;
- var artifactFilePaths = artifacts.map(function(a) { return a.filePath; });
- artifactFilePaths.forEach(addFilePath);
- }
-
- function addExternalStaticLibs(obj) {
- if (!obj.cpp)
- return;
- function ensureArray(a) {
- return Array.isArray(a) ? a : [];
- }
- function sanitizedModuleListProperty(obj, moduleName, propertyName) {
- return ensureArray(ModUtils.sanitizedModuleProperty(obj, moduleName, propertyName));
- }
- var externalLibs = [].concat(
- sanitizedModuleListProperty(obj, "cpp", "staticLibraries"));
- var staticLibrarySuffix = obj.moduleProperty("cpp", "staticLibrarySuffix");
- externalLibs.forEach(function(staticLibraryName) {
- if (!staticLibraryName.endsWith(staticLibrarySuffix))
- staticLibraryName += staticLibrarySuffix;
- addFilePath(staticLibraryName);
- });
- }
-
- function traverse(dep) {
- if (seen.hasOwnProperty(dep.name))
- return;
- seen[dep.name] = true;
-
- if (dep.parameters.cpp && dep.parameters.cpp.link === false)
- return;
-
- var staticLibraryArtifacts = dep.artifacts["staticlibrary"];
- if (staticLibraryArtifacts) {
- dep.dependencies.forEach(traverse);
- addArtifactFilePaths(dep, staticLibraryArtifacts);
- addExternalStaticLibs(dep);
+ p.readStdOut().trim().split(/\r?\n/g).map(function(line) {
+ var m = line.match(/\$\$INC_BEGIN\s\$\$FILEPATH\s\"([^"]*)/);
+ if (m) {
+ var includePath = m[1].replace(/\\\\/g, '/');
+ if (includePath && File.exists(includePath))
+ includePaths.push(includePath);
}
- }
-
- product.dependencies.forEach(traverse);
- addExternalStaticLibs(product);
- return result;
-}
-
-function compilerOutputArtifacts(input, useListing) {
- var artifacts = [];
- artifacts.push({
- fileTags: ["obj"],
- filePath: Utilities.getHash(input.baseDir) + "/"
- + input.fileName + input.cpp.objectSuffix
});
- if (useListing) {
- artifacts.push({
- fileTags: ["lst"],
- filePath: Utilities.getHash(input.baseDir) + "/"
- + input.fileName + ".lst"
- });
+
+ if (includePaths.length === 0) {
+ // This can happen if the compiler does not support the `--IDE3` flag,
+ // e.g. IAR for S08 architecture. In this case we use fallback to the
+ // detection of the `inc` directory.
+ var includePath = FileInfo.joinPaths(FileInfo.path(compilerFilePath), "../inc/");
+ if (File.exists(includePath))
+ includePaths.push(includePath);
}
- return artifacts;
-}
-function applicationLinkerOutputArtifacts(product) {
- var app = {
- fileTags: ["application"],
- filePath: FileInfo.joinPaths(
- product.destinationDirectory,
- PathTools.applicationFilePath(product))
- };
- var mem_map = {
- fileTags: ["mem_map"],
- filePath: FileInfo.joinPaths(
- product.destinationDirectory,
- product.targetName + ".map")
- };
- return [app, mem_map]
+ return includePaths;
}
-function staticLibraryLinkerOutputArtifacts(product) {
- var staticLib = {
- fileTags: ["staticlibrary"],
- filePath: FileInfo.joinPaths(
- product.destinationDirectory,
- PathTools.staticLibraryFilePath(product))
+function dumpDefaultPaths(compilerFilePath, tag) {
+ var includePaths = dumpCompilerIncludePaths(compilerFilePath, tag);
+ return {
+ "includePaths": includePaths
};
- return [staticLib]
}
function compilerFlags(project, product, input, outputs, explicitlyDependsOn) {
- // Determine which C-language we're compiling.
- var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(outputs.obj[0].fileTags));
-
var args = [];
// Input.
@@ -409,28 +513,15 @@ function compilerFlags(project, product, input, outputs, explicitlyDependsOn) {
// Output.
args.push("-o", outputs.obj[0].filePath);
+ // Preinclude headers.
+ args = args.concat(Cpp.collectPreincludePathsArguments(input, true));
+
// Defines.
- var allDefines = [];
- var platformDefines = input.cpp.platformDefines;
- if (platformDefines)
- allDefines = allDefines.uniqueConcat(platformDefines);
- var defines = input.cpp.defines;
- if (defines)
- allDefines = allDefines.uniqueConcat(defines);
- args = args.concat(allDefines.map(function(define) { return "-D" + define }));
+ args = args.concat(Cpp.collectDefinesArguments(input));
// Includes.
- var allIncludePaths = [];
- var includePaths = input.cpp.includePaths;
- if (includePaths)
- allIncludePaths = allIncludePaths.uniqueConcat(includePaths);
- var systemIncludePaths = input.cpp.systemIncludePaths;
- if (systemIncludePaths)
- allIncludePaths = allIncludePaths.uniqueConcat(systemIncludePaths);
- var compilerIncludePaths = input.cpp.compilerIncludePaths;
- if (compilerIncludePaths)
- allIncludePaths = allIncludePaths.uniqueConcat(compilerIncludePaths);
- args = args.concat(allIncludePaths.map(function(include) { return "-I" + include }));
+ args = args.concat(Cpp.collectIncludePathsArguments(input));
+ args = args.concat(Cpp.collectSystemIncludePathsArguments(input));
// Silent output generation flag.
args.push("--silent");
@@ -442,35 +533,40 @@ function compilerFlags(project, product, input, outputs, explicitlyDependsOn) {
// Optimization flags.
switch (input.cpp.optimization) {
case "small":
- args.push("-Ohs");
+ args.push("-Ohz");
break;
case "fast":
- args.push("-Ohz");
+ args.push("-Ohs");
break;
case "none":
args.push("-On");
break;
}
+ var architecture = input.qbs.architecture;
+ var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(outputs.obj[0].fileTags));
+
// Warning level flags.
switch (input.cpp.warningLevel) {
case "none":
args.push("--no_warnings");
break;
case "all":
- args.push("--deprecated_feature_warnings="
- +"+attribute_syntax,"
- +"+preprocessor_extensions,"
- +"+segment_pragmas");
- if (tag === "cpp")
- args.push("--warn_about_c_style_casts");
+ if (supportDeprecatedFeatureWarnings(architecture)) {
+ args.push("--deprecated_feature_warnings="
+ +"+attribute_syntax,"
+ +"+preprocessor_extensions,"
+ +"+segment_pragmas");
+ }
+ if (tag === "cpp" && supportCppWarningAboutCStyleCast(architecture))
+ args.push("--warn_about_c_style_casts");
break;
}
if (input.cpp.treatWarningsAsErrors)
args.push("--warnings_are_errors");
// C language version flags.
- if (tag === "c") {
+ if (tag === "c" && supportCLanguageVersion(architecture)) {
var knownValues = ["c89"];
var cLanguageVersion = Cpp.languageVersion(
input.cpp.cLanguageVersion, knownValues, "C");
@@ -479,58 +575,46 @@ function compilerFlags(project, product, input, outputs, explicitlyDependsOn) {
args.push("--c89");
break;
default:
- // Default C language version is C11/C99 that
+ // Default C language version is C18/C11/C99 that
// depends on the IAR version.
break;
}
}
- // Architecture specific flags.
- switch (input.qbs.architecture) {
- case "arm":
- case "rl78":
- // Byte order flags.
- var endianness = input.cpp.endianness;
- if (endianness && input.qbs.architecture === "arm")
- args.push("--endian=" + endianness);
- if (tag === "cpp") {
- // Enable C++ language flags.
- args.push("--c++");
- // Exceptions flags.
- if (!input.cpp.enableExceptions)
- args.push("--no_exceptions");
- // RTTI flags.
- if (!input.cpp.enableRtti)
- args.push("--no_rtti");
- }
- break;
- case "stm8":
- case "mcs51":
- case "avr":
- case "msp430":
- // Enable C++ language flags.
- if (tag === "cpp")
- args.push("--ec++");
- break;
+ // C++ language version flags.
+ var compilerFilePath = input.cpp.compilerPath;
+ if (tag === "cpp" && supportCppLanguage(compilerFilePath)) {
+ // C++ language flag.
+ var cppOption = cppLanguageOption(compilerFilePath);
+ args.push(cppOption);
+
+ // Exceptions flag.
+ var enableExceptions = input.cpp.enableExceptions;
+ if (!enableExceptions && supportCppExceptions(architecture))
+ args.push("--no_exceptions");
+
+ // RTTI flag.
+ var enableRtti = input.cpp.enableRtti;
+ if (!enableRtti && supportCppRtti(architecture))
+ args.push("--no_rtti");
}
+ // Byte order flags.
+ var endianness = input.cpp.endianness;
+ if (endianness && supportEndianness(architecture))
+ args.push("--endian=" + endianness);
+
// Listing files generation flag.
- if (product.cpp.generateCompilerListingFiles)
+ if (input.cpp.generateCompilerListingFiles)
args.push("-l", outputs.lst[0].filePath);
// Misc flags.
- args = args.concat(ModUtils.moduleProperty(input, "platformFlags"),
- ModUtils.moduleProperty(input, "flags"),
- ModUtils.moduleProperty(input, "platformFlags", tag),
- ModUtils.moduleProperty(input, "flags", tag),
- ModUtils.moduleProperty(input, "driverFlags", tag));
+ args = args.concat(Cpp.collectMiscCompilerArguments(input, tag),
+ Cpp.collectMiscDriverArguments(product));
return args;
}
function assemblerFlags(project, product, input, outputs, explicitlyDependsOn) {
- // Determine which C-language we"re compiling
- var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(outputs.obj[0].fileTags));
-
var args = [];
// Input.
@@ -539,24 +623,23 @@ function assemblerFlags(project, product, input, outputs, explicitlyDependsOn) {
// Output.
args.push("-o", outputs.obj[0].filePath);
+ var architecture = input.qbs.architecture;
+
+ // The `--preinclude` flag is only supported for a certain
+ // set of assemblers, not for all.
+ if (supportIAssembler(architecture))
+ args = args.concat(Cpp.collectPreincludePathsArguments(input));
+
// Includes.
- var allIncludePaths = [];
- var systemIncludePaths = input.cpp.systemIncludePaths;
- if (systemIncludePaths)
- allIncludePaths = allIncludePaths.uniqueConcat(systemIncludePaths);
- var compilerIncludePaths = input.cpp.compilerIncludePaths;
- if (compilerIncludePaths)
- allIncludePaths = allIncludePaths.uniqueConcat(compilerIncludePaths);
- args = args.concat(allIncludePaths.map(function(include) { return "-I" + include }));
+ args = args.concat(Cpp.collectIncludePathsArguments(input));
+ args = args.concat(Cpp.collectSystemIncludePathsArguments(input));
// Debug information flags.
if (input.cpp.debugInformation)
args.push("-r");
// Architecture specific flags.
- switch (input.qbs.architecture) {
- case "stm8":
- case "rl78":
+ if (supportIAssembler(architecture)) {
// Silent output generation flag.
args.push("--silent");
// Warning level flags.
@@ -564,104 +647,79 @@ function assemblerFlags(project, product, input, outputs, explicitlyDependsOn) {
args.push("--no_warnings");
if (input.cpp.treatWarningsAsErrors)
args.push("--warnings_are_errors");
- break;
- default:
+ } else if (supportXAssembler(architecture)){
// Silent output generation flag.
args.push("-S");
// Warning level flags.
args.push("-w" + (input.cpp.warningLevel === "none" ? "-" : "+"));
- break;
}
+ // Byte order flags.
+ var endianness = input.cpp.endianness;
+ if (endianness && supportEndianness(architecture))
+ args.push("--endian", endianness);
+
// Listing files generation flag.
- if (product.cpp.generateAssemblerListingFiles)
+ if (input.cpp.generateAssemblerListingFiles)
args.push("-l", outputs.lst[0].filePath);
// Misc flags.
- args = args.concat(ModUtils.moduleProperty(input, "platformFlags", tag),
- ModUtils.moduleProperty(input, "flags", tag),
- ModUtils.moduleProperty(input, "driverFlags", tag));
+ args = args.concat(Cpp.collectMiscAssemblerArguments(input, "asm"));
return args;
}
-function linkerFlags(project, product, input, outputs) {
+function linkerFlags(project, product, inputs, outputs) {
var args = [];
// Inputs.
- if (inputs.obj)
- args = args.concat(inputs.obj.map(function(obj) { return obj.filePath }));
+ args = args.concat(Cpp.collectLinkerObjectPaths(inputs));
// Output.
args.push("-o", outputs.application[0].filePath);
// Library paths.
- var allLibraryPaths = [];
- var libraryPaths = product.cpp.libraryPaths;
- if (libraryPaths)
- allLibraryPaths = allLibraryPaths.uniqueConcat(libraryPaths);
- var distributionLibraryPaths = product.cpp.distributionLibraryPaths;
- if (distributionLibraryPaths)
- allLibraryPaths = allLibraryPaths.uniqueConcat(distributionLibraryPaths);
- args = args.concat(allLibraryPaths.map(function(path) { return '-L' + path }));
+ args = args.concat(Cpp.collectLibraryPathsArguments(product));
// Library dependencies.
- var libraryDependencies = collectLibraryDependencies(product);
- if (libraryDependencies)
- args = args.concat(libraryDependencies.map(function(dep) { return dep.filePath }));
+ args = args.concat(Cpp.collectLibraryDependenciesArguments(product));
// Linker scripts.
- var linkerScripts = inputs.linkerscript
- ? inputs.linkerscript.map(function(a) { return a.filePath; }) : [];
+ args = args.concat(Cpp.collectLinkerScriptPathsArguments(product, inputs, true));
- // Architecture specific flags.
- switch (product.qbs.architecture) {
- case "arm":
- case "stm8":
- case "rl78":
- // Silent output generation flag.
- args.push("--silent");
- // Map file generation flag.
- if (product.cpp.generateLinkerMapFile)
- args.push("--map", outputs.mem_map[0].filePath);
- // Entry point flag.
- if (product.cpp.entryPoint)
- args.push("--entry", product.cpp.entryPoint);
- // Linker scripts flags.
- linkerScripts.forEach(function(script) { args.push("--config", script); });
- break;
- case "mcs51":
- case "avr":
- case "msp430":
- // Silent output generation flag.
- args.push("-S");
- // Debug information flag.
+ // Silent output generation flag.
+ args.push(product.cpp.linkerSilentFlag);
+
+ // Map file generation flag.
+ if (product.cpp.generateLinkerMapFile)
+ args.push(product.cpp.linkerMapFileFlag, outputs.mem_map[0].filePath);
+
+ // Entry point flag.
+ if (product.cpp.entryPoint)
+ args.push(product.cpp.linkerEntryPointFlag, product.cpp.entryPoint);
+
+ // Debug information flag.
+ if (supportXLinker(product.qbs.architecture)) {
if (product.cpp.debugInformation)
args.push("-rt");
- // Map file generation flag.
- if (product.cpp.generateLinkerMapFile)
- args.push("-l", outputs.mem_map[0].filePath);
- // Entry point flag.
- if (product.cpp.entryPoint)
- args.push("-s", product.cpp.entryPoint);
- // Linker scripts flags.
- linkerScripts.forEach(function(script) { args.push("-f", script); });
- break;
}
// Misc flags.
- args = args.concat(ModUtils.moduleProperty(product, "driverLinkerFlags"));
+ args = args.concat(Cpp.collectMiscEscapableLinkerArguments(product),
+ Cpp.collectMiscLinkerArguments(product),
+ Cpp.collectMiscDriverArguments(product));
return args;
}
-function archiverFlags(project, product, input, outputs) {
+function archiverFlags(project, product, inputs, outputs) {
var args = [];
// Inputs.
- if (inputs.obj)
- args = args.concat(inputs.obj.map(function(obj) { return obj.filePath }));
+ args = args.concat(Cpp.collectLinkerObjectPaths(inputs));
// Output.
- args.push("--create");
+ var architecture = product.qbs.architecture;
+ if (supportIArchiver(architecture))
+ args.push("--create");
args.push("-o", outputs.staticlibrary[0].filePath);
return args;
@@ -673,6 +731,7 @@ function prepareCompiler(project, product, inputs, outputs, input, output, expli
var cmd = new Command(compilerPath, args);
cmd.description = "compiling " + input.fileName;
cmd.highlight = "compiler";
+ cmd.jobPool = "compiler";
return [cmd];
}
@@ -682,25 +741,28 @@ function prepareAssembler(project, product, inputs, outputs, input, output, expl
var cmd = new Command(assemblerPath, args);
cmd.description = "assembling " + input.fileName;
cmd.highlight = "compiler";
+ cmd.jobPool = "assembler";
return [cmd];
}
function prepareLinker(project, product, inputs, outputs, input, output) {
var primaryOutput = outputs.application[0];
- var args = linkerFlags(project, product, input, outputs);
+ var args = linkerFlags(project, product, inputs, outputs);
var linkerPath = product.cpp.linkerPath;
var cmd = new Command(linkerPath, args);
cmd.description = "linking " + primaryOutput.fileName;
cmd.highlight = "linker";
+ cmd.jobPool = "linker";
return [cmd];
}
function prepareArchiver(project, product, inputs, outputs, input, output) {
- var args = archiverFlags(project, product, input, outputs);
+ var args = archiverFlags(project, product, inputs, outputs);
var archiverPath = product.cpp.archiverPath;
var cmd = new Command(archiverPath, args);
- cmd.description = "linking " + output.fileName;
+ cmd.description = "creating " + output.fileName;
cmd.highlight = "linker";
+ cmd.jobPool = "linker";
cmd.stdoutFilterFunction = function(output) {
return "";
};
diff --git a/share/qbs/modules/cpp/iar.qbs b/share/qbs/modules/cpp/iar.qbs
index bc226389b..558635ef5 100644
--- a/share/qbs/modules/cpp/iar.qbs
+++ b/share/qbs/modules/cpp/iar.qbs
@@ -28,17 +28,16 @@
**
****************************************************************************/
-import qbs 1.0
import qbs.File
import qbs.FileInfo
-import qbs.ModUtils
import qbs.PathTools
import qbs.Probes
import qbs.Utilities
+import "cpp.js" as Cpp
import "iar.js" as IAR
CppModule {
- condition: qbs.toolchain && qbs.toolchain.contains("iar")
+ condition: qbs.toolchain && qbs.toolchain.includes("iar")
Probes.BinaryProbe {
id: compilerPathProbe
@@ -54,6 +53,7 @@ CppModule {
}
qbs.architecture: iarProbe.found ? iarProbe.architecture : original
+ qbs.targetPlatform: "none"
compilerVersionMajor: iarProbe.versionMajor
compilerVersionMinor: iarProbe.versionMinor
@@ -63,45 +63,58 @@ CppModule {
compilerDefinesByLanguage: iarProbe.compilerDefinesByLanguage
compilerIncludePaths: iarProbe.includePaths
- property string toolchainInstallPath: compilerPathProbe.found
- ? compilerPathProbe.path : undefined
-
- property string compilerExtension: qbs.hostOS.contains("windows") ? ".exe" : ""
+ toolchainInstallPath: compilerPathProbe.found ? compilerPathProbe.path : undefined
/* Work-around for QtCreator which expects these properties to exist. */
property string cCompilerName: compilerName
property string cxxCompilerName: compilerName
- compilerName: IAR.compilerName(qbs) + compilerExtension
+ compilerName: toolchainDetails.compilerName + compilerExtension
compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName)
- assemblerName: IAR.assemblerName(qbs) + compilerExtension
+ assemblerName: toolchainDetails.assemblerName + compilerExtension
assemblerPath: FileInfo.joinPaths(toolchainInstallPath, assemblerName)
- linkerName: IAR.linkerName(qbs) + compilerExtension
+ linkerName: toolchainDetails.linkerName + compilerExtension
linkerPath: FileInfo.joinPaths(toolchainInstallPath, linkerName)
- property string archiverName: IAR.archiverName(qbs) + compilerExtension
+ property string archiverName: toolchainDetails.archiverName + compilerExtension
property string archiverPath: FileInfo.joinPaths(toolchainInstallPath, archiverName)
runtimeLibrary: "static"
- staticLibrarySuffix: IAR.staticLibrarySuffix(qbs)
- executableSuffix: IAR.executableSuffix(qbs)
-
- property string objectSuffix: IAR.objectSuffix(qbs)
+ staticLibrarySuffix: toolchainDetails.staticLibrarySuffix
+ executableSuffix: toolchainDetails.executableSuffix
+ objectSuffix: toolchainDetails.objectSuffix
- imageFormat: IAR.imageFormat(qbs)
+ imageFormat: toolchainDetails.imageFormat
enableExceptions: false
enableRtti: false
+ defineFlag: "-D"
+ includeFlag: "-I"
+ systemIncludeFlag: "-I"
+ preincludeFlag: "--preinclude"
+ libraryDependencyFlag: ""
+ libraryPathFlag: toolchainDetails.libraryPathFlag
+ linkerScriptFlag: toolchainDetails.linkerScriptFlag
+
+ property string linkerSilentFlag: toolchainDetails.linkerSilentFlag
+ property string linkerMapFileFlag: toolchainDetails.linkerMapFileFlag
+ property string linkerEntryPointFlag: toolchainDetails.linkerEntryPointFlag
+
+ toolchainDetails: IAR.toolchainDetails(qbs)
+
+ knownArchitectures: ["78k", "arm", "avr", "avr32", "cr16",
+ "hcs12", "hcs8", "m16c", "m32c", "m68k", "mcs51", "msp430",
+ "r32c", "rh850", "riscv", "rl78", "rx", "sh", "stm8", "v850"]
+
Rule {
id: assembler
inputs: ["asm"]
- outputFileTags: ["obj", "lst"]
- outputArtifacts: IAR.compilerOutputArtifacts(
- input, input.cpp.generateAssemblerListingFiles)
+ outputFileTags: Cpp.assemblerOutputTags(generateAssemblerListingFiles)
+ outputArtifacts: Cpp.assemblerOutputArtifacts(input)
prepare: IAR.prepareAssembler.apply(IAR, arguments)
}
@@ -114,9 +127,8 @@ CppModule {
id: compiler
inputs: ["cpp", "c"]
auxiliaryInputs: ["hpp"]
- outputFileTags: ["obj", "lst"]
- outputArtifacts: IAR.compilerOutputArtifacts(
- input, input.cpp.generateCompilerListingFiles)
+ outputFileTags: Cpp.compilerOutputTags(generateCompilerListingFiles)
+ outputArtifacts: Cpp.compilerOutputArtifacts(input)
prepare: IAR.prepareCompiler.apply(IAR, arguments)
}
@@ -125,8 +137,8 @@ CppModule {
multiplex: true
inputs: ["obj", "linkerscript"]
inputsFromDependencies: ["staticlibrary"]
- outputFileTags: ["application", "mem_map"]
- outputArtifacts: IAR.applicationLinkerOutputArtifacts(product)
+ outputFileTags: Cpp.applicationLinkerOutputTags(generateLinkerMapFile)
+ outputArtifacts: Cpp.applicationLinkerOutputArtifacts(product)
prepare: IAR.prepareLinker.apply(IAR, arguments)
}
@@ -135,8 +147,8 @@ CppModule {
multiplex: true
inputs: ["obj"]
inputsFromDependencies: ["staticlibrary"]
- outputFileTags: ["staticlibrary"]
- outputArtifacts: IAR.staticLibraryLinkerOutputArtifacts(product)
+ outputFileTags: Cpp.staticLibraryLinkerOutputTags()
+ outputArtifacts: Cpp.staticLibraryLinkerOutputArtifacts(product)
prepare: IAR.prepareArchiver.apply(IAR, arguments)
}
}
diff --git a/share/qbs/modules/cpp/ios-gcc.qbs b/share/qbs/modules/cpp/ios-gcc.qbs
index 0ff99679f..968b873da 100644
--- a/share/qbs/modules/cpp/ios-gcc.qbs
+++ b/share/qbs/modules/cpp/ios-gcc.qbs
@@ -31,21 +31,30 @@
import qbs.DarwinTools
import qbs.File
import qbs.FileInfo
+import qbs.Host
import qbs.ModUtils
import qbs.Utilities
DarwinGCC {
priority: 1
- condition: qbs.targetOS.contains('ios') &&
- qbs.toolchain && qbs.toolchain.contains('gcc')
+ condition: qbs.targetOS.includes('ios') &&
+ qbs.toolchain && qbs.toolchain.includes('gcc')
+ minimumIosVersion: {
+ if (Host.architecture() == "armv7a")
+ return "6.0";
+ // XCode 12 requres version (at least 8.0) to be present in the -target triplet
+ // when compiling for ios-simulator
+ if (xcode.present && Utilities.versionCompare(xcode.version, "12.0") >= 0)
+ return "8.0";
+ }
targetSystem: "ios" + (minimumIosVersion || "")
minimumDarwinVersion: minimumIosVersion
- minimumDarwinVersionCompilerFlag: qbs.targetOS.contains("ios-simulator")
+ minimumDarwinVersionCompilerFlag: qbs.targetOS.includes("ios-simulator")
? "-mios-simulator-version-min"
: "-miphoneos-version-min"
- minimumDarwinVersionLinkerFlag: qbs.targetOS.contains("ios-simulator")
+ minimumDarwinVersionLinkerFlag: qbs.targetOS.includes("ios-simulator")
? "-ios_simulator_version_min"
: "-iphoneos_version_min"
@@ -60,13 +69,13 @@ DarwinGCC {
readonly property stringList simulatorObjcFlags: {
// default in Xcode and also required for building 32-bit Simulator binaries with ARC
// since the default ABI version is 0 for 32-bit targets
- return qbs.targetOS.contains("ios-simulator")
+ return qbs.targetOS.includes("ios-simulator")
? ["-fobjc-abi-version=2", "-fobjc-legacy-dispatch"]
: [];
}
Rule {
- condition: !product.qbs.targetOS.contains("ios-simulator")
+ condition: !product.qbs.targetOS.includes("ios-simulator")
inputsFromDependencies: ["bundle.content"]
Artifact {
diff --git a/share/qbs/modules/cpp/keil.js b/share/qbs/modules/cpp/keil.js
index befcc5a33..8f3297aa2 100644
--- a/share/qbs/modules/cpp/keil.js
+++ b/share/qbs/modules/cpp/keil.js
@@ -39,382 +39,456 @@ var TemporaryDir = require("qbs.TemporaryDir");
var TextFile = require("qbs.TextFile");
var Utilities = require("qbs.Utilities");
-function compilerName(qbs) {
- switch (qbs.architecture) {
- case "mcs51":
- return "c51";
- case "arm":
- return "armcc";
- }
- throw "Unable to deduce compiler name for unsupported architecture: '"
- + qbs.architecture + "'";
+function isMcs51Architecture(architecture) {
+ return architecture === "mcs51";
}
-function assemblerName(qbs) {
- switch (qbs.architecture) {
- case "mcs51":
- return "a51";
- case "arm":
- return "armasm";
- }
- throw "Unable to deduce assembler name for unsupported architecture: '"
- + qbs.architecture + "'";
+function isMcs251Architecture(architecture) {
+ return architecture === "mcs251";
}
-function linkerName(qbs) {
- switch (qbs.architecture) {
- case "mcs51":
- return "bl51";
- case "arm":
- return "armlink";
- }
- throw "Unable to deduce linker name for unsupported architecture: '"
- + qbs.architecture + "'";
+function isMcsArchitecture(architecture) {
+ return isMcs51Architecture(architecture)
+ || isMcs251Architecture(architecture);
}
-function archiverName(qbs) {
- switch (qbs.architecture) {
- case "mcs51":
- return "lib51";
- case "arm":
- return "armar";
- }
- throw "Unable to deduce archiver name for unsupported architecture: '"
- + qbs.architecture + "'";
+function isC166Architecture(architecture) {
+ return architecture === "c166";
}
-function staticLibrarySuffix(qbs) {
- switch (qbs.architecture) {
- case "mcs51":
- case "arm":
- return ".lib";
- }
- throw "Unable to deduce static library suffix for unsupported architecture: '"
- + qbs.architecture + "'";
+function isArmArchitecture(architecture) {
+ return architecture.startsWith("arm");
}
-function executableSuffix(qbs) {
- switch (qbs.architecture) {
- case "mcs51":
- return ".abs";
- case "arm":
- return ".axf";
- }
- throw "Unable to deduce executable suffix for unsupported architecture: '"
- + qbs.architecture + "'";
+function isMcsCompiler(compilerPath) {
+ var base = FileInfo.baseName(compilerPath).toLowerCase();
+ return base === "c51" || base === "cx51" || base === "c251";
}
-function objectSuffix(qbs) {
- switch (qbs.architecture) {
- case "mcs51":
- return ".obj";
- case "arm":
- return ".o";
- }
- throw "Unable to deduce object file suffix for unsupported architecture: '"
- + qbs.architecture + "'";
-}
-
-function imageFormat(qbs) {
- switch (qbs.architecture) {
- case "mcs51":
- // Keil OMF51 or OMF2 Object Module Format (which is an
- // extension of the original Intel OMF51).
- return "omf";
- case "arm":
- return "elf";
+function isC166Compiler(compilerPath) {
+ return FileInfo.baseName(compilerPath).toLowerCase() === "c166";
+}
+
+function isArmCCCompiler(compilerPath) {
+ return FileInfo.baseName(compilerPath).toLowerCase() === "armcc";
+}
+
+function isArmClangCompiler(compilerPath) {
+ return FileInfo.baseName(compilerPath).toLowerCase() === "armclang";
+}
+
+function preincludeFlag(compilerPath) {
+ if (isArmCCCompiler(compilerPath))
+ return "--preinclude";
+ else if (isArmClangCompiler(compilerPath))
+ return "-include";
+}
+
+function toolchainDetails(qbs) {
+ var architecture = qbs.architecture;
+ if (isMcs51Architecture(architecture)) {
+ return {
+ "imageFormat": "omf",
+ "linkerMapSuffix":".m51",
+ "objectSuffix": ".obj",
+ "executableSuffix": ".abs",
+ "compilerName": "c51",
+ "assemblerName": "a51",
+ "linkerName": "bl51",
+ "archiverName": "lib51"
+ };
+ } else if (isMcs251Architecture(architecture)) {
+ return {
+ "imageFormat": "omf",
+ "linkerMapSuffix":".m51",
+ "objectSuffix": ".obj",
+ "executableSuffix": ".abs",
+ "compilerName": "c251",
+ "assemblerName": "a251",
+ "linkerName": "l251",
+ "archiverName": "lib251"
+ };
+ } else if (isC166Architecture(architecture)) {
+ return {
+ "imageFormat": "omf",
+ "linkerMapSuffix":".m66",
+ "objectSuffix": ".obj",
+ "executableSuffix": ".abs",
+ "compilerName": "c166",
+ "assemblerName": "a166",
+ "linkerName": "l166",
+ "archiverName": "lib166"
+ };
+ } else if (isArmArchitecture(architecture)) {
+ return {
+ "imageFormat": "elf",
+ "linkerMapSuffix":".map",
+ "objectSuffix": ".o",
+ "executableSuffix": ".axf",
+ "disassemblerName": "fromelf",
+ "compilerName": "armcc",
+ "assemblerName": "armasm",
+ "linkerName": "armlink",
+ "archiverName": "armar"
+ };
}
- throw "Unable to deduce image format for unsupported architecture: '"
- + qbs.architecture + "'";
+}
+
+function guessArmCCArchitecture(targetArchArm, targetArchThumb) {
+ var arch = "arm";
+ if (targetArchArm === "4" && targetArchThumb === "0")
+ arch += "v4";
+ else if (targetArchArm === "4" && targetArchThumb === "1")
+ arch += "v4t";
+ else if (targetArchArm === "5" && targetArchThumb === "2")
+ arch += "v5t";
+ else if (targetArchArm === "6" && targetArchThumb === "3")
+ arch += "v6";
+ else if (targetArchArm === "6" && targetArchThumb === "4")
+ arch += "v6t2";
+ else if (targetArchArm === "0" && targetArchThumb === "3")
+ arch += "v6m";
+ else if (targetArchArm === "7" && targetArchThumb === "4")
+ arch += "v7r";
+ else if (targetArchArm === "0" && targetArchThumb === "4")
+ arch += "v7m";
+ return arch;
+}
+
+function guessArmClangArchitecture(targetArchArm, targetArchProfile) {
+ targetArchProfile = targetArchProfile.replace(/'/g, "");
+ var arch = "arm";
+ if (targetArchArm !== "" && targetArchProfile !== "")
+ arch += "v" + targetArchArm + targetArchProfile.toLowerCase();
+ return arch;
}
function guessArchitecture(macros) {
if (macros["__C51__"])
return "mcs51";
- else if (macros["__CC_ARM"] === 1)
- return "arm";
+ else if (macros["__C251__"])
+ return "mcs251";
+ else if (macros["__C166__"])
+ return "c166";
+ else if (macros["__CC_ARM"] === "1")
+ return guessArmCCArchitecture(macros["__TARGET_ARCH_ARM"], macros["__TARGET_ARCH_THUMB"]);
+ else if (macros["__clang__"] === "1" && macros["__arm__"] === "1")
+ return guessArmClangArchitecture(macros["__ARM_ARCH"], macros["__ARM_ARCH_PROFILE"]);
}
function guessEndianness(macros) {
- if (macros["__C51__"]) {
+ if (macros["__C51__"] || macros["__C251__"]) {
// The 8051 processors are 8-bit. So, the data with an integer type
// represented by more than one byte is stored as big endian in the
// Keil toolchain. See for more info:
// * http://www.keil.com/support/man/docs/c51/c51_ap_2bytescalar.htm
// * http://www.keil.com/support/man/docs/c51/c51_ap_4bytescalar.htm
+ // * http://www.keil.com/support/man/docs/c251/c251_ap_2bytescalar.htm
+ // * http://www.keil.com/support/man/docs/c251/c251_ap_4bytescalar.htm
return "big";
- } else if (macros["__ARMCC_VERSION"]) {
+ } else if (macros["__C166__"]) {
+ // The C166 processors are 16-bit. So, the data with an integer type
+ // represented by more than one byte is stored as little endian in the
+ // Keil toolchain. See for more info:
+ // * http://www.keil.com/support/man/docs/c166/c166_ap_ints.htm
+ // * http://www.keil.com/support/man/docs/c166/c166_ap_longs.htm
+ return "little";
+ } else if (macros["__CC_ARM"]) {
return macros["__BIG_ENDIAN"] ? "big" : "little";
+ } else if (macros["__clang__"] && macros["__arm__"]) {
+ switch (macros["__BYTE_ORDER__"]) {
+ case "__ORDER_BIG_ENDIAN__":
+ return "big";
+ case "__ORDER_LITTLE_ENDIAN__":
+ return "little";
+ }
}
}
function guessVersion(macros) {
- if (macros["__C51__"]) {
- var mcsVersion = macros["__C51__"];
+ if (macros["__C51__"] || macros["__C251__"]) {
+ var mcsVersion = macros["__C51__"] || macros["__C251__"];
return { major: parseInt(mcsVersion / 100),
minor: parseInt(mcsVersion % 100),
- patch: 0,
- found: true }
- } else if (macros["__CC_ARM"]) {
+ patch: 0 }
+ } else if (macros["__C166__"]) {
+ var xcVersion = macros["__C166__"];
+ return { major: parseInt(xcVersion / 100),
+ minor: parseInt(xcVersion % 100),
+ patch: 0 }
+ } else if (macros["__CC_ARM"] || macros["__clang__"]) {
var armVersion = macros["__ARMCC_VERSION"];
return { major: parseInt(armVersion / 1000000),
minor: parseInt(armVersion / 10000) % 100,
- patch: parseInt(armVersion) % 10000,
- found: true }
+ patch: parseInt(armVersion) % 10000 }
}
}
-// Note: The KEIL 8051 compiler does not support the predefined
-// macros dumping. So, we do it with following trick where we try
-// to compile a temporary file and to parse the console output.
-function dumpC51CompilerMacros(compilerFilePath, tag) {
- // C51 compiler support only C language.
+function dumpMcsCompilerMacros(compilerFilePath, tag) {
+ // C51 or C251 compiler support only C language.
if (tag === "cpp")
return {};
- function createDumpMacrosFile() {
- var td = new TemporaryDir();
- var fn = FileInfo.fromNativeSeparators(td.path() + "/dump-macros.c");
- var tf = new TextFile(fn, TextFile.WriteOnly);
- tf.writeLine("#define VALUE_TO_STRING(x) #x");
- tf.writeLine("#define VALUE(x) VALUE_TO_STRING(x)");
- tf.writeLine("#define VAR_NAME_VALUE(var) \"\"\"|\"#var\"|\"VALUE(var)");
- tf.writeLine("#ifdef __C51__");
- tf.writeLine("#pragma message(VAR_NAME_VALUE(__C51__))");
- tf.writeLine("#endif");
- tf.close();
- return fn;
+ // Note: The C51 or C251 compiler does not support the predefined
+ // macros dumping. So, we do it with the following trick, where we try
+ // to create and compile a special temporary file and to parse the console
+ // output with the own magic pattern: (""|"key"|"value"|"").
+
+ var outputDirectory = new TemporaryDir();
+ var outputFilePath = FileInfo.fromNativeSeparators(FileInfo.joinPaths(outputDirectory.path(),
+ "dump-macros.c"));
+ var outputFile = new TextFile(outputFilePath, TextFile.WriteOnly);
+
+ outputFile.writeLine("#define VALUE_TO_STRING(x) #x");
+ outputFile.writeLine("#define VALUE(x) VALUE_TO_STRING(x)");
+
+ // Predefined keys for C51 and C251 compilers, see details:
+ // * https://www.keil.com/support/man/docs/c51/c51_pp_predefmacroconst.htm
+ // * https://www.keil.com/support/man/docs/c251/c251_pp_predefmacroconst.htm
+ var keys = ["__C51__", "__CX51__", "__C251__", "__MODEL__",
+ "__STDC__", "__FLOAT64__", "__MODSRC__"];
+
+ // For C51 compiler.
+ outputFile.writeLine("#if defined(__C51__) || defined(__CX51__)");
+ outputFile.writeLine("# define VAR_NAME_VALUE(var) \"(\"\"\"\"|\"#var\"|\"VALUE(var)\"|\"\"\"\")\"");
+ for (var i in keys) {
+ var key = keys[i];
+ outputFile.writeLine("# if defined (" + key + ")");
+ outputFile.writeLine("# pragma message (VAR_NAME_VALUE(" + key + "))");
+ outputFile.writeLine("# endif");
+ }
+ outputFile.writeLine("#endif");
+
+ // For C251 compiler.
+ outputFile.writeLine("#if defined(__C251__)");
+ outputFile.writeLine("# define VAR_NAME_VALUE(var) \"\"|#var|VALUE(var)|\"\"");
+ for (var i in keys) {
+ var key = keys[i];
+ outputFile.writeLine("# if defined (" + key + ")");
+ outputFile.writeLine("# warning (VAR_NAME_VALUE(" + key + "))");
+ outputFile.writeLine("# endif");
}
+ outputFile.writeLine("#endif");
- var fn = createDumpMacrosFile();
- var p = new Process();
- p.exec(compilerFilePath, [ fn ], false);
+ outputFile.close();
+
+ var process = new Process();
+ process.exec(compilerFilePath, [outputFilePath], false);
+ File.remove(outputFilePath);
var map = {};
- p.readStdOut().trim().split(/\r?\n/g).map(function(line) {
- var parts = line.split("\"|\"", 3);
- map[parts[1]] = parts[2];
+ process.readStdOut().trim().split(/\r?\n/g).map(function(line) {
+ var parts = line.split("\"|\"", 4);
+ if (parts.length === 4)
+ map[parts[1]] = parts[2];
});
return map;
}
-function dumpArmCompilerMacros(compilerFilePath, tag, nullDevice) {
- var args = [ "-E", "--list-macros", nullDevice ];
+function dumpC166CompilerMacros(compilerFilePath, tag) {
+ // C166 compiler support only C language.
if (tag === "cpp")
- args.push("--cpp");
+ return {};
- var p = new Process();
- p.exec(compilerFilePath, args, false);
- var map = {};
- p.readStdOut().trim().split(/\r?\n/g).map(function (line) {
- if (!line.startsWith("#define"))
- return;
- var parts = line.split(" ", 3);
- map[parts[1]] = parts[2];
- });
- return map;
-}
+ // Note: The C166 compiler does not support the predefined
+ // macros dumping. Also, it does not support the '#pragma' and
+ // '#message|warning|error' directives properly (it is impossible
+ // to print to console the value of macro).
+ // So, we do it with the following trick, where we try
+ // to create and compile a special temporary file and to parse the console
+ // output with the own magic pattern, e.g:
+ //
+ // *** WARNING C320 IN LINE 41 OF c51.c: __C166__
+ // *** WARNING C2 IN LINE 42 OF c51.c: '757': unknown #pragma/control, line ignored
+ //
+ // where the '__C166__' is a key, and the '757' is a value.
+
+ var outputDirectory = new TemporaryDir();
+ var outputFilePath = FileInfo.fromNativeSeparators(outputDirectory.path() + "/dump-macros.c");
+ var outputFile = new TextFile(outputFilePath, TextFile.WriteOnly);
+
+ // Predefined keys for C166 compiler, see details:
+ // * https://www.keil.com/support/man/docs/c166/c166_pp_predefmacroconst.htm
+ var keys = ["__C166__", "__DUS__", "__MAC__", "__MOD167__",
+ "__MODEL__", "__MODV2__", "__SAVEMAC__", "__STDC__"];
+
+ // For C166 compiler.
+ outputFile.writeLine("#if defined(__C166__)");
+ for (var i in keys) {
+ var key = keys[i];
+ outputFile.writeLine("# if defined (" + key + ")");
+ outputFile.writeLine("# warning " + key);
+ outputFile.writeLine("# pragma " + key);
+ outputFile.writeLine("# endif");
+ }
+ outputFile.writeLine("#endif");
-function dumpMacros(compilerFilePath, tag, nullDevice) {
- var map1 = dumpC51CompilerMacros(compilerFilePath, tag, nullDevice);
- var map2 = dumpArmCompilerMacros(compilerFilePath, tag, nullDevice);
- var map = {};
- for (var key1 in map1)
- map[key1] = map1[key1];
- for (var key2 in map2)
- map[key2] = map2[key2];
- return map;
-}
+ outputFile.close();
-function dumpDefaultPaths(compilerFilePath, architecture) {
- var incDir = (architecture === "arm") ? "include" : "inc";
- var includePath = compilerFilePath.replace(/bin[\\\/](.*)$/i, incDir);
- return {
- "includePaths": [includePath]
+ function extractKey(line, knownKeys) {
+ for (var i in keys) {
+ var key = knownKeys[i];
+ var regexp = new RegExp("^\\*\\*\\* WARNING C320 IN LINE .+: (" + key + ")$");
+ var match = regexp.exec(line);
+ if (match)
+ return key;
+ }
};
-}
-
-function adjustPathsToWindowsSeparators(sourcePaths) {
- var resulingPaths = [];
- sourcePaths.forEach(function(path) {
- resulingPaths.push(FileInfo.toWindowsSeparators(path));
- });
- return resulingPaths;
-}
-function getMaxExitCode(architecture) {
- if (architecture === "mcs51")
- return 1;
- else if (architecture === "arm")
- return 0;
-}
+ function extractValue(line) {
+ var regexp = new RegExp("^\\*\\*\\* WARNING C2 IN LINE .+'(.+)':.+$");
+ var match = regexp.exec(line);
+ if (match)
+ return match[1];
+ };
-function collectLibraryDependencies(product) {
- var seen = {};
- var result = [];
+ var process = new Process();
+ process.exec(compilerFilePath, [outputFilePath], false);
+ File.remove(outputFilePath);
+ var lines = process.readStdOut().trim().split(/\r?\n/g);
+ var map = {};
+ for (var i = 0; i < lines.length; ++i) {
+ // First line should contains the macro key.
+ var keyLine = lines[i];
+ var key = extractKey(keyLine, keys);
+ if (!key)
+ continue;
+
+ i += 1;
+ if (i >= lines.length)
+ break;
- function addFilePath(filePath) {
- result.push({ filePath: filePath });
+ // Second line should contains the macro value.
+ var valueLine = lines[i];
+ var value = extractValue(valueLine);
+ if (!value)
+ continue;
+ map[key] = value;
}
+ return map;
+}
- function addArtifactFilePaths(dep, artifacts) {
- if (!artifacts)
- return;
- var artifactFilePaths = artifacts.map(function(a) { return a.filePath; });
- artifactFilePaths.forEach(addFilePath);
- }
+function dumpArmCCCompilerMacros(compilerFilePath, tag, nullDevice) {
+ var args = [ "-E", "--list-macros", "--cpu=cortex-m0", nullDevice ];
+ if (tag === "cpp")
+ args.push("--cpp");
- function addExternalStaticLibs(obj) {
- if (!obj.cpp)
- return;
- function ensureArray(a) {
- return Array.isArray(a) ? a : [];
- }
- function sanitizedModuleListProperty(obj, moduleName, propertyName) {
- return ensureArray(ModUtils.sanitizedModuleProperty(obj, moduleName, propertyName));
- }
- var externalLibs = [].concat(
- sanitizedModuleListProperty(obj, "cpp", "staticLibraries"));
- var staticLibrarySuffix = obj.moduleProperty("cpp", "staticLibrarySuffix");
- externalLibs.forEach(function(staticLibraryName) {
- if (!staticLibraryName.endsWith(staticLibrarySuffix))
- staticLibraryName += staticLibrarySuffix;
- addFilePath(staticLibraryName);
- });
- }
+ var p = new Process();
+ p.exec(compilerFilePath, args, false);
+ return Cpp.extractMacros(p.readStdOut());
+}
- function traverse(dep) {
- if (seen.hasOwnProperty(dep.name))
- return;
- seen[dep.name] = true;
+function dumpArmClangCompilerMacros(compilerFilePath, tag, nullDevice) {
+ var args = [ "--target=arm-arm-none-eabi", "-mcpu=cortex-m0", "-dM", "-E",
+ "-x", ((tag === "cpp") ? "c++" : "c"), nullDevice ];
+ var p = new Process();
+ p.exec(compilerFilePath, args, false);
+ return Cpp.extractMacros(p.readStdOut());
+}
- if (dep.parameters.cpp && dep.parameters.cpp.link === false)
- return;
+function dumpMacros(compilerFilePath, tag, nullDevice) {
+ if (isMcsCompiler(compilerFilePath))
+ return dumpMcsCompilerMacros(compilerFilePath, tag, nullDevice);
+ else if (isC166Compiler(compilerFilePath))
+ return dumpC166CompilerMacros(compilerFilePath, tag, nullDevice);
+ else if (isArmCCCompiler(compilerFilePath))
+ return dumpArmCCCompilerMacros(compilerFilePath, tag, nullDevice);
+ else if (isArmClangCompiler(compilerFilePath))
+ return dumpArmClangCompilerMacros(compilerFilePath, tag, nullDevice);
+ return {};
+}
- var staticLibraryArtifacts = dep.artifacts["staticlibrary"];
- if (staticLibraryArtifacts) {
- dep.dependencies.forEach(traverse);
- addArtifactFilePaths(dep, staticLibraryArtifacts);
- addExternalStaticLibs(dep);
- }
- }
+function dumpMcsCompilerIncludePaths(compilerFilePath) {
+ var includePath = compilerFilePath.replace(/bin[\\\/](.*)$/i, "inc");
+ return [includePath];
+}
- product.dependencies.forEach(traverse);
- addExternalStaticLibs(product);
- return result;
-}
-
-function filterStdOutput(cmd) {
- cmd.stdoutFilterFunction = function(output) {
- var sourceLines = output.split("\n");
- var filteredLines = [];
- for (var i in sourceLines) {
- if (sourceLines[i].startsWith("***")
- || sourceLines[i].startsWith(">>")
- || sourceLines[i].startsWith(" ")
- || sourceLines[i].startsWith("Program Size:")
- || sourceLines[i].startsWith("A51 FATAL")
- || sourceLines[i].startsWith("C51 FATAL")
- || sourceLines[i].startsWith("ASSEMBLER INVOKED BY")
- || sourceLines[i].startsWith("LOC OBJ LINE SOURCE")
- ) {
- filteredLines.push(sourceLines[i]);
- } else {
- var regexp = /^([0-9A-F]{4})/;
- if (regexp.exec(sourceLines[i]))
- filteredLines.push(sourceLines[i]);
- }
- }
- return filteredLines.join("\n");
- };
+function dumpC166CompilerIncludePaths(compilerFilePath) {
+ // Same as for MCS compiler.
+ return dumpMcsCompilerIncludePaths(compilerFilePath);
}
-function compilerOutputArtifacts(input, useListing) {
- var artifacts = [];
- artifacts.push({
- fileTags: ["obj"],
- filePath: Utilities.getHash(input.baseDir) + "/"
- + input.fileName + input.cpp.objectSuffix
- });
- if (useListing) {
- artifacts.push({
- fileTags: ["lst"],
- filePath: Utilities.getHash(input.baseDir) + "/"
- + (input.cpp.architecture === "mcs51"
- ? input.fileName : input.baseName)
- + ".lst"
- });
- }
- return artifacts;
+function dumpArmCCCompilerIncludePaths(compilerFilePath) {
+ var includePath = compilerFilePath.replace(/bin[\\\/](.*)$/i, "include");
+ return [includePath];
}
-function applicationLinkerOutputArtifacts(product) {
- var app = {
- fileTags: ["application"],
- filePath: FileInfo.joinPaths(
- product.destinationDirectory,
- PathTools.applicationFilePath(product))
- };
- var mem_map = {
- fileTags: ["mem_map"],
- filePath: FileInfo.joinPaths(
- product.destinationDirectory,
- product.targetName
- + (product.cpp.architecture === "mcs51" ? ".m51" : ".map"))
- };
- return [app, mem_map];
+function dumpArmClangCompilerIncludePaths(compilerFilePath, nullDevice) {
+ var args = [ "--target=arm-arm-none-eabi", "-mcpu=cortex-m0", "-v", "-E",
+ "-x", "c++", nullDevice ];
+ var p = new Process();
+ p.exec(compilerFilePath, args, false);
+ var lines = p.readStdErr().trim().split(/\r?\n/g).map(function (line) { return line.trim(); });
+ var addIncludes = false;
+ var includePaths = [];
+ for (var i = 0; i < lines.length; ++i) {
+ var line = lines[i];
+ if (line === "#include <...> search starts here:")
+ addIncludes = true;
+ else if (line === "End of search list.")
+ addIncludes = false;
+ else if (addIncludes)
+ includePaths.push(line);
+ }
+ return includePaths;
}
-function staticLibraryLinkerOutputArtifacts(product) {
- var staticLib = {
- fileTags: ["staticlibrary"],
- filePath: FileInfo.joinPaths(
- product.destinationDirectory,
- PathTools.staticLibraryFilePath(product))
- };
- return [staticLib]
+function dumpDefaultPaths(compilerFilePath, nullDevice) {
+ var includePaths = [];
+ if (isMcsCompiler(compilerFilePath))
+ includePaths = dumpMcsCompilerIncludePaths(compilerFilePath);
+ else if (isC166Compiler(compilerFilePath))
+ includePaths = dumpC166CompilerIncludePaths(compilerFilePath);
+ else if (isArmCCCompiler(compilerFilePath))
+ includePaths = dumpArmCCCompilerIncludePaths(compilerFilePath);
+ else if (isArmClangCompiler(compilerFilePath))
+ includePaths = dumpArmClangCompilerIncludePaths(compilerFilePath, nullDevice);
+ return { "includePaths": includePaths };
}
+function filterMcsOutput(output) {
+ var filteredLines = [];
+ output.split(/\r\n|\r|\n/).forEach(function(line) {
+ var regexp = /^\s*\*{3}\s|^\s{29}|^\s{4}\S|^\s{2}[0-9A-F]{4}|^\s{21,25}\d+|^[0-9A-F]{4}\s\d+/;
+ if (regexp.exec(line))
+ filteredLines.push(line);
+ });
+ return filteredLines.join('\n');
+};
+
+function filterC166Output(output) {
+ var filteredLines = [];
+ output.split(/\r\n|\r|\n/).forEach(function(line) {
+ var regexp = /^\s*\*{3}\s|^\s{29}|^\s{27,28}\d+|^\s{21}\d+|^\s{4}\S|^\s{2}[0-9A-F]{4}|^[0-9A-F]{4}\s\d+/;
+ if (regexp.exec(line))
+ filteredLines.push(line);
+ });
+ return filteredLines.join('\n');
+};
+
function compilerFlags(project, product, input, outputs, explicitlyDependsOn) {
// Determine which C-language we're compiling.
var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(outputs.obj[0].fileTags));
var args = [];
- var allDefines = [];
- var platformDefines = input.cpp.platformDefines;
- if (platformDefines)
- allDefines = allDefines.uniqueConcat(platformDefines);
- var defines = input.cpp.defines;
- if (defines)
- allDefines = allDefines.uniqueConcat(defines);
-
- var allIncludePaths = [];
- var includePaths = input.cpp.includePaths;
- if (includePaths)
- allIncludePaths = allIncludePaths.uniqueConcat(includePaths);
- var systemIncludePaths = input.cpp.systemIncludePaths;
- if (systemIncludePaths)
- allIncludePaths = allIncludePaths.uniqueConcat(systemIncludePaths);
- var compilerIncludePaths = input.cpp.compilerIncludePaths;
- if (compilerIncludePaths)
- allIncludePaths = allIncludePaths.uniqueConcat(compilerIncludePaths);
-
var architecture = input.qbs.architecture;
- if (architecture === "mcs51") {
+ if (isMcsArchitecture(architecture) || isC166Architecture(architecture)) {
// Input.
- args.push(FileInfo.toWindowsSeparators(input.filePath));
+ args.push(input.filePath);
// Output.
- args.push("OBJECT (" + FileInfo.toWindowsSeparators(outputs.obj[0].filePath) + ")");
+ args.push("OBJECT(" + FileInfo.toWindowsSeparators(outputs.obj[0].filePath) + ")");
// Defines.
- if (allDefines.length > 0)
- args = args.concat("DEFINE (" + allDefines.join(",") + ")");
+ var defines = Cpp.collectDefines(input);
+ if (defines.length > 0)
+ args = args.concat("DEFINE (" + defines.join(",") + ")");
// Includes.
- if (allIncludePaths.length > 0) {
- var adjusted = adjustPathsToWindowsSeparators(allIncludePaths);
- args = args.concat("INCDIR (" + adjusted.join(";") + ")");
- }
+ var allIncludePaths = [].concat(Cpp.collectIncludePaths(input),
+ Cpp.collectSystemIncludePaths(input));
+ if (allIncludePaths.length > 0)
+ args = args.concat("INCDIR(" + allIncludePaths.map(function(path) {
+ return FileInfo.toWindowsSeparators(path); }).join(";") + ")");
// Debug information flags.
if (input.cpp.debugInformation)
@@ -440,153 +514,191 @@ function compilerFlags(project, product, input, outputs, explicitlyDependsOn) {
break;
case "all":
args.push("WARNINGLEVEL (2)");
- args.push("FARWARNING");
+ if (isMcs51Architecture(architecture))
+ args.push("FARWARNING");
break;
}
// Listing files generation flag.
- if (!product.cpp.generateCompilerListingFiles)
+ if (!input.cpp.generateCompilerListingFiles)
args.push("NOPRINT");
else
args.push("PRINT(" + FileInfo.toWindowsSeparators(outputs.lst[0].filePath) + ")");
- } else if (architecture === "arm") {
+ } else if (isArmArchitecture(architecture)) {
// Input.
args.push("-c", input.filePath);
// Output.
args.push("-o", outputs.obj[0].filePath);
+ // Preinclude headers.
+ args = args.concat(Cpp.collectPreincludePathsArguments(input, true));
+
// Defines.
- args = args.concat(allDefines.map(function(define) { return '-D' + define }));
+ args = args.concat(Cpp.collectDefinesArguments(input));
// Includes.
- args = args.concat(allIncludePaths.map(function(include) { return '-I' + include }));
+ args = args.concat(Cpp.collectIncludePathsArguments(input));
+ args = args.concat(Cpp.collectSystemIncludePathsArguments(input));
+
+ var compilerPath = input.cpp.compilerPath;
+ if (isArmCCCompiler(compilerPath)) {
+ // Debug information flags.
+ if (input.cpp.debugInformation) {
+ args.push("--debug");
+ args.push("-g");
+ }
- // Debug information flags.
- if (input.cpp.debugInformation) {
- args.push("--debug");
- args.push("-g");
- }
+ // Optimization level flags.
+ switch (input.cpp.optimization) {
+ case "small":
+ args.push("-Ospace")
+ break;
+ case "fast":
+ args.push("-Otime")
+ break;
+ case "none":
+ args.push("-O0")
+ break;
+ }
- // Optimization level flags.
- switch (input.cpp.optimization) {
- case "small":
- args.push("-Ospace")
- break;
- case "fast":
- args.push("-Otime")
- break;
- case "none":
- args.push("-O0")
- break;
- }
+ // Warning level flags.
+ switch (input.cpp.warningLevel) {
+ case "none":
+ args.push("-W");
+ break;
+ default:
+ // By default all warnings are enabled.
+ break;
+ }
- // Warning level flags.
- switch (input.cpp.warningLevel) {
- case "none":
- args.push("-W");
- break;
- default:
- // By default all warnings are enabled.
- break;
- }
+ if (tag === "c") {
+ // C language version flags.
+ var knownCLanguageValues = ["c99", "c90"];
+ var cLanguageVersion = Cpp.languageVersion(
+ input.cpp.cLanguageVersion, knownCLanguageValues, "C");
+ switch (cLanguageVersion) {
+ case "c99":
+ args.push("--c99");
+ break;
+ case "c90":
+ args.push("--c90");
+ break;
+ }
+ } else if (tag === "cpp") {
+ // C++ language version flags.
+ var knownCppLanguageValues = ["c++11", "c++03"];
+ var cppLanguageVersion = Cpp.languageVersion(
+ input.cpp.cxxLanguageVersion, knownCppLanguageValues, "C++");
+ switch (cppLanguageVersion) {
+ case "c++11":
+ args.push("--cpp11");
+ break;
+ default:
+ // Default C++ language is C++03.
+ args.push("--cpp");
+ break;
+ }
+
+ // Exceptions flags.
+ var enableExceptions = input.cpp.enableExceptions;
+ if (enableExceptions !== undefined)
+ args.push(enableExceptions ? "--exceptions" : "--no_exceptions");
+
+ // RTTI flags.
+ var enableRtti = input.cpp.enableRtti;
+ if (enableRtti !== undefined)
+ args.push(enableRtti ? "--rtti" : "--no_rtti");
+ }
- if (tag === "c") {
- // C language version flags.
- var knownCLanguageValues = ["c99", "c90"];
- var cLanguageVersion = Cpp.languageVersion(
- input.cpp.cLanguageVersion, knownCLanguageValues, "C");
- switch (cLanguageVersion) {
- case "c99":
- args.push("--c99");
+ // Listing files generation flag.
+ if (input.cpp.generateCompilerListingFiles) {
+ args.push("--list");
+ args.push("--list_dir", FileInfo.path(outputs.lst[0].filePath));
+ }
+ } else if (isArmClangCompiler(compilerPath)) {
+ // Debug information flags.
+ if (input.cpp.debugInformation)
+ args.push("-g");
+
+ // Optimization level flags.
+ switch (input.cpp.optimization) {
+ case "small":
+ args.push("-Oz")
+ break;
+ case "fast":
+ args.push("-Ofast")
break;
- case "c90":
- args.push("--c90");
+ case "none":
+ args.push("-O0")
break;
}
- } else if (tag === "cpp") {
- // C++ language version flags.
- var knownCppLanguageValues = ["c++11", "c++03"];
- var cppLanguageVersion = Cpp.languageVersion(
- input.cpp.cxxLanguageVersion, knownCppLanguageValues, "C++");
- switch (cppLanguageVersion) {
- case "c++11":
- args.push("--cpp11");
+
+ // Warning level flags.
+ switch (input.cpp.warningLevel) {
+ case "all":
+ args.push("-Wall");
break;
default:
- // Default C++ language is C++03.
- args.push("--cpp");
break;
}
- // Exceptions flags.
- var enableExceptions = input.cpp.enableExceptions;
- if (enableExceptions !== undefined)
- args.push(enableExceptions ? "--exceptions" : "--no_exceptions");
-
- // RTTI flags.
- var enableRtti = input.cpp.enableRtti;
- if (enableRtti !== undefined)
- args.push(enableRtti ? "--rtti" : "--no_rtti");
- }
+ if (input.cpp.treatWarningsAsErrors)
+ args.push("-Werror");
+
+ if (tag === "c") {
+ // C language version flags.
+ var knownCLanguageValues = ["c11", "c99", "c90", "c89"];
+ var cLanguageVersion = Cpp.languageVersion(
+ input.cpp.cLanguageVersion, knownCLanguageValues, "C");
+ if (cLanguageVersion)
+ args.push("-std=" + cLanguageVersion);
+ } else if (tag === "cpp") {
+ // C++ language version flags.
+ var knownCppLanguageValues = ["c++17", "c++14", "c++11", "c++03", "c++98"];
+ var cppLanguageVersion = Cpp.languageVersion(
+ input.cpp.cxxLanguageVersion, knownCppLanguageValues, "C++");
+ if (cppLanguageVersion)
+ args.push("-std=" + cppLanguageVersion);
+
+ // Exceptions flags.
+ var enableExceptions = input.cpp.enableExceptions;
+ if (enableExceptions !== undefined)
+ args.push(enableExceptions ? "-fexceptions" : "-fno-exceptions");
+
+ // RTTI flags.
+ var enableRtti = input.cpp.enableRtti;
+ if (enableRtti !== undefined)
+ args.push(enableRtti ? "-frtti" : "-fno-rtti");
+ }
- // Listing files generation flag.
- if (product.cpp.generateCompilerListingFiles) {
- args.push("--list");
- args.push("--list_dir", FileInfo.path(outputs.lst[0].filePath));
+ // Listing files generation does not supported!
+ // There are only a workaround: http://www.keil.com/support/docs/4152.htm
}
}
// Misc flags.
- args = args.concat(ModUtils.moduleProperty(input, "platformFlags"),
- ModUtils.moduleProperty(input, "flags"),
- ModUtils.moduleProperty(input, "platformFlags", tag),
- ModUtils.moduleProperty(input, "flags", tag),
- ModUtils.moduleProperty(input, "driverFlags", tag));
+ args = args.concat(Cpp.collectMiscCompilerArguments(input, tag),
+ Cpp.collectMiscDriverArguments(input));
return args;
}
function assemblerFlags(project, product, input, outputs, explicitlyDependsOn) {
- // Determine which C-language we're compiling
- var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(outputs.obj[0].fileTags));
var args = [];
-
- var allDefines = [];
- var platformDefines = input.cpp.platformDefines;
- if (platformDefines)
- allDefines = allDefines.uniqueConcat(platformDefines);
- var defines = input.cpp.defines;
- if (defines)
- allDefines = allDefines.uniqueConcat(defines);
-
- var allIncludePaths = [];
- var includePaths = input.cpp.includePaths;
- if (includePaths)
- allIncludePaths = allIncludePaths.uniqueConcat(includePaths);
- var systemIncludePaths = input.cpp.systemIncludePaths;
- if (systemIncludePaths)
- allIncludePaths = allIncludePaths.uniqueConcat(systemIncludePaths);
- var compilerIncludePaths = input.cpp.compilerIncludePaths;
- if (compilerIncludePaths)
- allIncludePaths = allIncludePaths.uniqueConcat(compilerIncludePaths);
-
var architecture = input.qbs.architecture;
- if (architecture === "mcs51") {
+ if (isMcsArchitecture(architecture) || isC166Architecture(architecture)) {
// Input.
- args.push(FileInfo.toWindowsSeparators(input.filePath));
+ args.push(input.filePath);
// Output.
- args.push("OBJECT (" + FileInfo.toWindowsSeparators(outputs.obj[0].filePath) + ")");
-
- // Defines.
- if (allDefines.length > 0)
- args = args.concat("DEFINE (" + allDefines.join(",") + ")");
+ args.push("OBJECT(" + FileInfo.toWindowsSeparators(outputs.obj[0].filePath) + ")");
// Includes.
- if (allIncludePaths.length > 0) {
- var adjusted = adjustPathsToWindowsSeparators(allIncludePaths);
- args = args.concat("INCDIR (" + adjusted.join(";") + ")");
- }
+ var allIncludePaths = [].concat(Cpp.collectIncludePaths(input),
+ Cpp.collectSystemIncludePaths(input));
+ if (allIncludePaths.length > 0)
+ args = args.concat("INCDIR(" + allIncludePaths.map(function(path) {
+ return FileInfo.toWindowsSeparators(path); }).join(";") + ")");
// Debug information flags.
if (input.cpp.debugInformation)
@@ -596,31 +708,20 @@ function assemblerFlags(project, product, input, outputs, explicitlyDependsOn) {
args.push("EP");
// Listing files generation flag.
- if (!product.cpp.generateAssemblerListingFiles)
+ if (!input.cpp.generateAssemblerListingFiles)
args.push("NOPRINT");
else
args.push("PRINT(" + FileInfo.toWindowsSeparators(outputs.lst[0].filePath) + ")");
- } else if (architecture === "arm") {
+ } else if (isArmArchitecture(architecture)) {
// Input.
args.push(input.filePath);
// Output.
args.push("-o", outputs.obj[0].filePath);
- // Defines.
- allDefines.forEach(function(define) {
- var parts = define.split("=");
- args.push("--pd");
- if (parts[1] === undefined)
- args.push(parts[0] + " SETA " + 1);
- else if (parts[1].contains("\""))
- args.push(parts[0] + " SETS " + parts[1]);
- else
- args.push(parts[0] + " SETA " + parts[1]);
- });
-
// Includes.
- args = args.concat(allIncludePaths.map(function(include) { return '-I' + include }));
+ args = args.concat(Cpp.collectIncludePathsArguments(input));
+ args = args.concat(Cpp.collectSystemIncludePathsArguments(input));
// Debug information flags.
if (input.cpp.debugInformation) {
@@ -638,72 +739,86 @@ function assemblerFlags(project, product, input, outputs, explicitlyDependsOn) {
args.push((endianness === "little") ? "--littleend" : "--bigend");
// Listing files generation flag.
- if (product.cpp.generateAssemblerListingFiles)
+ if (input.cpp.generateAssemblerListingFiles)
args.push("--list", outputs.lst[0].filePath);
}
// Misc flags.
- args = args.concat(ModUtils.moduleProperty(input, "platformFlags", tag),
- ModUtils.moduleProperty(input, "flags", tag),
- ModUtils.moduleProperty(input, "driverFlags", tag));
+ args = args.concat(Cpp.collectMiscAssemblerArguments(input, "asm"));
+ return args;
+}
+
+function disassemblerFlags(project, product, input, outputs, explicitlyDependsOn) {
+ var args = ["--disassemble", "--interleave=source"];
+ args.push(outputs.obj[0].filePath);
+ args.push("--output=" + outputs.lst[0].filePath);
return args;
}
-function linkerFlags(project, product, input, outputs) {
+function linkerFlags(project, product, inputs, outputs) {
var args = [];
+ var libraryPaths = Cpp.collectLibraryPaths(product);
+
var architecture = product.qbs.architecture;
- if (architecture === "mcs51") {
- // Note: The C51 linker does not distinguish an object files and
+ if (isMcsArchitecture(architecture) || isC166Architecture(architecture)) {
+ // Semi-intelligent handling the library paths.
+ // We need to add the full path prefix to the library file if this
+ // file is not absolute or not relative. Reason is that the C51, C251,
+ // and C166 linkers does not support the library paths.
+ function collectLibraryObjectPaths(product) {
+ var libraryObjects = Cpp.collectLibraryDependencies(product);
+ return libraryObjects.map(function(dep) {
+ var filePath = dep.filePath;
+ if (FileInfo.isAbsolutePath(filePath))
+ return filePath;
+ for (var i = 0; i < libraryPaths.length; ++i) {
+ var fullPath = FileInfo.joinPaths(libraryPaths[i], filePath);
+ if (File.exists(fullPath))
+ return fullPath;
+ }
+ return filePath;
+ });
+ }
+
+ // Note: The C51, C251, or C166 linker does not distinguish an object files and
// a libraries, it interpret all this stuff as an input objects,
// so, we need to pass it together in one string.
-
- var allObjectPaths = [];
- function addObjectPath(obj) {
- allObjectPaths.push(obj.filePath);
+ function collectAllObjectPathsArguments(product, inputs) {
+ return [].concat(Cpp.collectLinkerObjectPaths(inputs),
+ collectLibraryObjectPaths(product));
}
- // Inputs.
- if (inputs.obj)
- inputs.obj.map(function(obj) { addObjectPath(obj) });
-
- // Library dependencies.
- var libraryObjects = collectLibraryDependencies(product);
- libraryObjects.forEach(function(dep) { addObjectPath(dep); })
-
// Add all input objects as arguments (application and library object files).
- var adjusted = adjustPathsToWindowsSeparators(allObjectPaths);
- args = args.concat(adjusted.join(","));
+ var allObjectPaths = collectAllObjectPathsArguments(product, inputs);
+ if (allObjectPaths.length > 0)
+ args = args.concat(allObjectPaths.map(function(path) {
+ return FileInfo.toWindowsSeparators(path); }).join(","));
// Output.
- // Note: We need to wrap an output file name with quotes. Otherwise
- // the linker will ignore a specified file name.
- args.push("TO", '"' + FileInfo.toWindowsSeparators(outputs.application[0].filePath) + '"');
+ args.push("TO", FileInfo.toWindowsSeparators(outputs.application[0].filePath));
// Map file generation flag.
if (!product.cpp.generateLinkerMapFile)
- args.push("NOMAP");
- } else if (architecture === "arm") {
+ args.push("NOPRINT");
+ else
+ args.push("PRINT(" + FileInfo.toWindowsSeparators(outputs.mem_map[0].filePath) + ")");
+ } else if (isArmArchitecture(architecture)) {
// Inputs.
- if (inputs.obj)
- args = args.concat(inputs.obj.map(function(obj) { return obj.filePath }));
+ args = args.concat(Cpp.collectLinkerObjectPaths(inputs));
// Output.
args.push("--output", outputs.application[0].filePath);
// Library paths.
- var libraryPaths = product.cpp.libraryPaths;
- if (libraryPaths)
- args.push("--userlibpath=" + libraryPaths.join(","));
+ if (libraryPaths.length > 0)
+ args.push(product.cpp.libraryPathFlag + libraryPaths.join(","));
// Library dependencies.
- var libraryDependencies = collectLibraryDependencies(product);
- args = args.concat(libraryDependencies.map(function(dep) { return dep.filePath; }));
+ args = args.concat(Cpp.collectLibraryDependenciesArguments(product));
- // Debug information flag.
- var debugInformation = product.cpp.debugInformation;
- if (debugInformation !== undefined)
- args.push(debugInformation ? "--debug" : "--no_debug");
+ // Linker scripts.
+ args = args.concat(Cpp.collectLinkerScriptPathsArguments(product, inputs, true));
// Map file generation flag.
if (product.cpp.generateLinkerMapFile)
@@ -713,43 +828,38 @@ function linkerFlags(project, product, input, outputs) {
if (product.cpp.entryPoint)
args.push("--entry", product.cpp.entryPoint);
- // Linker scripts flags.
- var linkerScripts = inputs.linkerscript
- ? inputs.linkerscript.map(function(a) { return a.filePath; }) : [];
- linkerScripts.forEach(function(script) { args.push("--scatter", script); });
+ // Debug information flag.
+ var debugInformation = product.cpp.debugInformation;
+ if (debugInformation !== undefined)
+ args.push(debugInformation ? "--debug" : "--no_debug");
}
// Misc flags.
- args = args.concat(ModUtils.moduleProperty(product, "driverLinkerFlags"));
+ args = args.concat(Cpp.collectMiscEscapableLinkerArguments(product),
+ Cpp.collectMiscLinkerArguments(product),
+ Cpp.collectMiscDriverArguments(product));
return args;
}
-function archiverFlags(project, product, input, outputs) {
+function archiverFlags(project, product, inputs, outputs) {
var args = [];
+ // Inputs.
+ var objectPaths = Cpp.collectLinkerObjectPaths(inputs);
+
var architecture = product.qbs.architecture;
- if (architecture === "mcs51") {
+ if (isMcsArchitecture(architecture) || isC166Architecture(architecture)) {
// Library creation command.
args.push("TRANSFER");
- var allObjectPaths = [];
- function addObjectPath(obj) {
- allObjectPaths.push(obj.filePath);
- }
-
// Inputs.
- if (inputs.obj)
- inputs.obj.map(function(obj) { addObjectPath(obj) });
-
- // Add all input objects as arguments.
- var adjusted = adjustPathsToWindowsSeparators(allObjectPaths);
- args = args.concat(adjusted.join(","));
+ if (objectPaths.length > 0)
+ args = args.concat(objectPaths.map(function(path) {
+ return FileInfo.toWindowsSeparators(path); }).join(","));
// Output.
- // Note: We need to wrap a output file name with quotes. Otherwise
- // the linker will ignore a specified file name.
- args.push("TO", '"' + FileInfo.toWindowsSeparators(outputs.staticlibrary[0].filePath) + '"');
- } else if (architecture === "arm") {
+ args.push("TO", FileInfo.toWindowsSeparators(outputs.staticlibrary[0].filePath));
+ } else if (isArmArchitecture(architecture)) {
// Note: The ARM archiver command line expect the output file
// first, and then a set of input objects.
@@ -757,8 +867,7 @@ function archiverFlags(project, product, input, outputs) {
args.push("--create", outputs.staticlibrary[0].filePath);
// Inputs.
- if (inputs.obj)
- args = args.concat(inputs.obj.map(function(obj) { return obj.filePath }));
+ args = args.concat(objectPaths);
// Debug information flag.
if (product.cpp.debugInformation)
@@ -768,48 +877,116 @@ function archiverFlags(project, product, input, outputs) {
return args;
}
+// The ARMCLANG compiler does not support generation
+// for the listing files:
+// * https://www.keil.com/support/docs/4152.htm
+// So, we generate the listing files from the object files
+// using the disassembler.
+function generateClangCompilerListing(project, product, inputs, outputs, input, output) {
+ if (isArmClangCompiler(input.cpp.compilerPath) && input.cpp.generateCompilerListingFiles) {
+ var args = disassemblerFlags(project, product, input, outputs, explicitlyDependsOn);
+ var disassemblerPath = input.cpp.disassemblerPath;
+ var cmd = new Command(disassemblerPath, args);
+ cmd.silent = true;
+ return cmd;
+ }
+}
+
+// The ARMCC compiler generates the listing files only in a short form,
+// e.g. to 'module.lst' instead of 'module.{c|cpp}.lst', that complicates
+// the auto-tests. Therefore we need to rename generated listing files
+// with correct unified names.
+function generateArmccCompilerListing(project, product, inputs, outputs, input, output) {
+ if (isArmCCCompiler(input.cpp.compilerPath) && input.cpp.generateCompilerListingFiles) {
+ var listingPath = FileInfo.path(outputs.lst[0].filePath);
+ var cmd = new JavaScriptCommand();
+ cmd.oldListing = FileInfo.joinPaths(listingPath, input.baseName + ".lst");
+ cmd.newListing = FileInfo.joinPaths(
+ listingPath, input.fileName + input.cpp.compilerListingSuffix);
+ cmd.silent = true;
+ cmd.sourceCode = function() { File.move(oldListing, newListing); };
+ return cmd;
+ }
+}
+
function prepareCompiler(project, product, inputs, outputs, input, output, explicitlyDependsOn) {
+ var cmds = [];
var args = compilerFlags(project, product, input, outputs, explicitlyDependsOn);
var compilerPath = input.cpp.compilerPath;
var architecture = input.cpp.architecture;
var cmd = new Command(compilerPath, args);
cmd.description = "compiling " + input.fileName;
cmd.highlight = "compiler";
- cmd.maxExitCode = getMaxExitCode(architecture);
- filterStdOutput(cmd);
- return [cmd];
-}
+ cmd.jobPool = "compiler";
+ if (isMcsArchitecture(architecture)) {
+ cmd.maxExitCode = 1;
+ cmd.stdoutFilterFunction = filterMcsOutput;
+ } else if (isC166Architecture(architecture)) {
+ cmd.maxExitCode = 1;
+ cmd.stdoutFilterFunction = filterC166Output;
+ }
+ cmds.push(cmd);
+
+ cmd = generateClangCompilerListing(project, product, inputs, outputs, input, output);
+ if (cmd)
+ cmds.push(cmd);
+ cmd = generateArmccCompilerListing(project, product, inputs, outputs, input, output);
+ if (cmd)
+ cmds.push(cmd);
+
+ return cmds;
+}
function prepareAssembler(project, product, inputs, outputs, input, output, explicitlyDependsOn) {
var args = assemblerFlags(project, product, input, outputs, explicitlyDependsOn);
var assemblerPath = input.cpp.assemblerPath;
+ var architecture = input.cpp.architecture;
var cmd = new Command(assemblerPath, args);
cmd.description = "assembling " + input.fileName;
cmd.highlight = "compiler";
- filterStdOutput(cmd);
+ cmd.jobPool = "assembler";
+ if (isMcsArchitecture(architecture)) {
+ cmd.maxExitCode = 1;
+ cmd.stdoutFilterFunction = filterMcsOutput;
+ } else if (isC166Architecture(architecture)) {
+ cmd.maxExitCode = 1;
+ cmd.stdoutFilterFunction = filterC166Output;
+ }
return [cmd];
}
function prepareLinker(project, product, inputs, outputs, input, output) {
var primaryOutput = outputs.application[0];
- var args = linkerFlags(project, product, input, outputs);
+ var args = linkerFlags(project, product, inputs, outputs);
var linkerPath = product.cpp.linkerPath;
var architecture = product.cpp.architecture;
var cmd = new Command(linkerPath, args);
cmd.description = "linking " + primaryOutput.fileName;
cmd.highlight = "linker";
- cmd.maxExitCode = getMaxExitCode(architecture);
- filterStdOutput(cmd);
+ cmd.jobPool = "linker";
+ if (isMcsArchitecture(architecture)) {
+ cmd.maxExitCode = 1;
+ cmd.stdoutFilterFunction = filterMcsOutput;
+ } else if (isC166Architecture(architecture)) {
+ cmd.maxExitCode = 1;
+ cmd.stdoutFilterFunction = filterC166Output;
+ }
return [cmd];
}
function prepareArchiver(project, product, inputs, outputs, input, output) {
- var args = archiverFlags(project, product, input, outputs);
+ var args = archiverFlags(project, product, inputs, outputs);
var archiverPath = product.cpp.archiverPath;
+ var architecture = product.cpp.architecture;
var cmd = new Command(archiverPath, args);
- cmd.description = "linking " + output.fileName;
+ cmd.description = "creating " + output.fileName;
cmd.highlight = "linker";
- filterStdOutput(cmd);
+ cmd.jobPool = "linker";
+ if (isMcsArchitecture(architecture)) {
+ cmd.stdoutFilterFunction = filterMcsOutput;
+ } else if (isC166Architecture(architecture)) {
+ cmd.stdoutFilterFunction = filterC166Output;
+ }
return [cmd];
}
diff --git a/share/qbs/modules/cpp/keil.qbs b/share/qbs/modules/cpp/keil.qbs
index 67ea5e675..5922ad4e2 100644
--- a/share/qbs/modules/cpp/keil.qbs
+++ b/share/qbs/modules/cpp/keil.qbs
@@ -28,15 +28,15 @@
**
****************************************************************************/
-import qbs 1.0
import qbs.File
import qbs.FileInfo
-import qbs.ModUtils
+import qbs.Host
import qbs.Probes
+import "cpp.js" as Cpp
import "keil.js" as KEIL
CppModule {
- condition: qbs.hostOS.contains("windows") && qbs.toolchain && qbs.toolchain.contains("keil")
+ condition: Host.os().includes("windows") && qbs.toolchain && qbs.toolchain.includes("keil")
Probes.BinaryProbe {
id: compilerPathProbe
@@ -52,6 +52,7 @@ CppModule {
}
qbs.architecture: keilProbe.found ? keilProbe.architecture : original
+ qbs.targetPlatform: "none"
compilerVersionMajor: keilProbe.versionMajor
compilerVersionMinor: keilProbe.versionMinor
@@ -61,45 +62,56 @@ CppModule {
compilerDefinesByLanguage: keilProbe.compilerDefinesByLanguage
compilerIncludePaths: keilProbe.includePaths
- property string toolchainInstallPath: compilerPathProbe.found
- ? compilerPathProbe.path : undefined
-
- property string compilerExtension: qbs.hostOS.contains("windows") ? ".exe" : ""
+ toolchainInstallPath: compilerPathProbe.found ? compilerPathProbe.path : undefined
/* Work-around for QtCreator which expects these properties to exist. */
property string cCompilerName: compilerName
property string cxxCompilerName: compilerName
- compilerName: KEIL.compilerName(qbs) + compilerExtension
+ compilerName: toolchainDetails.compilerName + compilerExtension
compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName)
- assemblerName: KEIL.assemblerName(qbs) + compilerExtension
+ assemblerName: toolchainDetails.assemblerName + compilerExtension
assemblerPath: FileInfo.joinPaths(toolchainInstallPath, assemblerName)
- linkerName: KEIL.linkerName(qbs) + compilerExtension
+ linkerName: toolchainDetails.linkerName + compilerExtension
linkerPath: FileInfo.joinPaths(toolchainInstallPath, linkerName)
- property string archiverName: KEIL.archiverName(qbs) + compilerExtension
+ property string archiverName: toolchainDetails.archiverName + compilerExtension
property string archiverPath: FileInfo.joinPaths(toolchainInstallPath, archiverName)
- runtimeLibrary: "static"
+ property string disassemblerName: toolchainDetails.disassemblerName + compilerExtension
+ property string disassemblerPath: FileInfo.joinPaths(toolchainInstallPath, disassemblerName)
- staticLibrarySuffix: KEIL.staticLibrarySuffix(qbs)
- executableSuffix: KEIL.executableSuffix(qbs)
+ runtimeLibrary: "static"
- property string objectSuffix: KEIL.objectSuffix(qbs)
+ staticLibrarySuffix: ".lib"
+ executableSuffix: toolchainDetails.executableSuffix
+ objectSuffix: toolchainDetails.objectSuffix
+ linkerMapSuffix: toolchainDetails.linkerMapSuffix
- imageFormat: KEIL.imageFormat(qbs)
+ imageFormat: toolchainDetails.imageFormat
enableExceptions: false
enableRtti: false
+ defineFlag: "-D"
+ includeFlag: "-I"
+ systemIncludeFlag: "-I"
+ preincludeFlag: KEIL.preincludeFlag(compilerPath)
+ libraryDependencyFlag: ""
+ libraryPathFlag: "--userlibpath="
+ linkerScriptFlag: "--scatter"
+
+ toolchainDetails: KEIL.toolchainDetails(qbs)
+
+ knownArchitectures: ["arm", "c166", "mcs251", "mcs51"]
+
Rule {
id: assembler
inputs: ["asm"]
- outputFileTags: ["obj", "lst"]
- outputArtifacts: KEIL.compilerOutputArtifacts(
- input, input.cpp.generateAssemblerListingFiles)
+ outputFileTags: Cpp.assemblerOutputTags(generateAssemblerListingFiles)
+ outputArtifacts: Cpp.assemblerOutputArtifacts(input)
prepare: KEIL.prepareAssembler.apply(KEIL, arguments)
}
@@ -112,9 +124,8 @@ CppModule {
id: compiler
inputs: ["cpp", "c"]
auxiliaryInputs: ["hpp"]
- outputFileTags: ["obj", "lst"]
- outputArtifacts: KEIL.compilerOutputArtifacts(
- input, input.cpp.generateCompilerListingFiles)
+ outputFileTags: Cpp.compilerOutputTags(generateCompilerListingFiles)
+ outputArtifacts: Cpp.compilerOutputArtifacts(input)
prepare: KEIL.prepareCompiler.apply(KEIL, arguments)
}
@@ -122,8 +133,9 @@ CppModule {
id: applicationLinker
multiplex: true
inputs: ["obj", "linkerscript"]
- outputFileTags: ["application", "mem_map"]
- outputArtifacts: KEIL.applicationLinkerOutputArtifacts(product)
+ inputsFromDependencies: ["staticlibrary"]
+ outputFileTags: Cpp.applicationLinkerOutputTags(generateLinkerMapFile)
+ outputArtifacts: Cpp.applicationLinkerOutputArtifacts(product)
prepare: KEIL.prepareLinker.apply(KEIL, arguments)
}
@@ -132,8 +144,8 @@ CppModule {
multiplex: true
inputs: ["obj"]
inputsFromDependencies: ["staticlibrary"]
- outputFileTags: ["staticlibrary"]
- outputArtifacts: KEIL.staticLibraryLinkerOutputArtifacts(product)
+ outputFileTags: Cpp.staticLibraryLinkerOutputTags()
+ outputArtifacts: Cpp.staticLibraryLinkerOutputArtifacts(product)
prepare: KEIL.prepareArchiver.apply(KEIL, arguments)
}
}
diff --git a/share/qbs/modules/cpp/macos-gcc.qbs b/share/qbs/modules/cpp/macos-gcc.qbs
index 612b46ae8..c667bbc29 100644
--- a/share/qbs/modules/cpp/macos-gcc.qbs
+++ b/share/qbs/modules/cpp/macos-gcc.qbs
@@ -33,8 +33,8 @@ import qbs.Utilities
DarwinGCC {
priority: 1
- condition: qbs.targetOS.contains('macos') &&
- qbs.toolchain && qbs.toolchain.contains('gcc')
+ condition: qbs.targetOS.includes('macos') &&
+ qbs.toolchain && qbs.toolchain.includes('gcc')
targetSystem: "macosx" + (minimumMacosVersion || "")
diff --git a/share/qbs/modules/cpp/msvc.js b/share/qbs/modules/cpp/msvc.js
index b67ab811f..1700c21b3 100644
--- a/share/qbs/modules/cpp/msvc.js
+++ b/share/qbs/modules/cpp/msvc.js
@@ -28,6 +28,7 @@
**
****************************************************************************/
+var Codesign = require("../codesign/codesign.js");
var Cpp = require("cpp.js");
var File = require("qbs.File");
var FileInfo = require("qbs.FileInfo");
@@ -35,6 +36,22 @@ var ModUtils = require("qbs.ModUtils");
var Utilities = require("qbs.Utilities");
var WindowsUtils = require("qbs.WindowsUtils");
+function effectiveLinkerPath(product, inputs) {
+ if (product.cpp.linkerMode === "automatic") {
+ var compiler = product.cpp.compilerPath;
+ if (compiler) {
+ if (inputs.obj || inputs.staticlibrary) {
+ console.log("Found C/C++ objects, using compiler as a linker for " + product.name);
+ return compiler;
+ }
+ }
+
+ console.log("Found no C-language objects, choosing system linker for " + product.name);
+ }
+
+ return product.cpp.linkerPath;
+}
+
function handleCpuFeatures(input, flags) {
if (!input.qbs.architecture)
return;
@@ -62,20 +79,54 @@ function hasCxx17Option(input)
{
// Probably this is not the earliest version to support the flag, but we have tested this one
// and it's a pain to find out the exact minimum.
- return Utilities.versionCompare(input.cpp.compilerVersion, "19.12.25831") >= 0
- || (input.qbs.toolchain.contains("clang-cl") && input.cpp.compilerVersionMajor >= 7);
+ return (input.qbs.toolchain.includes("clang-cl") && input.cpp.compilerVersionMajor >= 7)
+ || Utilities.versionCompare(input.cpp.compilerVersion, "19.12.25831") >= 0;
+}
+
+function hasZCplusPlusOption(input)
+{
+ // /Zc:__cplusplus is supported starting from Visual Studio 15.7
+ // Looks like closest MSVC version is 14.14.26428 (cl ver 19.14.26433)
+ // At least, this version is tested
+ // https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus
+ // clang-cl supports this option starting around-ish versions 8/9, but it
+ // ignores this option, so this doesn't really matter
+ // https://reviews.llvm.org/D45877
+ return (input.qbs.toolchain.includes("clang-cl") && input.cpp.compilerVersionMajor >= 9)
+ || Utilities.versionCompare(input.cpp.compilerVersion, "19.14.26433") >= 0;
}
-function addLanguageVersionFlag(input, args) {
+function hasCxx20Option(input)
+{
+ return (input.qbs.toolchain.includes("clang-cl") && input.cpp.compilerVersionMajor >= 13)
+ || Utilities.versionCompare(input.cpp.compilerVersion, "19.29.30133.0") >= 0;
+}
+
+function hasCVerOption(input)
+{
+ return (input.qbs.toolchain.includes("clang-cl") && input.cpp.compilerVersionMajor >= 13)
+ || Utilities.versionCompare(input.cpp.compilerVersion, "19.29.30138.0") >= 0;
+}
+
+function supportsExternalIncludesOption(input) {
+ if (input.qbs.toolchain.includes("clang-cl"))
+ return false; // Exclude clang-cl.
+ // This option was introcuded since MSVC 2017 v15.6 (aka _MSC_VER 19.13).
+ // But due to some MSVC bugs:
+ // * https://developercommunity.visualstudio.com/content/problem/181006/externali-include-paths-not-working.html
+ // this option has been fixed since MSVC 2017 update 9, v15.9 (aka _MSC_VER 19.16).
+ return Utilities.versionCompare(input.cpp.compilerVersion, "19.16") >= 0;
+}
+
+function addCxxLanguageVersionFlag(input, args) {
var cxxVersion = Cpp.languageVersion(input.cpp.cxxLanguageVersion,
- ["c++17", "c++14", "c++11", "c++98"], "C++");
+ ["c++23", "c++20", "c++17", "c++14", "c++11", "c++98"], "C++");
if (!cxxVersion)
return;
- // Visual C++ 2013, Update 3
- var hasStdOption = Utilities.versionCompare(input.cpp.compilerVersion, "18.00.30723") >= 0
- // or clang-cl
- || input.qbs.toolchain.contains("clang-cl");
+ // Visual C++ 2013, Update 3 or clang-cl
+ var hasStdOption = input.qbs.toolchain.includes("clang-cl")
+ || Utilities.versionCompare(input.cpp.compilerVersion, "18.00.30723") >= 0;
if (!hasStdOption)
return;
@@ -84,12 +135,42 @@ function addLanguageVersionFlag(input, args) {
flag = "/std:c++14";
else if (cxxVersion === "c++17" && hasCxx17Option(input))
flag = "/std:c++17";
+ else if (cxxVersion === "c++20" && hasCxx20Option(input))
+ flag = "/std:c++20";
else if (cxxVersion !== "c++11" && cxxVersion !== "c++98")
flag = "/std:c++latest";
if (flag)
args.push(flag);
}
+function addCLanguageVersionFlag(input, args) {
+ var cVersion = Cpp.languageVersion(input.cpp.cLanguageVersion,
+ ["c17", "c11"], "C");
+ if (!cVersion)
+ return;
+
+ var hasStdOption = hasCVerOption(input);
+ if (!hasStdOption)
+ return;
+
+ var flag;
+ if (cVersion === "c17")
+ flag = "/std:c17";
+ else if (cVersion === "c11")
+ flag = "/std:c11";
+ if (flag)
+ args.push(flag);
+}
+
+function handleClangClArchitectureFlags(product, architecture, flags) {
+ if (product.qbs.toolchain.includes("clang-cl")) {
+ if (architecture === "x86")
+ flags.push("-m32");
+ else if (architecture === "x86_64")
+ flags.push("-m64");
+ }
+}
+
function prepareCompiler(project, product, inputs, outputs, input, output, explicitlyDependsOn) {
var i;
var debugInformation = input.cpp.debugInformation;
@@ -99,7 +180,7 @@ function prepareCompiler(project, product, inputs, outputs, input, output, expli
// Determine which C-language we're compiling
var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(Object.keys(outputs)));
- if (!["c", "cpp"].contains(tag))
+ if (!["c", "cpp"].includes(tag))
throw ("unsupported source language");
var enableExceptions = input.cpp.enableExceptions;
@@ -135,6 +216,8 @@ function prepareCompiler(project, product, inputs, outputs, input, output, expli
break;
}
+ handleClangClArchitectureFlags(product, input.cpp.architecture, args);
+
if (debugInformation) {
if (product.cpp.separateDebugInformation)
args.push('/Zi');
@@ -150,6 +233,8 @@ function prepareCompiler(project, product, inputs, outputs, input, output, expli
args.push(rtl);
}
+ args = args.concat(Cpp.collectMiscDriverArguments(product));
+
// warnings:
var warningLevel = input.cpp.warningLevel;
if (warningLevel === 'none')
@@ -158,24 +243,33 @@ function prepareCompiler(project, product, inputs, outputs, input, output, expli
args.push('/Wall')
if (input.cpp.treatWarningsAsErrors)
args.push('/WX')
- var allIncludePaths = [];
- var includePaths = input.cpp.includePaths;
- if (includePaths)
- allIncludePaths = allIncludePaths.uniqueConcat(includePaths);
- var systemIncludePaths = input.cpp.systemIncludePaths;
- if (systemIncludePaths)
- allIncludePaths = allIncludePaths.uniqueConcat(systemIncludePaths);
- for (i in allIncludePaths)
- args.push('/I' + FileInfo.toWindowsSeparators(allIncludePaths[i]))
- var allDefines = [];
- var platformDefines = input.cpp.platformDefines;
- if (platformDefines)
- allDefines = allDefines.uniqueConcat(platformDefines);
- var defines = input.cpp.defines;
- if (defines)
- allDefines = allDefines.uniqueConcat(defines);
- for (i in allDefines)
- args.push('/D' + allDefines[i].replace(/%/g, "%%"));
+
+ var includePaths = Cpp.collectIncludePaths(input);
+ args = args.concat([].uniqueConcat(includePaths).map(function(path) {
+ return input.cpp.includeFlag + FileInfo.toWindowsSeparators(path);
+ }));
+
+ var includeFlag = input.qbs.toolchain.includes("clang-cl")
+ ? input.cpp.systemIncludeFlag : input.cpp.includeFlag;
+ if (!input.qbs.toolchain.includes("clang-cl")) {
+ if (supportsExternalIncludesOption(input)) {
+ args.push("/experimental:external");
+ var enforcesSlashW =
+ Utilities.versionCompare(input.cpp.compilerVersion, "19.29.30037") >= 0
+ if (enforcesSlashW)
+ args.push("/external:W0")
+ includeFlag = input.cpp.systemIncludeFlag;
+ }
+ }
+ var systemIncludePaths = Cpp.collectSystemIncludePaths(input);
+ args = args.concat([].uniqueConcat(systemIncludePaths).map(function(path) {
+ return includeFlag + FileInfo.toWindowsSeparators(path);
+ }));
+
+ var defines = Cpp.collectDefines(input);
+ args = args.concat([].uniqueConcat(defines).map(function(define) {
+ return input.cpp.defineFlag + define.replace(/%/g, "%%");
+ }));
var minimumWindowsVersion = product.cpp.minimumWindowsVersion;
if (minimumWindowsVersion) {
@@ -183,7 +277,7 @@ function prepareCompiler(project, product, inputs, outputs, input, output, expli
if (hexVersion) {
var versionDefs = [ 'WINVER', '_WIN32_WINNT', '_WIN32_WINDOWS' ];
for (i in versionDefs) {
- args.push('/D' + versionDefs[i] + '=' + hexVersion);
+ args.push(input.cpp.defineFlag + versionDefs[i] + '=' + hexVersion);
}
}
}
@@ -191,21 +285,29 @@ function prepareCompiler(project, product, inputs, outputs, input, output, expli
if (product.cpp.debugInformation && product.cpp.separateDebugInformation)
args.push("/Fd" + product.targetName + ".cl" + product.cpp.debugInfoSuffix);
+ if (input.cpp.generateCompilerListingFiles)
+ args.push("/Fa" + FileInfo.toWindowsSeparators(outputs.lst[0].filePath));
+
+ if (input.cpp.enableCxxLanguageMacro && hasZCplusPlusOption(input))
+ args.push("/Zc:__cplusplus");
+
var objectMap = outputs.obj || outputs.intermediate_obj
var objOutput = objectMap ? objectMap[0] : undefined
args.push('/Fo' + FileInfo.toWindowsSeparators(objOutput.filePath))
args.push(FileInfo.toWindowsSeparators(input.filePath))
- var prefixHeaders = product.cpp.prefixHeaders;
- for (i in prefixHeaders)
- args.push("/FI" + FileInfo.toWindowsSeparators(prefixHeaders[i]));
+ var preincludePaths = Cpp.collectPreincludePaths(input);
+ args = args.concat([].uniqueConcat(preincludePaths).map(function(path) {
+ return input.cpp.preincludeFlag + FileInfo.toWindowsSeparators(path);
+ }));
// Language
if (tag === "cpp") {
args.push("/TP");
- addLanguageVersionFlag(input, args);
+ addCxxLanguageVersionFlag(input, args);
} else if (tag === "c") {
args.push("/TC");
+ addCLanguageVersionFlag(input, args);
}
// Whether we're compiling a precompiled header or normal source file
@@ -213,7 +315,7 @@ function prepareCompiler(project, product, inputs, outputs, input, output, expli
var pchInputs = explicitlyDependsOn[tag + "_pch"];
if (pchOutput) {
// create PCH
- if (input.qbs.toolchain.contains("clang-cl")) {
+ if (input.qbs.toolchain.includes("clang-cl")) {
// clang-cl does not support /Yc flag without filename
args.push("/Yc" + FileInfo.toWindowsSeparators(input.filePath));
// clang-cl complains when pch file is not included
@@ -243,10 +345,7 @@ function prepareCompiler(project, product, inputs, outputs, input, output, expli
}
}
- args = args.concat(ModUtils.moduleProperty(input, 'platformFlags'),
- ModUtils.moduleProperty(input, 'flags'),
- ModUtils.moduleProperty(input, 'platformFlags', tag),
- ModUtils.moduleProperty(input, 'flags', tag));
+ args = args.concat(Cpp.collectMiscCompilerArguments(input, tag));
var compilerPath = product.cpp.compilerPath;
var wrapperArgs = product.cpp.compilerWrapper;
@@ -272,74 +371,10 @@ function prepareCompiler(project, product, inputs, outputs, input, output, expli
return [cmd];
}
-function collectLibraryDependencies(product) {
- var seen = {};
- var result = [];
-
- function addFilePath(filePath, wholeArchive, productName) {
- result.push({ filePath: filePath, wholeArchive: wholeArchive, productName: productName });
- }
-
- function addArtifactFilePaths(dep, artifacts) {
- if (!artifacts)
- return;
- var artifactFilePaths = artifacts.map(function(a) { return a.filePath; });
- var wholeArchive = dep.parameters.cpp && dep.parameters.cpp.linkWholeArchive;
- var artifactsAreImportLibs = artifacts.length > 0
- && artifacts[0].fileTags.contains("dynamiclibrary_import");
- for (var i = 0; i < artifactFilePaths.length; ++i) {
- addFilePath(artifactFilePaths[i], wholeArchive,
- artifactsAreImportLibs ? dep.name : undefined);
- }
- }
-
- function addExternalLibs(obj) {
- if (!obj.cpp)
- return;
- function ensureArray(a) {
- return Array.isArray(a) ? a : [];
- }
- function sanitizedModuleListProperty(obj, moduleName, propertyName) {
- return ensureArray(ModUtils.sanitizedModuleProperty(obj, moduleName, propertyName));
- }
- var externalLibs = [].concat(
- sanitizedModuleListProperty(obj, "cpp", "staticLibraries"),
- sanitizedModuleListProperty(obj, "cpp", "dynamicLibraries"));
- externalLibs.forEach(function (libName) {
- if (!libName.match(/\.lib$/i) && !libName.startsWith('@'))
- libName += ".lib";
- addFilePath(libName, false);
- });
- }
-
- function traverse(dep) {
- if (seen.hasOwnProperty(dep.name))
- return;
- seen[dep.name] = true;
-
- if (dep.parameters.cpp && dep.parameters.cpp.link === false)
- return;
-
- var staticLibraryArtifacts = dep.artifacts["staticlibrary"];
- var dynamicLibraryArtifacts = staticLibraryArtifacts
- ? null : dep.artifacts["dynamiclibrary_import"];
- if (staticLibraryArtifacts) {
- dep.dependencies.forEach(traverse);
- addArtifactFilePaths(dep, staticLibraryArtifacts);
- addExternalLibs(dep);
- } else if (dynamicLibraryArtifacts) {
- addArtifactFilePaths(dep, dynamicLibraryArtifacts);
- }
- }
-
- product.dependencies.forEach(traverse);
- addExternalLibs(product);
- return result;
-}
-
function linkerSupportsWholeArchive(product)
{
- return Utilities.versionCompare(product.cpp.compilerVersion, "19.0.24215.1") >= 0
+ return product.qbs.toolchainType.includes("clang-cl") ||
+ Utilities.versionCompare(product.cpp.compilerVersion, "19.0.24215.1") >= 0
}
function handleDiscardProperty(product, flags) {
@@ -355,49 +390,76 @@ function prepareLinker(project, product, inputs, outputs, input, output) {
var linkDLL = (outputs.dynamiclibrary ? true : false)
var primaryOutput = (linkDLL ? outputs.dynamiclibrary[0] : outputs.application[0])
var debugInformation = product.cpp.debugInformation;
- var additionalManifestInputs = Array.prototype.map.call(inputs["native.pe.manifest"],
+ var additionalManifestInputs = Array.prototype.map.call(inputs["native.pe.manifest"] || [],
+ function (a) {
+ return a.filePath;
+ });
+ var moduleDefinitionInputs = Array.prototype.map.call(inputs["def"] || [],
function (a) {
return a.filePath;
});
var generateManifestFiles = !linkDLL && product.cpp.generateManifestFile;
- var canEmbedManifest = (product.cpp.compilerVersionMajor >= 17); // VS 2012
+ var useClangCl = product.qbs.toolchain.includes("clang-cl");
+ var canEmbedManifest = useClangCl || product.cpp.compilerVersionMajor >= 17 // VS 2012
+
+ var linkerPath = effectiveLinkerPath(product, inputs);
+ var useCompilerDriver = linkerPath === product.cpp.compilerPath;
+ // args variable is built as follows:
+ // [linkerWrapper] linkerPath /nologo [driverFlags driverLinkerFlags]
+ // allInputs libDeps [/link] linkerArgs
+ var args = []
+
+ if (useCompilerDriver) {
+ args.push('/nologo');
+ args = args.concat(Cpp.collectMiscDriverArguments(product),
+ Cpp.collectMiscLinkerArguments(product));
+ }
+
+ var allInputs = [].concat(Cpp.collectLinkerObjectPaths(inputs),
+ Cpp.collectResourceObjectPaths(inputs));
+ args = args.concat([].uniqueConcat(allInputs).map(function(path) {
+ return FileInfo.toWindowsSeparators(path);
+ }));
- var args = ['/nologo']
+ var linkerArgs = ['/nologo']
if (linkDLL) {
- args.push('/DLL');
- args.push('/IMPLIB:' + FileInfo.toWindowsSeparators(outputs.dynamiclibrary_import[0].filePath));
+ linkerArgs.push('/DLL');
+ linkerArgs.push('/IMPLIB:' + FileInfo.toWindowsSeparators(outputs.dynamiclibrary_import[0].filePath));
}
if (debugInformation) {
- args.push("/DEBUG");
+ linkerArgs.push("/DEBUG");
var debugInfo = outputs.debuginfo_app || outputs.debuginfo_dll;
if (debugInfo)
- args.push("/PDB:" + debugInfo[0].fileName);
+ linkerArgs.push("/PDB:" + debugInfo[0].fileName);
} else {
- args.push('/INCREMENTAL:NO')
+ linkerArgs.push('/INCREMENTAL:NO')
}
switch (product.qbs.architecture) {
case "x86":
- args.push("/MACHINE:X86");
+ linkerArgs.push("/MACHINE:X86");
break;
case "x86_64":
- args.push("/MACHINE:X64");
+ linkerArgs.push("/MACHINE:X64");
break;
case "ia64":
- args.push("/MACHINE:IA64");
+ linkerArgs.push("/MACHINE:IA64");
break;
case "armv7":
- args.push("/MACHINE:ARM");
+ linkerArgs.push("/MACHINE:ARM");
break;
case "arm64":
- args.push("/MACHINE:ARM64");
+ linkerArgs.push("/MACHINE:ARM64");
break;
}
+ if (useCompilerDriver)
+ handleClangClArchitectureFlags(product, product.qbs.architecture, args);
+
var requireAppContainer = product.cpp.requireAppContainer;
if (requireAppContainer !== undefined)
- args.push("/APPCONTAINER" + (requireAppContainer ? "" : ":NO"));
+ linkerArgs.push("/APPCONTAINER" + (requireAppContainer ? "" : ":NO"));
var minimumWindowsVersion = product.cpp.minimumWindowsVersion;
var subsystemSwitch = undefined;
@@ -407,26 +469,29 @@ function prepareLinker(project, product, inputs, outputs, input, output) {
subsystemSwitch = product.consoleApplication === false ? '/SUBSYSTEM:WINDOWS' : '/SUBSYSTEM:CONSOLE';
}
+ var useLldLink = useCompilerDriver && product.cpp.linkerVariant === "lld"
+ || !useCompilerDriver && product.cpp.linkerName === "lld-link.exe";
if (minimumWindowsVersion) {
var subsystemVersion = WindowsUtils.getWindowsVersionInFormat(minimumWindowsVersion,
'subsystem');
if (subsystemVersion) {
subsystemSwitch += ',' + subsystemVersion;
- if (product.cpp.linkerName !== "lld-link.exe") // llvm linker does not support /OSVERSION
- args.push('/OSVERSION:' + subsystemVersion);
+ // llvm linker does not support /OSVERSION
+ if (!useLldLink)
+ linkerArgs.push('/OSVERSION:' + subsystemVersion);
}
}
if (subsystemSwitch)
- args.push(subsystemSwitch);
+ linkerArgs.push(subsystemSwitch);
var linkerOutputNativeFilePath = FileInfo.toWindowsSeparators(primaryOutput.filePath);
var manifestFileNames = [];
if (generateManifestFiles) {
if (canEmbedManifest) {
- args.push("/MANIFEST:embed");
+ linkerArgs.push("/MANIFEST:embed");
additionalManifestInputs.forEach(function (manifestFileName) {
- args.push("/MANIFESTINPUT:" + manifestFileName);
+ linkerArgs.push("/MANIFESTINPUT:" + manifestFileName);
});
} else {
linkerOutputNativeFilePath
@@ -435,20 +500,19 @@ function prepareLinker(project, product, inputs, outputs, input, output) {
+ primaryOutput.fileName);
var manifestFileName = linkerOutputNativeFilePath + ".manifest";
- args.push('/MANIFEST', '/MANIFESTFILE:' + manifestFileName);
+ linkerArgs.push('/MANIFEST', '/MANIFESTFILE:' + manifestFileName);
manifestFileNames = [manifestFileName].concat(additionalManifestInputs);
}
}
- var allInputs = inputs.obj || [];
- for (i in allInputs) {
- var fileName = FileInfo.toWindowsSeparators(allInputs[i].filePath)
- args.push(fileName)
- }
+ if (moduleDefinitionInputs.length === 1)
+ linkerArgs.push("/DEF:" + moduleDefinitionInputs[0]);
+ else if (moduleDefinitionInputs.length > 1)
+ throw new Error("Only one '.def' file can be specified for linking");
var wholeArchiveSupported = linkerSupportsWholeArchive(product);
var wholeArchiveRequested = false;
- var libDeps = collectLibraryDependencies(product);
+ var libDeps = Cpp.collectLibraryDependencies(product);
var prevLib;
for (i = 0; i < libDeps.length; ++i) {
var dep = libDeps[i];
@@ -456,8 +520,16 @@ function prepareLinker(project, product, inputs, outputs, input, output) {
if (lib === prevLib)
continue;
prevLib = lib;
- args.push((wholeArchiveSupported && dep.wholeArchive ? "/WHOLEARCHIVE:" : "")
- + FileInfo.toWindowsSeparators(lib));
+
+ if (wholeArchiveSupported && dep.wholeArchive) {
+ // need to pass libraries to the driver to avoid "no input files" error if no object
+ // files are specified; thus libraries are duplicated when using "WHOLEARCHIVE"
+ if (useCompilerDriver && allInputs.length === 0)
+ args.push(FileInfo.toWindowsSeparators(lib));
+ linkerArgs.push("/WHOLEARCHIVE:" + FileInfo.toWindowsSeparators(lib));
+ } else {
+ args.push(FileInfo.toWindowsSeparators(lib));
+ }
if (dep.wholeArchive)
wholeArchiveRequested = true;
}
@@ -468,25 +540,31 @@ function prepareLinker(project, product, inputs, outputs, input, output) {
}
if (product.cpp.entryPoint)
- args.push("/ENTRY:" + product.cpp.entryPoint);
+ linkerArgs.push("/ENTRY:" + product.cpp.entryPoint);
- if (outputs.application && product.cpp.generateLinkerMapFile)
- args.push("/MAP:" + outputs.mem_map[0].filePath);
-
- args.push('/OUT:' + linkerOutputNativeFilePath)
- var libraryPaths = product.cpp.libraryPaths;
- if (libraryPaths)
- libraryPaths = [].uniqueConcat(libraryPaths);
- for (i in libraryPaths) {
- args.push('/LIBPATH:' + FileInfo.toWindowsSeparators(libraryPaths[i]))
+ if (outputs.application && product.cpp.generateLinkerMapFile) {
+ if (useLldLink)
+ linkerArgs.push("/lldmap:" + outputs.mem_map[0].filePath);
+ else
+ linkerArgs.push("/MAP:" + outputs.mem_map[0].filePath);
}
- handleDiscardProperty(product, args);
+
+ if (useCompilerDriver)
+ args.push('/Fe' + linkerOutputNativeFilePath);
+ else
+ linkerArgs.push('/OUT:' + linkerOutputNativeFilePath);
+
+ var libraryPaths = Cpp.collectLibraryPaths(product);
+ linkerArgs = linkerArgs.concat([].uniqueConcat(libraryPaths).map(function(path) {
+ return product.cpp.libraryPathFlag + FileInfo.toWindowsSeparators(path);
+ }));
+
+ handleDiscardProperty(product, linkerArgs);
var linkerFlags = product.cpp.platformLinkerFlags.concat(product.cpp.linkerFlags);
- args = args.concat(linkerFlags);
+ linkerArgs = linkerArgs.concat(linkerFlags);
if (product.cpp.allowUnresolvedSymbols)
- args.push("/FORCE:UNRESOLVED");
+ linkerArgs.push("/FORCE:UNRESOLVED");
- var linkerPath = product.cpp.linkerPath;
var wrapperArgs = product.cpp.linkerWrapper;
if (wrapperArgs && wrapperArgs.length > 0) {
args.unshift(linkerPath);
@@ -509,6 +587,10 @@ function prepareLinker(project, product, inputs, outputs, input, output) {
}
};
commands.push(warningCmd);
+
+ if (linkerArgs.length !== 0)
+ args = args.concat(useCompilerDriver ? ['/link'] : []).concat(linkerArgs);
+
var cmd = new Command(linkerPath, args)
cmd.description = 'linking ' + primaryOutput.fileName;
cmd.highlight = 'linker';
@@ -516,9 +598,13 @@ function prepareLinker(project, product, inputs, outputs, input, output) {
cmd.relevantEnvironmentVariables = ["LINK", "_LINK_", "LIB", "TMP"];
cmd.workingDirectory = FileInfo.path(primaryOutput.filePath)
cmd.responseFileUsagePrefix = '@';
+ cmd.responseFileSeparator = useCompilerDriver ? ' ' : '\n';
cmd.stdoutFilterFunction = function(output) {
res = output.replace(/^.*performing full link.*\s*/, "");
- return res.replace(/^ *Creating library.*\r\n$/, "");
+ res = res.replace(/^ *Creating library.*\s*/, "");
+ res = res.replace(/^\s*Generating code\s*/, "");
+ res = res.replace(/^\s*Finished generating code\s*/, "");
+ return res;
};
commands.push(cmd);
@@ -542,6 +628,12 @@ function prepareLinker(project, product, inputs, outputs, input, output) {
commands.push(cmd);
}
+ if (product.cpp.shouldSignArtifacts) {
+ Array.prototype.push.apply(
+ commands, Codesign.prepareSigntool(
+ project, product, inputs, outputs, input, output));
+ }
+
return commands;
}
diff --git a/share/qbs/modules/cpp/qnx-qcc.qbs b/share/qbs/modules/cpp/qnx-qcc.qbs
index a39a6a998..69288ddd8 100644
--- a/share/qbs/modules/cpp/qnx-qcc.qbs
+++ b/share/qbs/modules/cpp/qnx-qcc.qbs
@@ -33,8 +33,8 @@ import qbs.FileInfo
UnixGCC {
Depends { name: "qnx" }
- condition: qbs.targetOS.contains("qnx") &&
- qbs.toolchain && qbs.toolchain.contains("qcc")
+ condition: qbs.targetOS.includes("qnx") &&
+ qbs.toolchain && qbs.toolchain.includes("qcc")
priority: 1
distributionIncludePaths: FileInfo.joinPaths(qnx.targetDir, "usr", "include")
@@ -79,7 +79,7 @@ UnixGCC {
toolchainPrefix: target + "-"
- targetVendor: ["x86", "x86_64"].contains(qbs.architecture) ? "pc" : base
+ targetVendor: ["x86", "x86_64"].includes(qbs.architecture) ? "pc" : base
targetSystem: "nto"
targetAbi: "qnx" + qnx.version + (qnxTargetArchName === "armv7le" ? "eabi" : "")
diff --git a/share/qbs/modules/cpp/sdcc.js b/share/qbs/modules/cpp/sdcc.js
index 70d0506b9..49da8a715 100644
--- a/share/qbs/modules/cpp/sdcc.js
+++ b/share/qbs/modules/cpp/sdcc.js
@@ -28,10 +28,12 @@
**
****************************************************************************/
+var BinaryFile = require("qbs.BinaryFile");
var Cpp = require("cpp.js");
var Environment = require("qbs.Environment");
var File = require("qbs.File");
var FileInfo = require("qbs.FileInfo");
+var Host = require("qbs.Host");
var ModUtils = require("qbs.ModUtils");
var PathTools = require("qbs.PathTools");
var Process = require("qbs.Process");
@@ -40,34 +42,24 @@ var TextFile = require("qbs.TextFile");
var Utilities = require("qbs.Utilities");
var WindowsUtils = require("qbs.WindowsUtils");
-function compilerName(qbs) {
- return "sdcc";
-}
-
-function assemblerName(qbs) {
- switch (qbs.architecture) {
- case "mcs51":
- return "sdas8051";
- case "stm8":
- return "sdasstm8";
- }
- throw "Unable to deduce assembler name for unsupported architecture: '"
- + qbs.architecture + "'";
-}
-
-function linkerName(qbs) {
- switch (qbs.architecture) {
- case "mcs51":
- return "sdld";
- case "stm8":
- return "sdldstm8";
+function toolchainDetails(qbs) {
+ var architecture = qbs.architecture;
+ if (architecture === "mcs51") {
+ return {
+ "assemblerName": "sdas8051",
+ "linkerName": "sdld"
+ }
+ } else if (architecture === "stm8") {
+ return {
+ "assemblerName": "sdasstm8",
+ "linkerName": "sdldstm8"
+ }
+ } else if (architecture === "hcs8") {
+ return {
+ "assemblerName": "sdas6808",
+ "linkerName": "sdld6808"
+ }
}
- throw "Unable to deduce linker name for unsupported architecture: '"
- + qbs.architecture + "'";
-}
-
-function archiverName(qbs) {
- return "sdar";
}
function targetArchitectureFlag(architecture) {
@@ -75,6 +67,8 @@ function targetArchitectureFlag(architecture) {
return "-mmcs51";
if (architecture === "stm8")
return "-mstm8";
+ if (architecture === "hcs8")
+ return "-mhc08";
}
function guessArchitecture(macros) {
@@ -82,6 +76,8 @@ function guessArchitecture(macros) {
return "mcs51";
if (macros["__SDCC_stm8"] === "1")
return "stm8";
+ if (macros["__SDCC_hc08"] === "1")
+ return "hcs8";
}
function guessEndianness(macros) {
@@ -90,10 +86,20 @@ function guessEndianness(macros) {
}
function guessVersion(macros) {
- return { major: parseInt(macros["__SDCC_VERSION_MAJOR"], 10),
- minor: parseInt(macros["__SDCC_VERSION_MINOR"], 10),
- patch: parseInt(macros["__SDCC_VERSION_PATCH"], 10),
- found: macros["SDCC"] }
+ if ("__SDCC_VERSION_MAJOR" in macros
+ && "__SDCC_VERSION_MINOR" in macros
+ && "__SDCC_VERSION_PATCH" in macros) {
+ return { major: parseInt(macros["__SDCC_VERSION_MAJOR"], 10),
+ minor: parseInt(macros["__SDCC_VERSION_MINOR"], 10),
+ patch: parseInt(macros["__SDCC_VERSION_PATCH"], 10) }
+ } else if ("__SDCC" in macros) {
+ var versions = macros["__SDCC"].split("_");
+ if (versions.length === 3) {
+ return { major: parseInt(versions[0], 10),
+ minor: parseInt(versions[1], 10),
+ patch: parseInt(versions[2], 10) };
+ }
+ }
}
function dumpMacros(compilerFilePath, architecture) {
@@ -107,12 +113,7 @@ function dumpMacros(compilerFilePath, architecture) {
var p = new Process();
p.exec(compilerFilePath, args, true);
- var map = {};
- p.readStdOut().trim().split(/\r?\n/g).map(function (line) {
- var parts = line.split(" ", 3);
- map[parts[1]] = parts[2];
- });
- return map;
+ return Cpp.extractMacros(p.readStdOut());
}
function dumpDefaultPaths(compilerFilePath, architecture) {
@@ -137,7 +138,8 @@ function dumpDefaultPaths(compilerFilePath, architecture) {
|| line.startsWith("libpath:")) {
addIncludePaths = false;
} else if (addIncludePaths) {
- includePaths.push(line);
+ if (File.exists(line))
+ includePaths.push(line);
}
}
@@ -163,142 +165,69 @@ function escapeLinkerFlags(product, linkerFlags) {
return ["-Wl " + linkerFlags.join(",")];
}
-function collectLibraryDependencies(product) {
- var seen = {};
- var result = [];
-
- function addFilePath(filePath) {
- result.push({ filePath: filePath });
- }
-
- function addArtifactFilePaths(dep, artifacts) {
- if (!artifacts)
- return;
- var artifactFilePaths = artifacts.map(function(a) { return a.filePath; });
- artifactFilePaths.forEach(addFilePath);
- }
-
- function addExternalStaticLibs(obj) {
- if (!obj.cpp)
- return;
- function ensureArray(a) {
- return Array.isArray(a) ? a : [];
- }
- function sanitizedModuleListProperty(obj, moduleName, propertyName) {
- return ensureArray(ModUtils.sanitizedModuleProperty(obj, moduleName, propertyName));
- }
- var externalLibs = [].concat(
- sanitizedModuleListProperty(obj, "cpp", "staticLibraries"));
- var staticLibrarySuffix = obj.moduleProperty("cpp", "staticLibrarySuffix");
- externalLibs.forEach(function(staticLibraryName) {
- if (!staticLibraryName.endsWith(staticLibrarySuffix))
- staticLibraryName += staticLibrarySuffix;
- addFilePath(staticLibraryName);
- });
- }
-
- function traverse(dep) {
- if (seen.hasOwnProperty(dep.name))
- return;
- seen[dep.name] = true;
-
- if (dep.parameters.cpp && dep.parameters.cpp.link === false)
- return;
-
- var staticLibraryArtifacts = dep.artifacts["staticlibrary"];
- if (staticLibraryArtifacts) {
- dep.dependencies.forEach(traverse);
- addArtifactFilePaths(dep, staticLibraryArtifacts);
- addExternalStaticLibs(dep);
- }
- }
+function escapePreprocessorFlags(preprocessorFlags) {
+ if (!preprocessorFlags || preprocessorFlags.length === 0)
+ return preprocessorFlags;
+ return ["-Wp " + preprocessorFlags.join(",")];
+}
- product.dependencies.forEach(traverse);
- addExternalStaticLibs(product);
- return result;
+// We need to use the asm_adb, asm_src, asm_sym and rst_data
+// artifacts without of any conditions. Because SDCC always generates
+// it (and seems, this behavior can not be disabled for SDCC).
+function extraCompilerOutputTags() {
+ return ["asm_adb", "asm_src", "asm_sym", "rst_data"];
}
-function compilerOutputArtifacts(input) {
- var obj = {
- fileTags: ["obj"],
- filePath: Utilities.getHash(input.baseDir) + "/"
- + input.fileName + input.cpp.objectSuffix
- };
+// We need to use the lk_cmd, and mem_summary artifacts without
+// of any conditions. Because SDCC always generates
+// it (and seems, this behavior can not be disabled for SDCC).
+function extraApplicationLinkerOutputTags() {
+ return ["lk_cmd", "mem_summary"];
+}
- // We need to use the asm_adb, lst, asm_src, asm_sym and rst_data
- // artifacts without of any conditions. Because SDCC always generates
- // it (and seems, this behavior can not be disabled for SDCC).
- var asm_adb = {
+// We need to use the asm_adb, asm_src, asm_sym and rst_data
+// artifacts without of any conditions. Because SDCC always generates
+// it (and seems, this behavior can not be disabled for SDCC).
+function extraCompilerOutputArtifacts(input) {
+ return [{
fileTags: ["asm_adb"],
filePath: Utilities.getHash(input.baseDir) + "/"
- + input.fileName + ".adb"
- };
- var lst = {
- fileTags: ["lst"],
- filePath: Utilities.getHash(input.baseDir) + "/"
- + input.fileName + ".lst"
- };
- var asm_src = {
+ + input.fileName + ".adb"
+ }, {
fileTags: ["asm_src"],
filePath: Utilities.getHash(input.baseDir) + "/"
- + input.fileName + ".asm"
- };
- var asm_sym = {
+ + input.fileName + ".asm"
+ }, {
fileTags: ["asm_sym"],
filePath: Utilities.getHash(input.baseDir) + "/"
- + input.fileName + ".sym"
- };
- var rst_data = {
+ + input.fileName + ".sym"
+ }, {
fileTags: ["rst_data"],
filePath: Utilities.getHash(input.baseDir) + "/"
- + input.fileName + ".rst"
- };
- return [obj, asm_adb, lst, asm_src, asm_sym, rst_data];
+ + input.fileName + ".rst"
+ }];
}
-function applicationLinkerOutputArtifacts(product) {
- var app = {
- fileTags: ["application"],
- filePath: FileInfo.joinPaths(
- product.destinationDirectory,
- PathTools.applicationFilePath(product))
- };
- var lk_cmd = {
+// We need to use the lk_cmd, and mem_summary artifacts without
+// of any conditions. Because SDCC always generates
+// it (and seems, this behavior can not be disabled for SDCC).
+function extraApplicationLinkerOutputArtifacts(product) {
+ return [{
fileTags: ["lk_cmd"],
filePath: FileInfo.joinPaths(
- product.destinationDirectory,
- product.targetName + ".lk")
- };
- var mem_summary = {
+ product.destinationDirectory,
+ product.targetName + ".lk")
+ }, {
fileTags: ["mem_summary"],
filePath: FileInfo.joinPaths(
- product.destinationDirectory,
- product.targetName + ".mem")
- };
- var mem_map = {
- fileTags: ["mem_map"],
- filePath: FileInfo.joinPaths(
- product.destinationDirectory,
- product.targetName + ".map")
- };
- return [app, lk_cmd, mem_summary, mem_map]
-}
-
-function staticLibraryLinkerOutputArtifacts(product) {
- var staticLib = {
- fileTags: ["staticlibrary"],
- filePath: FileInfo.joinPaths(
- product.destinationDirectory,
- PathTools.staticLibraryFilePath(product))
- };
- return [staticLib]
+ product.destinationDirectory,
+ product.targetName + ".mem")
+ }];
}
function compilerFlags(project, product, input, outputs, explicitlyDependsOn) {
- // Determine which C-language we"re compiling.
- var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(outputs.obj[0].fileTags));
-
var args = [];
+ var escapablePreprocessorFlags = [];
// Input.
args.push(input.filePath);
@@ -307,29 +236,19 @@ function compilerFlags(project, product, input, outputs, explicitlyDependsOn) {
args.push("-c");
args.push("-o", outputs.obj[0].filePath);
+ // Prefix headers.
+ escapablePreprocessorFlags = escapablePreprocessorFlags.concat(
+ Cpp.collectPreincludePathsArguments(input));
+
// Defines.
- var allDefines = [];
- var platformDefines = input.cpp.platformDefines;
- if (platformDefines)
- allDefines = allDefines.uniqueConcat(platformDefines);
- var defines = input.cpp.defines;
- if (defines)
- allDefines = allDefines.uniqueConcat(defines);
- args = args.concat(allDefines.map(function(define) { return "-D" + define }));
+ args = args.concat(Cpp.collectDefinesArguments(input));
// Includes.
- var allIncludePaths = [];
- var includePaths = input.cpp.includePaths;
- if (includePaths)
- allIncludePaths = allIncludePaths.uniqueConcat(includePaths);
- var systemIncludePaths = input.cpp.systemIncludePaths;
- if (systemIncludePaths)
- allIncludePaths = allIncludePaths.uniqueConcat(systemIncludePaths);
- var compilerIncludePaths = input.cpp.compilerIncludePaths;
- if (compilerIncludePaths)
- allIncludePaths = allIncludePaths.uniqueConcat(compilerIncludePaths);
- args = args.concat(allIncludePaths.map(function(include) { return "-I" + include }));
+ args = args.concat(Cpp.collectIncludePathsArguments(input));
+ escapablePreprocessorFlags = escapablePreprocessorFlags.concat(
+ Cpp.collectSystemIncludePathsArguments(input));
+ // Target MCU flag.
var targetFlag = targetArchitectureFlag(input.cpp.architecture);
if (targetFlag)
args.push(targetFlag);
@@ -352,56 +271,56 @@ function compilerFlags(project, product, input, outputs, explicitlyDependsOn) {
}
// Warning level flags.
- if (input.cpp.warningLevel === "none")
+ var warnings = input.cpp.warningLevel
+ if (warnings === "none") {
args.push("--less-pedantic");
+ escapablePreprocessorFlags.push("-w");
+ } else if (warnings === "all") {
+ escapablePreprocessorFlags.push("-Wall");
+ }
if (input.cpp.treatWarningsAsErrors)
args.push("--Werror");
+ // Determine which C-language we"re compiling.
+ var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(outputs.obj[0].fileTags));
+
// C language version flags.
if (tag === "c") {
- var knownValues = ["c11", "c89"];
+ var knownValues = ["c2x", "c17", "c11", "c99", "c89"];
var cLanguageVersion = Cpp.languageVersion(
input.cpp.cLanguageVersion, knownValues, "C");
switch (cLanguageVersion) {
+ case "c17":
+ cLanguageVersion = "c11";
+ // fall through
case "c89":
- args.push("--std-c89");
- break;
+ case "c99":
case "c11":
- args.push("--std-c11");
+ case "c2x":
+ args.push("--std-" + cLanguageVersion);
break;
}
}
- // Misc flags.
- args = args.concat(ModUtils.moduleProperty(input, "platformFlags"),
- ModUtils.moduleProperty(input, "flags"),
- ModUtils.moduleProperty(input, "platformFlags", tag),
- ModUtils.moduleProperty(input, "flags", tag),
- ModUtils.moduleProperty(input, "driverFlags", tag));
+ var escapedPreprocessorFlags = escapePreprocessorFlags(escapablePreprocessorFlags);
+ if (escapedPreprocessorFlags)
+ Array.prototype.push.apply(args, escapedPreprocessorFlags);
+ // Misc flags.
+ args = args.concat(Cpp.collectMiscCompilerArguments(input, tag),
+ Cpp.collectMiscDriverArguments(input));
return args;
}
function assemblerFlags(project, product, input, outputs, explicitlyDependsOn) {
- // Determine which C-language we"re compiling
- var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(outputs.obj[0].fileTags));
-
var args = [];
// Includes.
- var allIncludePaths = [];
- var systemIncludePaths = input.cpp.systemIncludePaths;
- if (systemIncludePaths)
- allIncludePaths = allIncludePaths.uniqueConcat(systemIncludePaths);
- var compilerIncludePaths = input.cpp.compilerIncludePaths;
- if (compilerIncludePaths)
- allIncludePaths = allIncludePaths.uniqueConcat(compilerIncludePaths);
- args = args.concat(allIncludePaths.map(function(include) { return "-I" + include }));
+ args = args.concat(Cpp.collectIncludePathsArguments(input));
+ args = args.concat(Cpp.collectSystemIncludePathsArguments(input, input.cpp.includeFlag));
// Misc flags.
- args = args.concat(ModUtils.moduleProperty(input, "platformFlags", tag),
- ModUtils.moduleProperty(input, "flags", tag),
- ModUtils.moduleProperty(input, "driverFlags", tag));
+ args = args.concat(Cpp.collectMiscAssemblerArguments(input, "asm"));
args.push("-ol");
args.push(outputs.obj[0].filePath);
@@ -409,7 +328,7 @@ function assemblerFlags(project, product, input, outputs, explicitlyDependsOn) {
return args;
}
-function linkerFlags(project, product, input, outputs) {
+function linkerFlags(project, product, inputs, outputs) {
var args = [];
// Target MCU flag.
@@ -417,118 +336,237 @@ function linkerFlags(project, product, input, outputs) {
if (targetFlag)
args.push(targetFlag);
- var allLibraryPaths = [];
- var libraryPaths = product.cpp.libraryPaths;
- if (libraryPaths)
- allLibraryPaths = allLibraryPaths.uniqueConcat(libraryPaths);
- var distributionLibraryPaths = product.cpp.distributionLibraryPaths;
- if (distributionLibraryPaths)
- allLibraryPaths = allLibraryPaths.uniqueConcat(distributionLibraryPaths);
-
- var libraryDependencies = collectLibraryDependencies(product);
-
var escapableLinkerFlags = [];
// Map file generation flag.
if (product.cpp.generateLinkerMapFile)
escapableLinkerFlags.push("-m");
- if (product.cpp.platformLinkerFlags)
- Array.prototype.push.apply(escapableLinkerFlags, product.cpp.platformLinkerFlags);
- if (product.cpp.linkerFlags)
- Array.prototype.push.apply(escapableLinkerFlags, product.cpp.linkerFlags);
+ escapableLinkerFlags = escapableLinkerFlags.concat(Cpp.collectMiscEscapableLinkerArguments(product));
var useCompilerDriver = useCompilerDriverLinker(product);
- if (useCompilerDriver) {
- // Output.
- args.push("-o", outputs.application[0].filePath);
-
- // Inputs.
- if (inputs.obj)
- args = args.concat(inputs.obj.map(function(obj) { return obj.filePath }));
-
- // Library paths.
- args = args.concat(allLibraryPaths.map(function(path) { return "-L" + path }));
-
- // Linker scripts.
- var scripts = inputs.linkerscript
- ? inputs.linkerscript.map(function(scr) { return "-f" + scr.filePath; }) : [];
- if (scripts)
- Array.prototype.push.apply(escapableLinkerFlags, scripts);
- } else {
- // Output.
- args.push(outputs.application[0].filePath);
-
- // Inputs.
- if (inputs.obj)
- args = args.concat(inputs.obj.map(function(obj) { return obj.filePath }));
-
- // Library paths.
- args = args.concat(allLibraryPaths.map(function(path) { return "-k" + path }));
-
- // Linker scripts.
- // Note: We need to split the '-f' and the file path to separate
- // lines; otherwise the linking fails.
- inputs.linkerscript.forEach(function(scr) {
- escapableLinkerFlags.push("-f", scr.filePath);
- });
- }
+
+ // Output.
+ if (useCompilerDriver)
+ args.push("-o");
+ args.push(outputs.application[0].filePath);
+
+ // Inputs.
+ args = args.concat(Cpp.collectLinkerObjectPaths(inputs));
+
+ // Library paths.
+ var libraryPathFlag = useCompilerDriver ? "-L" : "-k";
+ args = args.concat(Cpp.collectLibraryPathsArguments(product, libraryPathFlag));
+
+ // Linker scripts.
+ // Note: We need to split the '-f' flag and the file path to separate
+ // lines when we don't use the compiler driver mode.
+ escapableLinkerFlags = escapableLinkerFlags.concat(
+ Cpp.collectLinkerScriptPathsArguments(product, inputs, !useCompilerDriver));
// Library dependencies.
- if (libraryDependencies)
- args = args.concat(libraryDependencies.map(function(dep) { return "-l" + dep.filePath }));
+ args = args.concat(Cpp.collectLibraryDependenciesArguments(product));
- // Misc flags.
var escapedLinkerFlags = escapeLinkerFlags(product, escapableLinkerFlags);
if (escapedLinkerFlags)
Array.prototype.push.apply(args, escapedLinkerFlags);
- var driverLinkerFlags = useCompilerDriver ? product.cpp.driverLinkerFlags : undefined;
- if (driverLinkerFlags)
- Array.prototype.push.apply(args, driverLinkerFlags);
+
+ // Misc flags.
+ if (useCompilerDriver) {
+ args = args.concat(Cpp.collectMiscLinkerArguments(product),
+ Cpp.collectMiscDriverArguments(product));
+ }
return args;
}
-function archiverFlags(project, product, input, outputs) {
+function archiverFlags(project, product, inputs, outputs) {
var args = ["-rc"];
args.push(outputs.staticlibrary[0].filePath);
- if (inputs.obj)
- args = args.concat(inputs.obj.map(function(obj) { return obj.filePath }));
+ args = args.concat(Cpp.collectLinkerObjectPaths(inputs));
return args;
}
+function buildLinkerMapFilePath(target, suffix) {
+ return FileInfo.joinPaths(FileInfo.path(target.filePath),
+ FileInfo.completeBaseName(target.fileName) + suffix);
+}
+
+// This is the workaround for the SDCC bug on a Windows host:
+// * https://sourceforge.net/p/sdcc/bugs/2970/
+// We need to replace the '\r\n\' line endings with the'\n' line
+// endings for each generated object file.
+function patchObjectFile(project, product, inputs, outputs, input, output) {
+ var isWindows = Host.os().includes("windows");
+ if (isWindows && input.cpp.debugInformation) {
+ var cmd = new JavaScriptCommand();
+ cmd.objectPath = outputs.obj[0].filePath;
+ cmd.silent = true;
+ cmd.sourceCode = function() {
+ var file = new BinaryFile(objectPath, BinaryFile.ReadWrite);
+ var data = file.read(file.size());
+ file.resize(0);
+ for (var pos = 0; pos < data.length; ++pos) {
+ // Find the next index of CR (\r) symbol.
+ var index = data.indexOf(0x0d, pos);
+ if (index < 0)
+ index = data.length;
+ // Write next data chunk between the previous position and the CR
+ // symbol, exclude the CR symbol.
+ file.write(data.slice(pos, index));
+ pos = index;
+ }
+ };
+ return cmd;
+ }
+}
+
+// It is a workaround which removes the generated linker map file
+// if it is disabled by cpp.generateLinkerMapFile property.
+// Reason is that the SDCC compiler always generates this file,
+// and does not have an option to disable generation for a linker
+// map file. So, we can to remove a listing files only after the
+// linking completes.
+function removeLinkerMapFile(project, product, inputs, outputs, input, output) {
+ if (!product.cpp.generateLinkerMapFile) {
+ var target = outputs.application[0];
+ var cmd = new JavaScriptCommand();
+ cmd.mapFilePath = buildLinkerMapFilePath(target, product.cpp.linkerMapSuffix)
+ cmd.silent = true;
+ cmd.sourceCode = function() { File.remove(mapFilePath); };
+ return cmd;
+ }
+}
+
+// It is a workaround to rename the extension of the output linker
+// map file to the specified one, since the linker generates only
+// files with the '.map' extension.
+function renameLinkerMapFile(project, product, inputs, outputs, input, output) {
+ if (product.cpp.generateLinkerMapFile && (product.cpp.linkerMapSuffix !== ".map")) {
+ var target = outputs.application[0];
+ var cmd = new JavaScriptCommand();
+ cmd.newMapFilePath = buildLinkerMapFilePath(target, product.cpp.linkerMapSuffix);
+ cmd.oldMapFilePath = buildLinkerMapFilePath(target, ".map");
+ cmd.silent = true;
+ cmd.sourceCode = function() { File.move(oldMapFilePath, newMapFilePath); };
+ return cmd;
+ }
+}
+
+// It is a workaround which removes the generated listing files
+// if it is disabled by cpp.generateCompilerListingFiles property
+// or when the cpp.compilerListingSuffix differs with '.lst'.
+// Reason is that the SDCC compiler does not have an option to
+// disable generation for a listing files. Besides, the SDCC
+// compiler use this files and for the linking. So, we can to
+// remove a listing files only after the linking completes.
+function removeCompilerListingFiles(project, product, inputs, outputs, input, output) {
+ var cmd = new JavaScriptCommand();
+ cmd.silent = true;
+ cmd.sourceCode = function() {
+ inputs.obj.forEach(function(object) {
+ if (!object.filePath.endsWith(".c" + object.cpp.objectSuffix))
+ return; // Skip the assembler generated objects.
+ if (!object.cpp.generateCompilerListingFiles
+ || (object.cpp.compilerListingSuffix !== ".lst")) {
+ var listingPath = FileInfo.joinPaths(FileInfo.path(object.filePath),
+ object.completeBaseName + ".lst");
+ File.remove(listingPath);
+ }
+ })
+ };
+ return cmd;
+}
+
+// It is a workaround that duplicates the generated listing files
+// but with desired names. The problem is that the SDCC compiler does
+// not support an options to specify names for the generated listing
+// files. At the same time, the compiler always generates the listing
+// files in the form of 'module.c.lst', which makes it impossible to
+// change the file suffix to a user-specified one. In addition, these
+// files are also somehow used for linking. Thus, we can not rename them
+// on the compiling stage.
+function duplicateCompilerListingFile(project, product, inputs, outputs, input, output) {
+ if (input.cpp.generateCompilerListingFiles
+ && (input.cpp.compilerListingSuffix !== ".lst")) {
+ var cmd = new JavaScriptCommand();
+ cmd.newListing = outputs.lst[0].filePath;
+ cmd.oldListing = FileInfo.joinPaths(FileInfo.path(outputs.lst[0].filePath),
+ outputs.lst[0].completeBaseName + ".lst");
+ cmd.silent = true;
+ cmd.sourceCode = function() { File.copy(oldListing, newListing); };
+ return cmd;
+ }
+}
+
function prepareCompiler(project, product, inputs, outputs, input, output, explicitlyDependsOn) {
+ var cmds = [];
var args = compilerFlags(project, product, input, outputs, explicitlyDependsOn);
var compilerPath = input.cpp.compilerPath;
var cmd = new Command(compilerPath, args);
cmd.description = "compiling " + input.fileName;
cmd.highlight = "compiler";
- return [cmd];
+ cmd.jobPool = "compiler";
+ cmds.push(cmd);
+
+ cmd = patchObjectFile(project, product, inputs, outputs, input, output);
+ if (cmd)
+ cmds.push(cmd);
+
+ cmd = duplicateCompilerListingFile(project, product, inputs, outputs, input, output);
+ if (cmd)
+ cmds.push(cmd);
+
+ return cmds;
}
function prepareAssembler(project, product, inputs, outputs, input, output, explicitlyDependsOn) {
+ var cmds = [];
var args = assemblerFlags(project, product, input, outputs, explicitlyDependsOn);
var assemblerPath = input.cpp.assemblerPath;
var cmd = new Command(assemblerPath, args);
cmd.description = "assembling " + input.fileName;
cmd.highlight = "compiler";
- return [cmd];
+ cmd.jobPool = "assembler";
+ cmds.push(cmd);
+
+ cmd = patchObjectFile(project, product, inputs, outputs, input, output);
+ if (cmd)
+ cmds.push(cmd);
+
+ return cmds;
}
function prepareLinker(project, product, inputs, outputs, input, output) {
- var primaryOutput = outputs.application[0];
- var args = linkerFlags(project, product, input, outputs);
+ var cmds = [];
+ var args = linkerFlags(project, product, inputs, outputs);
var linkerPath = effectiveLinkerPath(product);
var cmd = new Command(linkerPath, args);
- cmd.description = "linking " + primaryOutput.fileName;
+ cmd.description = "linking " + outputs.application[0].fileName;
cmd.highlight = "linker";
- return [cmd];
+ cmd.jobPool = "linker";
+ cmds.push(cmd);
+
+ cmd = removeCompilerListingFiles(project, product, inputs, outputs, input, output);
+ if (cmd)
+ cmds.push(cmd);
+
+ cmd = renameLinkerMapFile(project, product, inputs, outputs, input, output);
+ if (cmd)
+ cmds.push(cmd);
+
+ cmd = removeLinkerMapFile(project, product, inputs, outputs, input, output);
+ if (cmd)
+ cmds.push(cmd);
+
+ return cmds;
}
function prepareArchiver(project, product, inputs, outputs, input, output) {
- var args = archiverFlags(project, product, input, outputs);
+ var args = archiverFlags(project, product, inputs, outputs);
var archiverPath = product.cpp.archiverPath;
var cmd = new Command(archiverPath, args);
- cmd.description = "linking " + output.fileName;
+ cmd.description = "creating " + output.fileName;
cmd.highlight = "linker";
+ cmd.jobPool = "linker";
return [cmd];
}
diff --git a/share/qbs/modules/cpp/sdcc.qbs b/share/qbs/modules/cpp/sdcc.qbs
index ec763ba47..24cb6d738 100644
--- a/share/qbs/modules/cpp/sdcc.qbs
+++ b/share/qbs/modules/cpp/sdcc.qbs
@@ -28,15 +28,14 @@
**
****************************************************************************/
-import qbs 1.0
import qbs.File
import qbs.FileInfo
-import qbs.ModUtils
import qbs.Probes
+import "cpp.js" as Cpp
import "sdcc.js" as SDCC
CppModule {
- condition: qbs.toolchain && qbs.toolchain.contains("sdcc")
+ condition: qbs.toolchain && qbs.toolchain.includes("sdcc")
Probes.BinaryProbe {
id: compilerPathProbe
@@ -48,10 +47,12 @@ CppModule {
id: sdccProbe
condition: !_skipAllChecks
compilerFilePath: compilerPath
+ enableDefinesByLanguage: enableCompilerDefinesByLanguage
preferredArchitecture: qbs.architecture
}
qbs.architecture: sdccProbe.found ? sdccProbe.architecture : original
+ qbs.targetPlatform: "none"
compilerVersionMajor: sdccProbe.versionMajor
compilerVersionMinor: sdccProbe.versionMinor
@@ -61,10 +62,7 @@ CppModule {
compilerDefinesByLanguage: sdccProbe.compilerDefinesByLanguage
compilerIncludePaths: sdccProbe.includePaths
- property string toolchainInstallPath: compilerPathProbe.found
- ? compilerPathProbe.path : undefined
-
- property string compilerExtension: qbs.hostOS.contains("windows") ? ".exe" : ""
+ toolchainInstallPath: compilerPathProbe.found ? compilerPathProbe.path : undefined
/* Work-around for QtCreator which expects these properties to exist. */
property string cCompilerName: compilerName
@@ -72,47 +70,53 @@ CppModule {
property string linkerMode: "automatic"
- compilerName: SDCC.compilerName(qbs) + compilerExtension
+ compilerName: "sdcc" + compilerExtension
compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName)
- assemblerName: SDCC.assemblerName(qbs) + compilerExtension
+ assemblerName: toolchainDetails.assemblerName + compilerExtension
assemblerPath: FileInfo.joinPaths(toolchainInstallPath, assemblerName)
- linkerName: SDCC.linkerName(qbs) + compilerExtension
+ linkerName: toolchainDetails.linkerName + compilerExtension
linkerPath: FileInfo.joinPaths(toolchainInstallPath, linkerName)
- property string archiverName: SDCC.archiverName(qbs) + compilerExtension
+ property string archiverName: "sdar" + compilerExtension
property string archiverPath: FileInfo.joinPaths(toolchainInstallPath, archiverName)
runtimeLibrary: "static"
staticLibrarySuffix: ".lib"
executableSuffix: ".ihx"
-
- property string objectSuffix: ".rel"
+ objectSuffix: ".rel"
imageFormat: "ihx"
enableExceptions: false
enableRtti: false
+ defineFlag: "-D"
+ includeFlag: "-I"
+ systemIncludeFlag: "-isystem"
+ preincludeFlag: "-include"
+ libraryDependencyFlag: "-l"
+ libraryPathFlag: "-L"
+ linkerScriptFlag: "-f"
+
+ toolchainDetails: SDCC.toolchainDetails(qbs)
+
+ knownArchitectures: ["hcs8", "mcs51", "stm8"]
+
Rule {
id: assembler
inputs: ["asm"]
- outputFileTags: ["obj", "asm_adb", "lst", "asm_src", "asm_sym", "rst_data"]
- outputArtifacts: SDCC.compilerOutputArtifacts(input)
+ outputFileTags: SDCC.extraCompilerOutputTags().concat(
+ Cpp.assemblerOutputTags(generateAssemblerListingFiles))
+ outputArtifacts: SDCC.extraCompilerOutputArtifacts(input).concat(
+ Cpp.assemblerOutputArtifacts(input))
prepare: SDCC.prepareAssembler.apply(SDCC, arguments)
}
FileTagger {
- condition: qbs.architecture === "arm";
- patterns: "*.s"
- fileTags: ["asm"]
- }
-
- FileTagger {
- condition: qbs.architecture === "mcs51";
- patterns: ["*.s51", "*.asm"]
+ patterns: ["*.s", "*.a51", "*.asm"]
fileTags: ["asm"]
}
@@ -120,8 +124,10 @@ CppModule {
id: compiler
inputs: ["cpp", "c"]
auxiliaryInputs: ["hpp"]
- outputFileTags: ["obj", "asm_adb", "lst", "asm_src", "asm_sym", "rst_data"]
- outputArtifacts: SDCC.compilerOutputArtifacts(input)
+ outputFileTags: SDCC.extraCompilerOutputTags().concat(
+ Cpp.compilerOutputTags(generateCompilerListingFiles))
+ outputArtifacts: SDCC.extraCompilerOutputArtifacts(input).concat(
+ Cpp.compilerOutputArtifacts(input))
prepare: SDCC.prepareCompiler.apply(SDCC, arguments)
}
@@ -130,8 +136,10 @@ CppModule {
multiplex: true
inputs: ["obj", "linkerscript"]
inputsFromDependencies: ["staticlibrary"]
- outputFileTags: ["application", "lk_cmd", "mem_summary", "mem_map"]
- outputArtifacts: SDCC.applicationLinkerOutputArtifacts(product)
+ outputFileTags: SDCC.extraApplicationLinkerOutputTags().concat(
+ Cpp.applicationLinkerOutputTags(generateLinkerMapFile))
+ outputArtifacts: SDCC.extraApplicationLinkerOutputArtifacts(product).concat(
+ Cpp.applicationLinkerOutputArtifacts(product))
prepare: SDCC.prepareLinker.apply(SDCC, arguments)
}
@@ -140,8 +148,8 @@ CppModule {
multiplex: true
inputs: ["obj"]
inputsFromDependencies: ["staticlibrary"]
- outputFileTags: ["staticlibrary"]
- outputArtifacts: SDCC.staticLibraryLinkerOutputArtifacts(product)
+ outputFileTags: Cpp.staticLibraryLinkerOutputTags()
+ outputArtifacts: Cpp.staticLibraryLinkerOutputArtifacts(product)
prepare: SDCC.prepareArchiver.apply(SDCC, arguments)
}
}
diff --git a/share/qbs/modules/cpp/setuprunenv.js b/share/qbs/modules/cpp/setuprunenv.js
index 550d08d63..2ea331a30 100644
--- a/share/qbs/modules/cpp/setuprunenv.js
+++ b/share/qbs/modules/cpp/setuprunenv.js
@@ -30,11 +30,12 @@
var FileInfo = require("qbs.FileInfo");
var File = require("qbs.File");
+var Host = require("qbs.Host");
var ModUtils = require("qbs.ModUtils"); // TODO: append/prepend functionality should go to qbs.Environment
function addNewElement(list, elem)
{
- if (!list.contains(elem))
+ if (!list.includes(elem))
list.push(elem);
}
@@ -48,7 +49,7 @@ function artifactDir(artifact)
function addExternalLibPath(product, list, path)
{
addNewElement(list, path);
- if (product.qbs.hostOS.contains("windows") && FileInfo.fileName(path) === "lib") {
+ if (Host.os().includes("windows") && FileInfo.fileName(path) === "lib") {
var binPath = FileInfo.joinPaths(FileInfo.path(path), "bin");
if (File.exists(binPath))
addNewElement(list, binPath);
@@ -57,7 +58,7 @@ function addExternalLibPath(product, list, path)
function gatherPaths(product, libPaths, frameworkPaths, seenProducts)
{
- if (seenProducts.contains(product.name))
+ if (seenProducts.includes(product.name))
return;
seenProducts.push(product.name);
@@ -66,6 +67,8 @@ function gatherPaths(product, libPaths, frameworkPaths, seenProducts)
product.cpp.libraryPaths.forEach(function(p) { addExternalLibPath(product, libPaths, p); });
if (product.cpp && product.cpp.frameworkPaths)
product.cpp.frameworkPaths.forEach(function(p) { addNewElement(frameworkPaths, p); });
+ if (product.cpp && product.cpp.systemFrameworkPaths)
+ product.cpp.systemFrameworkPaths.forEach(function(p) { addNewElement(frameworkPaths, p); });
// Extract paths from dynamic libraries, if they are given as file paths.
if (product.cpp && product.cpp.dynamicLibraries) {
@@ -103,10 +106,10 @@ function gatherPaths(product, libPaths, frameworkPaths, seenProducts)
function setupRunEnvironment(product, config)
{
- if (config.contains("ignore-lib-dependencies"))
+ if (config.includes("ignore-lib-dependencies"))
return;
- if (product.qbs.hostPlatform !== product.qbs.targetPlatform)
+ if (Host.platform() !== product.qbs.targetPlatform)
return;
var libPaths = [];
@@ -117,8 +120,8 @@ function setupRunEnvironment(product, config)
if (runPaths && runPaths.length > 0) {
var canonicalRunPaths = runPaths.map(function(p) { return File.canonicalFilePath(p); });
var filterFunc = function(libPath) {
- return !runPaths.contains(libPath)
- && !canonicalRunPaths.contains(File.canonicalFilePath(libPath));
+ return !runPaths.includes(libPath)
+ && !canonicalRunPaths.includes(File.canonicalFilePath(libPath));
};
libPaths = libPaths.filter(filterFunc);
frameworkPaths = frameworkPaths.filter(filterFunc);
@@ -126,19 +129,19 @@ function setupRunEnvironment(product, config)
if (libPaths.length > 0) {
var envVarName;
- if (product.qbs.targetOS.contains("windows"))
+ if (product.qbs.targetOS.includes("windows"))
envVarName = "PATH";
- else if (product.qbs.targetOS.contains("macos"))
+ else if (product.qbs.targetOS.includes("macos"))
envVarName = "DYLD_LIBRARY_PATH";
else
envVarName = "LD_LIBRARY_PATH";
- var envVar = new ModUtils.EnvironmentVariable(envVarName, product.qbs.pathListSeparator,
- product.qbs.hostOS.contains("windows"));
+ var envVar = new ModUtils.EnvironmentVariable(envVarName, FileInfo.pathListSeparator(),
+ Host.os().includes("windows"));
libPaths.forEach(function(p) { envVar.prepend(p); });
envVar.set();
}
- if (product.qbs.targetOS.contains("macos") && frameworkPaths.length > 0) {
+ if (product.qbs.targetOS.includes("macos") && frameworkPaths.length > 0) {
envVar = new ModUtils.EnvironmentVariable("DYLD_FRAMEWORK_PATH", ':', false);
frameworkPaths.forEach(function(p) { envVar.prepend(p); });
envVar.set();
diff --git a/share/qbs/modules/cpp/tvos-gcc.qbs b/share/qbs/modules/cpp/tvos-gcc.qbs
index 19bc9b787..eba3b091e 100644
--- a/share/qbs/modules/cpp/tvos-gcc.qbs
+++ b/share/qbs/modules/cpp/tvos-gcc.qbs
@@ -30,16 +30,16 @@
DarwinGCC {
priority: 1
- condition: qbs.targetOS.contains('tvos') &&
- qbs.toolchain && qbs.toolchain.contains('gcc')
+ condition: qbs.targetOS.includes('tvos') &&
+ qbs.toolchain && qbs.toolchain.includes('gcc')
targetSystem: "tvos" + (minimumTvosVersion || "")
minimumDarwinVersion: minimumTvosVersion
- minimumDarwinVersionCompilerFlag: qbs.targetOS.contains("tvos-simulator")
+ minimumDarwinVersionCompilerFlag: qbs.targetOS.includes("tvos-simulator")
? "-mtvos-simulator-version-min"
: "-mtvos-version-min"
- minimumDarwinVersionLinkerFlag: qbs.targetOS.contains("tvos-simulator")
+ minimumDarwinVersionLinkerFlag: qbs.targetOS.includes("tvos-simulator")
? "-tvos_simulator_version_min"
: "-tvos_version_min"
}
diff --git a/share/qbs/modules/cpp/watchos-gcc.qbs b/share/qbs/modules/cpp/watchos-gcc.qbs
index 46e4bf874..3a160f6d0 100644
--- a/share/qbs/modules/cpp/watchos-gcc.qbs
+++ b/share/qbs/modules/cpp/watchos-gcc.qbs
@@ -31,16 +31,16 @@
DarwinGCC {
priority: 1
- condition: qbs.targetOS.contains('watchos') &&
- qbs.toolchain && qbs.toolchain.contains('gcc')
+ condition: qbs.targetOS.includes('watchos') &&
+ qbs.toolchain && qbs.toolchain.includes('gcc')
targetSystem: "watchos" + (minimumWatchosVersion || "")
minimumDarwinVersion: minimumWatchosVersion
- minimumDarwinVersionCompilerFlag: qbs.targetOS.contains("watchos-simulator")
+ minimumDarwinVersionCompilerFlag: qbs.targetOS.includes("watchos-simulator")
? "-mwatchos-simulator-version-min"
: "-mwatchos-version-min"
- minimumDarwinVersionLinkerFlag: qbs.targetOS.contains("watchos-simulator")
+ minimumDarwinVersionLinkerFlag: qbs.targetOS.includes("watchos-simulator")
? "-watchos_simulator_version_min"
: "-watchos_version_min"
}
diff --git a/share/qbs/modules/cpp/watcom.js b/share/qbs/modules/cpp/watcom.js
new file mode 100644
index 000000000..9ae893db9
--- /dev/null
+++ b/share/qbs/modules/cpp/watcom.js
@@ -0,0 +1,568 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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.
+**
+****************************************************************************/
+
+var Cpp = require("cpp.js");
+var Environment = require("qbs.Environment");
+var File = require("qbs.File");
+var FileInfo = require("qbs.FileInfo");
+var ModUtils = require("qbs.ModUtils");
+var PathTools = require("qbs.PathTools");
+var Process = require("qbs.Process");
+var TemporaryDir = require("qbs.TemporaryDir");
+var TextFile = require("qbs.TextFile");
+var Utilities = require("qbs.Utilities");
+
+function toolchainDetails(qbs) {
+ var platform = qbs.targetPlatform;
+ var details = {};
+ if (platform === "dos") {
+ details.imageFormat = "mz";
+ details.executableSuffix = ".exe";
+ } else if (platform === "os2") {
+ details.imageFormat = "pe";
+ details.executableSuffix = ".exe";
+ details.dynamicLibrarySuffix = ".dll";
+ } else if (platform === "windows") {
+ details.imageFormat = "pe";
+ details.executableSuffix = ".exe";
+ details.dynamicLibrarySuffix = ".dll";
+ } else if (platform === "linux") {
+ details.imageFormat = "elf";
+ details.executableSuffix = "";
+ details.dynamicLibrarySuffix = ".so";
+ }
+ return details;
+}
+
+function languageFlag(tag) {
+ if (tag === "c")
+ return "-xc";
+ else if (tag === "cpp")
+ return "-xc++";
+}
+
+function targetFlag(platform, architecture, type) {
+ if (platform === "dos") {
+ if (architecture === "x86_16")
+ return "-bdos";
+ else if (architecture === "x86")
+ return "-bdos4g";
+ } else if (platform === "os2") {
+ if (architecture === "x86_16")
+ return "-bos2";
+ else if (architecture === "x86")
+ return "-bos2v2";
+ } else if (platform === "windows") {
+ if (architecture === "x86_16") {
+ if (type.includes("dynamiclibrary"))
+ return "-bwindows_dll";
+ return "-bwindows";
+ } else if (architecture === "x86") {
+ if (type.includes("dynamiclibrary"))
+ return "-bnt_dll";
+ return "-bnt";
+ }
+ } else if (platform === "linux") {
+ return "-blinux";
+ }
+}
+
+function guessVersion(macros) {
+ var version = parseInt(macros["__WATCOMC__"], 10)
+ || parseInt(macros["__WATCOM_CPLUSPLUS__"], 10);
+ if (version) {
+ return { major: parseInt((version - 1100) / 100),
+ minor: parseInt(version / 10) % 10,
+ patch: ((version % 10) > 0) ? parseInt(version % 10) : 0 }
+ }
+}
+
+function guessEnvironment(hostOs, platform, architecture,
+ toolchainInstallPath, pathListSeparator) {
+ var toolchainRootPath = FileInfo.path(toolchainInstallPath);
+ if (!File.exists(toolchainRootPath)) {
+ throw "Unable to deduce environment due to compiler root directory: '"
+ + toolchainRootPath + "' does not exist";
+ }
+
+ var env = {};
+
+ function setVariable(key, properties, path, separator) {
+ var values = [];
+ for (var i = 0; i < properties.length; ++i) {
+ if (path) {
+ var fullpath = FileInfo.joinPaths(path, properties[i]);
+ values.push(FileInfo.toNativeSeparators(fullpath));
+ } else {
+ values.push(properties[i]);
+ }
+ }
+ env[key] = values.join(separator);
+ }
+
+ setVariable("WATCOM", [toolchainRootPath], undefined, pathListSeparator);
+ setVariable("EDPATH", ["eddat"], toolchainRootPath, pathListSeparator);
+
+ if (hostOs.includes("linux"))
+ setVariable("PATH", ["binl64", "binl"], toolchainRootPath, pathListSeparator);
+ else if (hostOs.includes("windows"))
+ setVariable("PATH", ["binnt64", "binnt"], toolchainRootPath, pathListSeparator);
+
+ if (platform === "linux") {
+ setVariable("INCLUDE", ["lh"], toolchainRootPath, pathListSeparator);
+ } else {
+ // Common for DOS, Windows, OS/2.
+ setVariable("WIPFC", ["wipfc"], toolchainRootPath, pathListSeparator);
+ setVariable("WHTMLHELP", ["binnt/help"], toolchainRootPath, pathListSeparator);
+
+ var includes = ["h"];
+ if (platform === "dos") {
+ // Same includes as before.
+ } else if (platform === "os2") {
+ if (architecture === "x86")
+ includes = includes.concat(["h/os2"]);
+ else if (architecture === "x86_16")
+ includes = includes.concat(["h/os21x"]);
+ } else if (platform === "windows") {
+ if (architecture === "x86")
+ includes = includes.concat(["h/nt", "h/nt/directx", "h/nt/ddk"]);
+ else if (architecture === "x86_16")
+ includes = includes.concat(["h/win"]);
+ } else {
+ throw "Unable to deduce environment for unsupported target platform: '"
+ + platform + "'";
+ }
+
+ setVariable("INCLUDE", includes, toolchainRootPath, pathListSeparator);
+ }
+
+ return env;
+}
+
+function dumpMacros(environment, compilerPath, platform, architecture, tag) {
+ // Note: The Open Watcom compiler does not support the predefined
+ // macros dumping. So, we do it with the following trick, where we try
+ // to create and compile a special temporary file and to parse the console
+ // output with the own magic pattern: #define <key> <value>.
+
+ var outputDirectory = new TemporaryDir();
+ var outputFilePath = FileInfo.joinPaths(outputDirectory.path(), "dump-macros.c");
+ var outputFile = new TextFile(outputFilePath, TextFile.WriteOnly);
+ outputFile.writeLine("#define VALUE_TO_STRING(x) #x");
+ outputFile.writeLine("#define VALUE(x) VALUE_TO_STRING(x)");
+ outputFile.writeLine("#define VAR_NAME_VALUE(var) \"#define \"#var\" \"VALUE(var)");
+ // Declare all available pre-defined macros of Watcon compiler.
+ var keys = [
+ // Prepare the DOS target macros.
+ "__DOS__", "_DOS", "MSDOS",
+ // Prepare the OS/2 target macros.
+ "__OS2__",
+ // Prepare the QNX target macros.
+ "__QNX__",
+ // Prepare the Netware target macros.
+ "__NETWARE__", "__NETWARE_386__",
+ // Prepare the Windows target macros.
+ "__NT__", "__WINDOWS__", "_WINDOWS", "__WINDOWS_386__",
+ // Prepare the Linux and Unix target macros.
+ "__LINUX__", "__UNIX__",
+ // Prepare the 16-bit target specific macros.
+ "__I86__", "M_I86", "_M_I86", "_M_IX86",
+ // Prepare the 32-bit target specific macros.
+ "__386__", "M_I386", "_M_I386", "_M_IX86",
+ // Prepare the indicated options macros.
+ "_MT", "_DLL", "__FPI__", "__CHAR_SIGNED__", "__INLINE_FUNCTIONS__",
+ "_CPPRTTI", "_CPPUNWIND", "NO_EXT_KEYS",
+ // Prepare the common memory model macros.
+ "__FLAT__", "__SMALL__", "__MEDIUM__",
+ "__COMPACT__", "__LARGE__", "__HUGE__",
+ // Prepare the 16-bit memory model macros.
+ "M_I86SM", "_M_I86SM", "M_I86MM", "_M_I86MM", "M_I86CM",
+ "_M_I86CM", "M_I86LM", "_M_I86LM", "M_I86HM", "_M_I86HM",
+ // Prepare the 32-bit memory model macros.
+ "M_386FM", "_M_386FM", "M_386SM", "M_386MM", "_M_386MM",
+ "M_386CM", "_M_386CM", "M_386LM", "_M_386LM",
+ // Prepare the compiler macros.
+ "__X86__", "__cplusplus", "__WATCOMC__", "__WATCOM_CPLUSPLUS__",
+ "_INTEGRAL_MAX_BITS", "_PUSHPOP_SUPPORTED", "_STDCALL_SUPPORTED",
+ // Prepare the other macros.
+ "__3R__", "_based", "_cdecl", "cdecl", "_export", "_far16", "_far", "far",
+ "_fastcall", "_fortran", "fortran", "_huge", "huge", "_inline", "_interrupt",
+ "interrupt", "_loadds", "_near", "near", "_pascal", "pascal", "_saveregs",
+ "_segment", "_segname", "_self", "SOMDLINK", "_STDCALL_SUPPORTED", "__SW_0",
+ "__SW_3R", "__SW_5", "__SW_FP287", "__SW_FP2", "__SW_FP387", "__SW_FP3",
+ "__SW_FPI", "__SW_MF", "__SW_MS", "__SW_ZDP", "__SW_ZFP", "__SW_ZGF",
+ "__SW_ZGP", "_stdcall", "_syscall", "__BIG_ENDIAN"
+ ];
+ for (var i = 0; i < keys.length; ++i) {
+ var key = keys[i];
+ outputFile.writeLine("#if defined(" + key + ")");
+ outputFile.writeLine("#pragma message (VAR_NAME_VALUE(" + key + "))");
+ outputFile.writeLine("#endif");
+ }
+ outputFile.close();
+
+ var process = new Process();
+ process.setWorkingDirectory(outputDirectory.path());
+ for (var envkey in environment)
+ process.setEnv(envkey, environment[envkey]);
+
+ var target = targetFlag(platform, architecture, ["application"]);
+ var lang = languageFlag(tag);
+ var args = [ target, lang, outputFilePath ];
+
+ process.exec(compilerPath, args, false);
+ var m = Cpp.extractMacros(process.readStdOut(), /"?(#define(\s\w+){1,2})"?$/);
+ if (tag === "cpp" && m["__cplusplus"] === "1")
+ return m;
+ else if (tag === "c")
+ return m;
+}
+
+function effectiveLinkerPath(product) {
+ if (product.cpp.linkerMode === "automatic") {
+ var compilerPath = product.cpp.compilerPath;
+ if (compilerPath)
+ return compilerPath;
+ console.log("Found no C-language objects, choosing system linker for " + product.name);
+ }
+ return product.cpp.linkerPath;
+}
+
+function useCompilerDriverLinker(product) {
+ var linker = effectiveLinkerPath(product);
+ var compiler = product.cpp.compilerPath;
+ return linker === compiler;
+}
+
+function escapeLinkerFlags(useCompilerDriver, linkerFlags) {
+ if (!linkerFlags || linkerFlags.length === 0)
+ return [];
+
+ if (useCompilerDriver) {
+ var sep = ",";
+ return [["-Wl"].concat(linkerFlags).join(sep)];
+ }
+ return linkerFlags;
+}
+
+function assemblerFlags(project, product, input, outputs, explicitlyDependsOn) {
+ var args = [FileInfo.toNativeSeparators(input.filePath)];
+ args.push("-fo=" + FileInfo.toNativeSeparators(outputs.obj[0].filePath));
+
+ args = args.concat(Cpp.collectPreincludePaths(input).map(function(path) {
+ return "-fi" + FileInfo.toNativeSeparators(path);
+ }));
+
+ args = args.concat(Cpp.collectDefinesArguments(input, "-d"));
+
+ var includePaths = [].concat(Cpp.collectIncludePaths(input)).concat(
+ Cpp.collectSystemIncludePaths(input));
+ args = args.concat(includePaths.map(function(path) {
+ return "-i" + FileInfo.toNativeSeparators(path);
+ }));
+
+ if (input.cpp.debugInformation)
+ args.push("-d1");
+
+ var warnings = input.cpp.warningLevel
+ if (warnings === "none")
+ args.push("-w0");
+ else if (warnings === "all")
+ args.push("-wx");
+ if (input.cpp.treatWarningsAsErrors)
+ args.push("-we");
+
+ args.push("-zq"); // Silent.
+ args = args.concat(Cpp.collectMiscAssemblerArguments(input));
+ return args;
+}
+
+function compilerFlags(project, product, input, outputs, explicitlyDependsOn) {
+ var args = ["-g" + (input.cpp.debugInformation ? "3" : "0")];
+
+ var target = targetFlag(product.qbs.targetPlatform, product.qbs.architecture,
+ product.type);
+ args.push(target);
+
+ if (product.type.includes("application")) {
+ if (product.qbs.targetPlatform === "windows") {
+ var consoleApplication = product.consoleApplication;
+ args.push(consoleApplication ? "-mconsole" : "-mwindows");
+ }
+ } else if (product.type.includes("dynamiclibrary")) {
+ args.push("-shared");
+ }
+
+ var optimization = input.cpp.optimization
+ if (optimization === "fast")
+ args.push("-Ot");
+ else if (optimization === "small")
+ args.push("-Os");
+ else if (optimization === "none")
+ args.push("-O0");
+
+ var warnings = input.cpp.warningLevel
+ if (warnings === "none") {
+ args.push("-w");
+ } else if (warnings === "all") {
+ args.push("-Wall");
+ args.push("-Wextra");
+ }
+ if (input.cpp.treatWarningsAsErrors)
+ args.push("-Werror");
+
+ var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(outputs.obj[0].fileTags));
+
+ var langFlag = languageFlag(tag);
+ if (langFlag)
+ args.push(langFlag);
+
+ if (tag === "cpp") {
+ var enableExceptions = input.cpp.enableExceptions;
+ if (enableExceptions) {
+ var ehModel = input.cpp.exceptionHandlingModel;
+ switch (ehModel) {
+ case "direct":
+ args.push("-feh-direct");
+ break;
+ case "table":
+ args.push("-feh-table");
+ break;
+ default:
+ args.push("-feh");
+ break;
+ }
+ } else {
+ args.push("-fno-eh");
+ }
+
+ var enableRtti = input.cpp.enableRtti;
+ args.push(enableRtti ? "-frtti" : "-fno-rtti");
+ } else if (tag === "c") {
+ var knownValues = ["c99", "c89"];
+ var cLanguageVersion = Cpp.languageVersion(input.cpp.cLanguageVersion, knownValues, "C");
+ switch (cLanguageVersion) {
+ case "c89":
+ args.push("-std=c89");
+ break;
+ case "c99":
+ args.push("-std=c99");
+ break;
+ }
+ }
+
+ var preincludePaths = Cpp.collectPreincludePaths(input);
+ for (var i = 0; i < preincludePaths.length; ++i)
+ args.push(input.cpp.preincludeFlag, preincludePaths[i]);
+
+ args = args.concat(Cpp.collectDefinesArguments(input));
+
+ args = args.concat(Cpp.collectIncludePaths(input).map(function(path) {
+ return input.cpp.includeFlag + FileInfo.toNativeSeparators(path);
+ }));
+ args = args.concat(Cpp.collectSystemIncludePaths(input).map(function(path) {
+ return input.cpp.systemIncludeFlag + FileInfo.toNativeSeparators(path);
+ }));
+
+ args = args.concat(Cpp.collectMiscCompilerArguments(input, tag),
+ Cpp.collectMiscDriverArguments(input));
+
+ args.push("-o", FileInfo.toNativeSeparators(outputs.obj[0].filePath));
+ args.push("-c", FileInfo.toNativeSeparators(input.filePath));
+
+ return args;
+}
+
+function resourceCompilerFlags(project, product, input, outputs) {
+ var args = [input.filePath];
+ args.push("-fo=" + FileInfo.toNativeSeparators(outputs.res[0].filePath));
+ args = args.concat(Cpp.collectDefinesArguments(input, "-d"));
+
+ args = args.concat(Cpp.collectIncludePaths(input).map(function(path) {
+ return input.cpp.includeFlag + FileInfo.toNativeSeparators(path);
+ }));
+ args = args.concat(Cpp.collectSystemIncludePaths(input).map(function(path) {
+ return input.cpp.includeFlag + FileInfo.toNativeSeparators(path);
+ }));
+ args.push("-q", "-ad", "-r");
+ return args;
+}
+
+function linkerFlags(project, product, inputs, outputs) {
+ var args = [];
+ var useCompilerDriver = useCompilerDriverLinker(product);
+ if (useCompilerDriver) {
+ var target = targetFlag(product.qbs.targetPlatform, product.qbs.architecture,
+ product.type);
+ args.push(target);
+
+ if (product.type.includes("application")) {
+ args.push("-o", FileInfo.toNativeSeparators(outputs.application[0].filePath));
+ if (product.cpp.generateLinkerMapFile)
+ args.push("-fm=" + FileInfo.toNativeSeparators(outputs.mem_map[0].filePath));
+ } else if (product.type.includes("dynamiclibrary")) {
+ if (product.qbs.targetPlatform === "windows") {
+ args.push("-Wl, option implib=" + FileInfo.toNativeSeparators(
+ outputs.dynamiclibrary_import[0].filePath));
+ }
+ args.push("-o", FileInfo.toNativeSeparators(outputs.dynamiclibrary[0].filePath))
+ }
+
+ var escapableLinkerFlags = [];
+ var targetLinkerFlags = product.cpp.targetLinkerFlags;
+ if (targetLinkerFlags)
+ escapableLinkerFlags = escapableLinkerFlags.concat(targetLinkerFlags);
+
+ escapableLinkerFlags = escapableLinkerFlags.concat(
+ Cpp.collectMiscEscapableLinkerArguments(product));
+
+ var escapedLinkerFlags = escapeLinkerFlags(useCompilerDriver, escapableLinkerFlags);
+ if (escapedLinkerFlags)
+ args = args.concat(escapedLinkerFlags);
+
+ args = args.concat(Cpp.collectLibraryPaths(product).map(function(path) {
+ return product.cpp.libraryPathFlag + FileInfo.toNativeSeparators(path);
+ }));
+ args = args.concat(Cpp.collectLinkerObjectPaths(inputs).map(function(path) {
+ return FileInfo.toNativeSeparators(path);
+ }));
+
+ var libraryDependencies = Cpp.collectLibraryDependencies(product);
+ for (var i = 0; i < libraryDependencies.length; ++i) {
+ var lib = libraryDependencies[i].filePath;
+ if (FileInfo.isAbsolutePath(lib) || lib.startsWith('@'))
+ args.push(FileInfo.toNativeSeparators(lib));
+ else
+ args.push("-Wl, libfile " + lib);
+ }
+
+ var resourcePaths = Cpp.collectResourceObjectPaths(inputs).map(function(path) {
+ return FileInfo.toNativeSeparators(path);
+ });
+ if (resourcePaths.length > 0)
+ args = args.concat("-Wl, resource " + resourcePaths.join(","));
+ }
+
+ args = args.concat(Cpp.collectMiscLinkerArguments(product),
+ Cpp.collectMiscDriverArguments(product));
+ return args;
+}
+
+function libraryManagerFlags(project, product, inputs, outputs) {
+ var args = ["-b", "-n", "-q"];
+ args = args.concat(Cpp.collectLinkerObjectPaths(inputs).map(function(path) {
+ return "+" + FileInfo.toNativeSeparators(path);
+ }));
+ args.push("-o", FileInfo.toNativeSeparators(outputs.staticlibrary[0].filePath));
+ return args;
+}
+
+function disassemblerFlags(project, product, inputs, outputs) {
+ var objectPath = Cpp.relativePath(product.buildDirectory, outputs.obj[0].filePath);
+ var listingPath = Cpp.relativePath(product.buildDirectory, outputs.lst[0].filePath);
+ var args = [];
+ args.push(FileInfo.toNativeSeparators(objectPath));
+ args.push("-l=" + FileInfo.toNativeSeparators(listingPath));
+ args.push("-s", "-a");
+ return args;
+}
+
+function generateCompilerListing(project, product, inputs, outputs, input, output) {
+ var args = disassemblerFlags(project, product, input, outputs);
+ var cmd = new Command(input.cpp.disassemblerPath, args);
+ cmd.workingDirectory = product.buildDirectory;
+ cmd.silent = true;
+ cmd.jobPool = "watcom_job_pool";
+ return cmd;
+}
+
+function prepareAssembler(project, product, inputs, outputs, input, output, explicitlyDependsOn) {
+ var cmds = [];
+ var args = assemblerFlags(project, product, input, outputs);
+ var cmd = new Command(input.cpp.assemblerPath, args);
+ cmd.workingDirectory = product.buildDirectory;
+ cmd.description = "assembling " + input.fileName;
+ cmd.highlight = "compiler";
+ cmd.jobPool = "watcom_job_pool";
+ cmds.push(cmd);
+ if (input.cpp.generateAssemblerListingFiles)
+ cmds.push(generateCompilerListing(project, product, inputs, outputs, input, output));
+ return cmds;
+}
+
+function prepareCompiler(project, product, inputs, outputs, input, output, explicitlyDependsOn) {
+ var cmds = [];
+ var args = compilerFlags(project, product, input, outputs, explicitlyDependsOn);
+ var cmd = new Command(input.cpp.compilerPath, args);
+ cmd.workingDirectory = product.buildDirectory;
+ cmd.description = "compiling " + input.fileName;
+ cmd.highlight = "compiler";
+ cmd.jobPool = "watcom_job_pool";
+ cmds.push(cmd);
+ if (input.cpp.generateCompilerListingFiles)
+ cmds.push(generateCompilerListing(project, product, inputs, outputs, input, output));
+ return cmds;
+}
+
+function prepareResourceCompiler(project, product, inputs, outputs, input, output,
+ explicitlyDependsOn) {
+ var args = resourceCompilerFlags(project, product, input, outputs);
+ var cmd = new Command(input.cpp.resourceCompilerPath, args);
+ // Set working directory to source directory as a workaround
+ // to make the resources compilable by resource compiler (it is magic).
+ cmd.workingDirectory = product.sourceDirectory;
+ cmd.description = "compiling " + input.fileName;
+ cmd.highlight = "compiler";
+ cmd.jobPool = "watcom_job_pool";
+ return [cmd];
+}
+
+function prepareLinker(project, product, inputs, outputs, input, output) {
+ var primaryOutput = outputs.dynamiclibrary ? outputs.dynamiclibrary[0]
+ : outputs.application[0];
+ var args = linkerFlags(project, product, inputs, outputs);
+ var linkerPath = effectiveLinkerPath(product);
+ var cmd = new Command(linkerPath, args);
+ cmd.workingDirectory = product.buildDirectory;
+ cmd.description = "linking " + primaryOutput.fileName;
+ cmd.highlight = "linker";
+ cmd.jobPool = "watcom_job_pool";
+ return [cmd];
+}
+
+function prepareLibraryManager(project, product, inputs, outputs, input, output) {
+ var args = libraryManagerFlags(project, product, inputs, outputs);
+ var cmd = new Command(product.cpp.libraryManagerPath, args);
+ cmd.workingDirectory = product.buildDirectory;
+ cmd.description = "linking " + outputs.staticlibrary[0].fileName;
+ cmd.highlight = "linker";
+ cmd.jobPool = "watcom_job_pool";
+ return [cmd];
+}
diff --git a/share/qbs/modules/cpp/watcom.qbs b/share/qbs/modules/cpp/watcom.qbs
new file mode 100644
index 000000000..84157b67b
--- /dev/null
+++ b/share/qbs/modules/cpp/watcom.qbs
@@ -0,0 +1,196 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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 1.0
+import qbs.File
+import qbs.FileInfo
+import qbs.ModUtils
+import qbs.Probes
+import "cpp.js" as Cpp
+import "watcom.js" as WATCOM
+
+CppModule {
+ condition: qbs.toolchain && qbs.toolchain.includes("watcom")
+
+ Probes.BinaryProbe {
+ id: compilerPathProbe
+ condition: !toolchainInstallPath && !_skipAllChecks
+ names: ["owcc"]
+ }
+
+ Probes.WatcomProbe {
+ id: watcomProbe
+ condition: !_skipAllChecks
+ compilerFilePath: compilerPath
+ enableDefinesByLanguage: enableCompilerDefinesByLanguage
+ _pathListSeparator: qbs.pathListSeparator
+ _toolchainInstallPath: toolchainInstallPath
+ _targetPlatform: qbs.targetPlatform
+ _targetArchitecture: qbs.architecture
+ }
+
+ qbs.architecture: watcomProbe.found ? watcomProbe.architecture : original
+ qbs.targetPlatform: watcomProbe.found ? watcomProbe.targetPlatform : original
+
+ compilerVersionMajor: watcomProbe.versionMajor
+ compilerVersionMinor: watcomProbe.versionMinor
+ compilerVersionPatch: watcomProbe.versionPatch
+ endianness: watcomProbe.endianness
+
+ compilerDefinesByLanguage: watcomProbe.compilerDefinesByLanguage
+ compilerIncludePaths: watcomProbe.includePaths
+
+ toolchainInstallPath: compilerPathProbe.found ? compilerPathProbe.path : undefined
+
+ /* Work-around for QtCreator which expects these properties to exist. */
+ property string cCompilerName: compilerName
+ property string cxxCompilerName: compilerName
+
+ compilerName: "owcc" + compilerExtension
+ compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName)
+
+ assemblerName: "wasm" + compilerExtension
+ assemblerPath: FileInfo.joinPaths(toolchainInstallPath, assemblerName)
+
+ linkerName: "wlink" + compilerExtension
+ linkerPath: FileInfo.joinPaths(toolchainInstallPath, linkerName)
+
+ property string disassemblerName: "wdis" + compilerExtension
+ property string disassemblerPath: FileInfo.joinPaths(toolchainInstallPath,
+ disassemblerName)
+ property string resourceCompilerName: "wrc" + compilerExtension
+ property string resourceCompilerPath: FileInfo.joinPaths(toolchainInstallPath,
+ resourceCompilerName)
+ property string libraryManagerName: "wlib" + compilerExtension
+ property string libraryManagerPath: FileInfo.joinPaths(toolchainInstallPath,
+ libraryManagerName)
+
+ runtimeLibrary: "dynamic"
+
+ staticLibrarySuffix: ".lib"
+ dynamicLibrarySuffix: toolchainDetails.dynamicLibrarySuffix
+ executableSuffix: toolchainDetails.executableSuffix
+ objectSuffix: ".obj"
+
+ imageFormat: toolchainDetails.imageFormat
+
+ defineFlag: "-D"
+ includeFlag: "-I"
+ systemIncludeFlag: "-I"
+ preincludeFlag: "-include"
+ libraryDependencyFlag: "-l"
+ libraryPathFlag: "-L"
+ linkerScriptFlag: ""
+
+ toolchainDetails: WATCOM.toolchainDetails(qbs)
+
+ knownArchitectures: ["x86", "x86_16"]
+
+ property var buildEnv: watcomProbe.environment
+ setupBuildEnvironment: {
+ for (var key in product.cpp.buildEnv) {
+ var v = new ModUtils.EnvironmentVariable(key, product.qbs.pathListSeparator);
+ v.prepend(product.cpp.buildEnv[key]);
+ v.set();
+ }
+ }
+
+ Rule {
+ id: assembler
+ inputs: ["asm"]
+ outputFileTags: Cpp.assemblerOutputTags(generateAssemblerListingFiles)
+ outputArtifacts: Cpp.assemblerOutputArtifacts(input)
+ prepare: WATCOM.prepareAssembler.apply(WATCOM, arguments)
+ }
+
+ FileTagger {
+ patterns: ["*.asm"]
+ fileTags: ["asm"]
+ }
+
+ Rule {
+ id: compiler
+ inputs: ["cpp", "c"]
+ auxiliaryInputs: ["hpp"]
+ outputFileTags: Cpp.compilerOutputTags(generateCompilerListingFiles)
+ outputArtifacts: Cpp.compilerOutputArtifacts(input)
+ prepare: WATCOM.prepareCompiler.apply(WATCOM, arguments)
+ }
+
+ Rule {
+ id: rccCompiler
+ inputs: ["rc"]
+ auxiliaryInputs: ["hpp"]
+ outputFileTags: Cpp.resourceCompilerOutputTags()
+ outputArtifacts: Cpp.resourceCompilerOutputArtifacts(input)
+ prepare: WATCOM.prepareResourceCompiler.apply(WATCOM, arguments)
+ }
+
+ FileTagger {
+ patterns: ["*.rc"]
+ fileTags: ["rc"]
+ }
+
+ Rule {
+ id: applicationLinker
+ multiplex: true
+ inputs: ["obj", "res", "linkerscript"]
+ inputsFromDependencies: ["staticlibrary", "dynamiclibrary_import"]
+ outputFileTags: Cpp.applicationLinkerOutputTags(generateLinkerMapFile)
+ outputArtifacts: Cpp.applicationLinkerOutputArtifacts(product)
+ prepare: WATCOM.prepareLinker.apply(WATCOM, arguments)
+ }
+
+ Rule {
+ id: dynamicLibraryLinker
+ condition: qbs.targetOS.includes("windows")
+ multiplex: true
+ inputs: ["obj", "res"]
+ inputsFromDependencies: ["staticlibrary", "dynamiclibrary_import"]
+ outputFileTags: Cpp.dynamicLibraryLinkerOutputTags();
+ outputArtifacts: Cpp.dynamicLibraryLinkerOutputArtifacts(product)
+ prepare: WATCOM.prepareLinker.apply(WATCOM, arguments)
+ }
+
+ Rule {
+ id: libraryManager
+ multiplex: true
+ inputs: ["obj"]
+ inputsFromDependencies: ["staticlibrary", "dynamiclibrary_import"]
+ outputFileTags: Cpp.staticLibraryLinkerOutputTags()
+ outputArtifacts: Cpp.staticLibraryLinkerOutputArtifacts(product)
+ prepare: WATCOM.prepareLibraryManager.apply(WATCOM, arguments)
+ }
+
+ JobLimit {
+ jobPool: "watcom_job_pool"
+ jobCount: 1
+ }
+}
diff --git a/share/qbs/modules/cpp/windows-clang-cl.qbs b/share/qbs/modules/cpp/windows-clang-cl.qbs
index 1b2833060..9aa9d7395 100644
--- a/share/qbs/modules/cpp/windows-clang-cl.qbs
+++ b/share/qbs/modules/cpp/windows-clang-cl.qbs
@@ -28,19 +28,19 @@
**
****************************************************************************/
-import qbs
+import qbs.Host
import qbs.ModUtils
import qbs.Probes
import qbs.FileInfo
import 'windows-msvc-base.qbs' as MsvcBaseModule
MsvcBaseModule {
- condition: qbs.hostOS.contains('windows') &&
- qbs.targetOS.contains('windows') &&
- qbs.toolchain && qbs.toolchain.contains('clang-cl')
+ condition: Host.os().includes('windows') &&
+ qbs.targetOS.includes('windows') &&
+ qbs.toolchain && qbs.toolchain.includes('clang-cl')
priority: 100
- Probes.BinaryProbe {
+ Probes.ClangClBinaryProbe {
id: clangPathProbe
condition: !toolchainInstallPath && !_skipAllChecks
names: ["clang-cl"]
@@ -52,9 +52,12 @@ MsvcBaseModule {
compilerFilePath: compilerPath
vcvarsallFilePath: vcvarsallPath
enableDefinesByLanguage: enableCompilerDefinesByLanguage
- architecture: qbs.architecture
+ preferredArchitecture: qbs.architecture
+ winSdkVersion: windowsSdkVersion
}
+ qbs.architecture: clangClProbe.found ? clangClProbe.architecture : original
+
compilerVersionMajor: clangClProbe.versionMajor
compilerVersionMinor: clangClProbe.versionMinor
compilerVersionPatch: clangClProbe.versionPatch
@@ -65,20 +68,34 @@ MsvcBaseModule {
: undefined
buildEnv: clangClProbe.buildEnv
- property string vcvarsallPath
+ property string linkerVariant
+ PropertyOptions {
+ name: "linkerVariant"
+ allowedValues: ["lld", "link"]
+ description: "Allows to specify the linker variant. Maps to clang-cl's -fuse-ld option."
+ }
+ Properties {
+ condition: linkerVariant
+ driverLinkerFlags: "-fuse-ld=" + linkerVariant
+ }
+
+ property string vcvarsallPath : clangPathProbe.found ? clangPathProbe.vcvarsallPath : undefined
compilerName: "clang-cl.exe"
linkerName: "lld-link.exe"
linkerPath: FileInfo.joinPaths(toolchainInstallPath, linkerName)
+ systemIncludeFlag: "/imsvc"
+
validateFunc: {
+ var baseFunc = base;
return function() {
if (_skipAllChecks)
return;
var validator = new ModUtils.PropertyValidator("cpp");
validator.setRequiredProperty("vcvarsallPath", vcvarsallPath);
validator.validate();
- base();
+ baseFunc();
}
}
}
diff --git a/share/qbs/modules/cpp/windows-clang-mingw.qbs b/share/qbs/modules/cpp/windows-clang-mingw.qbs
index 8389dbf2e..cfe6f2745 100644
--- a/share/qbs/modules/cpp/windows-clang-mingw.qbs
+++ b/share/qbs/modules/cpp/windows-clang-mingw.qbs
@@ -30,6 +30,7 @@
import qbs.File
import qbs.FileInfo
+import qbs.Host
import qbs.ModUtils
import qbs.Utilities
import "msvc.js" as MSVC
@@ -37,8 +38,8 @@ import "msvc.js" as MSVC
import "setuprunenv.js" as SetupRunEnv
MingwBaseModule {
- condition: qbs.targetOS.contains("windows") &&
- qbs.toolchain && qbs.toolchain.contains("clang")
+ condition: qbs.targetOS.includes("windows") &&
+ qbs.toolchain && qbs.toolchain.includes("clang")
priority: 0
// llvm-as and llvm-objopy are not shipped with the official binaries on Windows at the
@@ -68,16 +69,16 @@ MingwBaseModule {
"llvm-rc" + compilerExtension)
setupBuildEnvironment: {
- if (product.qbs.hostOS.contains("windows") && product.qbs.sysroot) {
- var v = new ModUtils.EnvironmentVariable("PATH", product.qbs.pathListSeparator, true);
+ if (Host.os().includes("windows") && product.qbs.sysroot) {
+ var v = new ModUtils.EnvironmentVariable("PATH", FileInfo.pathListSeparator(), true);
v.prepend(FileInfo.joinPaths(product.qbs.sysroot, "bin"));
v.set();
}
}
setupRunEnvironment: {
- if (product.qbs.hostOS.contains("windows") && product.qbs.sysroot) {
- var v = new ModUtils.EnvironmentVariable("PATH", product.qbs.pathListSeparator, true);
+ if (Host.os().includes("windows") && product.qbs.sysroot) {
+ var v = new ModUtils.EnvironmentVariable("PATH", FileInfo.pathListSeparator(), true);
v.prepend(FileInfo.joinPaths(product.qbs.sysroot, "bin"));
v.set();
SetupRunEnv.setupRunEnvironment(product, config);
@@ -89,10 +90,11 @@ MingwBaseModule {
auxiliaryInputs: ["hpp"]
Artifact {
- filePath: Utilities.getHash(input.baseDir) + "/" + input.completeBaseName + ".res"
+ filePath: FileInfo.joinPaths(Utilities.getHash(input.baseDir),
+ input.completeBaseName + ".res")
fileTags: ["obj"]
}
- prepare: MSVC.createRcCommand(product.cpp.rcFilePath, input, output);
+ prepare: MSVC.createRcCommand(product.cpp.rcFilePath, input, output)
}
}
diff --git a/share/qbs/modules/cpp/windows-mingw.qbs b/share/qbs/modules/cpp/windows-mingw.qbs
index ffed76cdd..9ba4258c5 100644
--- a/share/qbs/modules/cpp/windows-mingw.qbs
+++ b/share/qbs/modules/cpp/windows-mingw.qbs
@@ -33,11 +33,12 @@ import qbs.FileInfo
import qbs.ModUtils
import qbs.Utilities
+import 'cpp.js' as Cpp
import "setuprunenv.js" as SetupRunEnv
MingwBaseModule {
- condition: qbs.targetOS.contains("windows") &&
- qbs.toolchain && qbs.toolchain.contains("mingw")
+ condition: qbs.targetOS.includes("windows") &&
+ qbs.toolchain && qbs.toolchain.includes("mingw")
priority: 0
probeEnv: buildEnv
@@ -51,13 +52,13 @@ MingwBaseModule {
}
setupBuildEnvironment: {
- var v = new ModUtils.EnvironmentVariable("PATH", product.qbs.pathListSeparator, true);
+ var v = new ModUtils.EnvironmentVariable("PATH", FileInfo.pathListSeparator(), true);
v.prepend(product.cpp.toolchainInstallPath);
v.set();
}
setupRunEnvironment: {
- var v = new ModUtils.EnvironmentVariable("PATH", product.qbs.pathListSeparator, true);
+ var v = new ModUtils.EnvironmentVariable("PATH", FileInfo.pathListSeparator(), true);
v.prepend(product.cpp.toolchainInstallPath);
v.set();
SetupRunEnv.setupRunEnvironment(product, config);
@@ -66,12 +67,8 @@ MingwBaseModule {
Rule {
inputs: ["rc"]
auxiliaryInputs: ["hpp"]
-
- Artifact {
- filePath: Utilities.getHash(input.baseDir) + "/" + input.completeBaseName + "_res.o"
- fileTags: ["obj"]
- }
-
+ outputFileTags: Cpp.resourceCompilerOutputTags()
+ outputArtifacts: Cpp.resourceCompilerOutputArtifacts(input)
prepare: {
var platformDefines = input.cpp.platformDefines;
var defines = input.cpp.defines;
@@ -96,6 +93,7 @@ MingwBaseModule {
args.push(systemIncludePaths[i]);
}
+ args.push("-O", "coff"); // Set COFF format explicitly.
args = args.concat(['-i', input.filePath, '-o', output.filePath]);
var cmd = new Command(product.cpp.windresPath, args);
cmd.description = 'compiling ' + input.fileName;
diff --git a/share/qbs/modules/cpp/windows-msvc-base.qbs b/share/qbs/modules/cpp/windows-msvc-base.qbs
index aa1c8256c..9613800e5 100644
--- a/share/qbs/modules/cpp/windows-msvc-base.qbs
+++ b/share/qbs/modules/cpp/windows-msvc-base.qbs
@@ -35,11 +35,14 @@ import qbs.PathTools
import qbs.Probes
import qbs.Utilities
import qbs.WindowsUtils
+import 'cpp.js' as Cpp
import 'msvc.js' as MSVC
CppModule {
condition: false
+ Depends { name: "codesign" }
+
windowsApiCharacterSet: "unicode"
platformDefines: {
var defines = base.concat(WindowsUtils.characterSetDefines(windowsApiCharacterSet))
@@ -81,7 +84,6 @@ CppModule {
separateDebugInformation: true
property bool generateManifestFile: true
- property string toolchainInstallPath
architecture: qbs.architecture
endianness: "little"
@@ -89,9 +91,11 @@ CppModule {
dynamicLibrarySuffix: ".dll"
executableSuffix: ".exe"
debugInfoSuffix: ".pdb"
+ objectSuffix: ".obj"
+ precompiledHeaderSuffix: ".pch"
imageFormat: "pe"
Properties {
- condition: product.multiplexByQbsProperties.contains("buildVariants")
+ condition: product.multiplexByQbsProperties.includes("buildVariants")
&& qbs.buildVariants && qbs.buildVariants.length > 1
&& qbs.buildVariant !== "release"
&& product.type.containsAny(["staticlibrary", "dynamiclibrary"])
@@ -100,6 +104,9 @@ CppModule {
property var buildEnv
+ readonly property bool shouldSignArtifacts: codesign.enableCodeSigning
+ property bool enableCxxLanguageMacro: false
+
setupBuildEnvironment: {
for (var key in product.cpp.buildEnv) {
var v = new ModUtils.EnvironmentVariable(key, ';');
@@ -108,21 +115,21 @@ CppModule {
}
}
+ property string windowsSdkVersion
+
+ defineFlag: "/D"
+ includeFlag: "/I"
+ systemIncludeFlag: "/external:I"
+ preincludeFlag: "/FI"
+ libraryPathFlag: "/LIBPATH:"
+
Rule {
condition: useCPrecompiledHeader
inputs: ["c_pch_src"]
auxiliaryInputs: ["hpp"]
- Artifact {
- fileTags: ['obj']
- filePath: Utilities.getHash(input.completeBaseName) + '_c.obj'
- }
- Artifact {
- fileTags: ['c_pch']
- filePath: product.name + '_c.pch'
- }
- prepare: {
- return MSVC.prepareCompiler.apply(MSVC, arguments);
- }
+ outputFileTags: Cpp.precompiledHeaderOutputTags("c", true)
+ outputArtifacts: Cpp.precompiledHeaderOutputArtifacts(input, product, "c", true)
+ prepare: MSVC.prepareCompiler.apply(MSVC, arguments)
}
Rule {
@@ -130,17 +137,9 @@ CppModule {
inputs: ["cpp_pch_src"]
explicitlyDependsOn: ["c_pch"] // to prevent vc--0.pdb conflict
auxiliaryInputs: ["hpp"]
- Artifact {
- fileTags: ['obj']
- filePath: Utilities.getHash(input.completeBaseName) + '_cpp.obj'
- }
- Artifact {
- fileTags: ['cpp_pch']
- filePath: product.name + '_cpp.pch'
- }
- prepare: {
- return MSVC.prepareCompiler.apply(MSVC, arguments);
- }
+ outputFileTags: Cpp.precompiledHeaderOutputTags("cpp", true)
+ outputArtifacts: Cpp.precompiledHeaderOutputArtifacts(input, product, "cpp", true)
+ prepare: MSVC.prepareCompiler.apply(MSVC, arguments)
}
Rule {
@@ -148,21 +147,9 @@ CppModule {
inputs: ["cpp", "c"]
auxiliaryInputs: ["hpp"]
explicitlyDependsOn: ["c_pch", "cpp_pch"]
-
- outputFileTags: ["obj", "intermediate_obj"]
- outputArtifacts: {
- var tags = input.fileTags.contains("cpp_intermediate_object")
- ? ["intermediate_obj"]
- : ["obj"];
- return [{
- fileTags: tags,
- filePath: Utilities.getHash(input.baseDir) + "/" + input.fileName + ".obj"
- }];
- }
-
- prepare: {
- return MSVC.prepareCompiler.apply(MSVC, arguments);
- }
+ outputFileTags: Cpp.compilerOutputTags(generateCompilerListingFiles)
+ outputArtifacts: Cpp.compilerOutputArtifacts(input)
+ prepare: MSVC.prepareCompiler.apply(MSVC, arguments)
}
FileTagger {
@@ -170,16 +157,29 @@ CppModule {
fileTags: ["native.pe.manifest"]
}
+ FileTagger {
+ patterns: ["*.def"]
+ fileTags: ["def"]
+ }
+
Rule {
name: "applicationLinker"
multiplex: true
- inputs: ['obj', 'native.pe.manifest']
+ inputs: ['obj', 'res', 'native.pe.manifest', 'def']
inputsFromDependencies: ['staticlibrary', 'dynamiclibrary_import', "debuginfo_app"]
- outputFileTags: ["application", "debuginfo_app", "mem_map"]
+ outputFileTags: {
+ var tags = ["application", "debuginfo_app"];
+ if (generateLinkerMapFile)
+ tags.push("mem_map");
+ if (shouldSignArtifacts)
+ tags.push("codesign.signed_artifact");
+ return tags;
+ }
outputArtifacts: {
var app = {
- fileTags: ["application"],
+ fileTags: ["application"].concat(
+ product.cpp.shouldSignArtifacts ? ["codesign.signed_artifact"] : []),
filePath: FileInfo.joinPaths(
product.destinationDirectory,
PathTools.applicationFilePath(product))
@@ -197,33 +197,39 @@ CppModule {
fileTags: ["mem_map"],
filePath: FileInfo.joinPaths(
product.destinationDirectory,
- product.targetName + ".map")
+ product.targetName + product.cpp.linkerMapSuffix)
});
}
return artifacts;
}
- prepare: {
- return MSVC.prepareLinker.apply(MSVC, arguments);
- }
+ prepare: MSVC.prepareLinker.apply(MSVC, arguments)
}
Rule {
name: "dynamicLibraryLinker"
multiplex: true
- inputs: ['obj', 'native.pe.manifest']
+ inputs: ['obj', 'res', 'native.pe.manifest', 'def']
inputsFromDependencies: ['staticlibrary', 'dynamiclibrary_import', "debuginfo_dll"]
- outputFileTags: ["dynamiclibrary", "dynamiclibrary_import", "debuginfo_dll"]
+ outputFileTags: {
+ var tags = ["dynamiclibrary", "dynamiclibrary_import", "debuginfo_dll"];
+ if (shouldSignArtifacts)
+ tags.push("codesign.signed_artifact");
+ return tags;
+ }
outputArtifacts: {
var artifacts = [
{
- fileTags: ["dynamiclibrary"],
- filePath: product.destinationDirectory + "/" + PathTools.dynamicLibraryFilePath(product)
+ fileTags: ["dynamiclibrary"].concat(
+ product.cpp.shouldSignArtifacts ? ["codesign.signed_artifact"] : []),
+ filePath: FileInfo.joinPaths(product.destinationDirectory,
+ PathTools.dynamicLibraryFilePath(product))
},
{
fileTags: ["dynamiclibrary_import"],
- filePath: product.destinationDirectory + "/" + PathTools.importLibraryFilePath(product),
+ filePath: FileInfo.joinPaths(product.destinationDirectory,
+ PathTools.importLibraryFilePath(product)),
alwaysUpdated: false
}
];
@@ -238,15 +244,13 @@ CppModule {
return artifacts;
}
- prepare: {
- return MSVC.prepareLinker.apply(MSVC, arguments);
- }
+ prepare: MSVC.prepareLinker.apply(MSVC, arguments)
}
Rule {
name: "libtool"
multiplex: true
- inputs: ["obj"]
+ inputs: ["obj", "res"]
inputsFromDependencies: ["staticlibrary", "dynamiclibrary_import"]
outputFileTags: ["staticlibrary", "debuginfo_cl"]
outputArtifacts: {
@@ -274,6 +278,10 @@ CppModule {
var fileName = FileInfo.toWindowsSeparators(inputs.obj[i].filePath)
args.push(fileName)
}
+ for (var i in inputs.res) {
+ var fileName = FileInfo.toWindowsSeparators(inputs.res[i].filePath)
+ args.push(fileName)
+ }
var cmd = new Command("lib.exe", args);
cmd.description = 'creating ' + lib.fileName;
cmd.highlight = 'linker';
@@ -292,12 +300,8 @@ CppModule {
Rule {
inputs: ["rc"]
auxiliaryInputs: ["hpp"]
-
- Artifact {
- filePath: Utilities.getHash(input.baseDir) + "/" + input.completeBaseName + ".res"
- fileTags: ["obj"]
- }
-
+ outputFileTags: Cpp.resourceCompilerOutputTags()
+ outputArtifacts: Cpp.resourceCompilerOutputArtifacts(input)
prepare: {
// From MSVC 2010 on, the logo can be suppressed.
var logo = product.cpp.compilerVersionMajor >= 16
@@ -313,18 +317,14 @@ CppModule {
Rule {
inputs: ["asm"]
- Artifact {
- filePath: Utilities.getHash(input.baseDir) + "/" + input.completeBaseName + ".obj"
- fileTags: ["obj"]
- }
+ outputFileTags: Cpp.assemblerOutputTags(false)
+ outputArtifacts: Cpp.assemblerOutputArtifacts(input)
prepare: {
- var args = ["/nologo", "/c",
- "/Fo" + FileInfo.toWindowsSeparators(output.filePath),
- FileInfo.toWindowsSeparators(input.filePath)];
+ var args = ["/nologo", "/c", "/Fo" + FileInfo.toWindowsSeparators(output.filePath)];
if (product.cpp.debugInformation)
args.push("/Zi");
- args = args.concat(ModUtils.moduleProperty(input, 'platformFlags', 'asm'),
- ModUtils.moduleProperty(input, 'flags', 'asm'));
+ args = args.concat(Cpp.collectMiscAssemblerArguments(input, "asm"));
+ args.push(FileInfo.toWindowsSeparators(input.filePath));
var cmd = new Command(product.cpp.assemblerPath, args);
cmd.description = "assembling " + input.fileName;
cmd.jobPool = "assembler";
diff --git a/share/qbs/modules/cpp/windows-msvc.qbs b/share/qbs/modules/cpp/windows-msvc.qbs
index 59032d28a..c30cec239 100644
--- a/share/qbs/modules/cpp/windows-msvc.qbs
+++ b/share/qbs/modules/cpp/windows-msvc.qbs
@@ -29,17 +29,19 @@
**
****************************************************************************/
+import qbs.Host
import qbs.Probes
import "windows-msvc-base.qbs" as MsvcBaseModule
MsvcBaseModule {
- condition: qbs.hostOS.contains('windows') &&
- qbs.targetOS.contains('windows') &&
- qbs.toolchain && qbs.toolchain.contains('msvc')
+ condition: Host.os().includes('windows') &&
+ qbs.targetOS.includes('windows') &&
+ qbs.toolchain && qbs.toolchain.includes('msvc')
priority: 50
- Probes.BinaryProbe {
+ Probes.ClBinaryProbe {
id: compilerPathProbe
+ preferredArchitecture: qbs.architecture
condition: !toolchainInstallPath && !_skipAllChecks
names: ["cl"]
}
@@ -50,6 +52,7 @@ MsvcBaseModule {
compilerFilePath: compilerPath
enableDefinesByLanguage: enableCompilerDefinesByLanguage
preferredArchitecture: qbs.architecture
+ winSdkVersion: windowsSdkVersion
}
qbs.architecture: msvcProbe.found ? msvcProbe.architecture : original
@@ -63,4 +66,6 @@ MsvcBaseModule {
toolchainInstallPath: compilerPathProbe.found ? compilerPathProbe.path
: undefined
buildEnv: msvcProbe.buildEnv
+
+ enableCxxLanguageMacro: true
}
diff --git a/share/qbs/modules/dmg/DMGModule.qbs b/share/qbs/modules/dmg/DMGModule.qbs
index c5d097a0b..27a945033 100644
--- a/share/qbs/modules/dmg/DMGModule.qbs
+++ b/share/qbs/modules/dmg/DMGModule.qbs
@@ -31,15 +31,17 @@
import qbs.DarwinTools
import qbs.File
import qbs.FileInfo
+import qbs.Host
import qbs.ModUtils
import qbs.Process
+import qbs.Probes
import qbs.TextFile
import "dmg.js" as Dmg
Module {
Depends { name: "xcode"; required: false }
- condition: qbs.hostOS.contains("darwin") && qbs.targetOS.contains("darwin")
+ condition: Host.os().includes("darwin") && qbs.targetOS.includes("darwin")
property string volumeName: product.targetName
PropertyOptions {
@@ -72,6 +74,12 @@ Module {
property string sourceBase
+ Probes.BinaryProbe {
+ id: pythonProbe
+ names: ["python3"]
+ }
+ property string pythonExePath: pythonProbe.found ? pythonProbe.filePath : "python3"
+
readonly property string pythonPath: File.canonicalFilePath(FileInfo.joinPaths(path,
"..", "..",
"python"))
diff --git a/share/qbs/modules/dmg/dmg.js b/share/qbs/modules/dmg/dmg.js
index 4d972db9b..06fe7b906 100644
--- a/share/qbs/modules/dmg/dmg.js
+++ b/share/qbs/modules/dmg/dmg.js
@@ -57,7 +57,7 @@ function dmgbuildSettings(product, inputs) {
volumeIcon = volumeIcons[0].filePath;
}
- var licenseFileObjects = Array.prototype.map.call(inputs["dmg.license"], function (a) {
+ var licenseFileObjects = Array.prototype.map.call(inputs["dmg.license"] || [], function (a) {
return {
"dmg": {
"licenseLocale": localizationFromArtifact(a),
@@ -97,14 +97,14 @@ function dmgbuildSettings(product, inputs) {
}, {});
}
- var contentsArray = Array.prototype.map.call(inputs["dmg.input"], function (a) {
+ var contentsArray = Array.prototype.map.call(inputs["dmg.input"] || [], function (a) {
if (a.dmg.sourceBase && !a.filePath.startsWith(a.dmg.sourceBase)) {
throw new Error("Cannot install '" + a.filePath + "', " +
"because it doesn't start with the value of " +
"dmg.sourceBase '" + a.dmg.sourceBase + "'.");
}
- var isSymlink = a.fileTags.contains("dmg.input.symlink");
+ var isSymlink = a.fileTags.includes("dmg.input.symlink");
return {
"x": a.dmg.iconX,
"y": a.dmg.iconY,
@@ -114,7 +114,7 @@ function dmgbuildSettings(product, inputs) {
};
});
- Array.prototype.forEach.call(product.dmg.iconPositions, function (obj) {
+ Array.prototype.forEach.call(product.dmg.iconPositions || [], function (obj) {
var existingIndex = -1;
Array.prototype.forEach.call(contentsArray, function (contentsItem, i) {
if (contentsItem["name"] === obj["path"])
@@ -135,7 +135,7 @@ function dmgbuildSettings(product, inputs) {
}
});
- return {
+ var result = {
"title": product.dmg.volumeName,
"icon": !product.dmg.badgeVolumeIcon ? volumeIcon : undefined,
"badge-icon": product.dmg.badgeVolumeIcon ? volumeIcon : undefined,
@@ -154,13 +154,16 @@ function dmgbuildSettings(product, inputs) {
},
"format": product.dmg.format,
"compression-level": product.dmg.compressionLevel,
- "license": {
+ "contents": contentsArray
+ };
+ if (licenseFileObjects.length >= 0) {
+ result["license"] = {
"default-language": product.dmg.defaultLicenseLocale,
"licenses": reduceLicensesForKey(licenseFileObjects, "licenses"),
"buttons": reduceLicensesForKey(licenseFileObjects, "buttons")
- },
- "contents": contentsArray
- };
+ };
+ }
+ return result;
}
function prepareLicense(project, product, inputs, outputs, input, output) {
@@ -199,8 +202,10 @@ function prepareDmg(project, product, inputs, outputs, input, output) {
cmds.push(cmd);
// Create the actual DMG via dmgbuild
- cmd = new Command(FileInfo.joinPaths(product.qbs.libexecPath, "dmgbuild"),
- [product.dmg.volumeName,
+ cmd = new Command(product.dmg.pythonExePath,
+ ["-m",
+ "dmgbuild",
+ product.dmg.volumeName,
output.filePath,
"--no-hidpi", // qbs handles this by itself
"--settings", settingsJsonFilePath]);
diff --git a/share/qbs/modules/flatbuf/c/flatbuffers-c.qbs b/share/qbs/modules/flatbuf/c/flatbuffers-c.qbs
new file mode 100644
index 000000000..9f5b2b70c
--- /dev/null
+++ b/share/qbs/modules/flatbuf/c/flatbuffers-c.qbs
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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.FileInfo
+
+import "../flatbuffers.js" as Flatbuf
+import "../flatbuffersbase.qbs" as FlatbufBase
+
+FlatbufBase {
+ Depends { name: "cpp" }
+ Depends { name: "flatcc" }
+
+ compilerName: "flatcc"
+
+ _outputDir: FileInfo.joinPaths(product.buildDirectory, "flatbuf", "c")
+ _searchPaths: flatbuffers.hostBinDirs
+
+ cpp.systemIncludePaths: base.concat([_outputDir])
+
+ Rule {
+ inputs: ["flatbuf.input"]
+ outputFileTags: ["hpp"]
+ outputArtifacts: [Flatbuf.artifactC(input.flatbuf.c, input, "hpp", "_generated.h")]
+
+ prepare: {
+ return Flatbuf.doPrepareC(input.flatbuf.c, input);
+ }
+ }
+
+ validate: {
+ Flatbuf.validateCompiler(compilerName, compilerPath);
+ }
+}
diff --git a/share/qbs/modules/flatbuf/cpp/flatbuffers-cpp.qbs b/share/qbs/modules/flatbuf/cpp/flatbuffers-cpp.qbs
new file mode 100644
index 000000000..4614d4949
--- /dev/null
+++ b/share/qbs/modules/flatbuf/cpp/flatbuffers-cpp.qbs
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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.FileInfo
+
+import "../flatbuffers.js" as Flatbuf
+import "../flatbuffersbase.qbs" as FlatbufBase
+
+FlatbufBase {
+ Depends { name: "cpp" }
+ Depends { name: "flatbuffers" }
+
+ property string filenameExtension: "h"
+ property string filenameSuffix: "_generated"
+ property string includePrefix // TODO: test
+ property bool keepPrefix: false
+
+ _outputDir: FileInfo.joinPaths(product.buildDirectory, "flatbuf", "cpp")
+ _searchPaths: flatbuffers.hostBinDirs
+
+ cpp.cxxLanguageVersion: "c++11"
+ cpp.systemIncludePaths: base.concat([_outputDir])
+
+ Rule {
+ inputs: ["flatbuf.input"]
+ outputFileTags: ["hpp"]
+ outputArtifacts: {
+ var module = input.flatbuf.cpp;
+ var fullSuffix = module.filenameSuffix + "." + module.filenameExtension;
+ return [ Flatbuf.artifact(module, input, "hpp", fullSuffix) ];
+ }
+
+ prepare: {
+ return Flatbuf.doPrepareCpp(input.flatbuf.cpp, input, output);
+ }
+ }
+
+ validate: {
+ Flatbuf.validateCompiler(compilerName, compilerPath);
+ }
+}
diff --git a/share/qbs/modules/flatbuf/flatbuffers.js b/share/qbs/modules/flatbuf/flatbuffers.js
new file mode 100644
index 000000000..24fd91168
--- /dev/null
+++ b/share/qbs/modules/flatbuf/flatbuffers.js
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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.
+**
+****************************************************************************/
+
+var File = require("qbs.File");
+
+function validateCompiler(compilerName, compilerPath) {
+ if (!File.exists(compilerPath)) {
+ throw "Can't find '" + compilerName + "' binary. Please set the compilerPath property or "
+ + "make sure the compiler is found in PATH";
+ }
+}
+
+function getOutputDir(module, input) {
+ var outputDir = module._outputDir;
+ if (!module.keepPrefix)
+ return outputDir;
+ var importPaths = module.importPaths;
+ if (importPaths !== undefined && importPaths.length !== 0) {
+ var canonicalInput = File.canonicalFilePath(FileInfo.path(input.filePath));
+ for (var i = 0; i < importPaths.length; ++i) {
+ var path = File.canonicalFilePath(importPaths[i]);
+
+ if (canonicalInput.startsWith(path)) {
+ return outputDir + "/" + FileInfo.relativePath(path, canonicalInput);
+ }
+ }
+ }
+ return outputDir;
+}
+
+function artifactC(module, input, tag, suffix) {
+ var outputDir = module._outputDir;
+ return {
+ fileTags: [tag],
+ filePath: outputDir + "/" + FileInfo.baseName(input.fileName) + suffix,
+ cpp: { warningLevel: "none"}
+ };
+}
+
+function doPrepareC(module, input)
+{
+ var args = [];
+ args.push("-a") // write all
+ args.push("-o", input.flatbuf.c._outputDir) // output dir
+
+ var importPaths = module.importPaths;
+ importPaths.forEach(function(path) {
+ args.push("-I", path);
+ });
+
+ args.push(input.filePath);
+
+ var cmd = new Command(module.compilerPath, args);
+ cmd.workingDirectory = FileInfo.path(module._outputDir)
+ cmd.highlight = "codegen";
+ cmd.description = "generating C files for " + input.fileName;
+ return [cmd];
+}
+
+function artifact(module, input, tag, suffix) {
+ var outputDir = getOutputDir(module, input);
+ return {
+ fileTags: [tag],
+ filePath: outputDir + "/" + FileInfo.baseName(input.fileName) + suffix,
+ cpp: { warningLevel: "none" }
+ };
+}
+
+function doPrepareCpp(module, input, output)
+{
+ var outputDir = FileInfo.path(output.filePath);
+ var result = [];
+
+ var args = [];
+ args.push("--cpp")
+
+ var importPaths = module.importPaths;
+ importPaths.forEach(function(path) {
+ args.push("-I", path);
+ });
+
+ args.push("--filename-ext", module.filenameExtension);
+ args.push("--filename-suffix", module.filenameSuffix);
+
+ if (module.includePrefix)
+ args.push("--include-prefix", module.includePrefix);
+
+ if (module.keepPrefix)
+ args.push("--keep-prefix");
+
+ args.push(input.filePath);
+ var cmd = new Command(input.flatbuf.cpp.compilerPath, args);
+ cmd.workingDirectory = outputDir;
+ cmd.highlight = "codegen";
+ cmd.description = "generating C++ files for " + input.fileName;
+ result.push(cmd);
+
+ return result;
+}
diff --git a/share/qbs/modules/flatbuf/flatbuffersbase.qbs b/share/qbs/modules/flatbuf/flatbuffersbase.qbs
new file mode 100644
index 000000000..98eb2f344
--- /dev/null
+++ b/share/qbs/modules/flatbuf/flatbuffersbase.qbs
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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
+import qbs.Probes
+
+import "flatbuffers.js" as HelperFunctions
+
+Module {
+ property string compilerName: "flatc"
+ property string compilerPath: compilerProbe.filePath
+
+ property pathList importPaths: []
+
+ property string _outputDir: FileInfo.joinPaths(product.buildDirectory, "flatbuf")
+
+ property stringList _searchPaths
+
+ FileTagger {
+ patterns: ["*.fbs"]
+ fileTags: ["flatbuf.input"];
+ }
+
+ Probes.BinaryProbe {
+ id: compilerProbe
+ names: [compilerName]
+ searchPaths: _searchPaths
+ }
+}
diff --git a/share/qbs/modules/freedesktop/FreeDesktop.qbs b/share/qbs/modules/freedesktop/FreeDesktop.qbs
new file mode 100644
index 000000000..60722c674
--- /dev/null
+++ b/share/qbs/modules/freedesktop/FreeDesktop.qbs
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Alberto Mardegan <mardy@users.sourceforge.net>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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.ModUtils
+import qbs.TextFile
+import "freedesktop.js" as Fdo
+
+Module {
+ property string name: product.name
+ property string appName: name
+
+ property var desktopKeys
+
+ readonly property var defaultDesktopKeys: {
+ return {
+ 'Type': 'Application',
+ 'Name': product.freedesktop.appName,
+ 'Exec': product.targetName,
+ 'Terminal': 'false',
+ 'Version': '1.1',
+ }
+ }
+ property bool _fdoSupported: qbs.targetOS.includes("unix") && !qbs.targetOS.includes("darwin")
+
+ additionalProductTypes: "freedesktop.desktopfile"
+
+ FileTagger {
+ patterns: [ "*.desktop" ]
+ fileTags: [ "freedesktop.desktopfile_source" ]
+ }
+
+ Rule {
+ condition: _fdoSupported
+
+ inputs: [ "freedesktop.desktopfile_source" ]
+ outputFileTags: [ "freedesktop.desktopfile" ]
+
+ Artifact {
+ fileTags: [ "freedesktop.desktopfile" ]
+ filePath: input.fileName
+ }
+
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ cmd.description = "generating " + output.fileName + " from " + input.fileName;
+ cmd.highlight = "codegen";
+ cmd.sourceCode = function() {
+ var aggregateDesktopKeys = Fdo.parseDesktopFile(input.filePath);
+ var desktopKeys = ModUtils.moduleProperty(product, "desktopKeys") || {}
+ var mainSection = aggregateDesktopKeys['Desktop Entry'];
+ for (key in desktopKeys) {
+ if (desktopKeys.hasOwnProperty(key)) {
+ mainSection[key] = desktopKeys[key];
+ }
+ }
+
+ var defaultValues = product.freedesktop.defaultDesktopKeys
+ for (key in defaultValues) {
+ if (!(key in mainSection)) {
+ mainSection[key] = defaultValues[key];
+ }
+ }
+
+ Fdo.dumpDesktopFile(output.filePath, aggregateDesktopKeys);
+ }
+ return [cmd];
+ }
+ }
+
+ Group {
+ condition: product.freedesktop._fdoSupported
+ fileTagsFilter: [ "freedesktop.desktopfile" ]
+ qbs.install: true
+ qbs.installDir: "share/applications"
+ }
+
+ Group {
+ condition: product.freedesktop._fdoSupported
+ fileTagsFilter: [ "freedesktop.appIcon" ]
+ qbs.install: true
+ qbs.installDir: "share/icons/hicolor/scalable/apps"
+ }
+
+ FileTagger {
+ patterns: [ "*.metainfo.xml", "*.appdata.xml" ]
+ fileTags: [ "freedesktop.appstream" ]
+ }
+
+ Group {
+ condition: product.freedesktop._fdoSupported
+ fileTagsFilter: [ "freedesktop.appstream" ]
+ qbs.install: true
+ qbs.installDir: "share/metainfo"
+ }
+}
diff --git a/share/qbs/modules/freedesktop/freedesktop.js b/share/qbs/modules/freedesktop/freedesktop.js
new file mode 100644
index 000000000..d3c60b191
--- /dev/null
+++ b/share/qbs/modules/freedesktop/freedesktop.js
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Alberto Mardegan <mardy@users.sourceforge.net>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** 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.
+**
+****************************************************************************/
+
+var TextFile = require("qbs.TextFile");
+
+function parseDesktopFile(filePath) {
+ var file = new TextFile(filePath);
+ var fileValues = {};
+ var currentSection = {};
+ var sectionRex = /\[(.+)\]/g;
+ while (!file.atEof()) {
+ var line = file.readLine().trim();
+ if (line.length == 0) continue;
+ if (line[0] == '#') continue;
+ var match = sectionRex.exec(line);
+ if (match) {
+ var currentSectionName = match[1];
+ fileValues[currentSectionName] = {};
+ currentSection = fileValues[currentSectionName];
+ continue;
+ }
+ var parts = line.split('=', 2);
+ currentSection[parts[0]] = parts[1]
+ }
+ file.close();
+ return fileValues
+}
+
+function dumpDesktopFile(filePath, keys) {
+ var file = new TextFile(filePath, TextFile.WriteOnly);
+ for (var sectionName in keys) {
+ file.writeLine('[' + sectionName + ']');
+ var section = keys[sectionName];
+ for (var key in section) {
+ var line = key + '=' + section[key];
+ file.writeLine(line);
+ }
+ // Write an empty line between sections (and before EOF)
+ file.writeLine('');
+ }
+ file.close();
+}
diff --git a/share/qbs/modules/ib/IBModule.qbs b/share/qbs/modules/ib/IBModule.qbs
index 6af5e94e4..e6183e20c 100644
--- a/share/qbs/modules/ib/IBModule.qbs
+++ b/share/qbs/modules/ib/IBModule.qbs
@@ -31,6 +31,7 @@
import qbs.BundleTools
import qbs.DarwinTools
import qbs.File
+import qbs.Host
import qbs.FileInfo
import qbs.ModUtils
import qbs.Process
@@ -49,7 +50,7 @@ Module {
}
}
- condition: qbs.hostOS.contains("darwin") && qbs.targetOS.contains("darwin")
+ condition: Host.os().includes("darwin") && qbs.targetOS.includes("darwin")
property bool warnings: true
property bool errors: true
@@ -195,7 +196,7 @@ Module {
cmd.highlight = 'compiler';
// May not be strictly needed, but is set by some versions of Xcode
- if (input.fileTags.contains("storyboard"))
+ if (input.fileTags.includes("storyboard"))
cmd.environment.push("IBSC_MINIMUM_COMPATIBILITY_VERSION=" +
(product.moduleProperty("cpp", "minimumDarwinVersion") || ""));
diff --git a/share/qbs/modules/ib/ib.js b/share/qbs/modules/ib/ib.js
index 40bd1dc23..d6873b261 100644
--- a/share/qbs/modules/ib/ib.js
+++ b/share/qbs/modules/ib/ib.js
@@ -116,7 +116,7 @@ function ibtooldArguments(product, inputs, input, outputs, overrideOutput) {
var outputFormat = ModUtils.moduleProperty(product, "outputFormat");
if (outputFormat) {
- if (!["binary1", "xml1", "human-readable-text"].contains(outputFormat))
+ if (!["binary1", "xml1", "human-readable-text"].includes(outputFormat))
throw("Invalid ibtoold output format: " + outputFormat + ". " +
"Must be in [binary1, xml1, human-readable-text].");
@@ -173,7 +173,7 @@ function ibtooldArguments(product, inputs, input, outputs, overrideOutput) {
// --target-device and -output-partial-info-plist were introduced in Xcode 6.0 for ibtool
if (ModUtils.moduleProperty(product, "ibtoolVersionMajor") >= 6 || inputs.assetcatalog) {
args.push("--output-partial-info-plist", (outputs && outputs.partial_infoplist)
- ? outputs.partial_infoplist[0].filePath
+ ? outputs.partial_infoplist[outputs.partial_infoplist.length - 1].filePath
: "/dev/null");
// For iOS, we'd normally only output the devices specified in TARGETED_DEVICE_FAMILY
@@ -205,9 +205,9 @@ function ibtooldArguments(product, inputs, input, outputs, overrideOutput) {
function ibtoolFileTaggers(fileTags) {
var ext;
- if (fileTags.contains("nib") && !fileTags.contains("storyboard"))
+ if (fileTags.includes("nib") && !fileTags.includes("storyboard"))
ext = "nib";
- if (fileTags.contains("storyboard") && !fileTags.contains("nib"))
+ if (fileTags.includes("storyboard") && !fileTags.includes("nib"))
ext = "storyboard";
if (!ext)
@@ -223,9 +223,9 @@ function ibtoolFileTaggers(fileTags) {
function ibtoolCompiledDirSuffix(product, input) {
var suffix = input.completeBaseName;
- if (input.fileTags.contains("nib"))
+ if (input.fileTags.includes("nib"))
suffix += ModUtils.moduleProperty(product, "compiledNibSuffix");
- else if (input.fileTags.contains("storyboard"))
+ else if (input.fileTags.includes("storyboard"))
suffix += ModUtils.moduleProperty(product, "compiledStoryboardSuffix");
return suffix;
}
@@ -252,7 +252,7 @@ function ibtoolOutputArtifacts(product, inputs, input) {
var artifacts = tracker.artifacts(ibtoolBuildDirectory);
if (product.moduleProperty("ib", "ibtoolVersionMajor") >= 6) {
- var prefix = input.fileTags.contains("storyboard") ? "SB" : "";
+ var prefix = input.fileTags.includes("storyboard") ? "SB" : "";
var path = FileInfo.joinPaths(product.destinationDirectory, input.completeBaseName +
"-" + prefix + "PartialInfo.plist");
artifacts.push({ filePath: path, fileTags: ["partial_infoplist"] });
@@ -261,7 +261,7 @@ function ibtoolOutputArtifacts(product, inputs, input) {
// Let the output artifacts known the "main" output
// This can be either a file or directory so the artifact might already exist in the output list
for (var i = 0; i < artifacts.length; ++i) {
- if (artifacts[i].fileTags.contains("compiled_ibdoc"))
+ if (artifacts[i].fileTags.includes("compiled_ibdoc"))
artifacts[i].bundle = {
_bundleFilePath: artifacts[i].filePath.replace(ibtoolBuildDirectory, main)
};
@@ -296,7 +296,7 @@ function actoolOutputArtifacts(product, inputs) {
}
for (var i = 0; i < artifacts.length; ++i) {
- if (artifacts[i].fileTags.contains("compiled_assetcatalog")) {
+ if (artifacts[i].fileTags.includes("compiled_assetcatalog")) {
artifacts[i].bundle = {
_bundleFilePath: artifacts[i].filePath.replace(
product.buildDirectory + "/actool.dir",
diff --git a/share/qbs/modules/ico/ico.js b/share/qbs/modules/ico/ico.js
index 997a6dc23..dc96eedf3 100644
--- a/share/qbs/modules/ico/ico.js
+++ b/share/qbs/modules/ico/ico.js
@@ -29,6 +29,7 @@
****************************************************************************/
var File = require("qbs.File");
+var FileInfo = require("qbs.FileInfo");
var Process = require("qbs.Process");
function prepareIconset(project, product, inputs, outputs, input, output) {
@@ -39,20 +40,20 @@ function prepareIconset(project, product, inputs, outputs, input, output) {
ico: {}
};
});
- inputs = {"png": inputs.filter(function (a) { return a.fileTags.contains("png"); })};
+ inputs = {"png": inputs.filter(function (a) { return a.fileTags.includes("png"); })};
input = undefined;
return prepare(project, product, inputs, outputs, input, output);
}
function prepare(project, product, inputs, outputs, input, output) {
var args = ["--create", "--output=" + output.filePath];
- if (output.fileTags.contains("ico")) {
+ if (output.fileTags.includes("ico")) {
args.push("--icon");
if (product.ico.alphaThreshold !== undefined)
args.push("--alpha-threshold=" + product.ico.alphaThreshold);
}
- var isCursor = output.fileTags.contains("cur");
+ var isCursor = output.fileTags.includes("cur");
if (isCursor)
args.push("--cursor");
diff --git a/share/qbs/modules/innosetup/InnoSetupModule.qbs b/share/qbs/modules/innosetup/InnoSetupModule.qbs
index 1caf39dc8..9f1018ec4 100644
--- a/share/qbs/modules/innosetup/InnoSetupModule.qbs
+++ b/share/qbs/modules/innosetup/InnoSetupModule.qbs
@@ -33,7 +33,7 @@ import qbs.ModUtils
import qbs.Probes
Module {
- condition: qbs.targetOS.contains("windows")
+ condition: qbs.targetOS.includes("windows")
Probes.InnoSetupProbe {
id: innoSetupProbe
@@ -76,6 +76,10 @@ Module {
readonly property string executableSuffix: ".exe"
validate: {
+ if (!innoSetupProbe.found) {
+ throw ModUtils.ModuleError("Could not find InnoSetup in Windows registry. Make " +
+ "sure InnoSetup is installed correctly.");
+ }
var validator = new ModUtils.PropertyValidator("innosetup");
validator.setRequiredProperty("toolchainInstallPath", toolchainInstallPath);
validator.setRequiredProperty("version", version);
diff --git a/share/qbs/modules/java/JavaModule.qbs b/share/qbs/modules/java/JavaModule.qbs
index 71f7d8432..343b2f4ba 100644
--- a/share/qbs/modules/java/JavaModule.qbs
+++ b/share/qbs/modules/java/JavaModule.qbs
@@ -29,6 +29,7 @@
****************************************************************************/
import qbs.FileInfo
+import qbs.Host
import qbs.ModUtils
import qbs.Probes
import qbs.Process
@@ -122,10 +123,10 @@ Module {
} else {
paths.push(FileInfo.joinPaths(jdkPath, "include"));
- var hostOS = qbs.hostOS.contains("windows") ? qbs.hostOS.concat(["win32"]) : qbs.hostOS;
+ var hostOS = Host.os().includes("windows") ? Host.os().concat(["win32"]) : Host.os();
var platforms = ["win32", "darwin", "linux", "bsd", "solaris"];
for (var i = 0; i < platforms.length; ++i) {
- if (hostOS.contains(platforms[i])) {
+ if (hostOS.includes(platforms[i])) {
// Corresponds to JDK_INCLUDE_SUBDIR in the JDK Makefiles
paths.push(FileInfo.joinPaths(jdkPath, "include", platforms[i]));
break;
@@ -140,7 +141,7 @@ Module {
property path classFilesDir: FileInfo.joinPaths(product.buildDirectory, "classes")
property path internalClassFilesDir: FileInfo.joinPaths(product.buildDirectory, ".classes")
- property bool isAppleJava: qbs.hostOS.contains("darwin")
+ property bool isAppleJava: Host.os().includes("darwin")
&& (compilerVersionMajor < 1
|| (compilerVersionMajor === 1 && compilerVersionMinor < 7))
@@ -234,14 +235,18 @@ Module {
inputsFromDependencies: ["java.jar"]
explicitlyDependsOn: ["java.class-internal"]
- outputFileTags: ["java.class"].concat(_tagJniHeaders ? ["hpp"] : []) // Annotations can produce additional java source files. Ignored for now.
+ outputFileTags: ["java.class"].concat(_tagJniHeaders ? ["hpp"] : ["java.jni-hpp"]) // Annotations can produce additional java source files. Ignored for now.
outputArtifacts: {
var artifacts = JavaUtils.outputArtifacts(product, inputs);
if (!product.java._tagJniHeaders) {
for (var i = 0; i < artifacts.length; ++i) {
var a = artifacts[i];
- if (Array.isArray(a.fileTags))
- a.fileTags = a.fileTags.filter(function(tag) { return tag != "hpp"; });
+ if (a.fileTags instanceof Array)
+ a.fileTags = a.fileTags.map(function(tag) {
+ if (tag === "hpp")
+ return "java.jni-hpp";
+ return tag;
+ });
}
}
return artifacts;
@@ -249,7 +254,7 @@ Module {
prepare: {
var cmd = new Command(ModUtils.moduleProperty(product, "compilerFilePath"),
JavaUtils.javacArguments(product, inputs));
- cmd.description = "Compiling Java sources";
+ cmd.description = "compiling Java sources";
cmd.highlight = "compiler";
return [cmd];
}
diff --git a/share/qbs/modules/java/utils.js b/share/qbs/modules/java/utils.js
index ae0c1356b..a59b8d41d 100644
--- a/share/qbs/modules/java/utils.js
+++ b/share/qbs/modules/java/utils.js
@@ -74,13 +74,12 @@ function jdkRootRegistryKey(wow64) {
function findJdkPath(hostOS, arch, environmentPaths, searchPaths) {
var i;
- for (var key in environmentPaths) {
- if (environmentPaths[key]) {
- return environmentPaths[key];
- }
+ for (i = 0; i < environmentPaths.length; ++i) {
+ if (environmentPaths[i])
+ return environmentPaths[i];
}
- if (hostOS.contains("windows")) {
+ if (hostOS.includes("windows")) {
var rootKey = jdkRootRegistryKey(useWow64Key(arch));
if (rootKey) {
var current = Utilities.getNativeSetting(rootKey, "CurrentVersion"); // 1.8 etc.
@@ -95,27 +94,55 @@ function findJdkPath(hostOS, arch, environmentPaths, searchPaths) {
return undefined;
}
- if (hostOS.contains("macos")) {
+ if (hostOS.includes("macos")) {
var p = new Process();
try {
// We filter by architecture here so that we'll get a compatible JVM for JNI use.
var args = [];
+ var canonicalArch;
if (arch) {
// Hardcoding apple/macosx/macho here is fine because we know we're on macOS
- args.push("--arch",
- Utilities.canonicalTargetArchitecture(arch, undefined,
- "apple", "macosx", "macho"));
+ canonicalArch = Utilities.canonicalTargetArchitecture(arch, undefined, "apple",
+ "macosx", "macho");
+ args.push("--arch", canonicalArch);
}
// --failfast doesn't print the default JVM if nothing matches the filter(s).
var status = p.exec("/usr/libexec/java_home", args.concat(["--failfast"]));
- return status === 0 ? p.readStdOut().trim() : undefined;
+ if (status === 0)
+ return p.readStdOut().trim();
+
+ // It has been obvserved that java_home fails for any architecture that is passed,
+ // so try without the filter and look up the JDK architecture manually.
+ if (!canonicalArch)
+ return undefined;
+
+ if (p.exec("/usr/libexec/java_home", ["--failfast"]) !== 0)
+ return undefined;
+ var jdkPath = p.readStdOut().trim();
+ var releaseFile = new TextFile(jdkPath + "/release", TextFile.ReadOnly);
+ var line;
+ while ((line = releaseFile.readLine())) {
+ if (!line.startsWith("OS_ARCH="))
+ continue;
+ var firstQuote = line.indexOf('"');
+ if (firstQuote === -1)
+ break;
+ var secondQuote = line.indexOf('"', firstQuote + 1);
+ if (secondQuote === -1)
+ break;
+ var archFromFile = line.substring(firstQuote + 1, secondQuote);
+ if (archFromFile !== canonicalArch)
+ break;
+ return jdkPath;
+ }
+ return undefined;
} finally {
p.close();
}
}
- if (hostOS.contains("unix")) {
+ if (hostOS.includes("unix")) {
var requiredTools = ["javac", "java", "jar"];
for (i = 0; i < searchPaths.length; ++i) {
function fullToolPath(tool) {
@@ -136,7 +163,7 @@ function findJdkVersion(compilerFilePath) {
var p = new Process();
try {
p.exec(compilerFilePath, ["-version"]);
- var re = /^javac (([0-9]+(?:\.[0-9]+){0,2})(_([0-9]+))?)$/m;
+ var re = /^javac (([0-9]+(?:\.[0-9]+){0,2})(_([0-9]+))?)(.*)?$/m;
var match = p.readStdErr().trim().match(re);
if (!match)
match = p.readStdOut().trim().match(re);
@@ -194,7 +221,7 @@ function javacArguments(product, inputs, overrides) {
classPaths.push(inputs["java.jar"][i].filePath);
var debugArg = product.moduleProperty("qbs", "buildVariant") === "debug"
? "-g" : "-g:none";
- var pathListSeparator = product.moduleProperty("qbs", "pathListSeparator");
+ var pathListSeparator = FileInfo.pathListSeparator();
var args = [
"-classpath", classPaths.join(pathListSeparator),
"-s", product.buildDirectory,
@@ -247,7 +274,7 @@ function helperFullyQualifiedNames(type) {
];
if (type === "java") {
return names.filter(function (name) {
- return !name.contains("$");
+ return !name.includes("$");
});
} else if (type === "class") {
return names;
@@ -313,7 +340,7 @@ function outputArtifacts(product, inputs) {
process.setWorkingDirectory(
FileInfo.joinPaths(ModUtils.moduleProperty(product, "internalClassFilesDir")));
- var sep = product.moduleProperty("qbs", "pathListSeparator");
+ var sep = FileInfo.pathListSeparator();
var toolsJarPath = ModUtils.moduleProperty(product, "toolsJarPath");
var javaArgs = [
"-classpath", process.workingDirectory() + (toolsJarPath ? (sep + toolsJarPath) : ""),
@@ -347,7 +374,7 @@ function manifestContents(filePath) {
if (contents) {
var dict = {};
var lines = contents.split(/\r?\n/g).filter(function (line) { return line.length > 0; });
- for (var i in lines) {
+ for (var i = 0; i < lines.length; ++i) {
var kv = lines[i].split(":");
if (kv.length !== 2)
throw new Error("Syntax error in manifest file '"
diff --git a/share/qbs/modules/nodejs/NodeJS.qbs b/share/qbs/modules/nodejs/NodeJS.qbs
index 7fd992fdb..412f9b8bb 100644
--- a/share/qbs/modules/nodejs/NodeJS.qbs
+++ b/share/qbs/modules/nodejs/NodeJS.qbs
@@ -31,6 +31,7 @@
import qbs.Environment
import qbs.File
import qbs.FileInfo
+import qbs.Host
import qbs.ModUtils
import qbs.Probes
@@ -84,13 +85,13 @@ Module {
"tmp", "nodejs.intermediate")
setupBuildEnvironment: {
- var v = new ModUtils.EnvironmentVariable("PATH", product.qbs.pathListSeparator, product.qbs.hostOS.contains("windows"));
+ var v = new ModUtils.EnvironmentVariable("PATH", FileInfo.pathListSeparator(), Host.os().includes("windows"));
v.prepend(product.nodejs.toolchainInstallPath);
v.set();
}
setupRunEnvironment: {
- var v = new ModUtils.EnvironmentVariable("NODE_PATH", product.qbs.pathListSeparator, product.qbs.hostOS.contains("windows"));
+ var v = new ModUtils.EnvironmentVariable("NODE_PATH", FileInfo.pathListSeparator(), Host.os().includes("windows"));
v.prepend(FileInfo.path(Environment.getEnv("QBS_RUN_FILE_PATH")));
v.set();
}
@@ -118,7 +119,7 @@ Module {
outputArtifacts: {
var tags = ["nodejs_processed_js"];
- if (input.fileTags.contains("application_js") ||
+ if (input.fileTags.includes("application_js") ||
product.moduleProperty("nodejs", "applicationFile") === input.filePath)
tags.push("application");
diff --git a/share/qbs/modules/nsis/NSISModule.qbs b/share/qbs/modules/nsis/NSISModule.qbs
index e426aee56..11a5670b5 100644
--- a/share/qbs/modules/nsis/NSISModule.qbs
+++ b/share/qbs/modules/nsis/NSISModule.qbs
@@ -30,11 +30,12 @@
import qbs.File
import qbs.FileInfo
+import qbs.Host
import qbs.ModUtils
import qbs.Utilities
Module {
- condition: qbs.targetOS.contains("windows")
+ condition: qbs.targetOS.includes("windows")
property path toolchainInstallPath: Utilities.getNativeSetting(registryKey)
@@ -89,7 +90,7 @@ Module {
// Private properties
property string registryKey: {
- if (!qbs.hostOS.contains("windows"))
+ if (!Host.os().includes("windows"))
return undefined;
var keys = [ "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\NSIS" ];
@@ -104,7 +105,7 @@ Module {
// Only *require* the toolchain install path on Windows
// On other (Unix-like) operating systems it'll probably be in the PATH
- if (qbs.targetOS.contains("windows"))
+ if (qbs.targetOS.includes("windows"))
validator.setRequiredProperty("toolchainInstallPath", toolchainInstallPath);
validator.setRequiredProperty("versionMajor", versionMajor);
@@ -120,7 +121,7 @@ Module {
}
setupBuildEnvironment: {
- if (toolchainInstallPath) {
+ if (product.nsis.toolchainInstallPath) {
var v = new ModUtils.EnvironmentVariable("PATH", ";", true);
v.prepend(product.nsis.toolchainInstallPath);
v.prepend(FileInfo.joinPaths(product.nsis.toolchainInstallPath, "bin"));
@@ -148,7 +149,9 @@ Module {
Artifact {
fileTags: ["nsissetup", "application"]
- filePath: product.destinationDirectory + "/" + product.targetName + ModUtils.moduleProperty(product, "executableSuffix")
+ filePath: FileInfo.joinPaths(product.destinationDirectory,
+ product.targetName + ModUtils.moduleProperty(
+ product, "executableSuffix"))
}
prepare: {
@@ -156,7 +159,7 @@ Module {
var args = [];
// Prefix character for makensis options
- var opt = product.moduleProperty("qbs", "hostOS").contains("windows") ? "/" : "-";
+ var opt = product.moduleProperty("qbs", "hostOS").includes("windows") ? "/" : "-";
if (ModUtils.moduleProperty(product, "disableConfig")) {
args.push(opt + "NOCONFIG");
diff --git a/share/qbs/modules/pkgconfig/pkgconfig.qbs b/share/qbs/modules/pkgconfig/pkgconfig.qbs
index ec4b59188..901e7e02e 100644
--- a/share/qbs/modules/pkgconfig/pkgconfig.qbs
+++ b/share/qbs/modules/pkgconfig/pkgconfig.qbs
@@ -37,7 +37,6 @@
**
****************************************************************************/
-import qbs
import qbs.File
import qbs.Probes
@@ -48,7 +47,7 @@ Module {
}
property path sysroot: {
- if (qbs.targetOS.contains("macos"))
+ if (qbs.targetOS.includes("macos"))
return "";
return qbs.sysroot;
}
diff --git a/share/qbs/modules/protobuf/cpp/protobufcpp.qbs b/share/qbs/modules/protobuf/cpp/protobufcpp.qbs
index 0c511f2aa..bd4a08557 100644
--- a/share/qbs/modules/protobuf/cpp/protobufcpp.qbs
+++ b/share/qbs/modules/protobuf/cpp/protobufcpp.qbs
@@ -1,4 +1,3 @@
-import qbs
import qbs.File
import qbs.FileInfo
import qbs.Probes
@@ -7,15 +6,30 @@ import "../protobufbase.qbs" as ProtobufBase
import "../protobuf.js" as HelperFunctions
ProtobufBase {
- property string includePath: includeProbe.path
- property string libraryPath: libraryProbe.path
-
property bool useGrpc: false
- property string grpcIncludePath: grpcIncludeProbe.path
- property string grpcLibraryPath: grpcLibraryProbe.path
+ property bool _linkLibraries: true
+ readonly property bool _hasModules: protobuflib.present && (!useGrpc || grpcpp.present)
+
+ property string _cxxLanguageVersion: "c++17"
+
+ _searchPaths: protobuflib.present ? protobuflib.hostBinDirs : undefined
+ property stringList _grpcSearchPaths: grpcpp.present ? grpcpp.hostBinDirs : undefined
+
+ cpp.includePaths: outputDir
Depends { name: "cpp" }
+ Depends {
+ name: "protobuflib";
+ condition: _linkLibraries;
+ required: false
+ }
+ Depends {
+ name: "grpc++";
+ id: grpcpp
+ condition: _linkLibraries && useGrpc;
+ required: false
+ }
property path grpcPluginPath: grpcPluginProbe.filePath
@@ -23,41 +37,26 @@ ProtobufBase {
condition: useGrpc
id: grpcPluginProbe
names: "grpc_cpp_plugin"
+ searchPaths: _grpcSearchPaths
}
- cpp.libraryPaths: {
- var result = [libraryPath];
- if (useGrpc)
- result.push(grpcLibraryPath);
- return result;
- }
- cpp.dynamicLibraries: {
- var result = ["protobuf"];
- if (qbs.targetOS.contains("unix"))
- result.push("pthread");
- if (useGrpc)
- result.push("grpc++");
- return result;
- }
- cpp.includePaths: {
- var result = [outputDir, includePath];
- if (useGrpc)
- result.push("grpcIncludePath");
- return result;
- }
+ cpp.cxxLanguageVersion: _cxxLanguageVersion
Rule {
inputs: ["protobuf.input", "protobuf.grpc"]
- outputFileTags: ["hpp", "cpp"]
+ outputFileTags: ["hpp", "protobuf.hpp", "cpp"]
outputArtifacts: {
+ var outputDir = HelperFunctions.getOutputDir(input.protobuf.cpp, input);
var result = [
- HelperFunctions.cppArtifact(input.protobuf.cpp, product, input, "hpp", ".pb.h"),
- HelperFunctions.cppArtifact(input.protobuf.cpp, product, input, "cpp", ".pb.cc")
+ HelperFunctions.cppArtifact(outputDir, input, ["hpp", "protobuf.hpp"],
+ ".pb.h"),
+ HelperFunctions.cppArtifact(outputDir, input, "cpp", ".pb.cc")
];
- if (input.fileTags.contains("protobuf.grpc")) {
+ if (input.fileTags.includes("protobuf.grpc")) {
result.push(
- HelperFunctions.cppArtifact(input.protobuf.cpp, product, input, "hpp", ".grpc.pb.h"),
- HelperFunctions.cppArtifact(input.protobuf.cpp, product, input, "cpp", ".grpc.pb.cc"));
+ HelperFunctions.cppArtifact(outputDir, input, ["hpp", "protobuf.hpp"],
+ ".grpc.pb.h"),
+ HelperFunctions.cppArtifact(outputDir, input, ["cpp"], ".grpc.pb.cc"));
}
return result;
@@ -66,51 +65,25 @@ ProtobufBase {
prepare: {
var result = HelperFunctions.doPrepare(
input.protobuf.cpp, product, input, outputs, "cpp");
- if (input.fileTags.contains("protobuf.grpc")) {
- result = ModUtils.concatAll(result, HelperFunctions.doPrepareGrpc(
- input.protobuf.cpp, product, input, outputs, "cpp"));
+ if (input.fileTags.includes("protobuf.grpc")) {
+ result = ModUtils.concatAll(result, HelperFunctions.doPrepare(
+ input.protobuf.cpp, product, input, outputs, "grpc",
+ "protoc-gen-grpc=" + input.protobuf.cpp.grpcPluginPath));
}
return result;
}
}
- validateFunc: {
- return function() {
- base();
- if (!HelperFunctions.checkPath(includePath))
- throw "Can't find cpp protobuf include files. Please set the includePath property.";
- if (!HelperFunctions.checkPath(libraryPath))
- throw "Can't find cpp protobuf library. Please set the libraryPath property.";
+ validate: {
+ HelperFunctions.validateCompiler(compilerName, compilerPath);
- if (useGrpc) {
- if (!File.exists(grpcPluginPath))
- throw "Can't find grpc_cpp_plugin plugin. Please set the grpcPluginPath property.";
- if (!HelperFunctions.checkPath(grpcIncludePath))
- throw "Can't find grpc++ include files. Please set the grpcIncludePath property.";
- if (!HelperFunctions.checkPath(grpcLibraryPath))
- throw "Can't find grpc++ library. Please set the grpcLibraryPath property.";
- }
+ if (_linkLibraries && ! _hasModules) {
+ throw "Can't find cpp protobuf runtime. Make sure .pc files are present";
}
- }
- Probes.IncludeProbe {
- id: includeProbe
- names: "google/protobuf/message.h"
- }
-
- Probes.LibraryProbe {
- id: libraryProbe
- names: "protobuf"
- }
-
- Probes.IncludeProbe {
- id: grpcIncludeProbe
- pathSuffixes: "grpc++"
- names: "grpc++.h"
- }
-
- Probes.LibraryProbe {
- id: grpcLibraryProbe
- names: "grpc++"
+ if (useGrpc) {
+ if (!File.exists(grpcPluginPath))
+ throw "Can't find grpc_cpp_plugin plugin. Please set the grpcPluginPath property.";
+ }
}
}
diff --git a/share/qbs/modules/protobuf/nanopb/nanopb.qbs b/share/qbs/modules/protobuf/nanopb/nanopb.qbs
new file mode 100644
index 000000000..ada7c20bb
--- /dev/null
+++ b/share/qbs/modules/protobuf/nanopb/nanopb.qbs
@@ -0,0 +1,104 @@
+import qbs.File
+import qbs.FileInfo
+import qbs.Probes
+import qbs.ModUtils
+import "../protobufbase.qbs" as ProtobufBase
+import "../protobuf.js" as HelperFunctions
+
+ProtobufBase {
+ property string includePath: includeProbe.found ? includeProbe.path : undefined
+ property string libraryPath: libraryProbe.found ? libraryProbe.path : undefined
+ property string pluginPath: pluginProbe.filePath
+ property string pluginName: "protoc-gen-nanopb"
+ readonly property string _plugin: "protoc-gen-nanopb=" + pluginPath
+ readonly property string _libraryName: {
+ var libraryName;
+ if (libraryProbe.found) {
+ libraryName = FileInfo.baseName(libraryProbe.fileName);
+ if (libraryName.startsWith("lib"))
+ libraryName = libraryName.substring(3);
+ }
+ return libraryName;
+ }
+
+ Depends { name: "cpp" }
+
+ cpp.libraryPaths: {
+ var result = [];
+ if (libraryProbe.found)
+ result.push(libraryProbe.path);
+ return result;
+ }
+ cpp.dynamicLibraries: {
+ var result = [];
+ if (_libraryName)
+ result.push(_libraryName);
+ return result;
+ }
+ cpp.includePaths: {
+ var result = [outputDir];
+ if (includeProbe.found)
+ result.push(includePath);
+ return result;
+ }
+ cpp.cxxLanguageVersion: qbs.targetOS.contains("darwin") ? ["c++17"] : ["c++11"]
+
+ Rule {
+ inputs: ["protobuf.input"]
+ outputFileTags: ["hpp", "protobuf.hpp", "cpp"]
+ outputArtifacts: {
+ var outputDir = HelperFunctions.getOutputDir(input.protobuf.nanopb, input);
+ var result = [
+ HelperFunctions.cppArtifact(outputDir, input, ["hpp", "protobuf.hpp"],
+ ".pb.h"),
+ HelperFunctions.cppArtifact(outputDir, input, ["cpp"], ".pb.c")
+ ];
+
+ return result;
+ }
+
+ prepare: {
+ var options = input.protobuf.nanopb.importPaths.map(function (path) {
+ return "-I" + path;
+ })
+
+ var result = HelperFunctions.doPrepare(
+ input.protobuf.nanopb, product, input, outputs, "nanopb",
+ input.protobuf.nanopb._plugin, options);
+ return result;
+ }
+ }
+
+ Probes.IncludeProbe {
+ id: includeProbe
+ names: ["pb.h", "pb_encode.h", "pb_decode.h", "pb_common.h"]
+ platformSearchPaths: includePath ? [] : base
+ searchPaths: includePath ? [includePath] : []
+ }
+
+ Probes.LibraryProbe {
+ id: libraryProbe
+ names: [
+ "protobuf-nanopb",
+ "protobuf-nanopbd",
+ ]
+ platformSearchPaths: libraryPath ? [] : base
+ searchPaths: libraryPath ? [libraryPath] : []
+ }
+
+ Probes.BinaryProbe {
+ id: pluginProbe
+ names: pluginName
+ }
+
+ validate: {
+ HelperFunctions.validateCompiler(compilerName, compilerPath);
+
+ if (!includeProbe.found)
+ throw "Can't find nanopb protobuf include files. Please set the includePath property.";
+ if (!libraryProbe.found)
+ throw "Can't find nanopb protobuf library. Please set the libraryPath property.";
+ if (!HelperFunctions.checkPath(pluginPath))
+ throw "Can't find nanopb protobuf plugin. Please set the pluginPath property.";
+ }
+}
diff --git a/share/qbs/modules/protobuf/objc/protobufobjc.qbs b/share/qbs/modules/protobuf/objc/protobufobjc.qbs
index e2c4b5260..a3e708898 100644
--- a/share/qbs/modules/protobuf/objc/protobufobjc.qbs
+++ b/share/qbs/modules/protobuf/objc/protobufobjc.qbs
@@ -1,4 +1,3 @@
-import qbs
import qbs.File
import qbs.FileInfo
import qbs.Probes
@@ -12,49 +11,28 @@ ProtobufBase {
Depends { name: "cpp" }
- // library build
- Properties {
- condition: !frameworkPath
- cpp.includePaths: [outputDir, includePath]
- cpp.libraryPaths: [libraryPath]
- cpp.frameworks: ["Foundation"]
- cpp.dynamicLibraries: ["ProtocolBuffers"]
- }
-
- // framework build
- Properties {
- condition: frameworkPath
- cpp.includePaths: [outputDir]
- cpp.frameworkPaths: [frameworkPath]
- cpp.frameworks: ["Foundation", "Protobuf"]
- cpp.defines: ["GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS"]
- }
+ cpp.includePaths: [outputDir].concat(!frameworkPath && includePath ? [includePath] : [])
+ cpp.libraryPaths: !frameworkPath && libraryPath ? [libraryPath] : []
+ cpp.dynamicLibraries: !frameworkPath && libraryPath ? ["ProtocolBuffers"] : []
+ cpp.frameworkPaths: frameworkPath ? [frameworkPath] : []
+ cpp.frameworks: ["Foundation"].concat(frameworkPath ? ["Protobuf"] : [])
+ cpp.defines: frameworkPath ? ["GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS"] : []
Rule {
inputs: ["protobuf.input"]
- outputFileTags: ["hpp", "objc"]
+ outputFileTags: ["hpp", "protobuf.hpp", "objc"]
outputArtifacts: {
+ var outputDir = HelperFunctions.getOutputDir(input.protobuf.objc, input);
return [
- HelperFunctions.objcArtifact(input.protobuf.objc, product, input, "hpp", ".pbobjc.h"),
- HelperFunctions.objcArtifact(input.protobuf.objc, product, input, "objc", ".pbobjc.m")
+ HelperFunctions.objcArtifact(outputDir, input, ["hpp", "protobuf.hpp"],
+ ".pbobjc.h"),
+ HelperFunctions.objcArtifact(outputDir, input, ["objc"], ".pbobjc.m")
];
}
prepare: HelperFunctions.doPrepare(input.protobuf.objc, product, input, outputs, "objc")
}
- validateFunc: {
- return function() {
- base();
- if (!HelperFunctions.checkPath(frameworkPath)) {
- if (!HelperFunctions.checkPath(includePath))
- throw "Can't find objective-c protobuf include files. Please set the includePath or frameworkPath property.";
- if (!HelperFunctions.checkPath(libraryPath))
- throw "Can't find objective-c protobuf library. Please set the libraryPath or frameworkPath property.";
- }
- }
- }
-
Probes.IncludeProbe {
id: includeProbe
names: "GPBMessage.h"
@@ -69,4 +47,18 @@ ProtobufBase {
id: frameworkProbe
names: ["Protobuf"]
}
+
+ validate: {
+ HelperFunctions.validateCompiler(compilerName, compilerPath);
+ if (!HelperFunctions.checkPath(frameworkPath)) {
+ if (!HelperFunctions.checkPath(includePath)) {
+ throw "Can't find objective-c protobuf include files. Please set the includePath "
+ + "or frameworkPath property.";
+ }
+ if (!HelperFunctions.checkPath(libraryPath)) {
+ throw "Can't find objective-c protobuf library. Please set the libraryPath or "
+ + "frameworkPath property.";
+ }
+ }
+ }
}
diff --git a/share/qbs/modules/protobuf/protobuf.js b/share/qbs/modules/protobuf/protobuf.js
index 511f5a6c6..60d6f48e4 100644
--- a/share/qbs/modules/protobuf/protobuf.js
+++ b/share/qbs/modules/protobuf/protobuf.js
@@ -1,7 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2018 Ivan Komissarov
-** Contact: abbapoh@gmail.com
+** Copyright (C) 2018 Ivan Komissarov (abbapoh@gmail.com)
+** Contact: https://www.qt.io/licensing/
**
** This file is part of Qbs.
**
@@ -31,8 +31,15 @@
var File = require("qbs.File");
var FileInfo = require("qbs.FileInfo");
-var checkPath = function(path) {
- return path && File.exists(path)
+function validateCompiler(compilerName, compilerPath) {
+ if (!File.exists(compilerPath)) {
+ throw "Can't find '" + compilerName + "' binary. Please set the compilerPath property or "
+ + "make sure the compiler is found in PATH";
+ }
+}
+
+function checkPath(path) {
+ return path && File.exists(path);
};
function toCamelCase(str){
@@ -46,13 +53,13 @@ function toCamelCase(str){
}).join('');
}
-function getOutputDir(module, product, input) {
+function getOutputDir(module, input) {
var outputDir = module.outputDir;
var importPaths = module.importPaths;
if (importPaths.length !== 0) {
var canonicalInput = File.canonicalFilePath(FileInfo.path(input.filePath));
for (var i = 0; i < importPaths.length; ++i) {
- path = File.canonicalFilePath(importPaths[i]);
+ var path = File.canonicalFilePath(importPaths[i]);
if (canonicalInput.startsWith(path)) {
return outputDir + "/" + FileInfo.relativePath(path, canonicalInput);
@@ -62,61 +69,44 @@ function getOutputDir(module, product, input) {
return outputDir;
}
-function cppArtifact(module, product, input, tag, suffix) {
- var outputDir = getOutputDir(module, product, input);
+function cppArtifact(outputDir, input, tags, suffix) {
return {
- fileTags: [tag],
- filePath: outputDir + "/" + FileInfo.baseName(input.fileName) + suffix,
+ fileTags: tags,
+ filePath: FileInfo.joinPaths(outputDir, FileInfo.baseName(input.fileName) + suffix),
cpp: {
includePaths: [].concat(input.cpp.includePaths, outputDir),
+ defines: ["NDEBUG"],
warningLevel: "none",
}
};
}
-function objcArtifact(module, product, input, tag, suffix) {
- var outputDir = getOutputDir(module, product, input);
+function objcArtifact(outputDir, input, tags, suffix) {
return {
- fileTags: [tag],
- filePath: outputDir + "/" + toCamelCase(FileInfo.baseName(input.fileName)) + suffix,
+ fileTags: tags,
+ filePath: FileInfo.joinPaths(
+ outputDir, toCamelCase(FileInfo.baseName(input.fileName)) + suffix),
cpp: {
+ automaticReferenceCounting: false,
includePaths: [].concat(input.cpp.includePaths, outputDir),
warningLevel: "none",
}
}
}
-function doPrepare(module, product, input, outputs, lang)
+function doPrepare(module, product, input, outputs, generator, plugin, generatorOptions)
{
var outputDir = module.outputDir;
var args = [];
- args.push("--" + lang + "_out", outputDir);
-
- var importPaths = module.importPaths;
- if (importPaths.length === 0)
- importPaths = [FileInfo.path(input.filePath)];
- importPaths.forEach(function(path) {
- if (!FileInfo.isAbsolutePath(path))
- path = FileInfo.joinPaths(product.sourceDirectory, path);
- args.push("--proto_path", path);
- });
+ if (!!plugin)
+ args.push("--plugin=" + plugin)
- args.push(input.filePath);
-
- var cmd = new Command(module.protocBinary, args);
- cmd.highlight = "codegen";
- cmd.description = "generating " + lang + " files for " + input.fileName;
- return [cmd];
-}
-
-function doPrepareGrpc(module, product, input, outputs, lang)
-{
- var outputDir = module.outputDir;
- var args = [];
-
- args.push("--grpc_out", outputDir);
- args.push("--plugin=protoc-gen-grpc=" + module.grpcPluginPath);
+ args.push("--" + generator + "_out", outputDir);
+ if (!!generatorOptions) {
+ for (var i = 0; i < generatorOptions.length; ++i)
+ args.push("--" + generator + "_opt=" + generatorOptions[i])
+ }
var importPaths = module.importPaths;
if (importPaths.length === 0)
@@ -129,8 +119,8 @@ function doPrepareGrpc(module, product, input, outputs, lang)
args.push(input.filePath);
- var cmd = new Command(module.protocBinary, args);
+ var cmd = new Command(module.compilerPath, args);
cmd.highlight = "codegen";
- cmd.description = "generating " + lang + " files for " + input.fileName;
+ cmd.description = "generating " + generator + " files for " + input.fileName;
return [cmd];
}
diff --git a/share/qbs/modules/protobuf/protobufbase.qbs b/share/qbs/modules/protobuf/protobufbase.qbs
index 0ac6c1949..e32ee30b9 100644
--- a/share/qbs/modules/protobuf/protobufbase.qbs
+++ b/share/qbs/modules/protobuf/protobufbase.qbs
@@ -1,33 +1,25 @@
-import qbs
import qbs.File
import qbs.FileInfo
import qbs.Probes
import "protobuf.js" as HelperFunctions
Module {
- property string protocBinary: protocProbe.filePath
- property pathList importPaths: []
+ property string compilerName: "protoc"
+ property string compilerPath: compilerProbe.filePath
+ property var _searchPaths
- property string outputDir: product.buildDirectory + "/protobuf"
+ property pathList importPaths: []
- property var validateFunc: {
- return function() {
- if (!File.exists(protocBinary))
- throw "Can't find protoc binary. Please set the protocBinary property or make sure it is found in PATH";
- }
- }
+ readonly property string outputDir: product.buildDirectory + "/protobuf"
FileTagger {
patterns: ["*.proto"]
- fileTags: ["protobuf.input"];
+ fileTags: ["protobuf.input"]
}
Probes.BinaryProbe {
- id: protocProbe
- names: ["protoc"]
- }
-
- validate: {
- validateFunc();
+ id: compilerProbe
+ names: [compilerName]
+ searchPaths: _searchPaths
}
}
diff --git a/share/qbs/modules/qbs/common.qbs b/share/qbs/modules/qbs/common.qbs
index 63bc29f8e..8b31092a9 100644
--- a/share/qbs/modules/qbs/common.qbs
+++ b/share/qbs/modules/qbs/common.qbs
@@ -48,25 +48,26 @@ Module {
property string buildVariant: defaultBuildVariant
property bool enableDebugCode: buildVariant == "debug"
- property bool debugInformation: (buildVariant == "debug")
- property string optimization: (buildVariant == "debug" ? "none" : "fast")
+ property bool debugInformation: (buildVariant !== "release")
+ property string optimization: (buildVariant === "debug" ? "none" : "fast")
readonly property string hostPlatform: undefined // set internally
readonly property stringList hostOS: Utilities.canonicalPlatform(hostPlatform)
property string hostOSVersion: {
- if (hostOS && hostOS.contains("macos")) {
+ if (hostOS && hostOS.includes("macos")) {
return Utilities.getNativeSetting("/System/Library/CoreServices/ServerVersion.plist", "ProductVersion") ||
Utilities.getNativeSetting("/System/Library/CoreServices/SystemVersion.plist", "ProductVersion");
- } else if (hostOS && hostOS.contains("windows")) {
+ } else if (hostOS && hostOS.includes("windows")) {
var version = Utilities.getNativeSetting(windowsRegistryKey, "CurrentVersion");
return version + "." + hostOSBuildVersion;
}
}
+ readonly property string hostArchitecture: undefined // set internally
property string hostOSBuildVersion: {
- if (hostOS.contains("macos")) {
+ if (hostOS.includes("macos")) {
return Utilities.getNativeSetting("/System/Library/CoreServices/ServerVersion.plist", "ProductBuildVersion") ||
Utilities.getNativeSetting("/System/Library/CoreServices/SystemVersion.plist", "ProductBuildVersion");
- } else if (hostOS.contains("windows")) {
+ } else if (hostOS.includes("windows")) {
return Utilities.getNativeSetting(windowsRegistryKey, "CurrentBuildNumber");
}
}
@@ -78,19 +79,19 @@ Module {
property string targetPlatform: hostPlatform
readonly property stringList targetOS: Utilities.canonicalPlatform(targetPlatform)
- property string pathListSeparator: hostOS.contains("windows") ? ";" : ":"
- property string pathSeparator: hostOS.contains("windows") ? "\\" : "/"
- property string nullDevice: hostOS.contains("windows") ? "NUL" : "/dev/null"
- property path shellPath: hostOS.contains("windows") ? windowsShellPath : "/bin/sh"
+ property string pathListSeparator: hostOS.includes("windows") ? ";" : ":"
+ property string pathSeparator: hostOS.includes("windows") ? "\\" : "/"
+ property string nullDevice: hostOS.includes("windows") ? "NUL" : "/dev/null"
+ property path shellPath: hostOS.includes("windows") ? windowsShellPath : "/bin/sh"
property string profile: project.profile
property string toolchainType: {
- if (targetOS.contains("windows"))
- return hostOS.contains("windows") ? "msvc" : "mingw";
- if (targetOS.contains("darwin"))
- return hostOS.contains("macos") ? "xcode" : "clang";
- if (targetOS.contains("freebsd"))
+ if (targetOS.includes("windows"))
+ return hostOS.includes("windows") ? "msvc" : "mingw";
+ if (targetOS.includes("darwin"))
+ return hostOS.includes("macos") ? "xcode" : "clang";
+ if (targetOS.includes("freebsd"))
return "clang";
- if (targetOS.contains("qnx"))
+ if (targetOS.includes("qnx"))
return "qcc";
if (targetOS.containsAny(["haiku", "vxworks", "unix"]))
return "gcc";
@@ -101,12 +102,12 @@ Module {
property path installSourceBase
property string installRoot: project.buildDirectory + "/install-root"
property string installDir
- property string installPrefix: qbs.targetOS.contains("unix") ? "/usr/local" : ""
+ property string installPrefix: targetOS.includes("unix") ? "/usr/local" : ""
property path sysroot
PropertyOptions {
name: "buildVariant"
- allowedValues: ['debug', 'release']
+ allowedValues: ['debug', 'release', 'profiling']
description: "name of the build variant"
}
@@ -121,12 +122,12 @@ Module {
validator.setRequiredProperty("hostOS", hostOS);
validator.setRequiredProperty("targetOS", targetOS);
validator.addCustomValidator("targetOS", targetOS, function (value) {
- if (!value || (value.contains("osx") && !value.contains("macos")))
+ if (!value || (value.includes("osx") && !value.includes("macos")))
return false;
return true;
}, "the value 'osx' has been replaced by 'macos'; use that instead and update "
+ "hostOS and targetOS condition checks in your project accordingly");
- if (hostOS && (hostOS.contains("windows") || hostOS.contains("macos"))) {
+ if (hostOS && (hostOS.includes("windows") || hostOS.includes("macos"))) {
validator.setRequiredProperty("hostOSVersion", hostOSVersion,
"could not detect host operating system version; " +
"verify that system files and registry keys have not " +
@@ -142,8 +143,9 @@ Module {
validator.addCustomValidator("architecture", architecture, function (value) {
return !architecture || architecture === Utilities.canonicalArchitecture(architecture);
- }, "'" + architecture + "' is invalid. You must use the canonical name '" +
- Utilities.canonicalArchitecture(architecture) + "'");
+ }, "'" + architecture + "' is invalid." + (architecture
+ ? " You must use the canonical name '" + Utilities.canonicalArchitecture(architecture)
+ : "") + "'");
validator.addCustomValidator("toolchain", toolchain, function (value) {
if (toolchain === undefined)
@@ -168,7 +170,7 @@ Module {
];
var canonical = Utilities.canonicalToolchain.apply(Utilities, value);
for (var i = 0; i < pairs.length; ++i) {
- if (canonical.contains(pairs[i][0]) && canonical.contains(pairs[i][1]))
+ if (canonical.includes(pairs[i][0]) && canonical.includes(pairs[i][1]))
return false;
}
return true;
@@ -181,14 +183,14 @@ Module {
property string windowsRegistryKey: "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion"
property path windowsSystemRoot: FileInfo.fromWindowsSeparators(Utilities.getNativeSetting(windowsRegistryKey, "SystemRoot"))
property path windowsShellPath: FileInfo.fromWindowsSeparators(Environment.getEnv("COMSPEC")) || FileInfo.joinPaths(windowsSystemRoot, "System32", "cmd.exe")
- property string windowsPathVariable: hostOS.contains("windows") ? "PATH" : "WINEPATH"
+ property string windowsPathVariable: hostOS.includes("windows") ? "PATH" : "WINEPATH"
property var commonRunEnvironment: ({})
setupRunEnvironment: {
var env = product.qbs.commonRunEnvironment;
for (var i in env) {
var v = new ModUtils.EnvironmentVariable(i, product.qbs.pathListSeparator,
- product.qbs.hostOS.contains("windows"));
+ product.qbs.hostOS.includes("windows"));
v.value = env[i];
v.set();
}
diff --git a/share/qbs/modules/qnx/qnx.qbs b/share/qbs/modules/qnx/qnx.qbs
index 9cab5abb6..899b72441 100644
--- a/share/qbs/modules/qnx/qnx.qbs
+++ b/share/qbs/modules/qnx/qnx.qbs
@@ -31,6 +31,7 @@
import qbs.Environment
import qbs.File
import qbs.FileInfo
+import qbs.Host
import qbs.ModUtils
import qbs.Probes
import qbs.Utilities
@@ -39,7 +40,7 @@ Module {
Probes.PathProbe {
id: qnxSdkProbe
names: ["qnx700", "qnx660", "qnx650"]
- searchPaths: qbs.hostOS.contains("windows")
+ searchPaths: Host.os().includes("windows")
? [Environment.getEnv("USERPROFILE"), Environment.getEnv("SystemDrive")]
: [Environment.getEnv("HOME"), "/opt"]
}
@@ -77,11 +78,11 @@ Module {
property string hostArch: qnx7 ? "x86_64" : "x86"
property string hostOs: {
- if (qbs.hostOS.contains("linux"))
+ if (Host.os().includes("linux"))
return "linux";
- if (qbs.hostOS.contains("macos"))
+ if (Host.os().includes("macos"))
return "darwin";
- if (qbs.hostOS.contains("windows"))
+ if (Host.os().includes("windows"))
return qnx7 ? "win64" : "win32";
}
@@ -111,7 +112,7 @@ Module {
}
if (!hostOs) {
- throw ModUtils.ModuleError("Host operating system '" + qbs.hostOS
+ throw ModUtils.ModuleError("Host operating system '" + Host.os()
+ "' is not supported by the QNX SDK.");
} else if (!File.exists(hostDir)) {
throw ModUtils.ModuleError("Detected host tools operating system '" + hostOs
diff --git a/share/qbs/modules/typescript/TypeScriptModule.qbs b/share/qbs/modules/typescript/TypeScriptModule.qbs
index d8e61b17f..76df529c2 100644
--- a/share/qbs/modules/typescript/TypeScriptModule.qbs
+++ b/share/qbs/modules/typescript/TypeScriptModule.qbs
@@ -129,7 +129,7 @@ Module {
var preValidator = new ModUtils.PropertyValidator("nodejs");
preValidator.addCustomValidator("interpreterFileName", nodejs.interpreterFileName, function (value) {
- return value === "node" + (qbs.hostOS.contains("windows") ? ".exe" : "");
+ return value === "node" + FileInfo.executableSuffix();
}, interpreterMessage);
preValidator.addCustomValidator("interpreterFilePath", nodejs.interpreterFilePath, function (value) {
return value.endsWith(nodejs.interpreterFileName);
diff --git a/share/qbs/modules/typescript/typescript.js b/share/qbs/modules/typescript/typescript.js
index 858041b3d..199f486cf 100644
--- a/share/qbs/modules/typescript/typescript.js
+++ b/share/qbs/modules/typescript/typescript.js
@@ -132,7 +132,7 @@ function outputArtifacts(product, inputs) {
process.setEnv("NODE_PATH", [
ModUtils.moduleProperty(product, "toolchainInstallPath"),
product.moduleProperty("nodejs", "packageManagerRootPath")
- ].join(product.moduleProperty("qbs", "pathListSeparator")));
+ ].join(FileInfo.pathListSeparator()));
process.exec(product.moduleProperty("nodejs", "interpreterFilePath"),
[FileInfo.joinPaths(product.buildDirectory,
".io.qt.qbs.internal.typescript",
@@ -146,7 +146,7 @@ function outputArtifacts(product, inputs) {
var i, appIndex = -1;
if (product.moduleProperty("typescript", "singleFile")) {
for (i = 0; i < artifacts.length; ++i) {
- if (artifacts[i].fileTags.contains("compiled_typescript")) {
+ if (artifacts[i].fileTags.includes("compiled_typescript")) {
appIndex = i;
break;
}
@@ -169,7 +169,7 @@ function outputArtifacts(product, inputs) {
}
}
- if (appIndex === -1 || !artifacts[appIndex].fileTags.contains("compiled_typescript"))
+ if (appIndex === -1 || !artifacts[appIndex].fileTags.includes("compiled_typescript"))
throw "nodejs.applicationFile was set, but Qbs couldn't find the compiled " +
"JavaScript file corresponding to '" + applicationFile + "'";
diff --git a/share/qbs/modules/wix/WiXModule.qbs b/share/qbs/modules/wix/WiXModule.qbs
index ad8586da1..077f259f4 100644
--- a/share/qbs/modules/wix/WiXModule.qbs
+++ b/share/qbs/modules/wix/WiXModule.qbs
@@ -30,12 +30,13 @@
import qbs.File
import qbs.FileInfo
+import qbs.Host
import qbs.ModUtils
import qbs.Probes
import qbs.Utilities
Module {
- condition: qbs.targetOS.contains("windows")
+ condition: qbs.targetOS.includes("windows")
Probes.WiXProbe {
id: wixProbe
@@ -112,19 +113,19 @@ Module {
description: "the list of localizations to build the MSI for; leave undefined to build all localizations"
}
- property stringList extensions: product.type.contains("wixsetup") ? ["WixBalExtension"] : [] // default to WiX Standard Bootstrapper extension
+ property stringList extensions: product.type.includes("wixsetup") ? ["WixBalExtension"] : [] // default to WiX Standard Bootstrapper extension
// private properties
property string targetSuffix: {
- if (product.type.contains("msi")) {
+ if (product.type.includes("msi")) {
return windowsInstallerSuffix;
- } else if (product.type.contains("wixsetup")) {
+ } else if (product.type.includes("wixsetup")) {
return executableSuffix;
}
}
// MSI/MSM package validation only works natively on Windows
- property bool enablePackageValidation: qbs.hostOS.contains("windows")
+ property bool enablePackageValidation: Host.os().includes("windows")
property string executableSuffix: ".exe"
property string windowsInstallerSuffix: ".msi"
@@ -151,7 +152,7 @@ Module {
}
setupBuildEnvironment: {
- var v = new ModUtils.EnvironmentVariable("PATH", product.qbs.pathListSeparator, true);
+ var v = new ModUtils.EnvironmentVariable("PATH", FileInfo.pathListSeparator(), true);
v.prepend(product.wix.toolchainInstallPath);
v.prepend(product.wix.toolchainInstallRoot);
v.set();
@@ -226,7 +227,7 @@ Module {
if (ModUtils.moduleProperty(input, "visualStudioCompatibility")) {
var toolchain = product.moduleProperty("qbs", "toolchain");
var toolchainInstallPath = product.moduleProperty("cpp", "toolchainInstallPath");
- if (toolchain && toolchain.contains("msvc") && toolchainInstallPath) {
+ if (toolchain && toolchain.includes("msvc") && toolchainInstallPath) {
var vcDir = toolchainInstallPath.replace(/[\\/]bin$/i, "");
var vcRootDir = vcDir.replace(/[\\/]VC$/i, "");
args.push("-dDevEnvDir=" + FileInfo.toWindowsSeparators(FileInfo.joinPaths(vcRootDir, 'Common7', 'IDE')));
@@ -334,12 +335,12 @@ Module {
multiplex: true
inputs: ["wixobj", "wxl"]
auxiliaryInputs: ["installable"]
- inputsFromDependencies: product.type.contains("wixsetup") ? ["msi"] : []
+ inputsFromDependencies: product.type.includes("wixsetup") ? ["msi"] : []
outputArtifacts: {
var artifacts = [];
- if (product.type.contains("wixsetup")) {
+ if (product.type.includes("wixsetup")) {
artifacts.push({
fileTags: ["wixsetup", "application"],
filePath: FileInfo.joinPaths(product.destinationDirectory,
@@ -349,7 +350,7 @@ Module {
});
}
- if (product.type.contains("msi")) {
+ if (product.type.includes("msi")) {
artifacts.push({
fileTags: ["msi"],
filePath: FileInfo.joinPaths(product.destinationDirectory,
@@ -375,9 +376,9 @@ Module {
prepare: {
var i;
var primaryOutput;
- if (product.type.contains("wixsetup")) {
+ if (product.type.includes("wixsetup")) {
primaryOutput = outputs.wixsetup[0];
- } else if (product.type.contains("msi")) {
+ } else if (product.type.includes("msi")) {
primaryOutput = outputs.msi[0];
} else {
throw("WiX: Unsupported product type '" + product.type + "'");
@@ -426,7 +427,7 @@ Module {
args.push(FileInfo.toWindowsSeparators(inputs.wxl[i].filePath));
}
- if (product.type.contains("msi")) {
+ if (product.type.includes("msi")) {
var cultures = ModUtils.moduleProperty(product, "cultures");
args.push("-cultures:"
+ (cultures && cultures.length > 0 ? cultures.join(";") : "null"));
diff --git a/share/qbs/modules/xcode/xcode.js b/share/qbs/modules/xcode/xcode.js
index bda41ade9..726974579 100644
--- a/share/qbs/modules/xcode/xcode.js
+++ b/share/qbs/modules/xcode/xcode.js
@@ -93,6 +93,16 @@ var XcodeArchSpecsReader = (function () {
return XcodeArchSpecsReader;
}());
+function platformInfo(platformInfoPlist) {
+ var propertyList = new PropertyList();
+ try {
+ propertyList.readFromFile(platformInfoPlist);
+ return propertyList.toObject();
+ } finally {
+ propertyList.clear();
+ }
+}
+
function sdkInfoList(sdksPath) {
var sdkInfo = [];
var sdks = File.directoryEntries(sdksPath, File.Dirs | File.NoDotAndDotDot);
@@ -102,7 +112,7 @@ function sdkInfoList(sdksPath) {
if (!sdks[i].match(/[0-9]+/))
continue;
- if (sdks[i].startsWith("DriverKit"))
+ if (sdks[i].startsWith("DriverKit") || sdks[i].startsWith("AssetRuntime"))
continue;
var settingsPlist = FileInfo.joinPaths(sdksPath, sdks[i], "SDKSettings.plist");
@@ -114,7 +124,7 @@ function sdkInfoList(sdksPath) {
if (!plist || !plist["CanonicalName"] || !plist["Version"])
return false;
- var re = /^([0-9]+)\.([0-9]+)$/;
+ var re = /^[0-9]+\.[0-9]+(\.[0-9]+)?$/;
return plist["Version"].match(re);
}
@@ -132,19 +142,7 @@ function sdkInfoList(sdksPath) {
}
// Sort by SDK version number
- sdkInfo.sort(function (a, b) {
- var re = /^([0-9]+)\.([0-9]+)$/;
- a = a["Version"].match(re);
- if (a)
- a = {major: a[1], minor: a[2]};
- b = b["Version"].match(re);
- if (b)
- b = {major: b[1], minor: b[2]};
-
- if (a.major === b.major)
- return a.minor - b.minor;
- return a.major - b.major;
- });
+ sdkInfo.sort(function (a, b) { return Utilities.versionCompare(a["Version"], b["Version"]); });
return sdkInfo;
}
@@ -181,7 +179,7 @@ function findSigningIdentities(security, searchString) {
}
function provisioningProfilePlistContents(filePath) {
- if (filePath === undefined)
+ if (filePath === undefined || !File.exists(filePath))
return undefined;
var plist = new PropertyList();
@@ -193,14 +191,52 @@ function provisioningProfilePlistContents(filePath) {
}
}
-function archsSpecsPath(version, targetOS, platformType, platformPath, devicePlatformPath) {
+function boolFromSdkOrPlatform(varName, sdkProps, platformProps, defaultValue) {
+ var values = [(sdkProps || {})[varName], (platformProps || {})[varName]];
+ for (var i = 0; i < values.length; ++i) {
+ if (values[i] === "YES")
+ return true;
+ if (values[i] === "NO")
+ return false;
+ }
+ return defaultValue;
+}
+
+function archsSpecsPath(version, targetOS, platformType, platformPath, devicePlatformPath,
+ developerPath) {
+ if (Utilities.versionCompare(version, "13.3") >= 0) {
+ var pluginsDir;
+ if (Utilities.versionCompare(version, "15.3") >= 0) {
+ pluginsDir = FileInfo.joinPaths(developerPath, "..",
+ "SharedFrameworks", "XCBuild.framework", "PlugIns", "XCBBuildService.bundle",
+ "Contents", "PlugIns");
+ } else if (Utilities.versionCompare(version, "14.3") >= 0) {
+ pluginsDir = FileInfo.joinPaths(developerPath, "Library", "Xcode", "Plug-ins");
+ } else {
+ pluginsDir = FileInfo.joinPaths(developerPath, "..", "PlugIns");
+ }
+ var baseDir = FileInfo.joinPaths(pluginsDir,
+ "XCBSpecifications.ideplugin", "Contents", "Resources");
+
+ var baseName = targetOS.includes("macos") ? "MacOSX Architectures"
+ : targetOS.includes("ios-simulator") ? "iOS Simulator"
+ : targetOS.includes("ios") ? "iOS Device"
+ : targetOS.includes("tvos-simulator") ? "tvOS Simulator"
+ : targetOS.includes("tvos") ? "tvOS Device"
+ : targetOS.includes("watchos-simulator") ? "watchOS Simulator" : "watchOS Device";
+ return FileInfo.joinPaths(baseDir, baseName + ".xcspec");
+ }
var _specsPluginBaseName;
+ if (Utilities.versionCompare(version, "12") >= 0) {
+ if (targetOS.includes("macos"))
+ _specsPluginBaseName = "OSX";
+ }
if (Utilities.versionCompare(version, "7") >= 0) {
- if (targetOS.contains("ios"))
+ if (targetOS.includes("ios"))
_specsPluginBaseName = "iOSPlatform";
- if (targetOS.contains("tvos"))
+ if (targetOS.includes("tvos"))
_specsPluginBaseName = "AppleTV";
- if (targetOS.contains("watchos"))
+ if (targetOS.includes("watchos"))
_specsPluginBaseName = "Watch";
}
@@ -211,8 +247,8 @@ function archsSpecsPath(version, targetOS, platformType, platformPath, devicePla
"Resources")
: FileInfo.joinPaths(platformPath, "Developer", "Library", "Xcode", "Specifications");
- var _archSpecsFileBaseName = targetOS.contains("ios")
- ? (targetOS.contains("ios-simulator") ? "iPhone Simulator " : "iPhoneOS")
+ var _archSpecsFileBaseName = targetOS.includes("ios")
+ ? (targetOS.includes("ios-simulator") ? "iPhone Simulator " : "iPhoneOS")
: DarwinTools.applePlatformDirectoryName(targetOS, platformType) + " ";
if (_specsPluginBaseName) {
diff --git a/share/qbs/modules/xcode/xcode.qbs b/share/qbs/modules/xcode/xcode.qbs
index 922580505..2c0cd001a 100644
--- a/share/qbs/modules/xcode/xcode.qbs
+++ b/share/qbs/modules/xcode/xcode.qbs
@@ -6,27 +6,32 @@ import qbs.DarwinTools
import qbs.ModUtils
import qbs.Probes
import qbs.PropertyList
-import 'xcode.js' as Xcode
+import qbs.Utilities
Module {
- id: xcodeModule
+ Probes.XcodeLocationProbe {
+ id: xcodeLocationProbe
+ condition: !developerPath
+ }
Probes.XcodeProbe {
id: xcodeProbe
- developerPath: xcodeModule.developerPath
- platformType: xcodeModule.platformType
- platformPath: xcodeModule.platformPath
- devicePlatformPath: xcodeModule.devicePlatformPath
- xcodebuildPath: xcodeModule.xcodebuildPath
- sdksPath: xcodeModule.sdksPath
+ developerPath: parent.developerPath
+ platformType: parent.platformType
+ platformPath: parent.platformPath
+ devicePlatformPath: parent.devicePlatformPath
+ xcodebuildPath: parent.xcodebuildPath
+ sdksPath: parent.sdksPath
}
- condition: qbs.targetOS.contains("darwin") &&
- qbs.toolchain && qbs.toolchain.contains("xcode")
+ condition: qbs.targetOS.includes("darwin") &&
+ qbs.toolchain && qbs.toolchain.includes("xcode")
version: xcodeProbe.xcodeVersion
- property path developerPath: "/Applications/Xcode.app/Contents/Developer"
+ property path developerPath: xcodeLocationProbe.found
+ ? xcodeLocationProbe.developerPath
+ : undefined
property string sdk: DarwinTools.applePlatformName(qbs.targetOS, platformType)
property stringList targetDevices: DarwinTools.targetDevices(qbs.targetOS)
@@ -48,6 +53,12 @@ Module {
return _sdkSettings["Version"];
}
}
+ readonly property string shortSdkVersion: {
+ var v = sdkVersion;
+ if (v && v.split('.').length > 2)
+ v = v.slice(0, v.lastIndexOf('.'));
+ return v;
+ }
readonly property string latestSdkName: {
if (_latestSdk) {
@@ -73,31 +84,6 @@ Module {
}
}
- property string signingIdentity
- readonly property string actualSigningIdentity: {
- if (_actualSigningIdentity && _actualSigningIdentity.length === 1)
- return _actualSigningIdentity[0][0];
- }
-
- readonly property string actualSigningIdentityDisplayName: {
- if (_actualSigningIdentity && _actualSigningIdentity.length === 1)
- return _actualSigningIdentity[0][1];
- }
-
- property string signingTimestamp: "none"
-
- property string provisioningProfile
-
- property string xcodebuildName: "xcodebuild"
- property string xcodebuildPath: FileInfo.joinPaths(developerPath, "usr", "bin", xcodebuildName)
-
- property string securityName: "security"
- property string securityPath: securityName
-
- property string codesignName: "codesign"
- property string codesignPath: codesignName
- property stringList codesignFlags
-
readonly property path toolchainPath: FileInfo.joinPaths(toolchainsPath,
"XcodeDefault" + ".xctoolchain")
readonly property path platformPath: FileInfo.joinPaths(platformsPath,
@@ -116,8 +102,8 @@ Module {
+ ".platform")
readonly property path sdkPath: FileInfo.joinPaths(sdksPath,
DarwinTools.applePlatformDirectoryName(
- qbs.targetOS, platformType, sdkVersion)
- + ".sdk")
+ qbs.targetOS, platformType,
+ shortSdkVersion) + ".sdk")
// private properties
readonly property path toolchainsPath: FileInfo.joinPaths(developerPath, "Toolchains")
@@ -129,21 +115,11 @@ Module {
readonly property path toolchainInfoPlist: FileInfo.joinPaths(toolchainPath,
"ToolchainInfo.plist")
- readonly property stringList _actualSigningIdentity: {
- if (/^[A-Fa-f0-9]{40}$/.test(signingIdentity)) {
- return signingIdentity;
- }
-
- var identities = Xcode.findSigningIdentities(securityPath, signingIdentity);
- if (identities && identities.length > 1) {
- throw "Signing identity '" + signingIdentity + "' is ambiguous";
- }
-
- return identities;
- }
+ readonly property var _platformSettings: xcodeProbe.platformSettings
- property path provisioningProfilesPath: {
- return FileInfo.joinPaths(Environment.getEnv("HOME"), "Library/MobileDevice/Provisioning Profiles");
+ readonly property var _platformProps: {
+ if (_platformSettings)
+ return _platformSettings["DefaultProperties"];
}
readonly property stringList standardArchitectures: _architectureSettings["ARCHS_STANDARD"]
@@ -156,6 +132,7 @@ Module {
readonly property var _sdkSettings: {
if (_availableSdks) {
+ // see 'sdk' property doc to understand why this loop is needed
for (var i in _availableSdks) {
if (_availableSdks[i]["Version"] === sdk)
return _availableSdks[i];
@@ -163,12 +140,18 @@ Module {
return _availableSdks[i];
}
- // Latest SDK available for the platform
+ // Latest SDK available for the platform (default case)
if (DarwinTools.applePlatformName(qbs.targetOS, platformType) === sdk)
return _latestSdk;
}
}
+ readonly property var _sdkProps: {
+ if (_sdkSettings) {
+ return _sdkSettings["DefaultProperties"];
+ }
+ }
+
qbs.sysroot: sdkPath
validate: {
@@ -191,38 +174,25 @@ Module {
validator.setRequiredProperty("platformPath", platformPath);
validator.setRequiredProperty("sdksPath", sdkPath);
validator.setRequiredProperty("sdkPath", sdkPath);
- validator.addVersionValidator("sdkVersion", sdkVersion, 2, 2);
+ validator.addVersionValidator("sdkVersion", sdkVersion, 2, 3);
validator.addCustomValidator("sdkName", sdkName, function (value) {
return value === DarwinTools.applePlatformDirectoryName(
- qbs.targetOS, platformType, sdkVersion, false).toLowerCase();
+ qbs.targetOS, platformType, shortSdkVersion, false).toLowerCase();
}, "is '" + sdkName + "', but target OS is [" + qbs.targetOS.join(",")
+ "] and Xcode SDK version is '" + sdkVersion + "'");
validator.addCustomValidator("sdk", sdk, function (value) {
- return value === sdkName || (value + sdkVersion) === sdkName;
+ return value === sdkName || (value + shortSdkVersion) === sdkName;
}, "is '" + sdk + "', but canonical SDK name is '" + sdkName + "'");
validator.validate();
}
- property var buildEnv: {
- var env = {
- "DEVELOPER_DIR": developerPath,
- "SDKROOT": sdkPath
- };
-
- var prefixes = [platformPath + "/Developer", toolchainPath, developerPath];
- for (var i = 0; i < prefixes.length; ++i) {
- var codesign_allocate = prefixes[i] + "/usr/bin/codesign_allocate";
- if (File.exists(codesign_allocate)) {
- env["CODESIGN_ALLOCATE"] = codesign_allocate;
- break;
- }
- }
-
- return env;
- }
+ property var buildEnv: ({
+ "DEVELOPER_DIR": developerPath,
+ "SDKROOT": sdkPath
+ })
setupBuildEnvironment: {
- var v = new ModUtils.EnvironmentVariable("PATH", product.qbs.pathListSeparator, false);
+ var v = new ModUtils.EnvironmentVariable("PATH", FileInfo.pathListSeparator(), false);
v.prepend(product.xcode.platformPath + "/Developer/usr/bin");
v.prepend(product.xcode.developerPath + "/usr/bin");
v.set();
@@ -233,190 +203,4 @@ Module {
v.set();
}
}
-
- Group {
- name: "Provisioning Profiles"
- prefix: xcode.provisioningProfilesPath + "/"
- files: ["*.mobileprovision", "*.provisionprofile"]
- fileTags: [] // HACK: provisioning profile handling is not yet ready and can break autotests
- }
-
- FileTagger {
- fileTags: ["xcode.entitlements"]
- patterns: ["*.entitlements"]
- }
-
- FileTagger {
- fileTags: ["xcode.provisioningprofile"]
- patterns: ["*.mobileprovision", "*.provisionprofile"]
- }
-
- Rule {
- inputs: ["xcode.provisioningprofile"]
-
- Artifact {
- filePath: FileInfo.joinPaths(product.destinationDirectory,
- "provisioning-profiles",
- input.fileName + ".xml")
- fileTags: ["xcode.provisioningprofile.data"]
- }
-
- prepare: {
- var cmds = [];
-
- var cmd = new Command("openssl", ["smime", "-verify", "-noverify", "-inform", "DER",
- "-in", input.filePath, "-out", output.filePath]);
- cmd.silent = true;
- cmd.stderrFilterFunction = function (output) {
- return output.replace("Verification successful\n", "");
- };
- cmds.push(cmd);
-
- cmd = new JavaScriptCommand();
- cmd.silent = true;
- cmd.inputFilePath = input.filePath;
- cmd.outputFilePath = output.filePath;
- cmd.sourceCode = function() {
- var propertyList = new PropertyList();
- try {
- propertyList.readFromFile(outputFilePath);
- propertyList.readFromObject({
- data: propertyList.toObject(),
- fileName: FileInfo.fileName(inputFilePath),
- filePath: inputFilePath
- });
- propertyList.writeToFile(outputFilePath, "xml1");
- } finally {
- propertyList.clear();
- }
- };
- cmds.push(cmd);
-
- return cmds;
- }
- }
-
- Rule {
- multiplex: true
- inputs: ["xcode.provisioningprofile.data"]
- outputFileTags: ["xcode.provisioningprofile.main", "xcode.provisioningprofile.data.main"]
-
- outputArtifacts: {
- var artifacts = [];
- for (var i = 0; i < inputs["xcode.provisioningprofile.data"].length; ++i) {
- var dataFile = inputs["xcode.provisioningprofile.data"][i].filePath;
- var query = product.moduleProperty("xcode", "provisioningProfile");
- var obj = Xcode.provisioningProfilePlistContents(dataFile);
- if (obj.data && (obj.data.UUID === query || obj.data.Name === query)) {
- console.log("Using provisioning profile: " + obj.filePath);
-
- artifacts.push({
- filePath: FileInfo.joinPaths(product.destinationDirectory, obj.fileName),
- fileTags: ["xcode.provisioningprofile.main", obj.filePath]
- });
-
- artifacts.push({
- filePath: FileInfo.joinPaths(product.destinationDirectory, obj.fileName + ".xml"),
- fileTags: ["xcode.provisioningprofile.data.main", dataFile]
- });
- }
- }
- return artifacts;
- }
-
- prepare: {
- var cmds = [];
- for (var tag in outputs) {
- for (var i = 0; i < outputs[tag].length; ++i) {
- var output = outputs[tag][i];
- var cmd = new JavaScriptCommand();
- cmd.silent = true;
- cmd.inputFilePath = output.fileTags.filter(function(f) { return f.startsWith('/'); })[0] // QBS-754
- cmd.outputFilePath = output.filePath;
- cmd.sourceCode = function() {
- File.copy(inputFilePath, outputFilePath);
- };
- cmds.push(cmd);
- }
- }
- return cmds;
- }
- }
-
- Rule {
- inputs: ["xcode.entitlements", "xcode.provisioningprofile.data.main"]
-
- Artifact {
- filePath: FileInfo.joinPaths(product.destinationDirectory,
- product.targetName + ".xcent")
- fileTags: ["xcent", "bundle.input"]
- }
-
- prepare: {
- var cmd = new JavaScriptCommand();
- cmd.description = "generating entitlements";
- cmd.highlight = "codegen";
- cmd.bundleIdentifier = product.moduleProperty("bundle", "identifier");
- cmd.signingEntitlements = inputs["xcode.entitlements"].map(function (a) { return a.filePath; });
- cmd.platformPath = ModUtils.moduleProperty(product, "platformPath");
- cmd.sdkPath = ModUtils.moduleProperty(product, "sdkPath");
- cmd.sourceCode = function() {
- var i;
- var provData = Xcode.provisioningProfilePlistContents(input.filePath);
- if (provData)
- provData = provData.data;
-
- var aggregateEntitlements = {};
-
- // Start building up an aggregate entitlements plist from the files in the SDKs,
- // which contain placeholders in the same manner as Info.plist
- function entitlementsFileContents(path) {
- return File.exists(path) ? BundleTools.infoPlistContents(path) : undefined;
- }
- var entitlementsSources = [
- entitlementsFileContents(FileInfo.joinPaths(platformPath, "Entitlements.plist")),
- entitlementsFileContents(FileInfo.joinPaths(sdkPath, "Entitlements.plist"))
- ];
-
- for (i = 0; i < signingEntitlements.length; ++i) {
- entitlementsSources.push(entitlementsFileContents(signingEntitlements[i]));
- }
-
- for (i = 0; i < entitlementsSources.length; ++i) {
- var contents = entitlementsSources[i];
- for (var key in contents) {
- if (contents.hasOwnProperty(key))
- aggregateEntitlements[key] = contents[key];
- }
- }
-
- contents = provData["Entitlements"];
- for (key in contents) {
- if (contents.hasOwnProperty(key) && !aggregateEntitlements.hasOwnProperty(key))
- aggregateEntitlements[key] = contents[key];
- }
-
- // Expand entitlements variables with data from the provisioning profile
- var env = {
- "AppIdentifierPrefix": provData["ApplicationIdentifierPrefix"] + ".",
- "CFBundleIdentifier": bundleIdentifier
- };
- DarwinTools.expandPlistEnvironmentVariables(aggregateEntitlements, env, true);
-
- // Anything with an undefined or otherwise empty value should be removed
- // Only JSON-formatted plists can have null values, other formats error out
- // This also follows Xcode behavior
- DarwinTools.cleanPropertyList(aggregateEntitlements);
-
- var plist = new PropertyList();
- try {
- plist.readFromObject(aggregateEntitlements);
- plist.writeToFile(outputs.xcent[0].filePath, "xml1");
- } finally {
- plist.clear();
- }
- };
- return [cmd];
- }
- }
}