aboutsummaryrefslogtreecommitdiffstats
path: root/share/qbs/module-providers
diff options
context:
space:
mode:
Diffstat (limited to 'share/qbs/module-providers')
-rw-r--r--share/qbs/module-providers/Qt/provider.qbs10
-rw-r--r--share/qbs/module-providers/Qt/setup-qt.js1438
-rw-r--r--share/qbs/module-providers/Qt/templates/QtModule.qbs86
-rw-r--r--share/qbs/module-providers/Qt/templates/QtPlugin.qbs51
-rw-r--r--share/qbs/module-providers/Qt/templates/android_support.qbs2
-rw-r--r--share/qbs/module-providers/Qt/templates/core.qbs18
-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
18 files changed, 501 insertions, 1638 deletions
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 08fc8b999..9a314822b 100644
--- a/share/qbs/module-providers/Qt/setup-qt.js
+++ b/share/qbs/module-providers/Qt/setup-qt.js
@@ -37,1243 +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.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 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 = [];
@@ -1335,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";
}
@@ -1391,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";
}
@@ -1416,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) {
@@ -1447,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),
@@ -1464,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 = "";
@@ -1527,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"
@@ -1546,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;
}
@@ -1557,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);
@@ -1579,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";
@@ -1647,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/QtModule.qbs b/share/qbs/module-providers/Qt/templates/QtModule.qbs
deleted file mode 100644
index 62e05327b..000000000
--- a/share/qbs/module-providers/Qt/templates/QtModule.qbs
+++ /dev/null
@@ -1,86 +0,0 @@
-import qbs.FileInfo
-
-Module {
- condition: (qbs.targetPlatform === targetPlatform || isCombinedUIKitBuild)
- && (!qbs.architecture
- || architectures.length === 0
- || architectures.contains(qbs.architecture))
-
- readonly property bool isCombinedUIKitBuild: ["ios", "tvos", "watchos"].contains(targetPlatform)
- && ["x86", "x86_64"].contains(qbs.architecture)
- && qbs.targetPlatform === targetPlatform + "-simulator"
-
- Depends { name: "cpp" }
- Depends { name: "Qt.core" }
-
- Depends { name: "Qt.plugin_support" }
- property stringList pluginTypes
- Qt.plugin_support.pluginTypes: pluginTypes
- Depends {
- condition: Qt.core.staticBuild && !isPlugin
- name: "Qt";
- submodules: {
- // 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.
- // The real filtering is done later by the plugin module files themselves.
- var list = [];
- var allPlugins = Qt.plugin_support.allPluginsByType;
- for (var i = 0; i < (pluginTypes || []).length; ++i)
- Array.prototype.push.apply(list, allPlugins[pluginTypes[i]])
- return list;
- }
- }
-
- property string qtModuleName
- property path binPath: Qt.core.binPath
- property path incPath: Qt.core.incPath
- property path libPath: Qt.core.libPath
- property string qtLibInfix: Qt.core.libInfix
- property string libNameForLinkerDebug
- property string libNameForLinkerRelease
- property string libNameForLinker: Qt.core.qtBuildVariant === "debug"
- ? libNameForLinkerDebug : libNameForLinkerRelease
- property string libFilePathDebug
- property string libFilePathRelease
- property string libFilePath: Qt.core.qtBuildVariant === "debug"
- ? libFilePathDebug : libFilePathRelease
- version: Qt.core.version
- property bool hasLibrary: true
- property bool isStaticLibrary: false
- property bool isPlugin: false
-
- property stringList architectures
- property string targetPlatform
- property stringList staticLibsDebug
- property stringList staticLibsRelease
- property stringList dynamicLibsDebug
- property stringList dynamicLibsRelease
- property stringList linkerFlagsDebug
- property stringList linkerFlagsRelease
- property stringList staticLibs: Qt.core.qtBuildVariant === "debug"
- ? staticLibsDebug : staticLibsRelease
- property stringList dynamicLibs: Qt.core.qtBuildVariant === "debug"
- ? dynamicLibsDebug : dynamicLibsRelease
- property stringList frameworksDebug
- property stringList frameworksRelease
- property stringList frameworkPathsDebug
- property stringList frameworkPathsRelease
- property stringList mFrameworks: Qt.core.qtBuildVariant === "debug"
- ? frameworksDebug : frameworksRelease
- property stringList mFrameworkPaths: Qt.core.qtBuildVariant === "debug"
- ? frameworkPathsDebug: frameworkPathsRelease
- cpp.linkerFlags: Qt.core.qtBuildVariant === "debug"
- ? linkerFlagsDebug : linkerFlagsRelease
- property bool enableLinking: qtModuleName != undefined && hasLibrary
- property stringList moduleConfig
-
- Properties {
- condition: enableLinking
- cpp.staticLibraries: staticLibs
- cpp.dynamicLibraries: dynamicLibs
- cpp.frameworks: mFrameworks.concat(!isStaticLibrary && Qt.core.frameworkBuild
- ? [libNameForLinker] : [])
- cpp.systemFrameworkPaths: mFrameworkPaths
- }
-}
diff --git a/share/qbs/module-providers/Qt/templates/QtPlugin.qbs b/share/qbs/module-providers/Qt/templates/QtPlugin.qbs
deleted file mode 100644
index 883e34465..000000000
--- a/share/qbs/module-providers/Qt/templates/QtPlugin.qbs
+++ /dev/null
@@ -1,51 +0,0 @@
-import qbs.FileInfo
-import qbs.TextFile
-
-QtModule {
- isPlugin: true
-
- property string className
- property stringList extendsModules
-
- enableLinking: {
- if (!base)
- return false;
- if (!isStaticLibrary)
- return false;
- if (!Qt.plugin_support.linkPlugins)
- return false;
- if (!(Qt.plugin_support.enabledPlugins || []).contains(qtModuleName))
- return false;
- if (!extendsModules || extendsModules.length === 0)
- return true;
- for (var i = 0; i < extendsModules.length; ++i) {
- var moduleName = extendsModules[i];
- if (product.Qt[moduleName] && product.Qt[moduleName].present)
- return true;
- }
- return false;
- }
-
- Rule {
- condition: enableLinking
- multiplex: true
- Artifact {
- filePath: product.targetName + "_qt_plugin_import_"
- + product.moduleProperty(product.moduleName, "qtModuleName") + ".cpp"
- fileTags: "cpp"
- }
-
- prepare: {
- var cmd = new JavaScriptCommand();
- var pluginName = product.moduleProperty(product.moduleName, "qtModuleName");
- cmd.description = "creating static import for plugin '" + pluginName + "'";
- cmd.sourceCode = function() {
- var f = new TextFile(output.filePath, TextFile.WriteOnly);
- var className = product.moduleProperty(product.moduleName, "className");
- f.writeLine("#include <QtPlugin>\n\nQ_IMPORT_PLUGIN(" + className + ")");
- f.close();
- };
- return cmd;
- }
- }
-}
diff --git a/share/qbs/module-providers/Qt/templates/android_support.qbs b/share/qbs/module-providers/Qt/templates/android_support.qbs
index 66914d11b..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")
diff --git a/share/qbs/module-providers/Qt/templates/core.qbs b/share/qbs/module-providers/Qt/templates/core.qbs
index b980588ff..485402716 100644
--- a/share/qbs/module-providers/Qt/templates/core.qbs
+++ b/share/qbs/module-providers/Qt/templates/core.qbs
@@ -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
@@ -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 ccd08febd..885a6da7a 100644
--- a/share/qbs/module-providers/qbspkgconfig.qbs
+++ b/share/qbs/module-providers/qbspkgconfig.qbs
@@ -40,45 +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: 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 = {};
@@ -120,14 +129,12 @@ ModuleProvider {
return result;
}
- function getModuleName(packageName) { return packageName.replace(/\./g, '-'); }
-
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);
@@ -136,136 +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;
- if (options.sysroot)
- options.allowSystemLibraryPaths = true;
- 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 = getModuleName(moduleMapping[packageName]
- ? moduleMapping[packageName]
- : 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) {
- var depName = getModuleName(
- 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();
+ 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 "";
}