aboutsummaryrefslogtreecommitdiffstats
path: root/share
diff options
context:
space:
mode:
Diffstat (limited to 'share')
-rw-r--r--share/CMakeLists.txt19
-rw-r--r--share/qbs/imports/qbs/DarwinTools/darwin-tools.js13
-rw-r--r--share/qbs/imports/qbs/ModUtils/utils.js2
-rw-r--r--share/qbs/imports/qbs/PathTools/path-tools.js22
-rw-r--r--share/qbs/imports/qbs/Probes/LibraryProbe.qbs22
-rw-r--r--share/qbs/imports/qbs/Probes/PkgConfigProbe.qbs6
-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/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/AppleApplicationDiskImage.qbs3
-rw-r--r--share/qbs/imports/qbs/base/ApplicationExtension.qbs8
-rw-r--r--share/qbs/imports/qbs/base/QtModule.qbs (renamed from share/qbs/module-providers/Qt/templates/QtModule.qbs)1
-rw-r--r--share/qbs/imports/qbs/base/QtPlugin.qbs (renamed from share/qbs/module-providers/Qt/templates/QtPlugin.qbs)0
-rw-r--r--share/qbs/module-providers/Qt/provider.qbs10
-rw-r--r--share/qbs/module-providers/Qt/setup-qt.js1436
-rw-r--r--share/qbs/module-providers/Qt/templates/android_support.qbs10
-rw-r--r--share/qbs/module-providers/Qt/templates/core.qbs24
-rw-r--r--share/qbs/module-providers/Qt/templates/dbus.qbs1
-rw-r--r--share/qbs/module-providers/Qt/templates/gui.qbs1
-rw-r--r--share/qbs/module-providers/Qt/templates/module.qbs2
-rw-r--r--share/qbs/module-providers/Qt/templates/plugin.qbs2
-rw-r--r--share/qbs/module-providers/Qt/templates/qml.js26
-rw-r--r--share/qbs/module-providers/Qt/templates/qml.qbs9
-rw-r--r--share/qbs/module-providers/Qt/templates/quick.qbs1
-rw-r--r--share/qbs/module-providers/Qt/templates/scxml.qbs1
-rw-r--r--share/qbs/module-providers/__fallback/fallback.qbs2
-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.qbs238
-rw-r--r--share/qbs/modules/Android/sdk/sdk.qbs32
-rw-r--r--share/qbs/modules/Android/sdk/utils.js12
-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.js24
-rw-r--r--share/qbs/modules/Exporter/pkgconfig/pkgconfig.qbs4
-rw-r--r--share/qbs/modules/Exporter/qbs/qbsexporter.js44
-rw-r--r--share/qbs/modules/Sanitizers/address/asan.qbs13
-rw-r--r--share/qbs/modules/archiver/archiver.qbs6
-rw-r--r--share/qbs/modules/bundle/BundleModule.qbs127
-rw-r--r--share/qbs/modules/bundle/bundle.js21
-rw-r--r--share/qbs/modules/capnproto/capnprotobase.qbs7
-rw-r--r--share/qbs/modules/capnproto/cpp/capnprotocpp.qbs2
-rw-r--r--share/qbs/modules/cli/CLIModule.qbs6
-rw-r--r--share/qbs/modules/cli/cli.js10
-rw-r--r--share/qbs/modules/cli/mono.qbs6
-rw-r--r--share/qbs/modules/cli/windows-dotnet.qbs2
-rw-r--r--share/qbs/modules/codesign/android.qbs4
-rw-r--r--share/qbs/modules/codesign/apple.qbs22
-rw-r--r--share/qbs/modules/codesign/codesign.js106
-rw-r--r--share/qbs/modules/codesign/signtool.qbs6
-rw-r--r--share/qbs/modules/cpp/DarwinGCC.qbs39
-rw-r--r--share/qbs/modules/cpp/GenericGCC.qbs36
-rw-r--r--share/qbs/modules/cpp/LinuxGCC.qbs4
-rw-r--r--share/qbs/modules/cpp/MingwBaseModule.qbs6
-rw-r--r--share/qbs/modules/cpp/UnixGCC.qbs4
-rw-r--r--share/qbs/modules/cpp/android-gcc.qbs6
-rw-r--r--share/qbs/modules/cpp/cosmic.qbs2
-rw-r--r--share/qbs/modules/cpp/cpp.js18
-rw-r--r--share/qbs/modules/cpp/darwin.js4
-rw-r--r--share/qbs/modules/cpp/dmc.js12
-rw-r--r--share/qbs/modules/cpp/dmc.qbs2
-rw-r--r--share/qbs/modules/cpp/freebsd-gcc.qbs6
-rw-r--r--share/qbs/modules/cpp/gcc.js110
-rw-r--r--share/qbs/modules/cpp/iar.js2
-rw-r--r--share/qbs/modules/cpp/iar.qbs2
-rw-r--r--share/qbs/modules/cpp/ios-gcc.qbs12
-rw-r--r--share/qbs/modules/cpp/keil.qbs2
-rw-r--r--share/qbs/modules/cpp/macos-gcc.qbs4
-rw-r--r--share/qbs/modules/cpp/msvc.js59
-rw-r--r--share/qbs/modules/cpp/qnx-qcc.qbs6
-rw-r--r--share/qbs/modules/cpp/sdcc.js5
-rw-r--r--share/qbs/modules/cpp/sdcc.qbs2
-rw-r--r--share/qbs/modules/cpp/setuprunenv.js20
-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.js16
-rw-r--r--share/qbs/modules/cpp/watcom.qbs4
-rw-r--r--share/qbs/modules/cpp/windows-clang-cl.qbs11
-rw-r--r--share/qbs/modules/cpp/windows-clang-mingw.qbs8
-rw-r--r--share/qbs/modules/cpp/windows-mingw.qbs4
-rw-r--r--share/qbs/modules/cpp/windows-msvc-base.qbs7
-rw-r--r--share/qbs/modules/cpp/windows-msvc.qbs6
-rw-r--r--share/qbs/modules/dmg/DMGModule.qbs9
-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.qbs13
-rw-r--r--share/qbs/modules/ib/IBModule.qbs4
-rw-r--r--share/qbs/modules/ib/ib.js16
-rw-r--r--share/qbs/modules/ico/ico.js6
-rw-r--r--share/qbs/modules/innosetup/InnoSetupModule.qbs2
-rw-r--r--share/qbs/modules/java/JavaModule.qbs6
-rw-r--r--share/qbs/modules/java/utils.js44
-rw-r--r--share/qbs/modules/nodejs/NodeJS.qbs6
-rw-r--r--share/qbs/modules/nsis/NSISModule.qbs8
-rw-r--r--share/qbs/modules/pkgconfig/pkgconfig.qbs2
-rw-r--r--share/qbs/modules/protobuf/cpp/protobufcpp.qbs115
-rw-r--r--share/qbs/modules/protobuf/nanopb/nanopb.qbs1
-rw-r--r--share/qbs/modules/protobuf/protobufbase.qbs2
-rw-r--r--share/qbs/modules/qbs/common.qbs45
-rw-r--r--share/qbs/modules/qnx/qnx.qbs8
-rw-r--r--share/qbs/modules/typescript/typescript.js4
-rw-r--r--share/qbs/modules/wix/WiXModule.qbs24
-rw-r--r--share/qbs/modules/xcode/xcode.js41
-rw-r--r--share/qbs/modules/xcode/xcode.qbs23
-rw-r--r--share/share.qbs11
111 files changed, 3527 insertions, 2199 deletions
diff --git a/share/CMakeLists.txt b/share/CMakeLists.txt
index 2891f7272..e47bd74f0 100644
--- a/share/CMakeLists.txt
+++ b/share/CMakeLists.txt
@@ -8,22 +8,8 @@ endif()
# below we copy some files that are required to run qbs from the build directory
# emulating the same layout we will have after the installation
-# copy & install dmgbuild
-install(
- PROGRAMS ../src/3rdparty/python/bin/dmgbuild
- DESTINATION "${QBS_LIBEXEC_INSTALL_DIR}"
- )
-set(_DMGBUILD_INSTALL_PATH ${CMAKE_BINARY_DIR}/${QBS_OUTPUT_PREFIX}${QBS_LIBEXEC_INSTALL_DIR}/dmgbuild)
-add_custom_command(
- OUTPUT ${_DMGBUILD_INSTALL_PATH}
- COMMAND ${CMAKE_COMMAND} -E copy
- ${CMAKE_CURRENT_SOURCE_DIR}/../src/3rdparty/python/bin/dmgbuild
- ${CMAKE_BINARY_DIR}/${QBS_OUTPUT_PREFIX}${QBS_LIBEXEC_INSTALL_DIR}
- COMMENT "Copying dmgbuild script"
- )
-
# copy & install python packages
-set(_SITE_PACKAGES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../src/3rdparty/python/lib/python2.7/site-packages/)
+set(_SITE_PACKAGES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../src/3rdparty/python/lib/python3.9/site-packages/)
file(GLOB_RECURSE _SITE_PACKAGES_RELATIVE RELATIVE "${_SITE_PACKAGES_DIR}" "${_SITE_PACKAGES_DIR}/*.py")
set(_SITE_PACKAGES_SRC ${_SITE_PACKAGES_RELATIVE})
@@ -85,7 +71,7 @@ add_custom_command(
-f ${PROJECT_SOURCE_DIR}/qbs.qbs
-d ${PROJECT_BINARY_DIR}/
config:resources-build
- qbs.installPrefix:undefined
+ qbs.installPrefix:""
project.withCode:false
project.withDocumentation:false
profile:none
@@ -102,7 +88,6 @@ add_custom_command(
add_custom_target(
BuildQbsResources ALL
DEPENDS
- "${_DMGBUILD_INSTALL_PATH}"
${_SITE_PACKAGES_DST}
${_QBS_RESOURCES_DST}
"${_QMLTYPES_INSTALL_PATH}"
diff --git a/share/qbs/imports/qbs/DarwinTools/darwin-tools.js b/share/qbs/imports/qbs/DarwinTools/darwin-tools.js
index 15f2c54ec..9f7d92e59 100644
--- a/share/qbs/imports/qbs/DarwinTools/darwin-tools.js
+++ b/share/qbs/imports/qbs/DarwinTools/darwin-tools.js
@@ -182,7 +182,7 @@ var PropertyListVariableExpander = (function () {
return { "syntax": syntax, "index": idx };
}
- function expandString(key, str, env) {
+ function expandString(key, str, env, seenVars) {
if (!str)
return str;
var repl = indexOfReplacementStart(syntaxes, str);
@@ -194,7 +194,14 @@ var PropertyListVariableExpander = (function () {
var varParts = str.slice(i + repl.syntax.open.length, j).split(':');
var varName = varParts[0];
var varFormatter = varParts[1];
- var varValue = expandString(key, env[varName], env);
+ 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)
@@ -229,7 +236,7 @@ var PropertyListVariableExpander = (function () {
}
if (type !== "string")
continue;
- var expandedValue = expandString(key, value, env);
+ var expandedValue = expandString(key, value, env, []);
if (expandedValue !== value)
obj[key] = expandedValue;
}
diff --git a/share/qbs/imports/qbs/ModUtils/utils.js b/share/qbs/imports/qbs/ModUtils/utils.js
index dfb1f7639..a1ede5344 100644
--- a/share/qbs/imports/qbs/ModUtils/utils.js
+++ b/share/qbs/imports/qbs/ModUtils/utils.js
@@ -597,6 +597,8 @@ function guessArchitecture(m) {
architecture = "hcs12";
} else if (hasAnyOf(m, ["__e2k__"])) {
architecture = "e2k";
+ } else if (hasAnyOf(m, ["__hppa__"])) {
+ architecture = "hppa";
}
}
diff --git a/share/qbs/imports/qbs/PathTools/path-tools.js b/share/qbs/imports/qbs/PathTools/path-tools.js
index a857a7139..c928c33e4 100644
--- a/share/qbs/imports/qbs/PathTools/path-tools.js
+++ b/share/qbs/imports/qbs/PathTools/path-tools.js
@@ -232,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/LibraryProbe.qbs b/share/qbs/imports/qbs/Probes/LibraryProbe.qbs
index 7631eb441..d67a81372 100644
--- a/share/qbs/imports/qbs/Probes/LibraryProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/LibraryProbe.qbs
@@ -28,15 +28,11 @@
**
****************************************************************************/
+import qbs.PathTools
+
PathProbe {
property string endianness
- nameSuffixes: {
- if (qbs.targetOS.contains("windows"))
- return [".lib"];
- if (qbs.targetOS.contains("macos"))
- return [".dylib", ".a"];
- return [".so", ".a"];
- }
+ nameSuffixes: PathTools.librarySuffixes(qbs.targetOS, ["shared", "static"], true)
platformSearchPaths: {
var result = [];
if (qbs.targetOS.contains("unix")) {
@@ -65,17 +61,7 @@ PathProbe {
return result;
}
- nameFilter: {
- if (qbs.targetOS.contains("unix")) {
- return function(name) {
- return "lib" + name;
- }
- } else {
- return function(name) {
- return name;
- }
- }
- }
+ nameFilter: PathTools.libraryNameFilter(qbs.targetOS)
platformEnvironmentPaths: {
if (qbs.targetOS.contains("windows"))
return [ "PATH" ];
diff --git a/share/qbs/imports/qbs/Probes/PkgConfigProbe.qbs b/share/qbs/imports/qbs/Probes/PkgConfigProbe.qbs
index 61a9c0b74..0fe81c3cc 100644
--- a/share/qbs/imports/qbs/Probes/PkgConfigProbe.qbs
+++ b/share/qbs/imports/qbs/Probes/PkgConfigProbe.qbs
@@ -85,6 +85,12 @@ 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) {
stdout = p.readStdOut().trim();
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/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/AppleApplicationDiskImage.qbs b/share/qbs/imports/qbs/base/AppleApplicationDiskImage.qbs
index 6491bf14a..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)
diff --git a/share/qbs/imports/qbs/base/ApplicationExtension.qbs b/share/qbs/imports/qbs/base/ApplicationExtension.qbs
index eae5145ce..3d25d5f73 100644
--- a/share/qbs/imports/qbs/base/ApplicationExtension.qbs
+++ b/share/qbs/imports/qbs/base/ApplicationExtension.qbs
@@ -34,8 +34,12 @@ 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
diff --git a/share/qbs/module-providers/Qt/templates/QtModule.qbs b/share/qbs/imports/qbs/base/QtModule.qbs
index 62e05327b..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;
diff --git a/share/qbs/module-providers/Qt/templates/QtPlugin.qbs b/share/qbs/imports/qbs/base/QtPlugin.qbs
index 883e34465..883e34465 100644
--- a/share/qbs/module-providers/Qt/templates/QtPlugin.qbs
+++ b/share/qbs/imports/qbs/base/QtPlugin.qbs
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 db3ff67b8..9a314822b 100644
--- a/share/qbs/module-providers/Qt/setup-qt.js
+++ b/share/qbs/module-providers/Qt/setup-qt.js
@@ -37,1241 +37,13 @@
**
****************************************************************************/
-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 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 toNative(p) { return FileInfo.toNativeSeparators(p); }
-function exeSuffix(qbs) { return FileInfo.executableSuffix(); }
-
-function getQmakeFilePaths(qmakeFilePaths, qbs) {
- 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());
- var suffix = exeSuffix(qbs);
- 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);
- }
- }
- }
- 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 a qmake executable.");
- }
- 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 needsDSuffix(qtProps) {
- return !isForMinGw(qtProps) || Utilities.versionCompare(qtProps.qtVersion, "5.14.0") < 0
- || qtProps.configItems.contains("debug_and_release");
-}
-
-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");
- 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 && needsDSuffix(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 '" + toNative(qtProps.libraryPath)
- + "'. You will not be able to link Qt applications.");
- }
- return result;
-}
-
-function abiToArchitecture(abi) {
- switch (abi) {
- case "armeabi-v7a":
- return "armv7a";
- case "arm64-v8a":
- return "arm64";
- case "x86":
- case "x86_64":
- default:
- return abi;
- }
-}
-
-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.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 '" + toNative(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 (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", "harfbuzzng"
- ];
-
- if (qtProps.qtMajorVersion <= 5) {
- modulesNeverBuiltAsFrameworks.push("uitools"); // is framework since qt6
- }
-
- return !modulesNeverBuiltAsFrameworks.contains(modInfo.qbsName);
-}
-
-function libBaseName(modInfo, libName, debugBuild, qtProps) {
- var name = libName;
- if (qtProps.mkspecName.startsWith("win")) {
- if (debugBuild && needsDSuffix(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 (!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 = "";
- if (!modInfo.isExternal) {
- libName += !modInfo.modulePrefix && !libNameBroken ? "Qt" : modInfo.modulePrefix;
- if (qtProps.qtMajorVersion >= 5 && !isFramework(modInfo, qtProps) && !libNameBroken)
- libName += qtProps.qtMajorVersion;
- }
- libName += moduleNameWithoutPrefix(modInfo);
- if (!modInfo.isExternal)
- 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, 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(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);
- var libDir = prlFilePath;
- if (isFramework(modInfo, qtProps)) {
- prlFilePath = FileInfo.joinPaths(prlFilePath,
- libraryBaseName(modInfo, qtProps, false) + ".framework");
- libDir = prlFilePath;
- if (Utilities.versionCompare(qtProps.qtVersion, "5.14") >= 0)
- prlFilePath = FileInfo.joinPaths(prlFilePath, "Resources");
- }
- 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...
- // 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 '" + 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, 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 '" + 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)
- .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.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, 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 extractQbsArchs(module, qtProps) {
if (qtProps.mkspecName.startsWith("macx-")) {
var archs = [];
@@ -1333,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";
}
@@ -1389,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";
}
@@ -1414,7 +186,20 @@ function findVariable(content, start) {
}
function minVersionJsString(minVersion) {
- return !minVersion ? "original" : ModUtils.toJSLiteral(minVersion);
+ return !minVersion ? "" : ModUtils.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, abi) {
@@ -1445,7 +230,7 @@ function replaceSpecialValues(content, module, qtProps, abi) {
availableBuildVariants: ModUtils.toJSLiteral(qtProps.buildVariant),
staticBuild: ModUtils.toJSLiteral(qtProps.staticBuild),
frameworkBuild: ModUtils.toJSLiteral(qtProps.frameworkBuild),
- name: ModUtils.toJSLiteral(moduleNameWithoutPrefix(module)),
+ name: ModUtils.toJSLiteral(ProviderUtils.qtModuleNameWithoutPrefix(module)),
has_library: ModUtils.toJSLiteral(module.hasLibrary),
dependencies: ModUtils.toJSLiteral(module.dependencies),
includes: ModUtils.toJSLiteral(module.includePaths),
@@ -1462,18 +247,20 @@ function replaceSpecialValues(content, module, qtProps, abi) {
frameworksRelease: ModUtils.toJSLiteral(module.frameworksRelease),
libFilePathDebug: ModUtils.toJSLiteral(module.libFilePathDebug),
libFilePathRelease: ModUtils.toJSLiteral(module.libFilePathRelease),
- libNameForLinkerDebug: ModUtils.toJSLiteral(libNameForLinker(module, qtProps, true)),
+ libNameForLinkerDebug:
+ ModUtils.toJSLiteral(ProviderUtils.qtLibNameForLinker(module, qtProps, true)),
pluginTypes: ModUtils.toJSLiteral(module.supportedPluginTypes),
moduleConfig: ModUtils.toJSLiteral(module.config),
- libNameForLinkerRelease: ModUtils.toJSLiteral(libNameForLinker(module, qtProps, false)),
+ libNameForLinkerRelease:
+ ModUtils.toJSLiteral(ProviderUtils.qtLibNameForLinker(module, qtProps, false)),
entryPointLibsDebug: ModUtils.toJSLiteral(qtProps.entryPointLibsDebug),
entryPointLibsRelease: ModUtils.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),
+ 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 = "";
@@ -1525,16 +312,15 @@ function replaceSpecialValues(content, module, qtProps, abi) {
+ 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 += "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"
@@ -1544,9 +330,21 @@ function replaceSpecialValues(content, module, qtProps, abi) {
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;
}
@@ -1555,7 +353,7 @@ function copyTemplateFile(fileName, targetDirectory, qtProps, abi, location, all
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);
@@ -1577,67 +375,64 @@ function copyTemplateFile(fileName, targetDirectory, qtProps, abi, location, all
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 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 + "'");
+function setupOneQt(moduleName, qtInfo, outputBaseDir, uniquify, location) {
+ var qtProps = qtInfo.qtProps;
var relativeSearchPaths = [];
- for (a = 0; a < androidAbis.length; ++a) {
- if (androidAbis.length > 1)
- console.info("Configuring abi '" + androidAbis[a] + "'...");
- var modules = qtProps.qtMajorVersion < 5 ? allQt4Modules(qtProps) :
- allQt5Modules(qtProps,androidAbis[a]);
- 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) : "";
- relativeSearchPath = FileInfo.joinPaths(relativeSearchPath, androidAbis[a]);
+ 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");
- if (File.exists(qbsQtModuleBaseDir))
- File.remove(qbsQtModuleBaseDir);
+ // TODO:
+ // if (File.exists(qbsQtModuleBaseDir))
+ // File.remove(qbsQtModuleBaseDir);
var allFiles = [];
- copyTemplateFile("QtModule.qbs", qbsQtModuleBaseDir, qtProps, androidAbis[a], location,
- allFiles);
- copyTemplateFile("QtPlugin.qbs", qbsQtModuleBaseDir, qtProps, androidAbis[a], location,
- allFiles);
- copyTemplateFile("plugin_support.qbs",
- FileInfo.joinPaths(qbsQtModuleBaseDir, "plugin_support"), qtProps,
- androidAbis[a], location, allFiles, undefined, pluginsByType,
- nonEssentialPlugins);
+ 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.qmlLibExecPath,
+ "qmlcachegen" + FileInfo.executableSuffix()))) {
+ copyTemplateFile(qmlcacheStr + ".qbs",
+ FileInfo.joinPaths(qbsQtModuleBaseDir, qmlcacheStr), qtProps,
+ androidAbi, location, allFiles);
+ }
+ relativeSearchPaths.push(relativeSearchPath);
+ return relativeSearchPaths;
+ }
- for (i = 0; i < modules.length; ++i) {
- var module = modules[i];
+ 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, androidAbis[a], location,
+ copyTemplateFile("moc.js", qbsQtModuleDir, qtProps, androidAbi, location,
allFiles);
- copyTemplateFile("qdoc.js", qbsQtModuleDir, qtProps, androidAbis[a], location,
+ copyTemplateFile("qdoc.js", qbsQtModuleDir, qtProps, androidAbi, location,
allFiles);
- copyTemplateFile("rcc.js", qbsQtModuleDir, qtProps, androidAbis[a], location,
+ copyTemplateFile("rcc.js", qbsQtModuleDir, qtProps, androidAbi, location,
allFiles);
} else if (module.qbsName === "gui") {
moduleTemplateFileName = "gui.qbs";
@@ -1645,62 +440,51 @@ function setupOneQt(qmakeFilePath, outputBaseDir, uniquify, location, qbs) {
moduleTemplateFileName = "scxml.qbs";
} else if (module.qbsName === "dbus") {
moduleTemplateFileName = "dbus.qbs";
- copyTemplateFile("dbus.js", qbsQtModuleDir, qtProps, androidAbis[a], location,
+ copyTemplateFile("dbus.js", qbsQtModuleDir, qtProps, androidAbi, location,
allFiles);
} else if (module.qbsName === "qml") {
moduleTemplateFileName = "qml.qbs";
- copyTemplateFile("qml.js", qbsQtModuleDir, qtProps, androidAbis[a], location,
+ copyTemplateFile("qml.js", qbsQtModuleDir, qtProps, androidAbi, location,
allFiles);
- var qmlcacheStr = "qmlcache";
- if (File.exists(FileInfo.joinPaths(qtProps.qmlLibExecPath,
- "qmlcachegen" + exeSuffix(qbs)))) {
- copyTemplateFile(qmlcacheStr + ".qbs",
- FileInfo.joinPaths(qbsQtModuleBaseDir, qmlcacheStr), qtProps,
- androidAbis[a], location, allFiles);
- }
} else if (module.qbsName === "quick") {
moduleTemplateFileName = "quick.qbs";
- copyTemplateFile("quick.js", qbsQtModuleDir, qtProps, androidAbis[a], location,
+ copyTemplateFile("quick.js", qbsQtModuleDir, qtProps, androidAbi, location,
allFiles);
- copyTemplateFile("rcc.js", qbsQtModuleDir, qtProps, androidAbis[a], location,
+ copyTemplateFile("rcc.js", qbsQtModuleDir, qtProps, androidAbi, location,
allFiles);
} else if (module.isPlugin) {
moduleTemplateFileName = "plugin.qbs";
} else {
moduleTemplateFileName = "module.qbs";
}
- copyTemplateFile(moduleTemplateFileName, qbsQtModuleDir, qtProps, androidAbis[a],
+ copyTemplateFile(moduleTemplateFileName, qbsQtModuleDir, qtProps, androidAbi,
location, allFiles, module);
+ relativeSearchPaths.push(relativeSearchPath);
}
-
- // 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, androidAbis[a], location, allFiles);
- 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 uniquifySearchPath = qtInfos.length > 1;
var allSearchPaths = [];
- for (var i = 0; i < qmakeFilePaths.length; ++i) {
+ moduleName = moduleName.substring(3);
+ for (var i = 0; i < qtInfos.length; ++i) {
try {
- console.info("Setting up Qt at '" + toNative(qmakeFilePaths[i]) + "'...");
- var searchPaths = setupOneQt(qmakeFilePaths[i], outputBaseDir, uniquifySearchPath,
- location, qbs);
+ 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]);
- console.info("Qt was set up successfully.");
}
} 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 allSearchPaths;
diff --git a/share/qbs/module-providers/Qt/templates/android_support.qbs b/share/qbs/module-providers/Qt/templates/android_support.qbs
index 68276070f..6d548f194 100644
--- a/share/qbs/module-providers/Qt/templates/android_support.qbs
+++ b/share/qbs/module-providers/Qt/templates/android_support.qbs
@@ -21,7 +21,7 @@ Module {
property string _qtBinaryDir
property string _qtInstallDir
property bool _enableSdkSupport: product.type && product.type.contains("android.package")
- && !consoleApplication
+ && !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")
@@ -220,9 +220,11 @@ Module {
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 + '",');
- f.writeLine('"rcc-binary": "' + product.Qt.android_support.rccFilePath + '",');
+ 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 = [];
diff --git a/share/qbs/module-providers/Qt/templates/core.qbs b/share/qbs/module-providers/Qt/templates/core.qbs
index f00f16211..485402716 100644
--- a/share/qbs/module-providers/Qt/templates/core.qbs
+++ b/share/qbs/module-providers/Qt/templates/core.qbs
@@ -18,7 +18,7 @@ Module {
&& qbs.targetPlatform === targetPlatform + "-simulator"
Depends { name: "cpp" }
- Depends { name: "Sanitizers.address" }
+ Depends { name: "Sanitizers.address"; condition: config.contains("sanitize_address") }
Depends { name: "Qt.android_support"; condition: qbs.targetOS.contains("android") }
Properties {
@@ -76,6 +76,8 @@ Module {
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] : "";
}
@@ -107,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
@@ -121,8 +124,6 @@ Module {
property stringList moduleConfig: @moduleConfig@
- Sanitizers.address.enabled: config.contains("sanitize_address")
-
Properties {
condition: moduleConfig.contains("use_gold_linker")
cpp.linkerVariant: "gold"
@@ -151,6 +152,8 @@ 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: {
@@ -196,8 +199,7 @@ Module {
return undefined;
return frameworks;
}
- cpp.rpaths: qbs.targetOS.contains('linux') && !qbs.targetOS.contains("android") ? [libPath] :
- undefined
+ cpp.rpaths: useRPaths ? libPath : undefined
cpp.runtimeLibrary: qbs.toolchain.contains("msvc")
? config.contains("static_runtime") ? "static" : "dynamic"
: original
@@ -220,12 +222,12 @@ 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
diff --git a/share/qbs/module-providers/Qt/templates/dbus.qbs b/share/qbs/module-providers/Qt/templates/dbus.qbs
index 08e1e49e7..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 {
diff --git a/share/qbs/module-providers/Qt/templates/gui.qbs b/share/qbs/module-providers/Qt/templates/gui.qbs
index 6ba5e48c4..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"
diff --git a/share/qbs/module-providers/Qt/templates/module.qbs b/share/qbs/module-providers/Qt/templates/module.qbs
index ccafe4122..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@}
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/qml.js b/share/qbs/module-providers/Qt/templates/qml.js
index 2a2ff85ab..38462dcf7 100644
--- a/share/qbs/module-providers/Qt/templates/qml.js
+++ b/share/qbs/module-providers/Qt/templates/qml.js
@@ -39,17 +39,32 @@ function getPrlRhs(line)
return line.split('=')[1].trim();
}
-function getLibsForPlugin(pluginData, buildVariant, targetOS, toolchain, qtLibDir, qtPluginDir,
- qtDir)
+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)) {
@@ -77,7 +92,8 @@ function getLibsForPlugin(pluginData, buildVariant, targetOS, toolchain, qtLibDi
otherLibsLine = otherLibsLine.replace(/\$\$\[QT_INSTALL_LIBS\]/g, qtLibDir);
otherLibsLine = otherLibsLine.replace(/\$\$\[QT_INSTALL_PLUGINS\]/g, qtPluginDir);
otherLibsLine = otherLibsLine.replace(/\$\$\[QT_INSTALL_PREFIX\]/g, qtDir);
- otherLibs = otherLibs.concat(otherLibsLine.split(' '));
+ otherLibsLine = otherLibsLine.replace(/\$\$\[QT_INSTALL_QML\]/g, qtQmlPath);
+ otherLibs = otherLibs.concat(otherLibsLine.split(' ').map(FileInfo.cleanPath));
}
}
if (!pluginLib)
diff --git a/share/qbs/module-providers/Qt/templates/qml.qbs b/share/qbs/module-providers/Qt/templates/qml.qbs
index f15705cc5..0a938e58d 100644
--- a/share/qbs/module-providers/Qt/templates/qml.qbs
+++ b/share/qbs/module-providers/Qt/templates/qml.qbs
@@ -1,7 +1,6 @@
import qbs.FileInfo
import qbs.Host
import qbs.TextFile
-import '../QtModule.qbs' as QtModule
import "qml.js" as Qml
QtModule {
@@ -170,13 +169,7 @@ 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,
- product.Qt.core.pluginPath,
- product.Qt.core.installPrefixPath);
+ 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)
diff --git a/share/qbs/module-providers/Qt/templates/quick.qbs b/share/qbs/module-providers/Qt/templates/quick.qbs
index 27f49cbd6..5fc4aa349 100644
--- a/share/qbs/module-providers/Qt/templates/quick.qbs
+++ b/share/qbs/module-providers/Qt/templates/quick.qbs
@@ -33,7 +33,6 @@ import qbs.FileInfo
import qbs.Process
import qbs.TextFile
import qbs.Utilities
-import '../QtModule.qbs' as QtModule
import 'quick.js' as QC
QtModule {
diff --git a/share/qbs/module-providers/Qt/templates/scxml.qbs b/share/qbs/module-providers/Qt/templates/scxml.qbs
index b800dfe70..757041b52 100644
--- a/share/qbs/module-providers/Qt/templates/scxml.qbs
+++ b/share/qbs/module-providers/Qt/templates/scxml.qbs
@@ -1,6 +1,5 @@
import qbs.FileInfo
import qbs.Utilities
-import "../QtModule.qbs" as QtModule
QtModule {
qtModuleName: "Scxml"
diff --git a/share/qbs/module-providers/__fallback/fallback.qbs b/share/qbs/module-providers/__fallback/fallback.qbs
index 52a3f080a..349af3a52 100644
--- a/share/qbs/module-providers/__fallback/fallback.qbs
+++ b/share/qbs/module-providers/__fallback/fallback.qbs
@@ -46,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
index 2af3c42e4..885a6da7a 100644
--- a/share/qbs/module-providers/qbspkgconfig.qbs
+++ b/share/qbs/module-providers/qbspkgconfig.qbs
@@ -40,49 +40,54 @@
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 string executableFilePath
+ property stringList executableNames: ["pkgconf", "pkg-config"]
+ property string executableFilePath: pkgConfigProbe.filePath
property stringList extraPaths
property stringList libDirs
property bool staticMode: false
- property path sysroot: {
- if (qbs.targetOS.contains("macos"))
- return "";
- return qbs.sysroot;
- }
- property bool mergeDependencies: true
+ property bool definePrefix: Host.os().includes("windows")
- relativeSearchPaths: {
+ // 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
- function exeSuffix(qbs) { return FileInfo.executableSuffix(); }
+ Probes.BinaryProbe {
+ id: pkgConfigProbe
+ condition: !executableFilePath
+ names: executableNames
+ }
- // we need Probes in Providers...
- function getPkgConfigExecutable(qbs) {
- function splitNonEmpty(s, c) { return s.split(c).filter(function(e) { return e; }) }
+ Probes.QbsPkgConfigProbe {
+ id: theProbe
+ _executableFilePath: executableFilePath
+ _extraPaths: extraPaths
+ _sysroot: sysroot
+ _libDirs: libDirs
+ _staticMode: staticMode
+ _definePrefix: definePrefix
+ }
- var pathValue = Environment.getEnv("PATH");
- if (!pathValue)
- return undefined;
- var dirs = splitNonEmpty(pathValue, FileInfo.pathListSeparator());
- var suffix = exeSuffix(qbs);
- var filePaths = [];
- for (var i = 0; i < dirs.length; ++i) {
- var candidate = FileInfo.joinPaths(dirs[i], "pkg-config" + suffix);
- var canonicalCandidate = FileInfo.canonicalPath(candidate);
- if (!canonicalCandidate || !File.exists(canonicalCandidate))
- continue;
- return canonicalCandidate;
- }
- return undefined;
- }
+ Probes.QmakeProbe {
+ id: qmakeProbe
+ condition: moduleName.startsWith("Qt") && theProbe.qmakePaths
+ qmakePaths: theProbe.qmakePaths
+ }
+
+ isEager: false
+ relativeSearchPaths: {
function getModuleInfo(pkg, staticMode) {
var result = {};
@@ -124,14 +129,12 @@ ModuleProvider {
return result;
}
- function getModuleName(packageName) { return packageName.replace('.', '-'); }
-
function getModuleDependencies(pkg, staticMode) {
var mapper = function(p) {
var result = {};
for (var key in p)
result[key] = p[key];
- result.name = getModuleName(result.name);
+ result.name = ProviderUtils.pkgConfigToModuleName(result.name);
return result;
}
var result = pkg.requires.map(mapper);
@@ -140,132 +143,83 @@ ModuleProvider {
return result;
}
- console.debug("Running pkgconfig provider.")
+ console.debug("Running pkgconfig provider for " + moduleName + ".");
var outputDir = FileInfo.joinPaths(outputBaseDir, "modules");
File.makePath(outputDir);
- var options = {};
- options.libDirs = libDirs;
- options.sysroot = sysroot;
- options.staticMode = staticMode;
- options.mergeDependencies = mergeDependencies;
- options.extraPaths = extraPaths;
- if (options.sysroot && !options.libDirs) {
- options.libDirs = [
- sysroot + "/usr/lib/pkgconfig",
- sysroot + "/usr/share/pkgconfig"
- ];
- }
- if (!options.libDirs) {
- // if we have pkg-config installed, let's ask it for its search paths (since
- // built-in search paths can differ between platforms)
- var executable = executableFilePath ? executableFilePath : getPkgConfigExecutable(qbs);
- if (executable) {
- var p = new Process()
- if (p.exec(executable, ['pkg-config', '--variable=pc_path']) === 0) {
- var stdout = p.readStdOut().trim();
- // TODO: pathListSeparator? depends on what pkg-config prints on Windows
- options.libDirs = stdout ? stdout.split(':'): [];
- }
- }
+ var moduleMapping = {
+ "protobuf": "protobuflib"
}
-
- function setupQt(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 = exeSuffix(qbs);
- var qmakePaths = [FileInfo.joinPaths(binDir, "qmake" + suffix)];
+ 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");
- SetupQt.doSetup(qmakePaths, outputBaseDir, qtProviderDir, qbs);
+ return SetupQt.doSetup(packageName, qtInfos, outputBaseDir, qtProviderDir);
}
- }
- var moduleMapping = {
- "protobuf": "protobuflib",
- "grpc++": "grpcpp"
+ if (!sysroot) {
+ return setupQt(moduleName, qmakeProbe.qtInfos);
+ }
+ return [];
}
- var pkgConfig = new PkgConfig(options);
-
- var brokenPackages = [];
- var packages = pkgConfig.packages();
- for (var packageName in packages) {
- var pkg = packages[packageName];
- if (pkg.isBroken) {
- brokenPackages.push(pkg);
- continue;
- }
- if (packageName.startsWith("Qt")) {
- setupQt(pkg);
- continue;
- }
- var moduleName = moduleMapping[packageName]
- ? moduleMapping[packageName]
- : getModuleName(packageName);
- var moduleInfo = getModuleInfo(pkg, staticMode);
- var deps = getModuleDependencies(pkg, staticMode);
+ var pkg;
+ pkg = theProbe.packages[reverseMapping[moduleName]];
+ if (pkg === undefined)
+ pkg = theProbe.packagesByModuleName[moduleName];
+ if (pkg === undefined)
+ return [];
- 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) {
- module.write(" Depends { name: '" + dep.name + "'");
- 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();
+ if (pkg.isBroken) {
+ console.warn("Failed to load " + moduleName + " as it's pkg-config package is broken");
+ return [];
}
-
- if (brokenPackages.length !== 0) {
- console.warn("Failed to load some pkg-config packages:");
- for (var i = 0; i < brokenPackages.length; ++i) {
- console.warn(" " + brokenPackages[i].filePath
- + ": " + brokenPackages[i].errorText);
+ 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/sdk/sdk.qbs b/share/qbs/modules/Android/sdk/sdk.qbs
index d663a01e4..440448dcf 100644
--- a/share/qbs/modules/Android/sdk/sdk.qbs
+++ b/share/qbs/modules/Android/sdk/sdk.qbs
@@ -52,7 +52,7 @@ Module {
Probes.PathProbe {
id: bundletoolProbe
- platformSearchPaths: [Android.sdk.sdkDir]
+ 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",
@@ -102,36 +102,36 @@ Module {
Group {
name: "java sources"
- condition: Android.sdk.automaticSources
- prefix: FileInfo.resolvePath(product.sourceDirectory, 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: FileInfo.resolvePath(product.sourceDirectory, 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: FileInfo.resolvePath(product.sourceDirectory, 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] : [])
}
@@ -196,8 +196,8 @@ Module {
java.languageVersion: platformJavaVersion
java.runtimeVersion: platformJavaVersion
java.bootClassPaths: androidJarFilePath
- codesign.apksignerFilePath: Android.sdk.apksignerFilePath
- codesign._packageName: Android.sdk.apkBaseName + (_generateAab ? ".aab" : ".apk")
+ codesign.apksignerFilePath: apksignerFilePath
+ codesign._packageName: apkBaseName + (_generateAab ? ".aab" : ".apk")
codesign.useApksigner: !_generateAab
}
@@ -263,7 +263,7 @@ Module {
property bool customManifestProcessing: false
Group {
- condition: !Android.sdk.customManifestProcessing
+ condition: !product.Android.sdk.customManifestProcessing
fileTagsFilter: "android.manifest_processed"
fileTags: "android.manifest_final"
}
diff --git a/share/qbs/modules/Android/sdk/utils.js b/share/qbs/modules/Android/sdk/utils.js
index 2b111522e..232ee5a30 100644
--- a/share/qbs/modules/Android/sdk/utils.js
+++ b/share/qbs/modules/Android/sdk/utils.js
@@ -84,7 +84,7 @@ 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);
@@ -93,7 +93,7 @@ function prepareDex(project, product, inputs, outputs, input, output, explicitly
if (typeof product.artifacts["java.jar"] !== "undefined") {
product.artifacts["java.jar"].forEach(function(artifact) {
- if (!jarFiles.contains(artifact.filePath))
+ if (!jarFiles.includes(artifact.filePath))
jarFiles.push(artifact.filePath);
});
}
@@ -166,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);
}
}
@@ -181,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);
}
}
@@ -265,7 +265,7 @@ function prepareAapt2Link(project, product, inputs, outputs, input, output, expl
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);
}
}
@@ -429,7 +429,7 @@ function stlDeploymentData(product, inputs, type)
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);
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 52b4dffe3..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;
@@ -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 c36afd953..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"];
}
diff --git a/share/qbs/modules/Exporter/qbs/qbsexporter.js b/share/qbs/modules/Exporter/qbs/qbsexporter.js
index be46372c3..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,15 +103,6 @@ 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 (value instanceof Array) {
@@ -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,7 +144,7 @@ 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 + ": ";
@@ -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,7 +236,7 @@ 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 < imports.length; ++i)
diff --git a/share/qbs/modules/Sanitizers/address/asan.qbs b/share/qbs/modules/Sanitizers/address/asan.qbs
index 39605ef4e..9d8f5b97e 100644
--- a/share/qbs/modules/Sanitizers/address/asan.qbs
+++ b/share/qbs/modules/Sanitizers/address/asan.qbs
@@ -34,9 +34,9 @@ Module {
Depends { name: "cpp" }
property bool enabled: true
- readonly property bool _supported: qbs.toolchain.contains("gcc")
- || qbs.toolchain.contains("clang-cl")
- || (qbs.toolchain.contains("msvc")
+ 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
@@ -53,7 +53,7 @@ Module {
var flags = [];
if (!_enabled)
return flags;
- if (qbs.toolchain.contains("msvc") && !qbs.toolchain.contains("clang-cl")) {
+ if (qbs.toolchain.includes("msvc") && !qbs.toolchain.includes("clang-cl")) {
flags.push("/fsanitize=address");
if (detectUseAfterReturn !== "never")
flags.push("/fsanitize-address-use-after-return");
@@ -63,8 +63,9 @@ Module {
if (detectUseAfterScope)
flags.push("-fsanitize-address-use-after-scope");
if (detectUseAfterReturn) {
- if (qbs.toolchain.contains("llvm")) {
- if (Utilities.versionCompare(cpp.compilerVersion, "13") >= 0)
+ 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");
diff --git a/share/qbs/modules/archiver/archiver.qbs b/share/qbs/modules/archiver/archiver.qbs
index 6da3f43ff..069e76717 100644
--- a/share/qbs/modules/archiver/archiver.qbs
+++ b/share/qbs/modules/archiver/archiver.qbs
@@ -54,7 +54,7 @@ Module {
names: ["7z"]
platformSearchPaths: {
var paths = base;
- if (Host.os().contains("windows")) {
+ if (Host.os().includes("windows")) {
var env32 = Environment.getEnv("PROGRAMFILES(X86)");
var env64 = Environment.getEnv("PROGRAMFILES");
if (env64 === env32 && env64.endsWith(" (x86)"))
@@ -212,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)
@@ -221,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 + "'";
diff --git a/share/qbs/modules/bundle/BundleModule.qbs b/share/qbs/modules/bundle/BundleModule.qbs
index 6526fa314..f640fd55f 100644
--- a/share/qbs/modules/bundle/BundleModule.qbs
+++ b/share/qbs/modules/bundle/BundleModule.qbs
@@ -47,13 +47,13 @@ Module {
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
@@ -74,9 +74,9 @@ Module {
"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.contains("simulator") ? "-simulator" : "",
+ "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
@@ -118,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"
@@ -152,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"
@@ -187,11 +187,18 @@ 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
property var extraEnv: ({
"PRODUCT_BUNDLE_IDENTIFIER": identifier
@@ -225,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.";
@@ -271,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"]
@@ -279,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"),
@@ -288,7 +295,7 @@ Module {
bundle: {
_bundleFilePath: FileInfo.joinPaths(
product.destinationDirectory,
- ModUtils.moduleProperty(product, "infoPlistPath")),
+ product.bundle.infoPlistPath),
}
});
}
@@ -299,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;
@@ -341,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];
@@ -453,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].");
@@ -471,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;
@@ -512,7 +520,7 @@ Module {
}
Rule {
- condition: qbs.targetOS.contains("darwin")
+ condition: qbs.targetOS.includes("darwin")
multiplex: true
inputs: ["bundle.input",
"aggregate_infoplist", "pkginfo", "hpp",
@@ -533,12 +541,12 @@ Module {
"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,
@@ -550,20 +558,19 @@ Module {
for (i in provprofiles) {
artifacts.push({
filePath: FileInfo.joinPaths(product.destinationDirectory,
- ModUtils.moduleProperty(product,
- "contentsFolderPath"),
+ 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"]
});
}
@@ -571,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"]
});
}
@@ -604,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({
@@ -615,11 +622,11 @@ 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().contains("darwin") && product.codesign
+ if (Host.os().includes("darwin") && product.codesign
&& product.codesign.enableCodeSigning) {
artifacts.push({
filePath: FileInfo.joinPaths(product.bundle.contentsFolderPath, "_CodeSignature/CodeResources"),
@@ -632,7 +639,7 @@ Module {
prepare: {
var i, cmd, commands = [];
- var packageType = ModUtils.moduleProperty(product, "packageType");
+ var packageType = product.bundle.packageType;
var bundleType = "bundle";
if (packageType === "APPL")
@@ -650,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);
@@ -697,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) {
@@ -731,8 +738,8 @@ Module {
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) {
@@ -745,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) {
@@ -759,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) {
@@ -770,15 +777,17 @@ Module {
if (cmd.sources && cmd.sources.length)
commands.push(cmd);
- if (product.moduleProperty("qbs", "hostOS").contains("darwin")) {
+ if (product.qbs.hostOS.includes("darwin")) {
Array.prototype.push.apply(commands, Codesign.prepareSign(
project, product, inputs, outputs, input, output));
if (bundleType === "application"
- && product.moduleProperty("qbs", "targetOS").contains("macos")) {
- cmd = new Command(ModUtils.moduleProperty(product, "lsregisterPath"),
- ["-f", product.bundle.bundleName]);
- cmd.description = "registering " + ModUtils.moduleProperty(product, "bundleName");
+ && 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/bundle.js b/share/qbs/modules/bundle/bundle.js
index 7fb89974a..cf765f7be 100644
--- a/share/qbs/modules/bundle/bundle.js
+++ b/share/qbs/modules/bundle/bundle.js
@@ -83,7 +83,7 @@ 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";
@@ -152,13 +152,21 @@ function _assign(target, source) {
function macOSSpecsPaths(version, developerPath) {
var result = [];
- if (Utilities.versionCompare(version, "12.5") >= 0) {
+ 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"));
- }
-
- if (Utilities.versionCompare(version, "12") >= 0) {
+ } else if (Utilities.versionCompare(version, "12") >= 0) {
result.push(FileInfo.joinPaths(
developerPath, "Platforms", "MacOSX.platform", "Developer", "Library", "Xcode",
"PrivatePlugIns", "IDEOSXSupportCore.ideplugin", "Contents", "Resources"));
@@ -311,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) {
diff --git a/share/qbs/modules/capnproto/capnprotobase.qbs b/share/qbs/modules/capnproto/capnprotobase.qbs
index e84d39433..916e53a51 100644
--- a/share/qbs/modules/capnproto/capnprotobase.qbs
+++ b/share/qbs/modules/capnproto/capnprotobase.qbs
@@ -28,6 +28,7 @@
**
****************************************************************************/
+import qbs.FileInfo
import qbs.Probes
import "capnproto.js" as HelperFunctions
@@ -40,16 +41,20 @@ Module {
property pathList importPaths: []
- readonly property string outputDir: product.buildDirectory + "/capnp"
+ 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 {
diff --git a/share/qbs/modules/capnproto/cpp/capnprotocpp.qbs b/share/qbs/modules/capnproto/cpp/capnprotocpp.qbs
index f33bc9a48..83192b7de 100644
--- a/share/qbs/modules/capnproto/cpp/capnprotocpp.qbs
+++ b/share/qbs/modules/capnproto/cpp/capnprotocpp.qbs
@@ -39,6 +39,8 @@ CapnProtoBase {
Depends { name: "capnp-rpc"; condition: useRpc }
pluginName: "capnpc-c++"
+ version: capnp.version
+ _searchPaths: capnp.hostBinDirs
cpp.systemIncludePaths: outputDir
cpp.cxxLanguageVersion: "c++14"
diff --git a/share/qbs/modules/cli/CLIModule.qbs b/share/qbs/modules/cli/CLIModule.qbs
index df58942b5..3b12284ed 100644
--- a/share/qbs/modules/cli/CLIModule.qbs
+++ b/share/qbs/modules/cli/CLIModule.qbs
@@ -5,9 +5,9 @@ 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
}
@@ -89,7 +89,7 @@ Module {
setupBuildEnvironment: {
var v = new ModUtils.EnvironmentVariable("PATH", FileInfo.pathListSeparator(),
- Host.os().contains("windows"));
+ Host.os().includes("windows"));
v.prepend(product.cli.toolchainInstallPath);
v.set();
}
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 2ed65fd67..f16387dd7 100644
--- a/share/qbs/modules/cli/mono.qbs
+++ b/share/qbs/modules/cli/mono.qbs
@@ -3,7 +3,7 @@ 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"
@@ -15,9 +15,9 @@ CLIModule {
names: ["mono"]
platformSearchPaths: {
var paths = [];
- if (Host.os().contains("macos"))
+ if (Host.os().includes("macos"))
paths.push("/Library/Frameworks/Mono.framework/Commands");
- if (Host.os().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/android.qbs b/share/qbs/modules/codesign/android.qbs
index e149e033c..b1811dcfd 100644
--- a/share/qbs/modules/codesign/android.qbs
+++ b/share/qbs/modules/codesign/android.qbs
@@ -37,7 +37,7 @@ import qbs.Probes
import "codesign.js" as CodeSign
CodeSignModule {
- condition: qbs.targetOS.contains("android")
+ condition: qbs.targetOS.includes("android")
priority: 1
enableCodeSigning: true
@@ -55,7 +55,7 @@ CodeSignModule {
property string keytoolName: "keytool"
property string debugKeystorePath: FileInfo.joinPaths(
- Environment.getEnv(Host.os().contains("windows")
+ Environment.getEnv(Host.os().includes("windows")
? "USERPROFILE" : "HOME"),
".android", "debug.keystore")
readonly property string debugKeystorePassword: "android"
diff --git a/share/qbs/modules/codesign/apple.qbs b/share/qbs/modules/codesign/apple.qbs
index 05232d7c1..0d1335d92 100644
--- a/share/qbs/modules/codesign/apple.qbs
+++ b/share/qbs/modules/codesign/apple.qbs
@@ -43,14 +43,14 @@ import "codesign.js" as CodeSign
import "../xcode/xcode.js" as XcodeUtils
CodeSignModule {
- Depends { name: "xcode"; required: qbs.toolchain && qbs.toolchain.contains("xcode") }
+ Depends { name: "xcode"; required: qbs.toolchain && qbs.toolchain.includes("xcode") }
Probes.BinaryProbe {
id: codesignProbe
names: [codesignName]
}
- condition: Host.os().contains("macos") && qbs.targetOS.contains("darwin")
+ condition: Host.os().includes("macos") && qbs.targetOS.includes("darwin")
priority: 0
enableCodeSigning: _codeSigningRequired
@@ -78,15 +78,15 @@ CodeSignModule {
var isDebug = qbs.buildVariant !== "release";
- if (qbs.targetOS.contains("ios") || qbs.targetOS.contains("tvos")
- || qbs.targetOS.contains("watchos")) {
+ 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.contains("macos")) {
+ if (qbs.targetOS.includes("macos")) {
switch (signingType) {
case "app-store":
return isDebug ? "Mac Developer" : "3rd Party Mac Developer Application";
@@ -161,27 +161,27 @@ CodeSignModule {
readonly property bool _provisioningProfileAllowed:
product.bundle
&& product.bundle.isBundle
- && product.type.contains("application")
+ && 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.contains("macos")
+ _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.contains("macos"))
+ if (qbs.targetOS.includes("macos"))
return "OSX";
- if (qbs.targetOS.contains("ios") || qbs.targetOS.contains("watchos"))
+ if (qbs.targetOS.includes("ios") || qbs.targetOS.includes("watchos"))
return "iOS";
- if (qbs.targetOS.contains("tvos"))
+ if (qbs.targetOS.includes("tvos"))
return "tvOS";
}
readonly property string _embeddedProfileName:
- (xcode._platformProps || {})["EMBEDDED_PROFILE_NAME"]
+ (xcode._platformProps || {})["EMBEDDED_PROFILE_NAME"] || "embedded.mobileprovision"
setupBuildEnvironment: {
var prefixes = product.xcode ? [
diff --git a/share/qbs/modules/codesign/codesign.js b/share/qbs/modules/codesign/codesign.js
index 463e7cbb7..482225ea2 100644
--- a/share/qbs/modules/codesign/codesign.js
+++ b/share/qbs/modules/codesign/codesign.js
@@ -43,10 +43,12 @@ function findSigningIdentities(searchString, team) {
var matchedIdentities = {};
for (var key in identities) {
var identity = identities[key];
- if (team && ![identity.subjectInfo.O, identity.subjectInfo.OU].contains(team))
+ if (team && ![identity.subjectInfo.O, identity.subjectInfo.OU].includes(team))
continue;
- if (searchString === key || identity.subjectInfo.CN.startsWith(searchString))
+ if (searchString === key
+ || (identity.subjectInfo.CN && identity.subjectInfo.CN.startsWith(searchString))) {
matchedIdentities[key] = identity;
+ }
}
return matchedIdentities;
}
@@ -103,7 +105,7 @@ function findBestProvisioningProfile(product, files) {
// 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.contains("application"))
+ if (actualSigningIdentity.SHA1 === "-" || !product.type.includes("application"))
return undefined;
// Filter out any provisioning profiles we know to be unsuitable from the start
@@ -114,7 +116,7 @@ function findBestProvisioningProfile(product, files) {
var certCommonNames = (data["DeveloperCertificates"] || []).map(function (cert) {
return Utilities.certificateInfo(cert).subjectInfo.CN;
});
- if (!certCommonNames.contains(actualSigningIdentity.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(", ") + "): "
@@ -124,7 +126,7 @@ function findBestProvisioningProfile(product, files) {
}
var platforms = data["Platform"] || [];
- if (platforms.length > 0 && profilePlatform && !platforms.contains(profilePlatform)) {
+ if (platforms.length > 0 && profilePlatform && !platforms.includes(profilePlatform)) {
console.log("Skipping provisioning profile for platform " + platforms.join(", ")
+ " (current platform " + profilePlatform + ")"
+ ": " + profile.filePath);
@@ -132,7 +134,7 @@ function findBestProvisioningProfile(product, files) {
}
if (teamIdentifier
- && !data["TeamIdentifier"].contains(teamIdentifier)
+ && !data["TeamIdentifier"].includes(teamIdentifier)
&& data["TeamName"] !== teamIdentifier) {
console.log("Skipping provisioning profile for team " + data["TeamIdentifier"]
+ " (" + data["TeamName"] + ") (current team " + teamIdentifier + ")"
@@ -223,7 +225,7 @@ function findBestSignToolSearchPaths(arch) {
});
function addSearchPath(searchPath) {
- if (File.exists(searchPath) && !searchPaths.contains(searchPath)) {
+ if (File.exists(searchPath) && !searchPaths.includes(searchPath)) {
searchPaths.push(searchPath);
return true;
}
@@ -278,20 +280,21 @@ function prepareSign(project, product, inputs, outputs, input, output) {
return cmds;
var isBundle = "bundle.content" in outputs;
- var outputFilePath = isBundle
- ? FileInfo.joinPaths(product.destinationDirectory, product.bundle.bundleName)
- : outputs["codesign.signed_artifact"][0].filePath;
- var outputFileName = isBundle
- ? product.bundle.bundleName
- : outputs["codesign.signed_artifact"][0].fileName;
- var isProductBundle = product.bundle && product.bundle.isBundle;
- // If the product is a bundle, just sign the bundle
- // instead of signing the bundle and executable separately
+ 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 && shouldSignArtifact) {
+ if (enableCodeSigning) {
var actualSigningIdentity = product.codesign._actualSigningIdentity;
if (!actualSigningIdentity) {
throw "No codesigning identities (i.e. certificate and private key pairs) matching “"
@@ -308,36 +311,53 @@ function prepareSign(project, product, inputs, outputs, input, output) {
}
}
- 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);
+ // 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
- }
+ 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 = 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);
+ 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) {
diff --git a/share/qbs/modules/codesign/signtool.qbs b/share/qbs/modules/codesign/signtool.qbs
index 0fc50f1b7..111f0a307 100644
--- a/share/qbs/modules/codesign/signtool.qbs
+++ b/share/qbs/modules/codesign/signtool.qbs
@@ -35,9 +35,9 @@ import qbs.Probes
import "codesign.js" as CODESIGN
CodeSignModule {
- condition: qbs.targetOS.contains("windows")
- && Host.os().contains("windows")
- && qbs.toolchain.contains("msvc")
+ condition: qbs.targetOS.includes("windows")
+ && Host.os().includes("windows")
+ && qbs.toolchain.includes("msvc")
_canSignArtifacts: true
diff --git a/share/qbs/modules/cpp/DarwinGCC.qbs b/share/qbs/modules/cpp/DarwinGCC.qbs
index 81d8bded2..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"
@@ -107,39 +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.contains("ios") && minimumIosVersion)
+ if (qbs.targetOS.includes("ios") && minimumIosVersion)
dict["MinimumOSVersion"] = minimumIosVersion;
- else if (qbs.targetOS.contains("tvos") && minimumTvosVersion)
+ else if (qbs.targetOS.includes("tvos") && minimumTvosVersion)
dict["MinimumOSVersion"] = minimumTvosVersion;
- else if (qbs.targetOS.contains("watchos") && minimumWatchosVersion)
+ 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"])) {
@@ -150,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;
}
@@ -196,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)
@@ -215,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
@@ -268,7 +271,7 @@ UnixGCC {
}
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 025aad498..f84028940 100644
--- a/share/qbs/modules/cpp/GenericGCC.qbs
+++ b/share/qbs/modules/cpp/GenericGCC.qbs
@@ -43,7 +43,7 @@ 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" }
@@ -123,9 +123,9 @@ CppModule {
precompiledHeaderSuffix: ".gch"
- property bool compilerHasTargetOption: qbs.toolchain.contains("clang")
+ 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("-")
@@ -170,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."
}
@@ -182,9 +182,9 @@ CppModule {
property string toolchainPathPrefix: Gcc.pathPrefix(toolchainInstallPath, toolchainPrefix)
property string binutilsPathPrefix: Gcc.pathPrefix(binutilsPath, toolchainPrefix)
- 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,7 +216,7 @@ CppModule {
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
@@ -251,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 (!Host.os().contains("windows"))
+ if (!Host.os().includes("windows"))
prefix = FileInfo.joinPaths(toolchainInstallPath, "..", "lib", "gcc",
toolchainPrefix,
[compilerVersionMajor, compilerVersionMinor].join("."));
@@ -314,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) {
@@ -351,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;
}
}
@@ -403,7 +403,7 @@ CppModule {
inputs: {
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;
@@ -483,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 [{
@@ -521,7 +521,7 @@ CppModule {
inputs: {
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;
@@ -564,7 +564,7 @@ CppModule {
inputs: {
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;
diff --git a/share/qbs/modules/cpp/LinuxGCC.qbs b/share/qbs/modules/cpp/LinuxGCC.qbs
index 17346d048..4b594a0aa 100644
--- a/share/qbs/modules/cpp/LinuxGCC.qbs
+++ b/share/qbs/modules/cpp/LinuxGCC.qbs
@@ -32,8 +32,8 @@ 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"
diff --git a/share/qbs/modules/cpp/MingwBaseModule.qbs b/share/qbs/modules/cpp/MingwBaseModule.qbs
index e96f8ba41..c9cfe9bd8 100644
--- a/share/qbs/modules/cpp/MingwBaseModule.qbs
+++ b/share/qbs/modules/cpp/MingwBaseModule.qbs
@@ -47,7 +47,7 @@ GenericGCC {
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"])
@@ -96,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 94dfb1907..6f377c5c8 100644
--- a/share/qbs/modules/cpp/UnixGCC.qbs
+++ b/share/qbs/modules/cpp/UnixGCC.qbs
@@ -31,8 +31,8 @@
import qbs.File
GenericGCC {
- condition: qbs.toolchain && qbs.toolchain.contains("gcc")
- && qbs.targetOS.contains("unix")
+ condition: qbs.toolchain && qbs.toolchain.includes("gcc")
+ && qbs.targetOS.includes("unix")
priority: -50
dynamicLibraryPrefix: "lib"
diff --git a/share/qbs/modules/cpp/android-gcc.qbs b/share/qbs/modules/cpp/android-gcc.qbs
index aded485cd..7c45d3c6b 100644
--- a/share/qbs/modules/cpp/android-gcc.qbs
+++ b/share/qbs/modules/cpp/android-gcc.qbs
@@ -39,7 +39,7 @@ 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: []
@@ -58,7 +58,7 @@ LinuxGCC {
return "i686";
}
}
- property string targetDir: "android" + (["armeabi", "armeabi-v7a"].contains(Android.ndk.abi) ? "eabi" : "")
+ 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);
@@ -155,7 +155,7 @@ LinuxGCC {
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"
diff --git a/share/qbs/modules/cpp/cosmic.qbs b/share/qbs/modules/cpp/cosmic.qbs
index 46c904ac5..8bf0f22a3 100644
--- a/share/qbs/modules/cpp/cosmic.qbs
+++ b/share/qbs/modules/cpp/cosmic.qbs
@@ -37,7 +37,7 @@ import "cosmic.js" as COSMIC
import "cpp.js" as Cpp
CppModule {
- condition: qbs.toolchain && qbs.toolchain.contains("cosmic")
+ condition: qbs.toolchain && qbs.toolchain.includes("cosmic")
Probes.BinaryProbe {
id: compilerPathProbe
diff --git a/share/qbs/modules/cpp/cpp.js b/share/qbs/modules/cpp/cpp.js
index b93d42f21..9f907580a 100644
--- a/share/qbs/modules/cpp/cpp.js
+++ b/share/qbs/modules/cpp/cpp.js
@@ -42,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];
@@ -134,7 +134,7 @@ function assemblerOutputArtifacts(input) {
}
function compilerOutputArtifacts(input, inputs) {
- var objTags = input.fileTags.contains("cpp_intermediate_object")
+ var objTags = input.fileTags.includes("cpp_intermediate_object")
? ["intermediate_obj"]
: ["obj"];
if (inputs) {
@@ -233,7 +233,7 @@ function collectLibraryDependencies(product) {
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");
+ && artifacts[0].fileTags.includes("dynamiclibrary_import");
for (var i = 0; i < artifactFilePaths.length; ++i) {
addFilePath(artifactFilePaths[i], wholeArchive,
artifactsAreImportLibs ? dep.name : undefined);
@@ -254,7 +254,7 @@ function collectLibraryDependencies(product) {
externalLibs.forEach(function(libName) {
var isObjectFile = objSuffix && libName.endsWith(objSuffix);
if (isObjectFile) {
- if (seenObjectFiles.contains(libName))
+ if (seenObjectFiles.includes(libName))
return;
seenObjectFiles.push(libName);
}
@@ -327,7 +327,10 @@ function collectIncludePaths(input) {
var includePaths = input.cpp.includePaths;
if (includePaths)
allIncludePaths = allIncludePaths.uniqueConcat(includePaths);
- return allIncludePaths;
+ var builtIns = input.cpp.compilerIncludePaths;
+ return allIncludePaths.filter(function(p) {
+ return !builtIns.includes(p);
+ });
}
function collectSystemIncludePaths(input) {
@@ -338,7 +341,10 @@ function collectSystemIncludePaths(input) {
var distributionIncludePaths = input.cpp.distributionIncludePaths;
if (distributionIncludePaths)
allIncludePaths = allIncludePaths.uniqueConcat(distributionIncludePaths);
- return allIncludePaths;
+ var builtIns = input.cpp.compilerIncludePaths;
+ return allIncludePaths.filter(function(p) {
+ return !builtIns.includes(p);
+ });
}
function collectPreincludePaths(input) {
diff --git a/share/qbs/modules/cpp/darwin.js b/share/qbs/modules/cpp/darwin.js
index e4f740dbe..0223c5ed3 100644
--- a/share/qbs/modules/cpp/darwin.js
+++ b/share/qbs/modules/cpp/darwin.js
@@ -73,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) {
@@ -137,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] : [];
}));
diff --git a/share/qbs/modules/cpp/dmc.js b/share/qbs/modules/cpp/dmc.js
index a398d6581..ea7cd7bb5 100644
--- a/share/qbs/modules/cpp/dmc.js
+++ b/share/qbs/modules/cpp/dmc.js
@@ -56,15 +56,15 @@ function targetFlags(platform, architecture, extender, consoleApp, type) {
var flags = [];
if (architecture === "x86_16") {
flags.push("-ml");
- if (type.contains("application") && !consoleApp)
+ if (type.includes("application") && !consoleApp)
flags.push("-WA");
- else if (type.contains("dynamiclibrary"))
+ else if (type.includes("dynamiclibrary"))
flags.push("-WD");
} else if (architecture === "x86") {
flags.push("-mn");
- if (type.contains("application"))
+ if (type.includes("application"))
flags.push("-WA");
- else if (type.contains("dynamiclibrary"))
+ else if (type.includes("dynamiclibrary"))
flags.push("-WD");
}
return flags;
@@ -350,12 +350,12 @@ function linkerFlags(project, product, inputs, outputs) {
}));
// Output.
- if (product.type.contains("application")) {
+ 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.contains("dynamiclibrary")) {
+ } 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");
diff --git a/share/qbs/modules/cpp/dmc.qbs b/share/qbs/modules/cpp/dmc.qbs
index db9e6b2fb..ac89550e8 100644
--- a/share/qbs/modules/cpp/dmc.qbs
+++ b/share/qbs/modules/cpp/dmc.qbs
@@ -38,7 +38,7 @@ import "dmc.js" as DMC
import "cpp.js" as Cpp
CppModule {
- condition: Host.os().contains("windows") && qbs.toolchain && qbs.toolchain.contains("dmc")
+ condition: Host.os().includes("windows") && qbs.toolchain && qbs.toolchain.includes("dmc")
Probes.BinaryProbe {
id: compilerPathProbe
diff --git a/share/qbs/modules/cpp/freebsd-gcc.qbs b/share/qbs/modules/cpp/freebsd-gcc.qbs
index fb6d45b37..e04ed7f2b 100644
--- a/share/qbs/modules/cpp/freebsd-gcc.qbs
+++ b/share/qbs/modules/cpp/freebsd-gcc.qbs
@@ -32,11 +32,11 @@ import "freebsd.js" as FreeBSD
import qbs.Host
UnixGCC {
- condition: 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" + (Host.os().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 25fe06861..90f8fc933 100644
--- a/share/qbs/modules/cpp/gcc.js
+++ b/share/qbs/modules/cpp/gcc.js
@@ -78,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"
@@ -170,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) {
@@ -193,6 +196,7 @@ function collectLibraryDependencies(product, isDarwin) {
publicDeps[dep.name] = true;
} else {
addArtifactFilePaths(dep, tagForLinkingAgainstSharedLib, addPrivateFilePath);
+ privateDeps[dep.name] = true;
}
}
}
@@ -204,7 +208,6 @@ function collectLibraryDependencies(product, isDarwin) {
product.dependencies.forEach(traverseDirectDependency);
addExternalLibs(product);
- var seenRPathLinkDirs = {};
var result = { libraries: [], rpath_link: [] };
objects.forEach(
function (obj) {
@@ -215,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;
@@ -230,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
@@ -247,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.");
@@ -262,7 +262,7 @@ function escapeLinkerFlags(product, inputs, linkerFlags) {
}
function linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPath) {
- 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
@@ -356,11 +356,11 @@ function linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPat
}
function isNotSystemRunPath(p) {
- return !FileInfo.isAbsolutePath(p) || (!systemRunPaths.contains(p)
- && !canonicalSystemRunPaths.contains(File.canonicalFilePath(p)));
+ return !FileInfo.isAbsolutePath(p) || (!systemRunPaths.includes(p)
+ && !canonicalSystemRunPaths.includes(File.canonicalFilePath(p)));
};
- if (!product.qbs.targetOS.contains("windows")) {
+ if (!product.qbs.targetOS.includes("windows")) {
for (i in rpaths) {
if (isNotSystemRunPath(rpaths[i]))
escapableLinkerFlags.push("-rpath", fixupRPath(rpaths[i]));
@@ -370,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];
@@ -398,13 +401,13 @@ 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 = Cpp.collectLibraryPaths(product);
- if (systemRunPaths.length > 0)
- allLibraryPaths = allLibraryPaths.filter(isNotSystemRunPath);
+ 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));
@@ -472,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)
@@ -530,7 +536,7 @@ function linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPat
Array.prototype.push.apply(escapedLinkerFlags, args);
if (useCompilerDriver)
escapedLinkerFlags = escapedLinkerFlags.concat(Cpp.collectMiscLinkerArguments(product));
- if (product.qbs.toolchain.contains("mingw") && product.cpp.runtimeLibrary === "static")
+ if (product.qbs.toolchain.includes("mingw") && product.cpp.runtimeLibrary === "static")
escapedLinkerFlags = ['-static-libgcc', '-static-libstdc++'].concat(escapedLinkerFlags);
return escapedLinkerFlags;
}
@@ -577,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)];
}
@@ -585,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) {
@@ -593,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)
@@ -601,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' : '')];
@@ -749,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.
@@ -771,7 +777,7 @@ function compilerFlags(project, product, input, output, explicitlyDependsOn) {
// 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,
@@ -804,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));
@@ -817,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");
}
}
@@ -846,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')
@@ -862,7 +868,7 @@ function compilerFlags(project, product, input, output, explicitlyDependsOn) {
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)) {
@@ -875,7 +881,7 @@ function compilerFlags(project, product, input, output, explicitlyDependsOn) {
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;
@@ -887,7 +893,7 @@ function compilerFlags(project, product, input, output, explicitlyDependsOn) {
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' ];
@@ -921,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);
}
}
@@ -936,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");
}
@@ -987,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"];
@@ -999,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",
@@ -1018,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))
@@ -1028,7 +1034,7 @@ function linkerEnvVars(config, inputs)
function setResponseFileThreshold(command, product)
{
- if (product.qbs.targetOS.contains("windows") && Host.os().contains("windows"))
+ if (product.qbs.targetOS.includes("windows") && Host.os().includes("windows"))
command.responseFileThreshold = 10000;
}
@@ -1036,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;
@@ -1126,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 '"
@@ -1338,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,
@@ -1358,7 +1364,7 @@ function prepareLinker(project, product, inputs, outputs, input, output) {
setResponseFileThreshold(cmd, product);
commands.push(cmd);
- if (product.qbs.targetOS.contains("darwin")) {
+ if (product.qbs.targetOS.includes("darwin")) {
if (!product.aggregate) {
commands = commands.concat(separateDebugInfoCommandsDarwin(
product, outputs, [primaryOutput]));
@@ -1492,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 {
@@ -1520,9 +1526,9 @@ function targetLinkerFlags(targetArch, targetOS) {
"x86_64": "elf_x86_64",
}
};
- if (targetOS.contains("windows"))
+ if (targetOS.includes("windows"))
return linkerFlags["windows"][targetArch];
- else if (targetOS.contains("freebsd"))
+ else if (targetOS.includes("freebsd"))
return linkerFlags["freebsd"][targetArch];
return linkerFlags["other"][targetArch];
}
diff --git a/share/qbs/modules/cpp/iar.js b/share/qbs/modules/cpp/iar.js
index d5f019cbc..ed58ac262 100644
--- a/share/qbs/modules/cpp/iar.js
+++ b/share/qbs/modules/cpp/iar.js
@@ -450,6 +450,7 @@ function dumpMacros(compilerFilePath, tag) {
args.push(cppLanguageOption(compilerFilePath));
var p = new Process();
+ p.setWorkingDirectory(tempDir.path());
p.exec(compilerFilePath, args, true);
var outFile = new TextFile(outFilePath, TextFile.ReadOnly);
return Cpp.extractMacros(outFile.readAll());
@@ -471,6 +472,7 @@ function dumpCompilerIncludePaths(compilerFilePath, tag) {
var includePaths = [];
var p = new Process();
+ 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);
diff --git a/share/qbs/modules/cpp/iar.qbs b/share/qbs/modules/cpp/iar.qbs
index f02c033ce..558635ef5 100644
--- a/share/qbs/modules/cpp/iar.qbs
+++ b/share/qbs/modules/cpp/iar.qbs
@@ -37,7 +37,7 @@ 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
diff --git a/share/qbs/modules/cpp/ios-gcc.qbs b/share/qbs/modules/cpp/ios-gcc.qbs
index 92e072a0a..968b873da 100644
--- a/share/qbs/modules/cpp/ios-gcc.qbs
+++ b/share/qbs/modules/cpp/ios-gcc.qbs
@@ -37,8 +37,8 @@ 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")
@@ -51,10 +51,10 @@ DarwinGCC {
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"
@@ -69,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.qbs b/share/qbs/modules/cpp/keil.qbs
index edee1697b..5922ad4e2 100644
--- a/share/qbs/modules/cpp/keil.qbs
+++ b/share/qbs/modules/cpp/keil.qbs
@@ -36,7 +36,7 @@ import "cpp.js" as Cpp
import "keil.js" as KEIL
CppModule {
- condition: Host.os().contains("windows") && qbs.toolchain && qbs.toolchain.contains("keil")
+ condition: Host.os().includes("windows") && qbs.toolchain && qbs.toolchain.includes("keil")
Probes.BinaryProbe {
id: compilerPathProbe
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 1b70904c0..1700c21b3 100644
--- a/share/qbs/modules/cpp/msvc.js
+++ b/share/qbs/modules/cpp/msvc.js
@@ -79,8 +79,8 @@ 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)
@@ -92,24 +92,24 @@ function hasZCplusPlusOption(input)
// 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 Utilities.versionCompare(input.cpp.compilerVersion, "19.14.26433") >= 0
- || (input.qbs.toolchain.contains("clang-cl") && input.cpp.compilerVersionMajor >= 9);
+ return (input.qbs.toolchain.includes("clang-cl") && input.cpp.compilerVersionMajor >= 9)
+ || Utilities.versionCompare(input.cpp.compilerVersion, "19.14.26433") >= 0;
}
function hasCxx20Option(input)
{
- return Utilities.versionCompare(input.cpp.compilerVersion, "19.29.30133.0") >= 0
- || (input.qbs.toolchain.contains("clang-cl") && input.cpp.compilerVersionMajor >= 13);
+ 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 Utilities.versionCompare(input.cpp.compilerVersion, "19.29.30138.0") >= 0
- || (input.qbs.toolchain.contains("clang-cl") && input.cpp.compilerVersionMajor >= 13);
+ 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.contains("clang-cl"))
+ 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:
@@ -124,10 +124,9 @@ function addCxxLanguageVersionFlag(input, args) {
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;
@@ -164,7 +163,7 @@ function addCLanguageVersionFlag(input, args) {
}
function handleClangClArchitectureFlags(product, architecture, flags) {
- if (product.qbs.toolchain.contains("clang-cl")) {
+ if (product.qbs.toolchain.includes("clang-cl")) {
if (architecture === "x86")
flags.push("-m32");
else if (architecture === "x86_64")
@@ -181,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;
@@ -250,14 +249,17 @@ function prepareCompiler(project, product, inputs, outputs, input, output, expli
return input.cpp.includeFlag + FileInfo.toWindowsSeparators(path);
}));
- var includeFlag = input.cpp.includeFlag;
- 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 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) {
@@ -313,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
@@ -371,7 +373,8 @@ function prepareCompiler(project, product, inputs, outputs, input, output, expli
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) {
@@ -387,16 +390,16 @@ 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"],
+ var moduleDefinitionInputs = Array.prototype.map.call(inputs["def"] || [],
function (a) {
return a.filePath;
});
var generateManifestFiles = !linkDLL && product.cpp.generateManifestFile;
- var useClangCl = product.qbs.toolchain.contains("clang-cl");
+ var useClangCl = product.qbs.toolchain.includes("clang-cl");
var canEmbedManifest = useClangCl || product.cpp.compilerVersionMajor >= 17 // VS 2012
var linkerPath = effectiveLinkerPath(product, inputs);
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 928ded5cf..49da8a715 100644
--- a/share/qbs/modules/cpp/sdcc.js
+++ b/share/qbs/modules/cpp/sdcc.js
@@ -396,7 +396,7 @@ function buildLinkerMapFilePath(target, suffix) {
// 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().contains("windows");
+ var isWindows = Host.os().includes("windows");
if (isWindows && input.cpp.debugInformation) {
var cmd = new JavaScriptCommand();
cmd.objectPath = outputs.obj[0].filePath;
@@ -461,10 +461,9 @@ function renameLinkerMapFile(project, product, inputs, outputs, input, output) {
// remove a listing files only after the linking completes.
function removeCompilerListingFiles(project, product, inputs, outputs, input, output) {
var cmd = new JavaScriptCommand();
- cmd.objects = inputs.obj.map(function(a) { return a; });
cmd.silent = true;
cmd.sourceCode = function() {
- objects.forEach(function(object) {
+ inputs.obj.forEach(function(object) {
if (!object.filePath.endsWith(".c" + object.cpp.objectSuffix))
return; // Skip the assembler generated objects.
if (!object.cpp.generateCompilerListingFiles
diff --git a/share/qbs/modules/cpp/sdcc.qbs b/share/qbs/modules/cpp/sdcc.qbs
index 4e6f05bc0..24cb6d738 100644
--- a/share/qbs/modules/cpp/sdcc.qbs
+++ b/share/qbs/modules/cpp/sdcc.qbs
@@ -35,7 +35,7 @@ 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
diff --git a/share/qbs/modules/cpp/setuprunenv.js b/share/qbs/modules/cpp/setuprunenv.js
index df034e72a..2ea331a30 100644
--- a/share/qbs/modules/cpp/setuprunenv.js
+++ b/share/qbs/modules/cpp/setuprunenv.js
@@ -35,7 +35,7 @@ var ModUtils = require("qbs.ModUtils"); // TODO: append/prepend functionality sh
function addNewElement(list, elem)
{
- if (!list.contains(elem))
+ if (!list.includes(elem))
list.push(elem);
}
@@ -49,7 +49,7 @@ function artifactDir(artifact)
function addExternalLibPath(product, list, path)
{
addNewElement(list, path);
- if (Host.os().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);
@@ -58,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);
@@ -106,7 +106,7 @@ function gatherPaths(product, libPaths, frameworkPaths, seenProducts)
function setupRunEnvironment(product, config)
{
- if (config.contains("ignore-lib-dependencies"))
+ if (config.includes("ignore-lib-dependencies"))
return;
if (Host.platform() !== product.qbs.targetPlatform)
@@ -120,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);
@@ -129,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, FileInfo.pathListSeparator(),
- Host.os().contains("windows"));
+ 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
index 005780c7d..9ae893db9 100644
--- a/share/qbs/modules/cpp/watcom.js
+++ b/share/qbs/modules/cpp/watcom.js
@@ -81,11 +81,11 @@ function targetFlag(platform, architecture, type) {
return "-bos2v2";
} else if (platform === "windows") {
if (architecture === "x86_16") {
- if (type.contains("dynamiclibrary"))
+ if (type.includes("dynamiclibrary"))
return "-bwindows_dll";
return "-bwindows";
} else if (architecture === "x86") {
- if (type.contains("dynamiclibrary"))
+ if (type.includes("dynamiclibrary"))
return "-bnt_dll";
return "-bnt";
}
@@ -130,9 +130,9 @@ function guessEnvironment(hostOs, platform, architecture,
setVariable("WATCOM", [toolchainRootPath], undefined, pathListSeparator);
setVariable("EDPATH", ["eddat"], toolchainRootPath, pathListSeparator);
- if (hostOs.contains("linux"))
+ if (hostOs.includes("linux"))
setVariable("PATH", ["binl64", "binl"], toolchainRootPath, pathListSeparator);
- else if (hostOs.contains("windows"))
+ else if (hostOs.includes("windows"))
setVariable("PATH", ["binnt64", "binnt"], toolchainRootPath, pathListSeparator);
if (platform === "linux") {
@@ -311,12 +311,12 @@ function compilerFlags(project, product, input, outputs, explicitlyDependsOn) {
product.type);
args.push(target);
- if (product.type.contains("application")) {
+ if (product.type.includes("application")) {
if (product.qbs.targetPlatform === "windows") {
var consoleApplication = product.consoleApplication;
args.push(consoleApplication ? "-mconsole" : "-mwindows");
}
- } else if (product.type.contains("dynamiclibrary")) {
+ } else if (product.type.includes("dynamiclibrary")) {
args.push("-shared");
}
@@ -423,11 +423,11 @@ function linkerFlags(project, product, inputs, outputs) {
product.type);
args.push(target);
- if (product.type.contains("application")) {
+ 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.contains("dynamiclibrary")) {
+ } else if (product.type.includes("dynamiclibrary")) {
if (product.qbs.targetPlatform === "windows") {
args.push("-Wl, option implib=" + FileInfo.toNativeSeparators(
outputs.dynamiclibrary_import[0].filePath));
diff --git a/share/qbs/modules/cpp/watcom.qbs b/share/qbs/modules/cpp/watcom.qbs
index eed63692c..84157b67b 100644
--- a/share/qbs/modules/cpp/watcom.qbs
+++ b/share/qbs/modules/cpp/watcom.qbs
@@ -37,7 +37,7 @@ import "cpp.js" as Cpp
import "watcom.js" as WATCOM
CppModule {
- condition: qbs.toolchain && qbs.toolchain.contains("watcom")
+ condition: qbs.toolchain && qbs.toolchain.includes("watcom")
Probes.BinaryProbe {
id: compilerPathProbe
@@ -170,7 +170,7 @@ CppModule {
Rule {
id: dynamicLibraryLinker
- condition: qbs.targetOS.contains("windows")
+ condition: qbs.targetOS.includes("windows")
multiplex: true
inputs: ["obj", "res"]
inputsFromDependencies: ["staticlibrary", "dynamiclibrary_import"]
diff --git a/share/qbs/modules/cpp/windows-clang-cl.qbs b/share/qbs/modules/cpp/windows-clang-cl.qbs
index cc58097f6..9aa9d7395 100644
--- a/share/qbs/modules/cpp/windows-clang-cl.qbs
+++ b/share/qbs/modules/cpp/windows-clang-cl.qbs
@@ -35,9 +35,9 @@ import qbs.FileInfo
import 'windows-msvc-base.qbs' as MsvcBaseModule
MsvcBaseModule {
- condition: Host.os().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.ClangClBinaryProbe {
@@ -85,14 +85,17 @@ MsvcBaseModule {
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 b5bac0572..cfe6f2745 100644
--- a/share/qbs/modules/cpp/windows-clang-mingw.qbs
+++ b/share/qbs/modules/cpp/windows-clang-mingw.qbs
@@ -38,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
@@ -69,7 +69,7 @@ MingwBaseModule {
"llvm-rc" + compilerExtension)
setupBuildEnvironment: {
- if (Host.os().contains("windows") && product.qbs.sysroot) {
+ 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();
@@ -77,7 +77,7 @@ MingwBaseModule {
}
setupRunEnvironment: {
- if (Host.os().contains("windows") && product.qbs.sysroot) {
+ 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();
diff --git a/share/qbs/modules/cpp/windows-mingw.qbs b/share/qbs/modules/cpp/windows-mingw.qbs
index 4c20eda5f..9ba4258c5 100644
--- a/share/qbs/modules/cpp/windows-mingw.qbs
+++ b/share/qbs/modules/cpp/windows-mingw.qbs
@@ -37,8 +37,8 @@ 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
diff --git a/share/qbs/modules/cpp/windows-msvc-base.qbs b/share/qbs/modules/cpp/windows-msvc-base.qbs
index d188d53f3..9613800e5 100644
--- a/share/qbs/modules/cpp/windows-msvc-base.qbs
+++ b/share/qbs/modules/cpp/windows-msvc-base.qbs
@@ -95,7 +95,7 @@ CppModule {
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"])
@@ -320,12 +320,11 @@ CppModule {
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(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 a57c4cc5a..c30cec239 100644
--- a/share/qbs/modules/cpp/windows-msvc.qbs
+++ b/share/qbs/modules/cpp/windows-msvc.qbs
@@ -34,9 +34,9 @@ import qbs.Probes
import "windows-msvc-base.qbs" as MsvcBaseModule
MsvcBaseModule {
- condition: Host.os().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.ClBinaryProbe {
diff --git a/share/qbs/modules/dmg/DMGModule.qbs b/share/qbs/modules/dmg/DMGModule.qbs
index f069cb5dc..27a945033 100644
--- a/share/qbs/modules/dmg/DMGModule.qbs
+++ b/share/qbs/modules/dmg/DMGModule.qbs
@@ -34,13 +34,14 @@ 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: Host.os().contains("darwin") && qbs.targetOS.contains("darwin")
+ condition: Host.os().includes("darwin") && qbs.targetOS.includes("darwin")
property string volumeName: product.targetName
PropertyOptions {
@@ -73,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
index c892a2615..60722c674 100644
--- a/share/qbs/modules/freedesktop/FreeDesktop.qbs
+++ b/share/qbs/modules/freedesktop/FreeDesktop.qbs
@@ -33,22 +33,21 @@ import qbs.TextFile
import "freedesktop.js" as Fdo
Module {
- id: fdoModule
-
property string name: product.name
+ property string appName: name
property var desktopKeys
readonly property var defaultDesktopKeys: {
return {
'Type': 'Application',
- 'Name': product.freedesktop.name,
+ 'Name': product.freedesktop.appName,
'Exec': product.targetName,
'Terminal': 'false',
'Version': '1.1',
}
}
- property bool _fdoSupported: qbs.targetOS.contains("unix") && !qbs.targetOS.contains("darwin")
+ property bool _fdoSupported: qbs.targetOS.includes("unix") && !qbs.targetOS.includes("darwin")
additionalProductTypes: "freedesktop.desktopfile"
@@ -96,14 +95,14 @@ Module {
}
Group {
- condition: fdoModule._fdoSupported
+ condition: product.freedesktop._fdoSupported
fileTagsFilter: [ "freedesktop.desktopfile" ]
qbs.install: true
qbs.installDir: "share/applications"
}
Group {
- condition: fdoModule._fdoSupported
+ condition: product.freedesktop._fdoSupported
fileTagsFilter: [ "freedesktop.appIcon" ]
qbs.install: true
qbs.installDir: "share/icons/hicolor/scalable/apps"
@@ -115,7 +114,7 @@ Module {
}
Group {
- condition: fdoModule._fdoSupported
+ condition: product.freedesktop._fdoSupported
fileTagsFilter: [ "freedesktop.appstream" ]
qbs.install: true
qbs.installDir: "share/metainfo"
diff --git a/share/qbs/modules/ib/IBModule.qbs b/share/qbs/modules/ib/IBModule.qbs
index 4ff8abea2..e6183e20c 100644
--- a/share/qbs/modules/ib/IBModule.qbs
+++ b/share/qbs/modules/ib/IBModule.qbs
@@ -50,7 +50,7 @@ Module {
}
}
- condition: Host.os().contains("darwin") && qbs.targetOS.contains("darwin")
+ condition: Host.os().includes("darwin") && qbs.targetOS.includes("darwin")
property bool warnings: true
property bool errors: true
@@ -196,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 ebb615e8e..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].");
@@ -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 a61d585ab..dc96eedf3 100644
--- a/share/qbs/modules/ico/ico.js
+++ b/share/qbs/modules/ico/ico.js
@@ -40,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 930d85a9a..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
diff --git a/share/qbs/modules/java/JavaModule.qbs b/share/qbs/modules/java/JavaModule.qbs
index d4d7c4492..343b2f4ba 100644
--- a/share/qbs/modules/java/JavaModule.qbs
+++ b/share/qbs/modules/java/JavaModule.qbs
@@ -123,10 +123,10 @@ Module {
} else {
paths.push(FileInfo.joinPaths(jdkPath, "include"));
- var hostOS = Host.os().contains("windows") ? Host.os().concat(["win32"]) : Host.os();
+ 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;
@@ -141,7 +141,7 @@ Module {
property path classFilesDir: FileInfo.joinPaths(product.buildDirectory, "classes")
property path internalClassFilesDir: FileInfo.joinPaths(product.buildDirectory, ".classes")
- property bool isAppleJava: Host.os().contains("darwin")
+ property bool isAppleJava: Host.os().includes("darwin")
&& (compilerVersionMajor < 1
|| (compilerVersionMajor === 1 && compilerVersionMinor < 7))
diff --git a/share/qbs/modules/java/utils.js b/share/qbs/modules/java/utils.js
index 8fb9661fa..a59b8d41d 100644
--- a/share/qbs/modules/java/utils.js
+++ b/share/qbs/modules/java/utils.js
@@ -79,7 +79,7 @@ function findJdkPath(hostOS, arch, environmentPaths, searchPaths) {
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.
@@ -94,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) {
@@ -246,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;
diff --git a/share/qbs/modules/nodejs/NodeJS.qbs b/share/qbs/modules/nodejs/NodeJS.qbs
index db10fb36f..412f9b8bb 100644
--- a/share/qbs/modules/nodejs/NodeJS.qbs
+++ b/share/qbs/modules/nodejs/NodeJS.qbs
@@ -85,13 +85,13 @@ Module {
"tmp", "nodejs.intermediate")
setupBuildEnvironment: {
- var v = new ModUtils.EnvironmentVariable("PATH", FileInfo.pathListSeparator(), Host.os().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", FileInfo.pathListSeparator(), Host.os().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();
}
@@ -119,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 cf8626949..11a5670b5 100644
--- a/share/qbs/modules/nsis/NSISModule.qbs
+++ b/share/qbs/modules/nsis/NSISModule.qbs
@@ -35,7 +35,7 @@ import qbs.ModUtils
import qbs.Utilities
Module {
- condition: qbs.targetOS.contains("windows")
+ condition: qbs.targetOS.includes("windows")
property path toolchainInstallPath: Utilities.getNativeSetting(registryKey)
@@ -90,7 +90,7 @@ Module {
// Private properties
property string registryKey: {
- if (!Host.os().contains("windows"))
+ if (!Host.os().includes("windows"))
return undefined;
var keys = [ "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\NSIS" ];
@@ -105,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);
@@ -159,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 b436263e9..901e7e02e 100644
--- a/share/qbs/modules/pkgconfig/pkgconfig.qbs
+++ b/share/qbs/modules/pkgconfig/pkgconfig.qbs
@@ -47,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 f377c63cf..bd4a08557 100644
--- a/share/qbs/modules/protobuf/cpp/protobufcpp.qbs
+++ b/share/qbs/modules/protobuf/cpp/protobufcpp.qbs
@@ -6,39 +6,29 @@ 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 bool useGrpc: false
property bool _linkLibraries: true
readonly property bool _hasModules: protobuflib.present && (!useGrpc || grpcpp.present)
- property string grpcIncludePath: grpcIncludeProbe.found ? grpcIncludeProbe.path : undefined
- property string grpcLibraryPath: grpcLibraryProbe.found ? grpcLibraryProbe.path : undefined
+ property string _cxxLanguageVersion: "c++17"
- readonly property string _libraryName: {
- var libraryName;
- if (libraryProbe.found) {
- libraryName = FileInfo.baseName(libraryProbe.fileName);
- if (libraryName.startsWith("lib"))
- libraryName = libraryName.substring(3);
- }
- return libraryName;
- }
+ _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;
- enableFallback: false
+ required: false
}
Depends {
- name: "grpcpp";
+ name: "grpc++";
+ id: grpcpp
condition: _linkLibraries && useGrpc;
- required: false;
- enableFallback: false
+ required: false
}
property path grpcPluginPath: grpcPluginProbe.filePath
@@ -47,43 +37,10 @@ ProtobufBase {
condition: useGrpc
id: grpcPluginProbe
names: "grpc_cpp_plugin"
+ searchPaths: _grpcSearchPaths
}
- cpp.libraryPaths: {
- if (!_linkLibraries || _hasModules)
- return [];
-
- var result = [];
- if (libraryProbe.found)
- result.push(libraryProbe.path);
- if (useGrpc && grpcLibraryProbe.found)
- result.push(grpcLibraryPath);
- return result;
- }
- cpp.dynamicLibraries: {
- if (!_linkLibraries || _hasModules)
- return [];
-
- var result = [];
- if (_libraryName)
- result.push(_libraryName)
- if (qbs.targetOS.contains("unix"))
- result.push("pthread");
- if (useGrpc)
- result.push("grpc++");
- return result;
- }
- cpp.includePaths: {
- if (!_linkLibraries || _hasModules)
- return [outputDir];
-
- var result = [outputDir];
- if (includeProbe.found)
- result.push(includePath);
- if (useGrpc && grpcIncludeProbe.found)
- result.push(grpcIncludePath);
- return result;
- }
+ cpp.cxxLanguageVersion: _cxxLanguageVersion
Rule {
inputs: ["protobuf.input", "protobuf.grpc"]
@@ -95,7 +52,7 @@ ProtobufBase {
".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(outputDir, input, ["hpp", "protobuf.hpp"],
".grpc.pb.h"),
@@ -108,7 +65,7 @@ ProtobufBase {
prepare: {
var result = HelperFunctions.doPrepare(
input.protobuf.cpp, product, input, outputs, "cpp");
- if (input.fileTags.contains("protobuf.grpc")) {
+ 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));
@@ -117,56 +74,16 @@ ProtobufBase {
}
}
- Probes.IncludeProbe {
- id: includeProbe
- names: "google/protobuf/message.h"
- platformSearchPaths: includePath ? [] : base
- searchPaths: includePath ? [includePath] : []
- }
-
- Probes.LibraryProbe {
- id: libraryProbe
- names: [
- "protobuf",
- "protobufd",
- ]
- platformSearchPaths: libraryPath ? [] : base
- searchPaths: libraryPath ? [libraryPath] : []
- }
-
- Probes.IncludeProbe {
- id: grpcIncludeProbe
- pathSuffixes: "grpc++"
- names: "grpc++.h"
- platformSearchPaths: grpcIncludePath ? [] : base
- searchPaths: grpcIncludePath ? [grpcIncludePath] : []
- }
-
- Probes.LibraryProbe {
- id: grpcLibraryProbe
- names: "grpc++"
- platformSearchPaths: grpcLibraryPath ? [] : base
- searchPaths: grpcLibraryPath ? [grpcLibraryPath] : []
- }
-
validate: {
HelperFunctions.validateCompiler(compilerName, compilerPath);
- if (_hasModules)
- return;
-
- if (_linkLibraries && !includeProbe.found)
- throw "Can't find cpp protobuf include files. Please set the includePath property.";
- if (_linkLibraries && !libraryProbe.found)
- throw "Can't find cpp protobuf library. Please set the libraryPath property.";
+ if (_linkLibraries && ! _hasModules) {
+ throw "Can't find cpp protobuf runtime. Make sure .pc files are present";
+ }
if (useGrpc) {
if (!File.exists(grpcPluginPath))
throw "Can't find grpc_cpp_plugin plugin. Please set the grpcPluginPath property.";
- if (_linkLibraries && !grpcIncludeProbe.found)
- throw "Can't find grpc++ include files. Please set the grpcIncludePath property.";
- if (_linkLibraries && !grpcLibraryProbe.found)
- throw "Can't find grpc++ library. Please set the grpcLibraryPath property.";
}
}
}
diff --git a/share/qbs/modules/protobuf/nanopb/nanopb.qbs b/share/qbs/modules/protobuf/nanopb/nanopb.qbs
index 898e230b6..ada7c20bb 100644
--- a/share/qbs/modules/protobuf/nanopb/nanopb.qbs
+++ b/share/qbs/modules/protobuf/nanopb/nanopb.qbs
@@ -41,6 +41,7 @@ ProtobufBase {
result.push(includePath);
return result;
}
+ cpp.cxxLanguageVersion: qbs.targetOS.contains("darwin") ? ["c++17"] : ["c++11"]
Rule {
inputs: ["protobuf.input"]
diff --git a/share/qbs/modules/protobuf/protobufbase.qbs b/share/qbs/modules/protobuf/protobufbase.qbs
index e302d3758..e32ee30b9 100644
--- a/share/qbs/modules/protobuf/protobufbase.qbs
+++ b/share/qbs/modules/protobuf/protobufbase.qbs
@@ -6,6 +6,7 @@ import "protobuf.js" as HelperFunctions
Module {
property string compilerName: "protoc"
property string compilerPath: compilerProbe.filePath
+ property var _searchPaths
property pathList importPaths: []
@@ -19,5 +20,6 @@ Module {
Probes.BinaryProbe {
id: compilerProbe
names: [compilerName]
+ searchPaths: _searchPaths
}
}
diff --git a/share/qbs/modules/qbs/common.qbs b/share/qbs/modules/qbs/common.qbs
index 8ddfc582d..8b31092a9 100644
--- a/share/qbs/modules/qbs/common.qbs
+++ b/share/qbs/modules/qbs/common.qbs
@@ -53,10 +53,10 @@ Module {
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;
}
@@ -64,10 +64,10 @@ Module {
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");
}
}
@@ -79,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";
@@ -102,7 +102,7 @@ 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 {
@@ -122,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 " +
@@ -143,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)
@@ -169,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;
@@ -182,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 f329db18c..899b72441 100644
--- a/share/qbs/modules/qnx/qnx.qbs
+++ b/share/qbs/modules/qnx/qnx.qbs
@@ -40,7 +40,7 @@ Module {
Probes.PathProbe {
id: qnxSdkProbe
names: ["qnx700", "qnx660", "qnx650"]
- searchPaths: Host.os().contains("windows")
+ searchPaths: Host.os().includes("windows")
? [Environment.getEnv("USERPROFILE"), Environment.getEnv("SystemDrive")]
: [Environment.getEnv("HOME"), "/opt"]
}
@@ -78,11 +78,11 @@ Module {
property string hostArch: qnx7 ? "x86_64" : "x86"
property string hostOs: {
- if (Host.os().contains("linux"))
+ if (Host.os().includes("linux"))
return "linux";
- if (Host.os().contains("macos"))
+ if (Host.os().includes("macos"))
return "darwin";
- if (Host.os().contains("windows"))
+ if (Host.os().includes("windows"))
return qnx7 ? "win64" : "win32";
}
diff --git a/share/qbs/modules/typescript/typescript.js b/share/qbs/modules/typescript/typescript.js
index 7b2cf98df..199f486cf 100644
--- a/share/qbs/modules/typescript/typescript.js
+++ b/share/qbs/modules/typescript/typescript.js
@@ -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 31bdac51f..077f259f4 100644
--- a/share/qbs/modules/wix/WiXModule.qbs
+++ b/share/qbs/modules/wix/WiXModule.qbs
@@ -36,7 +36,7 @@ import qbs.Probes
import qbs.Utilities
Module {
- condition: qbs.targetOS.contains("windows")
+ condition: qbs.targetOS.includes("windows")
Probes.WiXProbe {
id: wixProbe
@@ -113,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: Host.os().contains("windows")
+ property bool enablePackageValidation: Host.os().includes("windows")
property string executableSuffix: ".exe"
property string windowsInstallerSuffix: ".msi"
@@ -227,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')));
@@ -335,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,
@@ -350,7 +350,7 @@ Module {
});
}
- if (product.type.contains("msi")) {
+ if (product.type.includes("msi")) {
artifacts.push({
fileTags: ["msi"],
filePath: FileInfo.joinPaths(product.destinationDirectory,
@@ -376,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 + "'");
@@ -427,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 c6c77ca73..726974579 100644
--- a/share/qbs/modules/xcode/xcode.js
+++ b/share/qbs/modules/xcode/xcode.js
@@ -112,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");
@@ -205,27 +205,38 @@ function boolFromSdkOrPlatform(varName, sdkProps, platformProps, defaultValue) {
function archsSpecsPath(version, targetOS, platformType, platformPath, devicePlatformPath,
developerPath) {
if (Utilities.versionCompare(version, "13.3") >= 0) {
- var baseDir = FileInfo.joinPaths(developerPath, "..",
- "PlugIns/XCBSpecifications.ideplugin/Contents/Resources");
- var baseName = targetOS.contains("macos") ? "MacOSX Architectures"
- : targetOS.contains("ios-simulator") ? "iOS Simulator"
- : targetOS.contains("ios") ? "iOS Device"
- : targetOS.contains("tvos-simulator") ? "tvOS Simulator"
- : targetOS.contains("tvos") ? "tvOS Device"
- : targetOS.contains("watchos-simulator") ? "watchOS Simulator" : "watchOS Device";
+ 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.contains("macos"))
+ 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";
}
@@ -236,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 1975f04b7..2c0cd001a 100644
--- a/share/qbs/modules/xcode/xcode.qbs
+++ b/share/qbs/modules/xcode/xcode.qbs
@@ -9,25 +9,23 @@ import qbs.PropertyList
import qbs.Utilities
Module {
- id: xcodeModule
-
Probes.XcodeLocationProbe {
id: xcodeLocationProbe
- condition: !xcodeModule.developerPath
+ 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
@@ -134,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];
@@ -141,7 +140,7 @@ 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;
}
diff --git a/share/share.qbs b/share/share.qbs
index 97af30396..75e1e83ba 100644
--- a/share/share.qbs
+++ b/share/share.qbs
@@ -18,22 +18,13 @@ Product {
}
Group {
- name: "Python executables"
- files: ["../src/3rdparty/python/bin/dmgbuild"]
- fileTags: ["qbs resources"]
- qbs.install: true
- qbs.installDir: qbsbuildconfig.libexecInstallDir
- qbs.installSourceBase: "../src/3rdparty/python/bin"
- }
-
- Group {
name: "Python packages"
prefix: "../src/3rdparty/python/**/"
files: ["*.py"]
fileTags: ["qbs resources"]
qbs.install: true
qbs.installDir: qbsbuildconfig.resourcesInstallDir + "/share/qbs/python"
- qbs.installSourceBase: "../src/3rdparty/python/lib/python2.7/site-packages"
+ qbs.installSourceBase: "../src/3rdparty/python/lib/python3.9/site-packages"
}
Group {