aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/qbs.qdoc10
-rw-r--r--doc/reference/modules/qt-modules.qdoc16
-rw-r--r--qbs.pro5
-rw-r--r--share/qbs/module-providers/Qt/provider.qbs6
-rw-r--r--share/qbs/module-providers/Qt/setup-qt.js1504
-rw-r--r--share/qbs/module-providers/Qt/templates/QtModule.qbs (renamed from src/lib/qtprofilesetup/templates/QtModule.qbs)0
-rw-r--r--share/qbs/module-providers/Qt/templates/QtPlugin.qbs (renamed from src/lib/qtprofilesetup/templates/QtPlugin.qbs)0
-rw-r--r--share/qbs/module-providers/Qt/templates/android_support.qbs (renamed from src/lib/qtprofilesetup/templates/android_support.qbs)0
-rw-r--r--share/qbs/module-providers/Qt/templates/core.qbs (renamed from src/lib/qtprofilesetup/templates/core.qbs)0
-rw-r--r--share/qbs/module-providers/Qt/templates/dbus.js (renamed from src/lib/qtprofilesetup/templates/dbus.js)0
-rw-r--r--share/qbs/module-providers/Qt/templates/dbus.qbs (renamed from src/lib/qtprofilesetup/templates/dbus.qbs)0
-rw-r--r--share/qbs/module-providers/Qt/templates/gui.qbs (renamed from src/lib/qtprofilesetup/templates/gui.qbs)0
-rw-r--r--share/qbs/module-providers/Qt/templates/moc.js (renamed from src/lib/qtprofilesetup/templates/moc.js)0
-rw-r--r--share/qbs/module-providers/Qt/templates/module.qbs (renamed from src/lib/qtprofilesetup/templates/module.qbs)0
-rw-r--r--share/qbs/module-providers/Qt/templates/plugin.qbs (renamed from src/lib/qtprofilesetup/templates/plugin.qbs)0
-rw-r--r--share/qbs/module-providers/Qt/templates/plugin_support.qbs (renamed from src/lib/qtprofilesetup/templates/plugin_support.qbs)0
-rw-r--r--share/qbs/module-providers/Qt/templates/qdoc.js (renamed from src/lib/qtprofilesetup/templates/qdoc.js)0
-rw-r--r--share/qbs/module-providers/Qt/templates/qml.js (renamed from src/lib/qtprofilesetup/templates/qml.js)0
-rw-r--r--share/qbs/module-providers/Qt/templates/qml.qbs (renamed from src/lib/qtprofilesetup/templates/qml.qbs)0
-rw-r--r--share/qbs/module-providers/Qt/templates/qmlcache.qbs (renamed from src/lib/qtprofilesetup/templates/qmlcache.qbs)0
-rw-r--r--share/qbs/module-providers/Qt/templates/quick.js (renamed from src/lib/qtprofilesetup/templates/quick.js)0
-rw-r--r--share/qbs/module-providers/Qt/templates/quick.qbs (renamed from src/lib/qtprofilesetup/templates/quick.qbs)0
-rw-r--r--share/qbs/module-providers/Qt/templates/scxml.qbs (renamed from src/lib/qtprofilesetup/templates/scxml.qbs)0
-rw-r--r--src/app/qbs-setup-android/android-setup.cpp8
-rw-r--r--src/app/qbs-setup-qt/main.cpp11
-rw-r--r--src/app/qbs-setup-qt/qbs-setup-qt.pro1
-rw-r--r--src/app/qbs-setup-qt/qbs-setup-qt.qbs1
-rw-r--r--src/app/qbs-setup-qt/setupqt.cpp311
-rw-r--r--src/app/qbs-setup-qt/setupqt.h25
-rw-r--r--src/lib/corelib/jsextensions/utilitiesextension.cpp262
-rw-r--r--src/lib/libs.qbs1
-rw-r--r--src/lib/qtprofilesetup/qtenvironment.h101
-rw-r--r--src/lib/qtprofilesetup/qtmoduleinfo.cpp839
-rw-r--r--src/lib/qtprofilesetup/qtmoduleinfo.h115
-rw-r--r--src/lib/qtprofilesetup/qtmsvctools.cpp79
-rw-r--r--src/lib/qtprofilesetup/qtmsvctools.h49
-rw-r--r--src/lib/qtprofilesetup/qtprofilesetup.cpp930
-rw-r--r--src/lib/qtprofilesetup/qtprofilesetup.h59
-rw-r--r--src/lib/qtprofilesetup/qtprofilesetup.pro31
-rw-r--r--src/lib/qtprofilesetup/qtprofilesetup.qbs31
-rw-r--r--src/lib/qtprofilesetup/templates.qrc22
-rw-r--r--src/lib/qtprofilesetup/use_installed_qtprofilesetup.pri20
-rw-r--r--src/lib/qtprofilesetup/use_qtprofilesetup.pri46
-rw-r--r--src/packages/archive/archive.qbs1
-rw-r--r--tests/auto/blackbox/tst_blackboxqt.cpp15
45 files changed, 1906 insertions, 2593 deletions
diff --git a/doc/qbs.qdoc b/doc/qbs.qdoc
index f559b481d..a87e88bdc 100644
--- a/doc/qbs.qdoc
+++ b/doc/qbs.qdoc
@@ -675,7 +675,7 @@
For example, a profile for building C++ applications contains at least the
installation path and the type of the compiler toolchain. A profile for
building Qt applications contains the toolchain-specific properties as well
- as the installation paths of the Qt modules.
+ as \l{Qt-specific Module Provider Properties}{the path to the Qt installation}.
This topic describes profiles stored in the \QBS settings. In some cases it
might be beneficial to keep profiles explicitly in the project sources. This
@@ -707,7 +707,7 @@
\endcode
You have successfully built your first \QBS project. If you want to build
- projects that use Qt, additional steps are necessary. Please refer to
+ projects that use Qt, additional steps might be necessary. Please refer to
\l{Managing Qt Versions} for more information.
\section1 Global Preferences
@@ -754,10 +754,10 @@
\section1 Introduction
- To let \QBS know where the Qt build or Qt version is that you want to use,
- you must register it.
+ If your environment has the right \c qmake binary in its \c PATH and is also set up
+ properly for a matching toolchain, then you do not necessarily need a profile
+ to build projects with a Qt dependency. Otherwise, you should create one:
- Register a Qt version like this:
\code
qbs setup-qt /usr/bin/qmake myqt
\endcode
diff --git a/doc/reference/modules/qt-modules.qdoc b/doc/reference/modules/qt-modules.qdoc
index 638160104..df5219ccd 100644
--- a/doc/reference/modules/qt-modules.qdoc
+++ b/doc/reference/modules/qt-modules.qdoc
@@ -55,6 +55,22 @@
The Qt modules that have properties and relevant file tags are described in
separate topics.
+ \section1 Qt-specific Module Provider Properties
+
+ Looking up a Qt installation happens via a \l{Module Providers}{module provider}.
+ By default, if a dependency to a Qt module is encountered, \QBS collects all Qt installations
+ it can find. This lookup happens by searching for \c qmake executables in the \c PATH
+ environment variable. Alternatively, you can explicitly tell \QBS which Qt
+ installations it should consider by setting the \c Qt.qmakeFilePaths
+ \l{Parameterizing Module Providers}{module provider property}. In that case,
+ the environment will be ignored. For instance, with the following Linux command line,
+ \QBS will build the project against a custom Qt instead of the standard one in \c{/usr/bin}:
+ \code
+ $ qbs moduleProviders.Qt.qmakeFilePaths:/opt/myqt/bin/qmake
+ \endcode
+ You can also set the module provider property in a profile. The simplest way to do
+ this is via the \l setup-qt tool.
+
\section1 List of Submodules
\table
diff --git a/qbs.pro b/qbs.pro
index 8b4fe3f9d..4be68099b 100644
--- a/qbs.pro
+++ b/qbs.pro
@@ -31,10 +31,8 @@ defineTest(minQtVersion) {
TEMPLATE = subdirs
corelib.file = src/lib/corelib/corelib.pro
-setupqtprofilelib.subdir = src/lib/qtprofilesetup
-setupqtprofilelib.depends = corelib
src_app.subdir = src/app
-src_app.depends = setupqtprofilelib
+src_app.depends = corelib
src_libexec.subdir = src/libexec
src_plugins.subdir = src/plugins
CONFIG(shared, static|shared): src_plugins.depends = corelib
@@ -48,7 +46,6 @@ qbs_use_bundled_qtscript {
}
SUBDIRS += \
corelib\
- setupqtprofilelib\
src_app\
src_libexec\
src_plugins\
diff --git a/share/qbs/module-providers/Qt/provider.qbs b/share/qbs/module-providers/Qt/provider.qbs
new file mode 100644
index 000000000..33083c51d
--- /dev/null
+++ b/share/qbs/module-providers/Qt/provider.qbs
@@ -0,0 +1,6 @@
+import "setup-qt.js" as SetupQt
+
+ModuleProvider {
+ property stringList qmakeFilePaths
+ relativeSearchPaths: SetupQt.doSetup(qmakeFilePaths, outputBaseDir, path, qbs)
+}
diff --git a/share/qbs/module-providers/Qt/setup-qt.js b/share/qbs/module-providers/Qt/setup-qt.js
new file mode 100644
index 000000000..0f0755409
--- /dev/null
+++ b/share/qbs/module-providers/Qt/setup-qt.js
@@ -0,0 +1,1504 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qbs.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+var Environment = require("qbs.Environment");
+var File = require("qbs.File");
+var FileInfo = require("qbs.FileInfo");
+var Process = require("qbs.Process");
+var TextFile = require("qbs.TextFile");
+var Utilities = require("qbs.Utilities");
+
+function splitNonEmpty(s, c) { return s.split(c).filter(function(e) { return e; }); }
+function toNative(p) { return FileInfo.toNativeSeparators(p); }
+function exeSuffix(qbs) { return qbs.hostOS.contains("windows") ? ".exe" : ""; }
+
+function getQmakeFilePaths(qmakeFilePaths, qbs) {
+ if (qmakeFilePaths && qmakeFilePaths.length > 0)
+ return qmakeFilePaths;
+ console.info("Detecting Qt installations...");
+ var pathValue = Environment.getEnv("PATH");
+ if (!pathValue)
+ return [];
+ var dirs = splitNonEmpty(pathValue, qbs.pathListSeparator);
+ var suffix = exeSuffix(qbs);
+ var filePaths = [];
+ for (var i = 0; i < dirs.length; ++i) {
+ var candidate = FileInfo.canonicalPath(FileInfo.joinPaths(dirs[i], "qmake" + suffix));
+ if (candidate && File.exists(candidate) && !filePaths.contains(candidate)) {
+ console.info("Found Qt at '" + toNative(candidate) + "'.");
+ filePaths.push(candidate);
+ }
+ }
+ return filePaths;
+}
+
+function queryQmake(qmakeFilePath) {
+ var qmakeProcess = new Process;
+ qmakeProcess.exec(qmakeFilePath, ["-query"]);
+ 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"
+ };
+ return mapping[year];
+}
+
+function msvcCompilerVersionFromMkspecName(mkspecName) {
+ return msvcCompilerVersionForYear(mkspecName.slice(msvcPrefix().length));
+}
+
+function addQtBuildVariant(qtProps, buildVariantName) {
+ if (qtProps.qtConfigItems.contains(buildVariantName))
+ qtProps.buildVariant.push(buildVariantName);
+}
+
+function checkForStaticBuild(qtProps) {
+ if (qtProps.qtMajorVersion >= 5)
+ return qtProps.qtConfigItems.contains("static");
+ if (qtProps.frameworkBuild)
+ return false; // there are no Qt4 static frameworks
+ var isWin = qtProps.mkspecName.startsWith("win");
+ var libDir = isWin ? qtProps.binaryPath : qtProps.libraryPath;
+ var coreLibFiles = File.directoryEntries(libDir, File.Files)
+ .filter(function(fp) { return fp.contains("Core"); });
+ if (coreLibFiles.length === 0)
+ throw "Could not determine whether Qt is a static build.";
+ for (var i = 0; i < coreLibFiles.length; ++i) {
+ if (Utilities.isSharedLibrary(coreLibFiles[i]))
+ return false;
+ }
+ return true;
+}
+
+function isForMinGw(qtProps) {
+ return qtProps.mkspecName.startsWith("win32-g++") || qtProps.mkspecName.startsWith("mingw");
+}
+
+function targetsDesktopWindows(qtProps) {
+ return qtProps.mkspecName.startsWith("win32-") || isForMinGw(qtProps);
+}
+
+function guessMinimumWindowsVersion(qtProps) {
+ if (qtProps.mkspecName.startsWith("winrt-"))
+ return "10.0";
+ if (!targetsDesktopWindows(qtProps))
+ return "";
+ if (qtProps.architecture === "x86_64" || qtProps.architecture === "ia64")
+ return "5.2"
+ var match = qtProps.mkspecName.match(/^win32-msvc(\d+)$/);
+ if (match) {
+ var msvcVersion = match[1];
+ if (msvcVersion < 2012)
+ return "5.0";
+ return "5.1";
+ }
+ return qtProps.qtMajorVersion < 5 ? "5.0" : "5.1";
+}
+
+function fillEntryPointLibs(qtProps, debug) {
+ result = [];
+ var isMinGW = isForMinGw(qtProps);
+
+ // Some Linux distributions rename the qtmain library.
+ var qtMainCandidates = ["qtmain"];
+ if (isMinGW && qtProps.qtMajorVersion === 5)
+ qtMainCandidates.push("qt5main");
+
+ for (var i = 0; i < qtMainCandidates.length; ++i) {
+ var baseNameCandidate = qtMainCandidates[i];
+ var qtmain = qtProps.libraryPath + '/';
+ if (isMinGW)
+ qtmain += "lib";
+ qtmain += baseNameCandidate + qtProps.qtLibInfix;
+ if (debug)
+ qtmain += 'd';
+ if (isMinGW) {
+ qtmain += ".a";
+ } else {
+ qtmain += ".lib";
+ if (Utilities.versionCompare(qtProps.qtVersion, "5.4.0") >= 0)
+ result.push("Shell32.lib");
+ }
+ if (File.exists(qtmain)) {
+ result.push(qtmain);
+ break;
+ }
+ }
+ if (result.length === 0) {
+ console.warn("Could not find the qtmain library at '" + toNative(qtProps.libraryPath)
+ + "'. You will not be able to link Qt applications.");
+ }
+ return result;
+}
+
+function getQtProperties(qmakeFilePath, qbs) {
+ var queryResult = queryQmake(qmakeFilePath);
+ var qtProps = {};
+ qtProps.installPrefixPath = pathQueryValue(queryResult, "QT_INSTALL_PREFIX");
+ qtProps.documentationPath = pathQueryValue(queryResult, "QT_INSTALL_DOCS");
+ qtProps.includePath = pathQueryValue(queryResult, "QT_INSTALL_HEADERS");
+ qtProps.libraryPath = pathQueryValue(queryResult, "QT_INSTALL_LIBS");
+ qtProps.binaryPath = pathQueryValue(queryResult, "QT_HOST_BINS")
+ || pathQueryValue(queryResult, "QT_INSTALL_BINS");
+ qtProps.documentationPath = pathQueryValue(queryResult, "QT_INSTALL_DOCS");
+ qtProps.pluginPath = pathQueryValue(queryResult, "QT_INSTALL_PLUGINS");
+ qtProps.qmlPath = pathQueryValue(queryResult, "QT_INSTALL_QML");
+ qtProps.qmlImportPath = pathQueryValue(queryResult, "QT_INSTALL_IMPORTS");
+ qtProps.qtVersion = queryResult.QT_VERSION;
+
+ var mkspecsBaseSrcPath;
+ if (Utilities.versionCompare(qtProps.qtVersion, "5") >= 0) {
+ qtProps.mkspecBasePath = FileInfo.joinPaths(pathQueryValue(queryResult, "QT_HOST_DATA"),
+ "mkspecs");
+ mkspecsBaseSrcPath = FileInfo.joinPaths(pathQueryValue(queryResult, "QT_HOST_DATA/src"),
+ "mkspecs");
+ } else {
+ qtProps.mkspecBasePath = FileInfo.joinPaths
+ (pathQueryValue(queryResult, "QT_INSTALL_DATA"), "mkspecs");
+ }
+ if (!File.exists(qtProps.mkspecBasePath))
+ throw "Cannot extract the mkspecs directory.";
+
+ var qconfigContent = readFileContent(FileInfo.joinPaths(qtProps.mkspecBasePath,
+ "qconfig.pri"));
+ qtProps.qtMajorVersion = parseInt(configVariable(qconfigContent, "QT_MAJOR_VERSION"));
+ qtProps.qtMinorVersion = parseInt(configVariable(qconfigContent, "QT_MINOR_VERSION"));
+ qtProps.qtPatchVersion = parseInt(configVariable(qconfigContent, "QT_PATCH_VERSION"));
+ qtProps.qtNameSpace = configVariable(qconfigContent, "QT_NAMESPACE");
+ qtProps.qtLibInfix = configVariable(qconfigContent, "QT_LIBINFIX") || "";
+ qtProps.architecture = configVariable(qconfigContent, "QT_TARGET_ARCH")
+ || configVariable(qconfigContent, "QT_ARCH") || "x86";
+ qtProps.configItems = configVariableItems(qconfigContent, "CONFIG");
+ qtProps.qtConfigItems = configVariableItems(qconfigContent, "QT_CONFIG");
+
+ // retrieve the mkspec
+ if (qtProps.qtMajorVersion >= 5) {
+ qtProps.mkspecName = queryResult.QMAKE_XSPEC;
+ qtProps.mkspecPath = FileInfo.joinPaths(qtProps.mkspecBasePath, qtProps.mkspecName);
+ if (mkspecsBaseSrcPath && !File.exists(qtProps.mkspecPath))
+ qtProps.mkspecPath = FileInfo.joinPaths(mkspecsBaseSrcPath, qtProps.mkspecName);
+ } else {
+ if (qbs.hostOS.contains("windows")) {
+ var baseDirPath = FileInfo.joinPaths(qtProps.mkspecBasePath, "default");
+ var fileContent = readFileContent(FileInfo.joinPaths(baseDirPath, "qmake.conf"));
+ qtProps.mkspecPath = configVariable(fileContent, "QMAKESPEC_ORIGINAL");
+ if (!File.exists(qtProps.mkspecPath)) {
+ // Work around QTBUG-28792.
+ // The value of QMAKESPEC_ORIGINAL is wrong for MinGW packages. Y u h8 me?
+ var match = fileContent.exec(/\binclude\(([^)]+)\/qmake\.conf\)/m);
+ if (match) {
+ qtProps.mkspecPath = FileInfo.cleanPath(FileInfo.joinPaths(
+ baseDirPath, match[1]));
+ }
+ }
+ } else {
+ qtProps.mkspecPath = FileInfo.canonicalPath(
+ FileInfo.joinPaths(qtProps.mkspecBasePath, "default"));
+ }
+
+ // E.g. in qmake.conf for Qt 4.8/mingw we find this gem:
+ // QMAKESPEC_ORIGINAL=C:\\Qt\\Qt\\4.8\\mingw482\\mkspecs\\win32-g++
+ qtProps.mkspecPath = FileInfo.cleanPath(qtProps.mkspecPath);
+
+ qtProps.mkspecName = qtProps.mkspecPath;
+ var idx = qtProps.mkspecName.lastIndexOf('/');
+ if (idx !== -1)
+ qtProps.mkspecName = qtProps.mkspecName.slice(idx + 1);
+ }
+ if (!File.exists(qtProps.mkspecPath))
+ throw "mkspec '" + toNative(qtProps.mkspecPath) + "' does not exist";
+
+ // determine MSVC version
+ if (isMsvcQt(qtProps)) {
+ var msvcMajor = configVariable(qconfigContent, "QT_MSVC_MAJOR_VERSION");
+ var msvcMinor = configVariable(qconfigContent, "QT_MSVC_MINOR_VERSION");
+ var msvcPatch = configVariable(qconfigContent, "QT_MSVC_PATCH_VERSION");
+ if (msvcMajor && msvcMinor && msvcPatch)
+ qtProps.msvcVersion = msvcMajor + "." + msvcMinor + "." + msvcPatch;
+ else
+ qtProps.msvcVersion = msvcCompilerVersionFromMkspecName(qtProps.mkspecName);
+ }
+
+ // determine whether we have a framework build
+ qtProps.frameworkBuild = qtProps.mkspecPath.contains("macx")
+ && qtProps.configItems.contains("qt_framework");
+
+ // determine whether Qt is built with debug, release or both
+ qtProps.buildVariant = [];
+ addQtBuildVariant(qtProps, "debug");
+ addQtBuildVariant(qtProps, "release");
+
+ qtProps.staticBuild = checkForStaticBuild(qtProps);
+
+ // determine whether user apps require C++11
+ if (qtProps.qtConfigItems.contains("c++11") && qtProps.staticBuild)
+ qtProps.configItems.push("c++11");
+
+ // Set the minimum operating system versions appropriate for this Qt version
+ qtProps.windowsVersion = guessMinimumWindowsVersion(qtProps);
+ if (qtProps.windowsVersion) { // Is target OS Windows?
+ if (qtProps.buildVariant.contains("debug"))
+ qtProps.entryPointLibsDebug = fillEntryPointLibs(qtProps, true);
+ if (qtProps.buildVariant.contains("release"))
+ qtProps.entryPointLibsRelease = fillEntryPointLibs(qtProps, false);
+ } else if (qtProps.mkspecPath.contains("macx")) {
+ if (qtProps.qtMajorVersion >= 5) {
+ try {
+ var qmakeConf = new TextFile(FileInfo.joinPaths(qtProps.mkspecPath, "qmake.conf"),
+ TextFile.ReadOnly);
+ while (!qmakeConf.atEof()) {
+ var line = qmakeConf.readLine().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;
+ }
+ }
+ }
+ catch (e) {}
+ finally {
+ if (qmakeConf)
+ qmakeConf.close();
+ }
+ 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 !== "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.config = [];
+ moduleInfo.supportedPluginTypes = [];
+ moduleInfo.pluginData = makePluginData();
+ return moduleInfo;
+}
+
+function frameworkHeadersPath(qtModuleInfo, qtProps) {
+ return FileInfo.joinPaths(qtProps.libraryPath, qtModuleInfo.name + ".framework", "Headers");
+}
+
+function qt4ModuleIncludePaths(qtModuleInfo, qtProps) {
+ var paths = [];
+ if (isFramework(qtModuleInfo, qtProps))
+ paths.push(frameworkHeadersPath(qtModuleInfo, qtProps));
+ else
+ paths.push(qtProps.includePath, FileInfo.joinPaths(qtProps.includePath, qtModuleInfo.name));
+ return paths;
+}
+
+// We erroneously called the "testlib" module "test" for quite a while. Let's not punish users
+// for that.
+function addTestModule(modules) {
+ var testModule = makeQtModuleInfo("QtTest", "test", ["testlib"]);
+ testModule.hasLibrary = false;
+ modules.push(testModule);
+}
+
+// See above.
+function addDesignerComponentsModule(modules) {
+ var module = makeQtModuleInfo("QtDesignerComponents", "designercomponents",
+ ["designercomponents-private"]);
+ module.hasLibrary = false;
+ modules.push(module);
+}
+
+function isFramework(modInfo, qtProps) {
+ if (!qtProps.frameworkBuild || modInfo.isStaticLibrary)
+ return false;
+ var modulesNeverBuiltAsFrameworks = [
+ "bootstrap", "openglextensions", "platformsupport", "qmldevtools", "uitools", "harfbuzzng"
+ ];
+ return !modulesNeverBuiltAsFrameworks.contains(modInfo.qbsName);
+}
+
+function libBaseName(modInfo, libName, debugBuild, qtProps) {
+ var name = libName;
+ if (qtProps.mkspecName.startsWith("win")) {
+ if (debugBuild)
+ name += 'd';
+ if (!modInfo.isStaticLibrary && qtProps.qtMajorVersion < 5)
+ name += qtProps.qtMajorVersion;
+ }
+ if (qtProps.mkspecName.contains("macx")
+ || qtProps.mkspecName.contains("ios")
+ || qtProps.mkspecName.contains("darwin")) {
+ if (!isFramework(modInfo, qtProps)
+ && qtProps.buildVariant.contains("debug")
+ && (!qtProps.buildVariant.contains("release") || debugBuild)) {
+ name += "_debug";
+ }
+ }
+ return name;
+}
+
+function moduleNameWithoutPrefix(modInfo) {
+ if (modInfo.name === "Phonon")
+ return "phonon";
+ if (!modInfo.modulePrefix && modInfo.name.startsWith("Qt"))
+ return modInfo.name.slice(2); // Strip off "Qt".
+ if (modInfo.name.startsWith(modInfo.modulePrefix))
+ return modInfo.name.slice(modInfo.modulePrefix.length);
+ return modInfo.name;
+}
+
+function libraryBaseName(modInfo, qtProps, debugBuild) {
+ if (modInfo.isPlugin)
+ return libBaseName(modInfo, name, debugBuild, qtProps);
+
+ // Some modules use a different naming scheme, so it doesn't get boring.
+ var libNameBroken = modInfo.name === "Enginio"
+ || modInfo.name === "DataVisualization"
+ || modInfo.name === "Phonon";
+
+ var libName = !modInfo.modulePrefix && !libNameBroken ? "Qt" : modInfo.modulePrefix;
+ if (qtProps.qtMajorVersion >= 5 && !isFramework(modInfo, qtProps) && !libNameBroken)
+ libName += qtProps.qtMajorVersion;
+ libName += moduleNameWithoutPrefix(modInfo);
+ libName += qtProps.qtLibInfix;
+ return libBaseName(modInfo, libName, debugBuild, qtProps);
+}
+
+function libNameForLinker(modInfo, qtProps, debugBuild) {
+ if (!modInfo.hasLibrary)
+ return undefined;
+ var libName = libraryBaseName(modInfo, qtProps, debugBuild);
+ if (qtProps.mkspecName.contains("msvc"))
+ libName += ".lib";
+ return libName;
+}
+
+function guessLibraryFilePath(prlFilePath, libDir, qtProps) {
+ var baseName = FileInfo.baseName(prlFilePath);
+ var prefixCandidates = ["", "lib"];
+ var suffixCandidates = ["so." + qtProps.qtVersion, "so", "a", "lib", "dll.a"];
+ for (var i = 0; i < prefixCandidates.length; ++i) {
+ var prefix = prefixCandidates[i];
+ for (var j = 0; j < suffixCandidates.length; ++j) {
+ var suffix = suffixCandidates[j];
+ var candidate = FileInfo.joinPaths(libDir, prefix + baseName + '.' + suffix);
+ if (File.exists(candidate))
+ return candidate;
+ }
+ }
+}
+
+function doReplaceQtLibNamesWithFilePath(namePathMap, libList) {
+ for (var i = 0; i < libList.length; ++i) {
+ var lib = libList[i];
+ var path = namePathMap[lib];
+ if (path)
+ libList[i] = path;
+ }
+}
+
+function replaceQtLibNamesWithFilePath(modules, qtProps) {
+ // We don't want to add the libraries for Qt modules via "-l", because of the
+ // danger that a wrong one will be picked up, e.g. from /usr/lib. Instead,
+ // we pull them in using the full file path.
+ var linkerNamesToFilePathsDebug = {};
+ var linkerNamesToFilePathsRelease = {};
+ for (var i = 0; i < modules.length; ++i) {
+ var m = modules[i];
+ linkerNamesToFilePathsDebug[libNameForLinker(m, qtProps, true)] = m.libFilePathDebug;
+ linkerNamesToFilePathsRelease[libNameForLinker(m, qtProps, false)] = m.libFilePathRelease;
+ }
+ for (i = 0; i < modules.length; ++i) {
+ var module = modules[i];
+ doReplaceQtLibNamesWithFilePath(linkerNamesToFilePathsDebug, module.dynamicLibrariesDebug);
+ doReplaceQtLibNamesWithFilePath(linkerNamesToFilePathsDebug, module.staticLibrariesDebug);
+ doReplaceQtLibNamesWithFilePath(linkerNamesToFilePathsRelease,
+ module.dynamicLibrariesRelease);
+ doReplaceQtLibNamesWithFilePath(linkerNamesToFilePathsRelease,
+ module.staticLibrariesRelease);
+ }
+}
+
+function doSetupLibraries(modInfo, qtProps, debugBuild, nonExistingPrlFiles) {
+ if (!modInfo.hasLibrary)
+ return; // Can happen for Qt4 convenience modules, like "widgets".
+
+ if (debugBuild) {
+ if (!qtProps.buildVariant.contains("debug"))
+ return;
+ var modulesNeverBuiltAsDebug = ["bootstrap", "qmldevtools"];
+ for (var i = 0; i < modulesNeverBuiltAsDebug.length; ++i) {
+ var m = modulesNeverBuiltAsDebug[i];
+ if (modInfo.qbsName === m || modInfo.qbsName === m + "-private")
+ return;
+ }
+ } else if (!qtProps.buildVariant.contains("release")) {
+ return;
+ }
+
+ var libs = modInfo.isStaticLibrary
+ ? (debugBuild ? modInfo.staticLibrariesDebug : modInfo.staticLibrariesRelease)
+ : (debugBuild ? modInfo.dynamicLibrariesDebug : modInfo.dynamicLibrariesRelease);
+ var frameworks = debugBuild ? modInfo.frameworksDebug : modInfo.frameworksRelease;
+ var frameworkPaths = debugBuild ? modInfo.frameworkPathsDebug : modInfo.frameworkPathsRelease;
+ var flags = debugBuild ? modInfo.linkerFlagsDebug : modInfo.linkerFlagsRelease;
+ var libFilePath;
+
+ if (qtProps.mkspecName.contains("ios") && modInfo.isStaticLibrary) {
+ libs.push("z", "m");
+ if (qtProps.qtMajorVersion === 5 && qtProps.qtMinorVersion < 8) {
+ var platformSupportModule = makeQtModuleInfo("QtPlatformSupport", "platformsupport");
+ libs.push(libNameForLinker(platformSupportModule, qtProps, debugBuild));
+ }
+ if (modInfo.name === "qios") {
+ flags.push("-force_load", FileInfo.joinPaths(
+ qtProps.pluginPath, "platforms",
+ libBaseName(modInfo, "libqios", debugBuild, qtProps) + ".a"));
+ }
+ }
+ var prlFilePath = modInfo.isPlugin
+ ? FileInfo.joinPaths(qtProps.pluginPath, modInfo.pluginData.type)
+ : qtProps.libraryPath;
+ if (isFramework(modInfo, qtProps)) {
+ prlFilePath = FileInfo.joinPaths(prlFilePath,
+ libraryBaseName(modInfo, qtProps, false) + ".framework");
+ }
+ var libDir = prlFilePath;
+ var baseName = libraryBaseName(modInfo, qtProps, debugBuild);
+ if (!qtProps.mkspecName.startsWith("win") && !isFramework(modInfo, qtProps))
+ baseName = "lib" + baseName;
+ prlFilePath = FileInfo.joinPaths(prlFilePath, baseName);
+ var isNonStaticQt4OnWindows = qtProps.mkspecName.startsWith("win")
+ && !modInfo.isStaticLibrary && qtProps.qtMajorVersion < 5;
+ if (isNonStaticQt4OnWindows)
+ prlFilePath = prlFilePath.slice(0, prlFilePath.length - 1); // The prl file base name does *not* contain the version number...
+ prlFilePath += ".prl";
+ try {
+ var prlFile = new TextFile(prlFilePath, TextFile.ReadOnly);
+ while (!prlFile.atEof()) {
+ var line = prlFile.readLine().trim();
+ var equalsOffset = line.indexOf('=');
+ if (equalsOffset === -1)
+ continue;
+ if (line.startsWith("QMAKE_PRL_TARGET")) {
+ var isMingw = qtProps.mkspecName.startsWith("win")
+ && qtProps.mkspecName.contains("g++");
+ var isQtVersionBefore56 = qtProps.qtMajorVersion < 5
+ || (qtProps.qtMajorVersion === 5 && qtProps.qtMinorVersion < 6);
+
+ // QMAKE_PRL_TARGET has a "lib" prefix, except for mingw.
+ // Of course, the exception has an exception too: For static libs, mingw *does*
+ // have the "lib" prefix.
+ var libFileName = "";
+ if (isQtVersionBefore56 && qtProps.qtMajorVersion === 5 && isMingw
+ && !modInfo.isStaticLibrary) {
+ libFileName += "lib";
+ }
+
+ libFileName += line.slice(equalsOffset + 1).trim();
+ if (isNonStaticQt4OnWindows)
+ libFileName += 4; // This is *not* part of QMAKE_PRL_TARGET...
+ if (isQtVersionBefore56) {
+ if (qtProps.mkspecName.contains("msvc")) {
+ libFileName += ".lib";
+ } else if (isMingw) {
+ libFileName += ".a";
+ if (!File.exists(FileInfo.joinPaths(libDir, libFileName)))
+ libFileName = libFileName.slice(0, -2) + ".dll";
+ }
+ }
+ libFilePath = FileInfo.joinPaths(libDir, libFileName);
+ continue;
+ }
+ if (line.startsWith("QMAKE_PRL_CONFIG")) {
+ modInfo.config = splitNonEmpty(line.slice(equalsOffset + 1).trim(), ' ');
+ continue;
+ }
+ if (!line.startsWith("QMAKE_PRL_LIBS"))
+ continue;
+
+ // Assuming lib names and directories without spaces here.
+ var parts = splitNonEmpty(line.slice(equalsOffset + 1).trim(), ' ');
+ for (i = 0; i < parts.length; ++i) {
+ var part = parts[i];
+ part = part.replace("$$[QT_INSTALL_LIBS]", qtProps.libraryPath);
+ if (part.startsWith("-l")) {
+ libs.push(part.slice(2));
+ } else if (part.startsWith("-L")) {
+ modInfo.libraryPaths.push(part.slice(2));
+ } else if (part.startsWith("-F")) {
+ frameworkPaths.push(part.slice(2));
+ } else if (part === "-framework") {
+ if (++i < parts.length)
+ frameworks.push(parts[i]);
+ } else if (part === "-pthread") {
+ libs.push("pthread");
+ } else if (part.startsWith('-')) { // Some other option
+ console.debug("QMAKE_PRL_LIBS contains non-library option '" + part
+ + "' in file '" + prlFilePath + "'");
+ flags.push(part);
+ } else if (part.startsWith("/LIBPATH:")) {
+ libraryPaths.push(part.slice(9).replace(/\\/g, '/'));
+ } else { // Assume it's a file path/name.
+ libs.push(part.replace(/\\/g, '/'));
+ }
+ }
+ }
+ } catch (e) {
+ libFilePath = guessLibraryFilePath(prlFilePath, libDir, qtProps);
+ if (nonExistingPrlFiles.contains(prlFilePath))
+ return;
+ nonExistingPrlFiles.push(prlFilePath);
+ if (!libFilePath && modInfo.mustExist) {
+ console.warn("Could not open prl file '" + toNative(prlFilePath) + "' for module '"
+ + modInfo.name
+ + "' (" + e + "), and failed to deduce the library file path. "
+ + " This module will likely not be usable by qbs.");
+ }
+ }
+ finally {
+ if (prlFile)
+ prlFile.close();
+ }
+
+ if (debugBuild)
+ modInfo.libFilePathDebug = libFilePath;
+ else
+ modInfo.libFilePathRelease = libFilePath;
+}
+
+function setupLibraries(qtModuleInfo, qtProps, nonExistingPrlFiles) {
+ doSetupLibraries(qtModuleInfo, qtProps, true, nonExistingPrlFiles);
+ doSetupLibraries(qtModuleInfo, qtProps, false, nonExistingPrlFiles);
+}
+
+function allQt4Modules(qtProps) {
+ // as per http://doc.qt.io/qt-4.8/modules.html + private stuff.
+ var modules = [];
+
+ var core = makeQtModuleInfo("QtCore", "core");
+ core.compilerDefines.push("QT_CORE_LIB");
+ if (qtProps.qtNameSpace)
+ core.compilerDefines.push("QT_NAMESPACE=" + qtProps.qtNameSpace);
+ modules.push(core,
+ makeQtModuleInfo("QtCore", "core-private", ["core"]),
+ makeQtModuleInfo("QtGui", "gui"),
+ makeQtModuleInfo("QtGui", "gui-private", ["gui"]),
+ makeQtModuleInfo("QtMultimedia", "multimedia", ["gui", "network"]),
+ makeQtModuleInfo("QtMultimedia", "multimedia-private", ["multimedia"]),
+ makeQtModuleInfo("QtNetwork", "network"),
+ makeQtModuleInfo("QtNetwork", "network-private", ["network"]),
+ makeQtModuleInfo("QtOpenGL", "opengl", ["gui"]),
+ makeQtModuleInfo("QtOpenGL", "opengl-private", ["opengl"]),
+ makeQtModuleInfo("QtOpenVG", "openvg", ["gui"]),
+ makeQtModuleInfo("QtScript", "script"),
+ makeQtModuleInfo("QtScript", "script-private", ["script"]),
+ makeQtModuleInfo("QtScriptTools", "scripttools", ["script", "gui"]),
+ makeQtModuleInfo("QtScriptTools", "scripttools-private", ["scripttools"]),
+ makeQtModuleInfo("QtSql", "sql"),
+ makeQtModuleInfo("QtSql", "sql-private", ["sql"]),
+ makeQtModuleInfo("QtSvg", "svg", ["gui"]),
+ makeQtModuleInfo("QtSvg", "svg-private", ["svg"]),
+ makeQtModuleInfo("QtWebKit", "webkit", ["gui", "network"]),
+ makeQtModuleInfo("QtWebKit", "webkit-private", ["webkit"]),
+ makeQtModuleInfo("QtXml", "xml"),
+ makeQtModuleInfo("QtXml", "xml-private", ["xml"]),
+ makeQtModuleInfo("QtXmlPatterns", "xmlpatterns", ["network"]),
+ makeQtModuleInfo("QtXmlPatterns", "xmlpatterns-private", ["xmlpatterns"]),
+ makeQtModuleInfo("QtDeclarative", "declarative", ["gui", "script"]),
+ makeQtModuleInfo("QtDeclarative", "declarative-private", ["declarative"]),
+ makeQtModuleInfo("QtDesigner", "designer", ["gui", "xml"]),
+ makeQtModuleInfo("QtDesigner", "designer-private", ["designer"]),
+ makeQtModuleInfo("QtUiTools", "uitools"),
+ makeQtModuleInfo("QtUiTools", "uitools-private", ["uitools"]),
+ makeQtModuleInfo("QtHelp", "help", ["network", "sql"]),
+ makeQtModuleInfo("QtHelp", "help-private", ["help"]),
+ makeQtModuleInfo("QtTest", "testlib"),
+ makeQtModuleInfo("QtTest", "testlib-private", ["testlib"]));
+ if (qtProps.mkspecName.startsWith("win")) {
+ var axcontainer = makeQtModuleInfo("QAxContainer", "axcontainer");
+ axcontainer.modulePrefix = "Q";
+ axcontainer.isStaticLibrary = true;
+ axcontainer.includePaths.push(FileInfo.joinPaths(qtProps.includePath, "ActiveQt"));
+ modules.push(axcontainer);
+
+ var axserver = makeQtModuleInfo("QAxServer", "axserver");
+ axserver.modulePrefix = "Q";
+ axserver.isStaticLibrary = true;
+ axserver.compilerDefines.push("QAXSERVER");
+ axserver.includePaths.push(FileInfo.joinPaths(qtProps.includePath, "ActiveQt"));
+ modules.push(axserver);
+ } else {
+ modules.push(makeQtModuleInfo("QtDBus", "dbus"));
+ modules.push(makeQtModuleInfo("QtDBus", "dbus-private", ["dbus"]));
+ }
+
+ var designerComponentsPrivate = makeQtModuleInfo(
+ "QtDesignerComponents", "designercomponents-private",
+ ["gui-private", "designer-private"]);
+ designerComponentsPrivate.hasLibrary = true;
+ modules.push(designerComponentsPrivate);
+
+ var phonon = makeQtModuleInfo("Phonon", "phonon");
+ phonon.includePaths = qt4ModuleIncludePaths(phonon, qtProps);
+ modules.push(phonon);
+
+ // Set up include paths that haven't been set up before this point.
+ for (i = 0; i < modules.length; ++i) {
+ var module = modules[i];
+ if (module.includePaths.length > 0)
+ continue;
+ module.includePaths = qt4ModuleIncludePaths(module, qtProps);
+ }
+
+ // Set up compiler defines haven't been set up before this point.
+ for (i = 0; i < modules.length; ++i) {
+ module = modules[i];
+ if (module.compilerDefines.length > 0)
+ continue;
+ module.compilerDefines.push("QT_" + module.qbsName.toUpperCase() + "_LIB");
+ }
+
+ // These are for the convenience of project file authors. It allows them
+ // to add a dependency to e.g. "Qt.widgets" without a version check.
+ var virtualModule = makeQtModuleInfo(undefined, "widgets", ["core", "gui"]);
+ virtualModule.hasLibrary = false;
+ modules.push(virtualModule);
+ virtualModule = makeQtModuleInfo(undefined, "quick", ["declarative"]);
+ virtualModule.hasLibrary = false;
+ modules.push(virtualModule);
+ virtualModule = makeQtModuleInfo(undefined, "concurrent");
+ virtualModule.hasLibrary = false;
+ modules.push(virtualModule);
+ virtualModule = makeQtModuleInfo(undefined, "printsupport", ["core", "gui"]);
+ virtualModule.hasLibrary = false;
+ modules.push(virtualModule);
+
+ addTestModule(modules);
+ addDesignerComponentsModule(modules);
+
+ var modulesThatCanBeDisabled = [
+ "xmlpatterns", "multimedia", "phonon", "svg", "webkit", "script", "scripttools",
+ "declarative", "gui", "dbus", "opengl", "openvg"];
+ var nonExistingPrlFiles = [];
+ for (i = 0; i < modules.length; ++i) {
+ module = modules[i];
+ var name = module.qbsName;
+ var privateIndex = name.indexOf("-private");
+ if (privateIndex !== -1)
+ name = name.slice(0, privateIndex);
+ if (modulesThatCanBeDisabled.contains(name))
+ module.mustExist = false;
+ if (qtProps.staticBuild)
+ module.isStaticLibrary = true;
+ setupLibraries(module, qtProps, nonExistingPrlFiles);
+ }
+ replaceQtLibNamesWithFilePath(modules, qtProps);
+
+ return modules;
+}
+
+function getPriFileContentsRecursively(priFilePath) {
+ var priFile = new TextFile(priFilePath, TextFile.ReadOnly);
+ var lines = splitNonEmpty(priFile.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(priFilePath) + "'");
+ continue;
+ }
+ var includedFilePath = line.slice(offset, closingParenPos - offset);
+ var includedContents = getPriFileContentsRecursively(includedFilePath);
+ var j = i;
+ for (var k = 0; k < includedContents.length; ++k)
+ lines.splice(++j, 0, includedContents[k]);
+ lines.splice(i--, 1);
+ }
+ priFile.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(rhs.slice(startIndex, endIndex));
+ startIndex = endIndex + 1;
+ }
+ return paths;
+}
+
+function removeDuplicatedDependencyLibs(modules) {
+ var revDeps = {};
+ var currentPath;
+ var getLibraries;
+ var getLibFilePath;
+
+ function setupReverseDependencies(modules) {
+ var moduleByName = {};
+ for (var i = 0; i < modules.length; ++i)
+ moduleByName[modules[i].qbsName] = modules[i];
+ for (i = 0; i < modules.length; ++i) {
+ var module = modules[i];
+ for (var j = 0; j < module.dependencies.length; ++j) {
+ var depmod = moduleByName[module.dependencies[j]];
+ if (!depmod)
+ continue;
+ if (!revDeps[depmod])
+ revDeps[depmod] = [];
+ revDeps[depmod].push(module);
+ }
+ }
+ }
+
+ function roots(modules) {
+ var result = [];
+ for (i = 0; i < modules.length; ++i) {
+ var module = modules[i]
+ if (module.dependencies.lenegth === 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();
+
+ for (i = 0; i < (revDeps[module] || []).length; ++i)
+ traverse(revDeps[module][i], libs);
+
+ m_currentPath.pop();
+ }
+
+ setupReverseDependencies(modules);
+
+ // Traverse the debug variants of modules.
+ getLibraries = function(module) {
+ return [module.dynamicLibrariesDebug, module.staticLibrariesDebug];
+ };
+ getLibFilePath = function(module) { return module.libFilePathDebug; };
+ var rootModules = roots(modules);
+ for (var i = 0; i < rootModules.length; ++i)
+ traverse(rootModules[i], []);
+
+ // Traverse the release variants of modules.
+ getLibraries = function(module) {
+ return [module.dynamicLibrariesRelease, module.staticLibrariesRelease];
+ };
+ getLibFilePath = function(module) { return module.libFilePathRelease; };
+ for (i = 0; i < rootModules.length; ++i)
+ traverse(rootModules[i], []);
+}
+
+function allQt5Modules(qtProps) {
+ var nonExistingPrlFiles = [];
+ var modules = [];
+ var modulesDir = FileInfo.joinPaths(qtProps.mkspecBasePath, "modules");
+ var modulePriFiles = File.directoryEntries(modulesDir, File.Files);
+ for (var i = 0; i < modulePriFiles.length; ++i) {
+ var priFileName = modulePriFiles[i];
+ var priFilePath = FileInfo.joinPaths(modulesDir, priFileName);
+ var moduleFileNamePrefix = "qt_lib_";
+ var pluginFileNamePrefix = "qt_plugin_";
+ var moduleFileNameSuffix = ".pri";
+ var fileHasPluginPrefix = priFileName.startsWith(pluginFileNamePrefix);
+ if (!fileHasPluginPrefix && (!priFileName.startsWith(moduleFileNamePrefix))
+ || !priFileName.endsWith(moduleFileNameSuffix)) {
+ continue;
+ }
+ var moduleInfo = makeQtModuleInfo();
+ moduleInfo.isPlugin = fileHasPluginPrefix;
+ var fileNamePrefix = moduleInfo.isPlugin ? pluginFileNamePrefix : moduleFileNamePrefix;
+ moduleInfo.qbsName = priFileName.slice(fileNamePrefix.length, -moduleFileNameSuffix.length);
+ if (moduleInfo.isPlugin) {
+ moduleInfo.name = moduleInfo.qbsName;
+ moduleInfo.isStaticLibrary = true;
+ }
+ var moduleKeyPrefix = (moduleInfo.isPlugin ? "QT_PLUGIN" : "QT")
+ + '.' + moduleInfo.qbsName + '.';
+ moduleInfo.qbsName = moduleInfo.qbsName.replace("_private", "-private");
+ var hasV2 = false;
+ var hasModuleEntry = false;
+ var lines = getPriFileContentsRecursively(priFilePath);
+ for (var j = 0; j < lines.length; ++j) {
+ var line = lines[j].trim();
+ var firstEqualsOffset = line.indexOf('=');
+ if (firstEqualsOffset === -1)
+ continue;
+ var key = line.slice(0, firstEqualsOffset).trim();
+ var value = line.slice(firstEqualsOffset + 1).trim();
+ if (!key.startsWith(moduleKeyPrefix) || !value)
+ continue;
+ if (key.endsWith(".name")) {
+ moduleInfo.name = value;
+ } else if (key.endsWith(".module")) {
+ hasModuleEntry = true;
+ } else if (key.endsWith(".depends")) {
+ moduleInfo.dependencies = splitNonEmpty(value, ' ');
+ for (var k = 0; k < moduleInfo.dependencies.length; ++k) {
+ moduleInfo.dependencies[k]
+ = moduleInfo.dependencies[k].replace("_private", "-private");
+ }
+ } else if (key.endsWith(".module_config")) {
+ var elems = splitNonEmpty(value, ' ');
+ for (k = 0; k < elems.length; ++k) {
+ var elem = elems[k];
+ if (elem === "no_link")
+ moduleInfo.hasLibrary = false;
+ else if (elem === "staticlib")
+ moduleInfo.isStaticLibrary = true;
+ else if (elem === "internal_module")
+ moduleInfo.isPrivate = true;
+ else if (elem === "v2")
+ hasV2 = true;
+ }
+ } else if (key.endsWith(".includes")) {
+ moduleInfo.includePaths = extractPaths(value, priFilePath);
+ for (k = 0; k < moduleInfo.includePaths.length; ++k) {
+ moduleInfo.includePaths[k] = moduleInfo.includePaths[k]
+ .replace("$$QT_MODULE_INCLUDE_BASE", qtProps.includePath)
+ .replace("$$QT_MODULE_LIB_BASE", 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.splice(k, 1);
+ moduleInfo.pluginData.autoLoad = false;
+ break;
+ }
+ }
+ } else if (key.endsWith(".CLASS_NAME")) {
+ moduleInfo.pluginData.className = value;
+ }
+ }
+ if (hasV2 && !hasModuleEntry)
+ moduleInfo.hasLibrary = false;
+
+ // Fix include paths for Apple frameworks.
+ // The qt_lib_XXX.pri files contain wrong values for versions < 5.6.
+ if (!hasV2 && isFramework(moduleInfo, qtProps)) {
+ moduleInfo.includePaths = [];
+ var baseIncDir = frameworkHeadersPath(moduleInfo, qtProps);
+ if (moduleInfo.isPrivate) {
+ baseIncDir = FileInfo.joinPaths(baseIncDir, moduleInfo.version);
+ moduleInfo.includePaths.push(baseIncDir,
+ FileInfo.joinPaths(baseIncDir, moduleInfo.name));
+ } else {
+ moduleInfo.includePaths.push(baseIncDir);
+ }
+ }
+
+ setupLibraries(moduleInfo, qtProps, nonExistingPrlFiles);
+
+ modules.push(moduleInfo);
+ if (moduleInfo.qbsName === "testlib")
+ addTestModule(modules);
+ if (moduleInfo.qbsName === "designercomponents-private")
+ addDesignerComponentsModule(modules);
+ }
+
+ replaceQtLibNamesWithFilePath(modules, qtProps);
+ removeDuplicatedDependencyLibs(modules);
+ return modules;
+}
+
+function extractQbsArchs(module, qtProps) {
+ if (qtProps.mkspecName.startsWith("macx-")) {
+ var archs = [];
+ if (module.libFilePathRelease)
+ archs = Utilities.getArchitecturesFromBinary(module.libFilePathRelease);
+ return archs;
+ }
+ var qbsArch = Utilities.canonicalArchitecture(qtProps.architecture);
+ if (qbsArch === "arm" && qtProps.mkspecPath.contains("android"))
+ qbsArch = "armv7a";
+
+ // Qt4 has "QT_ARCH = windows" in qconfig.pri for both MSVC and mingw.
+ if (qbsArch === "windows")
+ return []
+
+ return [qbsArch];
+}
+
+function qbsTargetPlatformFromQtMkspec(qtProps) {
+ var mkspec = qtProps.mkspecName;
+ var idx = mkspec.lastIndexOf('/');
+ if (idx !== -1)
+ mkspec = mkspec.slice(idx + 1);
+ if (mkspec.startsWith("aix-"))
+ return "aix";
+ if (mkspec.startsWith("android-"))
+ return "android";
+ if (mkspec.startsWith("cygwin-"))
+ return "windows";
+ if (mkspec.startsWith("darwin-"))
+ return "macos";
+ if (mkspec.startsWith("freebsd-"))
+ return "freebsd";
+ if (mkspec.startsWith("haiku-"))
+ return "haiku";
+ if (mkspec.startsWith(("hpux-")) || mkspec.startsWith(("hpuxi-")))
+ return "hpux";
+ if (mkspec.startsWith("hurd-"))
+ return "hurd";
+ if (mkspec.startsWith("integrity-"))
+ return "integrity";
+ if (mkspec.startsWith("linux-"))
+ return "linux";
+ if (mkspec.startsWith("macx-")) {
+ if (mkspec.startsWith("macx-ios-"))
+ return "ios";
+ if (mkspec.startsWith("macx-tvos-"))
+ return "tvos";
+ if (mkspec.startsWith("macx-watchos-"))
+ return "watchos";
+ return "macos";
+ }
+ if (mkspec.startsWith("netbsd-"))
+ return "netbsd";
+ if (mkspec.startsWith("openbsd-"))
+ return "openbsd";
+ if (mkspec.startsWith("qnx-"))
+ return "qnx";
+ if (mkspec.startsWith("solaris-"))
+ return "solaris";
+ if (mkspec.startsWith("vxworks-"))
+ return "vxworks";
+ if (targetsDesktopWindows(qtProps) || mkspec.startsWith("winrt-"))
+ return "windows";
+}
+
+function pathToJSLiteral(path) { return JSON.stringify(FileInfo.fromNativeSeparators(path)); }
+
+function defaultQpaPlugin(module, qtProps) {
+ if (qtProps.qtMajorVersion < 5)
+ return undefined;
+ if (qtProps.qtMajorVersion === 5 && qtProps.qtMinorVersion < 8) {
+ var qConfigPri = new TextFile(FileInfo.joinPaths(qtProps.mkspecBasePath, "qconfig.pri"));
+ var magicString = "QT_DEFAULT_QPA_PLUGIN =";
+ while (!qConfigPri.atEof()) {
+ var line = qConfigPri.readLine().trim();
+ if (line.startsWith(magicString))
+ return line.slice(magicString.length).trim();
+ }
+ qConfigPri.close();
+ } else {
+ var gtGuiHeadersPath = qtProps.frameworkBuild
+ ? FileInfo.joinPaths(qtProps.libraryPath, "QtGui.framework", "Headers")
+ : FileInfo.joinPaths(qtProps.includePath, "QtGui");
+ var qtGuiConfigHeader = FileInfo.joinPaths(gtGuiHeadersPath, "qtgui-config.h");
+ var headerFiles = [];
+ headerFiles.push(qtGuiConfigHeader);
+ while (headerFiles.length > 0) {
+ var filePath = headerFiles.shift();
+ var headerFile = new TextFile(filePath, TextFile.ReadOnly);
+ var regexp = /^#define QT_QPA_DEFAULT_PLATFORM_NAME "(.+)".*$/;
+ var includeRegexp = /^#include "(.+)".*$/;
+ while (!headerFile.atEof()) {
+ line = headerFile.readLine().trim();
+ var match = line.match(regexp);
+ if (match)
+ return 'q' + match[1];
+ match = line.match(includeRegexp);
+ if (match) {
+ var includedFile = match[1];
+ if (!FileInfo.isAbsolute(includedFile)) {
+ includedFile = FileInfo.cleanPath(
+ FileInfo.joinPaths(FileInfo.path(filePath), includedFile));
+ }
+ headerFiles.push(includedFile);
+ }
+ }
+ headerFile.close();
+ }
+ }
+
+ if (module.isStaticLibrary)
+ console.warn("Could not determine default QPA plugin for static Qt.");
+}
+
+function libraryFileTag(module, qtProps) {
+ if (module.isStaticLibrary)
+ return "staticlibrary";
+ return isMsvcQt(qtProps) || qtProps.mkspecName.startsWith("win32-g++")
+ ? "dynamiclibrary_import" : "dynamiclibrary";
+}
+
+function findVariable(content, start) {
+ var result = [-1, -1];
+ result[0] = content.indexOf('@', start);
+ if (result[0] === -1)
+ return result;
+ result[1] = content.indexOf('@', result[0] + 1);
+ if (result[1] === -1) {
+ result[0] = -1;
+ return result;
+ }
+ var forbiddenChars = [' ', '\n'];
+ for (var i = 0; i < forbiddenChars.length; ++i) {
+ var forbidden = forbiddenChars[i];
+ var k = content.indexOf(forbidden, result[0] + 1);
+ if (k !== -1 && k < result[1])
+ return findVariable(content, result[0] + 1);
+ }
+ return result;
+}
+
+function toJSLiteral(v) {
+ if (v === undefined)
+ return "undefined";
+ return JSON.stringify(v);
+}
+
+function minVersionJsString(minVersion) {
+ return !minVersion ? "original" : toJSLiteral(minVersion);
+}
+
+function replaceSpecialValues(content, module, qtProps) {
+ var dict = {
+ archs: toJSLiteral(extractQbsArchs(module, qtProps)),
+ targetPlatform: toJSLiteral(qbsTargetPlatformFromQtMkspec(qtProps)),
+ config: toJSLiteral(qtProps.configItems),
+ qtConfig: toJSLiteral(qtProps.qtConfigItems),
+ binPath: toJSLiteral(qtProps.binaryPath),
+ libPath: toJSLiteral(qtProps.libraryPath),
+ pluginPath: toJSLiteral(qtProps.pluginPath),
+ incPath: toJSLiteral(qtProps.includePath),
+ docPath: toJSLiteral(qtProps.documentationPath),
+ mkspecName: toJSLiteral(qtProps.mkspecName),
+ mkspecPath: toJSLiteral(qtProps.mkspecPath),
+ version: toJSLiteral(qtProps.qtVersion),
+ libInfix: toJSLiteral(qtProps.qtLibInfix),
+ availableBuildVariants: toJSLiteral(qtProps.buildVariant),
+ staticBuild: toJSLiteral(qtProps.staticBuild),
+ frameworkBuild: toJSLiteral(qtProps.frameworkBuild),
+ name: toJSLiteral(moduleNameWithoutPrefix(module)),
+ has_library: toJSLiteral(module.hasLibrary),
+ dependencies: toJSLiteral(module.dependencies),
+ includes: toJSLiteral(module.includePaths),
+ staticLibsDebug: toJSLiteral(module.staticLibrariesDebug),
+ staticLibsRelease: toJSLiteral(module.staticLibrariesRelease),
+ dynamicLibsDebug: toJSLiteral(module.dynamicLibrariesDebug),
+ dynamicLibsRelease: toJSLiteral(module.dynamicLibrariesRelease),
+ linkerFlagsDebug: toJSLiteral(module.linkerFlagsDebug),
+ linkerFlagsRelease: toJSLiteral(module.linkerFlagsRelease),
+ libraryPaths: toJSLiteral(module.libraryPaths),
+ frameworkPathsDebug: toJSLiteral(module.frameworkPathsDebug),
+ frameworkPathsRelease: toJSLiteral(module.frameworkPathsRelease),
+ frameworksDebug: toJSLiteral(module.frameworksDebug),
+ frameworksRelease: toJSLiteral(module.frameworksRelease),
+ libFilePathDebug: toJSLiteral(module.libFilePathDebug),
+ libFilePathRelease: toJSLiteral(module.libFilePathRelease),
+ libNameForLinkerDebug: toJSLiteral(libNameForLinker(module, qtProps, true)),
+ pluginTypes: toJSLiteral(module.supportedPluginTypes),
+ moduleConfig: toJSLiteral(module.config),
+ libNameForLinkerRelease: toJSLiteral(libNameForLinker(module, qtProps, false)),
+ entryPointLibsDebug: toJSLiteral(qtProps.entryPointLibsDebug),
+ entryPointLibsRelease: toJSLiteral(qtProps.entryPointLibsRelease),
+ minWinVersion: minVersionJsString(qtProps.windowsVersion),
+ minMacVersion: minVersionJsString(qtProps.macosVersion),
+ minIosVersion: minVersionJsString(qtProps.iosVersion),
+ minTvosVersion: minVersionJsString(qtProps.tvosVersion),
+ minWatchosVersion: minVersionJsString(qtProps.watchosVersion),
+ minAndroidVersion: minVersionJsString(qtProps.androidVersion),
+ };
+
+ var additionalContent = "";
+ var compilerDefines = toJSLiteral(module.compilerDefines);
+ if (module.qbsName === "declarative" || module.qbsName === "quick") {
+ var debugMacro = module.qbsName === "declarative" || qtProps.qtMajorVersion < 5
+ ? "QT_DECLARATIVE_DEBUG" : "QT_QML_DEBUG";
+ var indent = " ";
+ additionalContent = "property bool qmlDebugging: false\n"
+ + indent + "property string qmlPath";
+ if (qtProps.qmlPath)
+ additionalContent += ": " + pathToJSLiteral(qtProps.qmlPath) + '\n';
+ else
+ additionalContent += '\n';
+
+ additionalContent += indent + "property string qmlImportsPath: "
+ + pathToJSLiteral(qtProps.qmlImportPath);
+
+ compilerDefines = "{\n"
+ + indent + indent + "var result = " + compilerDefines + ";\n"
+ + indent + indent + "if (qmlDebugging)\n"
+ + indent + indent + indent + "result.push(\"" + debugMacro + "\");\n"
+ + indent + indent + "return result;\n"
+ + indent + "}";
+ }
+ dict.defines = compilerDefines;
+ if (module.qbsName === "gui")
+ dict.defaultQpaPlugin = toJSLiteral(defaultQpaPlugin(module, qtProps));
+ if (module.qbsName === "qml")
+ dict.qmlPath = pathToJSLiteral(qtProps.qmlPath);
+ if (module.isStaticLibrary && module.qbsName !== "core") {
+ if (additionalContent)
+ additionalContent += "\n ";
+ additionalContent += "isStaticLibrary: true";
+ }
+ if (module.isPlugin) {
+ dict.className = toJSLiteral(module.pluginData.className);
+ dict["extends"] = toJSLiteral(module.pluginData["extends"]);
+ }
+ if (module.hasLibrary && !isFramework(module, qtProps)) {
+ if (additionalContent)
+ additionalContent += "\n";
+ indent = " ";
+ additionalContent += "Group {\n";
+ if (module.isPlugin) {
+ additionalContent += indent + indent
+ + "condition: Qt[\"" + module.qbsName + "\"].enableLinking\n";
+ }
+ additionalContent += indent + indent + "files: [Qt[\"" + module.qbsName + "\"]"
+ + ".libFilePath]\n"
+ + indent + indent + "filesAreTargets: true\n"
+ + indent + indent + "fileTags: [\"" + libraryFileTag(module, qtProps)
+ + "\"]\n"
+ + indent + "}";
+ }
+ dict.additionalContent = additionalContent;
+
+ 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;
+ }
+ return content;
+}
+
+function copyTemplateFile(fileName, targetDirectory, qtProps, location, allFiles, module, pluginMap,
+ nonEssentialPlugins)
+{
+ if (!File.makePath(targetDirectory)) {
+ throw "Cannot create directory '" + toNative(targetDirectory) + "'.";
+ }
+ var sourceFile = new TextFile(FileInfo.joinPaths(location, "templates", fileName),
+ TextFile.ReadOnly);
+ var newContent = sourceFile.readAll();
+ if (module) {
+ newContent = replaceSpecialValues(newContent, module, qtProps);
+ } else {
+ newContent = newContent.replace("@allPluginsByType@",
+ '(' + toJSLiteral(pluginMap) + ')');
+ newContent = newContent.replace("@nonEssentialPlugins@",
+ toJSLiteral(nonEssentialPlugins));
+ }
+ sourceFile.close();
+ var targetPath = FileInfo.joinPaths(targetDirectory, fileName);
+ allFiles.push(targetPath);
+ var targetFile = new TextFile(targetPath, TextFile.WriteOnly);
+ targetFile.write(newContent);
+ targetFile.close();
+}
+
+function setupOneQt(qmakeFilePath, outputBaseDir, uniquify, location, qbs) {
+ if (!File.exists(qmakeFilePath))
+ throw "The specified qmake file path '" + toNative(qmakeFilePath) + "' does not exist.";
+ var qtProps = getQtProperties(qmakeFilePath, qbs);
+ var modules = qtProps.qtMajorVersion < 5 ? allQt4Modules(qtProps) : allQt5Modules(qtProps);
+ var pluginsByType = [];
+ var nonEssentialPlugins = [];
+ for (var i = 0; i < modules.length; ++i) {
+ var m = modules[i];
+ if (m.isPlugin) {
+ if (!pluginsByType[m.pluginData.type])
+ pluginsByType[m.pluginData.type] = [];
+ pluginsByType[m.pluginData.type].push(m.name);
+ if (!m.pluginData.autoLoad)
+ nonEssentialPlugins.push(m.name);
+ }
+ }
+
+ var relativeSearchPath = uniquify ? Utilities.getHash(qmakeFilePath) : "";
+ var qbsQtModuleBaseDir = FileInfo.joinPaths(outputBaseDir, relativeSearchPath, "modules", "Qt");
+ if (File.exists(qbsQtModuleBaseDir))
+ File.remove(qbsQtModuleBaseDir);
+
+ var allFiles = [];
+ copyTemplateFile("QtModule.qbs", qbsQtModuleBaseDir, qtProps, location, allFiles);
+ copyTemplateFile("QtPlugin.qbs", qbsQtModuleBaseDir, qtProps, location, allFiles);
+ copyTemplateFile("plugin_support.qbs", FileInfo.joinPaths(qbsQtModuleBaseDir, "plugin_support"),
+ qtProps, location, allFiles, undefined, pluginsByType, nonEssentialPlugins);
+
+ for (i = 0; i < modules.length; ++i) {
+ var module = modules[i];
+ var qbsQtModuleDir = FileInfo.joinPaths(qbsQtModuleBaseDir, module.qbsName);
+ var moduleTemplateFileName;
+ if (module.qbsName === "core") {
+ moduleTemplateFileName = "core.qbs";
+ copyTemplateFile("moc.js", qbsQtModuleDir, qtProps, location, allFiles);
+ copyTemplateFile("qdoc.js", qbsQtModuleDir, qtProps, location, allFiles);
+ } else if (module.qbsName === "gui") {
+ moduleTemplateFileName = "gui.qbs";
+ } else if (module.qbsName === "scxml") {
+ moduleTemplateFileName = "scxml.qbs";
+ } else if (module.qbsName === "dbus") {
+ moduleTemplateFileName = "dbus.qbs";
+ copyTemplateFile("dbus.js", qbsQtModuleDir, qtProps, location, allFiles);
+ } else if (module.qbsName === "qml") {
+ moduleTemplateFileName = "qml.qbs";
+ copyTemplateFile("qml.js", qbsQtModuleDir, qtProps, location, allFiles);
+ var qmlcacheStr = "qmlcache";
+ if (File.exists(FileInfo.joinPaths(qtProps.binaryPath,
+ "qmlcachegen" + exeSuffix(qbs)))) {
+ copyTemplateFile(qmlcacheStr + ".qbs",
+ FileInfo.joinPaths(qbsQtModuleBaseDir, qmlcacheStr), qtProps,
+ location, allFiles);
+ }
+ } else if (module.qbsName === "quick") {
+ moduleTemplateFileName = "quick.qbs";
+ copyTemplateFile("quick.js", qbsQtModuleDir, qtProps, location, allFiles);
+ } else if (module.isPlugin) {
+ moduleTemplateFileName = "plugin.qbs";
+ } else {
+ moduleTemplateFileName = "module.qbs";
+ }
+ copyTemplateFile(moduleTemplateFileName, qbsQtModuleDir, qtProps, location, allFiles,
+ module);
+ }
+
+ // Note that it's not strictly necessary to copy this one, as it has no variable content.
+ // But we do it anyway for consistency.
+ copyTemplateFile("android_support.qbs",
+ FileInfo.joinPaths(qbsQtModuleBaseDir, "android_support"),
+ qtProps, location, allFiles);
+ return relativeSearchPath;
+}
+
+function doSetup(qmakeFilePaths, outputBaseDir, location, qbs) {
+ qmakeFilePaths = getQmakeFilePaths(qmakeFilePaths, qbs);
+ if (!qmakeFilePaths || qmakeFilePaths.length === 0)
+ return [];
+ var uniquifySearchPath = qmakeFilePaths.length > 1;
+ var searchPaths = [];
+ for (var i = 0; i < qmakeFilePaths.length; ++i) {
+ try {
+ console.info("Setting up Qt at '" + toNative(qmakeFilePaths[i]) + "'...");
+ var searchPath = setupOneQt(qmakeFilePaths[i], outputBaseDir, uniquifySearchPath,
+ location, qbs);
+ if (searchPath !== undefined) {
+ searchPaths.push(searchPath);
+ console.info("Qt was set up successfully.");
+ }
+ } catch (e) {
+ console.warn("Error setting up Qt for '" + toNative(qmakeFilePaths[i]) + "': " + e);
+ }
+ }
+ return searchPaths;
+}
diff --git a/src/lib/qtprofilesetup/templates/QtModule.qbs b/share/qbs/module-providers/Qt/templates/QtModule.qbs
index aa7c1d15a..aa7c1d15a 100644
--- a/src/lib/qtprofilesetup/templates/QtModule.qbs
+++ b/share/qbs/module-providers/Qt/templates/QtModule.qbs
diff --git a/src/lib/qtprofilesetup/templates/QtPlugin.qbs b/share/qbs/module-providers/Qt/templates/QtPlugin.qbs
index 23a6795f3..23a6795f3 100644
--- a/src/lib/qtprofilesetup/templates/QtPlugin.qbs
+++ b/share/qbs/module-providers/Qt/templates/QtPlugin.qbs
diff --git a/src/lib/qtprofilesetup/templates/android_support.qbs b/share/qbs/module-providers/Qt/templates/android_support.qbs
index 79276a494..79276a494 100644
--- a/src/lib/qtprofilesetup/templates/android_support.qbs
+++ b/share/qbs/module-providers/Qt/templates/android_support.qbs
diff --git a/src/lib/qtprofilesetup/templates/core.qbs b/share/qbs/module-providers/Qt/templates/core.qbs
index b2f05d8e9..b2f05d8e9 100644
--- a/src/lib/qtprofilesetup/templates/core.qbs
+++ b/share/qbs/module-providers/Qt/templates/core.qbs
diff --git a/src/lib/qtprofilesetup/templates/dbus.js b/share/qbs/module-providers/Qt/templates/dbus.js
index 0674bf684..0674bf684 100644
--- a/src/lib/qtprofilesetup/templates/dbus.js
+++ b/share/qbs/module-providers/Qt/templates/dbus.js
diff --git a/src/lib/qtprofilesetup/templates/dbus.qbs b/share/qbs/module-providers/Qt/templates/dbus.qbs
index 6556e2c9b..6556e2c9b 100644
--- a/src/lib/qtprofilesetup/templates/dbus.qbs
+++ b/share/qbs/module-providers/Qt/templates/dbus.qbs
diff --git a/src/lib/qtprofilesetup/templates/gui.qbs b/share/qbs/module-providers/Qt/templates/gui.qbs
index eb69e0cad..eb69e0cad 100644
--- a/src/lib/qtprofilesetup/templates/gui.qbs
+++ b/share/qbs/module-providers/Qt/templates/gui.qbs
diff --git a/src/lib/qtprofilesetup/templates/moc.js b/share/qbs/module-providers/Qt/templates/moc.js
index aa67766b9..aa67766b9 100644
--- a/src/lib/qtprofilesetup/templates/moc.js
+++ b/share/qbs/module-providers/Qt/templates/moc.js
diff --git a/src/lib/qtprofilesetup/templates/module.qbs b/share/qbs/module-providers/Qt/templates/module.qbs
index b09f79a87..b09f79a87 100644
--- a/src/lib/qtprofilesetup/templates/module.qbs
+++ b/share/qbs/module-providers/Qt/templates/module.qbs
diff --git a/src/lib/qtprofilesetup/templates/plugin.qbs b/share/qbs/module-providers/Qt/templates/plugin.qbs
index e73e2a4d9..e73e2a4d9 100644
--- a/src/lib/qtprofilesetup/templates/plugin.qbs
+++ b/share/qbs/module-providers/Qt/templates/plugin.qbs
diff --git a/src/lib/qtprofilesetup/templates/plugin_support.qbs b/share/qbs/module-providers/Qt/templates/plugin_support.qbs
index 13d95c383..13d95c383 100644
--- a/src/lib/qtprofilesetup/templates/plugin_support.qbs
+++ b/share/qbs/module-providers/Qt/templates/plugin_support.qbs
diff --git a/src/lib/qtprofilesetup/templates/qdoc.js b/share/qbs/module-providers/Qt/templates/qdoc.js
index 72c161c56..72c161c56 100644
--- a/src/lib/qtprofilesetup/templates/qdoc.js
+++ b/share/qbs/module-providers/Qt/templates/qdoc.js
diff --git a/src/lib/qtprofilesetup/templates/qml.js b/share/qbs/module-providers/Qt/templates/qml.js
index c7829d81b..c7829d81b 100644
--- a/src/lib/qtprofilesetup/templates/qml.js
+++ b/share/qbs/module-providers/Qt/templates/qml.js
diff --git a/src/lib/qtprofilesetup/templates/qml.qbs b/share/qbs/module-providers/Qt/templates/qml.qbs
index 2b11abbd5..2b11abbd5 100644
--- a/src/lib/qtprofilesetup/templates/qml.qbs
+++ b/share/qbs/module-providers/Qt/templates/qml.qbs
diff --git a/src/lib/qtprofilesetup/templates/qmlcache.qbs b/share/qbs/module-providers/Qt/templates/qmlcache.qbs
index 9111eb500..9111eb500 100644
--- a/src/lib/qtprofilesetup/templates/qmlcache.qbs
+++ b/share/qbs/module-providers/Qt/templates/qmlcache.qbs
diff --git a/src/lib/qtprofilesetup/templates/quick.js b/share/qbs/module-providers/Qt/templates/quick.js
index 4f3da2fb0..4f3da2fb0 100644
--- a/src/lib/qtprofilesetup/templates/quick.js
+++ b/share/qbs/module-providers/Qt/templates/quick.js
diff --git a/src/lib/qtprofilesetup/templates/quick.qbs b/share/qbs/module-providers/Qt/templates/quick.qbs
index 5968949c8..5968949c8 100644
--- a/src/lib/qtprofilesetup/templates/quick.qbs
+++ b/share/qbs/module-providers/Qt/templates/quick.qbs
diff --git a/src/lib/qtprofilesetup/templates/scxml.qbs b/share/qbs/module-providers/Qt/templates/scxml.qbs
index 7125ec53c..7125ec53c 100644
--- a/src/lib/qtprofilesetup/templates/scxml.qbs
+++ b/share/qbs/module-providers/Qt/templates/scxml.qbs
diff --git a/src/app/qbs-setup-android/android-setup.cpp b/src/app/qbs-setup-android/android-setup.cpp
index d32cdbc05..8c7373652 100644
--- a/src/app/qbs-setup-android/android-setup.cpp
+++ b/src/app/qbs-setup-android/android-setup.cpp
@@ -224,7 +224,7 @@ static void setupNdk(qbs::Settings *settings, const QString &profileName, const
mainProfile.setValue(qls("qbs.architecture"), archsForProfile.front());
else
mainProfile.setValue(qls("qbs.architectures"), archsForProfile);
- QStringList searchPaths;
+ QStringList qmakeFilePaths;
QString platform;
for (const QString &arch : archs) {
const QtAndroidInfo qtAndroidInfo = infoPerArch.value(arch);
@@ -248,11 +248,11 @@ static void setupNdk(qbs::Settings *settings, const QString &profileName, const
}
settings->sync();
qbs::Internal::TemporaryProfile p(subProName, settings);
- searchPaths << p.p.value(qls("preferences.qbsSearchPaths")).toStringList();
+ qmakeFilePaths << p.p.value(qls("moduleProviders.Qt.qmakeFilePaths")).toStringList();
platform = maximumPlatform(platform, qtAndroidInfo.platform);
}
- if (!searchPaths.empty())
- mainProfile.setValue(qls("preferences.qbsSearchPaths"), searchPaths);
+ if (!qmakeFilePaths.empty())
+ mainProfile.setValue(qls("moduleProviders.Qt.qmakeFilePaths"), qmakeFilePaths);
if (!platform.isEmpty())
mainProfile.setValue(qls("Android.ndk.platform"), platform);
}
diff --git a/src/app/qbs-setup-qt/main.cpp b/src/app/qbs-setup-qt/main.cpp
index d1bfd9614..94185c4d7 100644
--- a/src/app/qbs-setup-qt/main.cpp
+++ b/src/app/qbs-setup-qt/main.cpp
@@ -40,7 +40,6 @@
#include "commandlineparser.h"
-#include <qtprofilesetup.h>
#include <logging/translator.h>
#include <tools/settings.h>
@@ -72,16 +71,16 @@ int main(int argc, char *argv[])
if (clParser.autoDetectionMode()) {
// search all Qt's in path and dump their settings
- const std::vector<EnhancedQtEnvironment> qtEnvironments = SetupQt::fetchEnvironments();
+ const std::vector<QtEnvironment> qtEnvironments = SetupQt::fetchEnvironments();
if (qtEnvironments.empty()) {
std::cout << qPrintable(Tr::tr("No Qt installations detected. "
"No profiles created."))
<< std::endl;
}
- for (const EnhancedQtEnvironment &qtEnvironment : qtEnvironments) {
- QString profileName = QLatin1String("qt-") + qtEnvironment.qtVersion;
+ for (const QtEnvironment &qtEnvironment : qtEnvironments) {
+ QString profileName = QLatin1String("qt-") + qtEnvironment.qtVersion.toString();
if (SetupQt::checkIfMoreThanOneQtWithTheSameVersion(qtEnvironment.qtVersion, qtEnvironments)) {
- QStringList prefixPathParts = qtEnvironment.installPrefixPath
+ QStringList prefixPathParts = QFileInfo(qtEnvironment.qmakeFilePath).path()
.split(QLatin1Char('/'), QString::SkipEmptyParts);
if (!prefixPathParts.empty())
profileName += QLatin1String("-") + prefixPathParts.last();
@@ -97,7 +96,7 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}
- EnhancedQtEnvironment qtEnvironment = SetupQt::fetchEnvironment(clParser.qmakePath());
+ const QtEnvironment qtEnvironment = SetupQt::fetchEnvironment(clParser.qmakePath());
QString profileName = clParser.profileName();
profileName.replace(QLatin1Char('.'), QLatin1Char('-'));
SetupQt::saveToQbsSettings(profileName, qtEnvironment, &settings);
diff --git a/src/app/qbs-setup-qt/qbs-setup-qt.pro b/src/app/qbs-setup-qt/qbs-setup-qt.pro
index 036a4e74c..a5694d6b7 100644
--- a/src/app/qbs-setup-qt/qbs-setup-qt.pro
+++ b/src/app/qbs-setup-qt/qbs-setup-qt.pro
@@ -1,5 +1,4 @@
include(../app.pri)
-include($${PWD}/../../lib/qtprofilesetup/use_qtprofilesetup.pri)
TARGET = qbs-setup-qt
diff --git a/src/app/qbs-setup-qt/qbs-setup-qt.qbs b/src/app/qbs-setup-qt/qbs-setup-qt.qbs
index 8bd4ae263..f4cd9d6b8 100644
--- a/src/app/qbs-setup-qt/qbs-setup-qt.qbs
+++ b/src/app/qbs-setup-qt/qbs-setup-qt.qbs
@@ -2,7 +2,6 @@ import qbs 1.0
QbsApp {
name: "qbs-setup-qt"
- Depends { name: "qbsqtprofilesetup" }
files: [
"commandlineparser.cpp",
"commandlineparser.h",
diff --git a/src/app/qbs-setup-qt/setupqt.cpp b/src/app/qbs-setup-qt/setupqt.cpp
index f54411b48..d4a59e30b 100644
--- a/src/app/qbs-setup-qt/setupqt.cpp
+++ b/src/app/qbs-setup-qt/setupqt.cpp
@@ -40,8 +40,6 @@
#include "setupqt.h"
#include "../shared/logging/consolelogger.h"
-#include <qtmsvctools.h>
-#include <qtprofilesetup.h>
#include <logging/translator.h>
#include <tools/architectures.h>
#include <tools/hostosinfo.h>
@@ -56,10 +54,10 @@
#include <QtCore/qdir.h>
#include <QtCore/qfileinfo.h>
#include <QtCore/qprocess.h>
-#include <QtCore/qregexp.h>
#include <QtCore/qstringlist.h>
#include <algorithm>
+#include <regex>
namespace qbs {
using Internal::none_of;
@@ -105,210 +103,91 @@ bool SetupQt::isQMakePathValid(const QString &qmakePath)
return qmakeFileInfo.exists() && qmakeFileInfo.isFile() && qmakeFileInfo.isExecutable();
}
-std::vector<EnhancedQtEnvironment> SetupQt::fetchEnvironments()
+std::vector<QtEnvironment> SetupQt::fetchEnvironments()
{
- std::vector<EnhancedQtEnvironment> qtEnvironments;
-
+ std::vector<QtEnvironment> qtEnvironments;
const auto qmakePaths = collectQmakePaths();
for (const QString &qmakePath : qmakePaths) {
- const EnhancedQtEnvironment env = fetchEnvironment(qmakePath);
- if (none_of(qtEnvironments, [&env](const EnhancedQtEnvironment &otherEnv) {
- return env.includePath == otherEnv.includePath;
+ const QtEnvironment env = fetchEnvironment(qmakePath);
+ if (none_of(qtEnvironments, [&env](const QtEnvironment &otherEnv) {
+ return env.qmakeFilePath == otherEnv.qmakeFilePath;
})) {
qtEnvironments.push_back(env);
}
}
-
return qtEnvironments;
}
-void SetupQt::addQtBuildVariant(QtEnvironment *env, const QString &buildVariantName)
+// These functions work only for Qt from installer.
+static QStringList qbsToolchainFromDirName(const QString &dir)
{
- if (env->qtConfigItems.contains(buildVariantName))
- env->buildVariant << buildVariantName;
+ if (dir.startsWith(QLatin1String("msvc")))
+ return QStringList(QLatin1String("msvc"));
+ if (dir.startsWith(QLatin1String("mingw")))
+ return QStringList{QLatin1String("mingw"), QLatin1String("gcc")};
+ if (dir.startsWith(QLatin1String("clang")))
+ return QStringList{QLatin1String("clang"), QLatin1String("llvm"), QLatin1String("gcc")};
+ if (dir.startsWith(QLatin1String("gcc")))
+ return QStringList(QLatin1String("gcc"));
+ return QStringList();
}
-static QMap<QByteArray, QByteArray> qmakeQueryOutput(const QString &qmakePath)
+static Version msvcVersionFromDirName(const QString &dir)
{
- QProcess qmakeProcess;
- qmakeProcess.start(qmakePath, QStringList() << QLatin1String("-query"));
- if (!qmakeProcess.waitForStarted())
- throw ErrorInfo(SetupQt::tr("%1 cannot be started.").arg(qmakePath));
- qmakeProcess.waitForFinished();
- const QByteArray output = qmakeProcess.readAllStandardOutput();
-
- QMap<QByteArray, QByteArray> ret;
- const auto lines = output.split('\n');
- for (const QByteArray &line : lines) {
- int idx = line.indexOf(':');
- if (idx >= 0)
- ret[line.left(idx)] = line.mid(idx + 1).trimmed();
- }
- return ret;
+ static const std::regex regexp("^msvc(\\d\\d\\d\\d)_.*$");
+ std::smatch match;
+ const std::string dirString = dir.toStdString();
+ if (!std::regex_match(dirString, match, regexp))
+ return Version();
+ QMap<std::string, std::string> mapping{
+ std::make_pair("2005", "14"), std::make_pair("2008", "15"), std::make_pair("2010", "16"),
+ std::make_pair("2012", "17"), std::make_pair("2013", "18"), std::make_pair("2015", "19"),
+ std::make_pair("2017", "19.1")
+ };
+ return Version::fromString(QString::fromStdString(mapping.value(match[1].str())));
}
-static QByteArray readFileContent(const QString &filePath)
+static QString archFromDirName(const QString &dir)
{
- QFile file(filePath);
- if (file.open(QFile::ReadOnly))
- return file.readAll();
-
- return QByteArray();
+ static const std::regex regexp("^[^_]+_(.*).*$");
+ std::smatch match;
+ const std::string dirString = dir.toStdString();
+ if (!std::regex_match(dirString, match, regexp))
+ return QString();
+ const QString arch = QString::fromStdString(match[1]);
+ if (arch == QLatin1String("32"))
+ return QLatin1String("x86");
+ if (arch == QLatin1String("64"))
+ return QLatin1String("x86_64");
+ if (arch.contains(QLatin1String("arm64")))
+ return QLatin1String("arm64");
+ return arch;
}
-static QString configVariable(const QByteArray &configContent, const QString &key)
+static QString platformFromDirName(const QString &dir)
{
- QRegExp regexp(QLatin1String("\\s*") + key + QLatin1String("\\s*\\+{0,1}=(.*)"),
- Qt::CaseSensitive);
-
- const QList<QByteArray> configContentLines = configContent.split('\n');
-
- bool success = false;
-
- for (const QByteArray &configContentLine : configContentLines) {
- success = regexp.exactMatch(QString::fromLocal8Bit(configContentLine));
- if (success)
- break;
- }
-
- if (success)
- return regexp.capturedTexts()[1].simplified();
-
- return QString();
-}
-
-static QStringList configVariableItems(const QByteArray &configContent, const QString &key)
-{
- return configVariable(configContent, key).split(QLatin1Char(' '), QString::SkipEmptyParts);
-}
-
-typedef QMap<QByteArray, QByteArray> QueryMap;
-
-static QString pathQueryValue(const QueryMap &queryMap, const QByteArray &key)
-{
- return QDir::fromNativeSeparators(QString::fromLocal8Bit(queryMap.value(key)));
+ if (dir.startsWith(QLatin1String("android")))
+ return QLatin1String("android");
+ if (dir == QLatin1String("Boot2Qt"))
+ return QLatin1String("linux");
+ return QString::fromStdString(HostOsInfo::hostOSIdentifier());
}
-EnhancedQtEnvironment SetupQt::fetchEnvironment(const QString &qmakePath)
+QtEnvironment SetupQt::fetchEnvironment(const QString &qmakePath)
{
- EnhancedQtEnvironment qtEnvironment;
- QueryMap queryOutput = qmakeQueryOutput(qmakePath);
-
- qtEnvironment.installPrefixPath = pathQueryValue(queryOutput, "QT_INSTALL_PREFIX");
- qtEnvironment.documentationPath = pathQueryValue(queryOutput, "QT_INSTALL_DOCS");
- qtEnvironment.includePath = pathQueryValue(queryOutput, "QT_INSTALL_HEADERS");
- qtEnvironment.libraryPath = pathQueryValue(queryOutput, "QT_INSTALL_LIBS");
- qtEnvironment.binaryPath = pathQueryValue(queryOutput, "QT_HOST_BINS");
- if (qtEnvironment.binaryPath.isEmpty())
- qtEnvironment.binaryPath = pathQueryValue(queryOutput, "QT_INSTALL_BINS");
- qtEnvironment.documentationPath = pathQueryValue(queryOutput, "QT_INSTALL_DOCS");
- qtEnvironment.pluginPath = pathQueryValue(queryOutput, "QT_INSTALL_PLUGINS");
- qtEnvironment.qmlPath = pathQueryValue(queryOutput, "QT_INSTALL_QML");
- qtEnvironment.qmlImportPath = pathQueryValue(queryOutput, "QT_INSTALL_IMPORTS");
- qtEnvironment.qtVersion = QString::fromLocal8Bit(queryOutput.value("QT_VERSION"));
-
- const Version qtVersion = Version::fromString(qtEnvironment.qtVersion);
-
- QString mkspecsBaseSrcPath;
- if (qtVersion.majorVersion() >= 5) {
- qtEnvironment.mkspecBasePath
- = pathQueryValue(queryOutput, "QT_HOST_DATA") + QLatin1String("/mkspecs");
- mkspecsBaseSrcPath
- = pathQueryValue(queryOutput, "QT_HOST_DATA/src") + QLatin1String("/mkspecs");
- } else {
- qtEnvironment.mkspecBasePath
- = pathQueryValue(queryOutput, "QT_INSTALL_DATA") + QLatin1String("/mkspecs");
- }
-
- if (!QFile::exists(qtEnvironment.mkspecBasePath))
- throw ErrorInfo(tr("Cannot extract the mkspecs directory."));
-
- const QByteArray qconfigContent = readFileContent(qtEnvironment.mkspecBasePath
- + QLatin1String("/qconfig.pri"));
- qtEnvironment.qtMajorVersion = configVariable(qconfigContent,
- QLatin1String("QT_MAJOR_VERSION")).toInt();
- qtEnvironment.qtMinorVersion = configVariable(qconfigContent,
- QLatin1String("QT_MINOR_VERSION")).toInt();
- qtEnvironment.qtPatchVersion = configVariable(qconfigContent,
- QLatin1String("QT_PATCH_VERSION")).toInt();
- qtEnvironment.qtNameSpace = configVariable(qconfigContent, QLatin1String("QT_NAMESPACE"));
- qtEnvironment.qtLibInfix = configVariable(qconfigContent, QLatin1String("QT_LIBINFIX"));
- qtEnvironment.architecture = configVariable(qconfigContent, QLatin1String("QT_TARGET_ARCH"));
- if (qtEnvironment.architecture.isEmpty())
- qtEnvironment.architecture = configVariable(qconfigContent, QLatin1String("QT_ARCH"));
- if (qtEnvironment.architecture.isEmpty())
- qtEnvironment.architecture = QLatin1String("x86");
- qtEnvironment.configItems = configVariableItems(qconfigContent, QLatin1String("CONFIG"));
- qtEnvironment.qtConfigItems = configVariableItems(qconfigContent, QLatin1String("QT_CONFIG"));
-
- // retrieve the mkspec
- if (qtVersion.majorVersion() >= 5) {
- const QString mkspecName = QString::fromLocal8Bit(queryOutput.value("QMAKE_XSPEC"));
- qtEnvironment.mkspecName = mkspecName;
- qtEnvironment.mkspecPath = qtEnvironment.mkspecBasePath + QLatin1Char('/') + mkspecName;
- if (!mkspecsBaseSrcPath.isEmpty() && !QFile::exists(qtEnvironment.mkspecPath))
- qtEnvironment.mkspecPath = mkspecsBaseSrcPath + QLatin1Char('/') + mkspecName;
- } else {
- if (HostOsInfo::isWindowsHost()) {
- const QString baseDirPath = qtEnvironment.mkspecBasePath + QLatin1String("/default/");
- const QByteArray fileContent = readFileContent(baseDirPath
- + QLatin1String("qmake.conf"));
- qtEnvironment.mkspecPath = configVariable(fileContent,
- QLatin1String("QMAKESPEC_ORIGINAL"));
- if (!QFile::exists(qtEnvironment.mkspecPath)) {
- // Work around QTBUG-28792.
- // The value of QMAKESPEC_ORIGINAL is wrong for MinGW packages. Y u h8 me?
- const QRegExp rex(QLatin1String("\\binclude\\(([^)]+)/qmake\\.conf\\)"));
- if (rex.indexIn(QString::fromLocal8Bit(fileContent)) != -1)
- qtEnvironment.mkspecPath = QDir::cleanPath(baseDirPath + rex.cap(1));
- }
- } else {
- qtEnvironment.mkspecPath = QFileInfo(qtEnvironment.mkspecBasePath
- + QLatin1String("/default")).symLinkTarget();
- }
-
- // 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++
- qtEnvironment.mkspecPath = QDir::cleanPath(qtEnvironment.mkspecPath);
-
- qtEnvironment.mkspecName = qtEnvironment.mkspecPath;
- int idx = qtEnvironment.mkspecName.lastIndexOf(QLatin1Char('/'));
- if (idx != -1)
- qtEnvironment.mkspecName.remove(0, idx + 1);
+ QtEnvironment env;
+ env.qmakeFilePath = qmakePath;
+ QDir qtDir = QFileInfo(qmakePath).dir();
+ if (qtDir.dirName() == QLatin1String("bin")) {
+ qtDir.cdUp();
+ env.qbsToolchain = qbsToolchainFromDirName(qtDir.dirName());
+ env.msvcVersion = msvcVersionFromDirName(qtDir.dirName());
+ env.architecture = archFromDirName(qtDir.dirName());
+ env.targetPlatform = platformFromDirName(qtDir.dirName());
+ qtDir.cdUp();
+ env.qtVersion = Version::fromString(qtDir.dirName());
}
-
- // determine MSVC version
- if (isMsvcQt(qtEnvironment)) {
- bool ok;
- qtEnvironment.msvcVersion.setMajorVersion(
- configVariable(qconfigContent,
- QLatin1String("QT_MSVC_MAJOR_VERSION")).toInt(&ok));
- if (ok) {
- qtEnvironment.msvcVersion.setMinorVersion(
- configVariable(qconfigContent,
- QLatin1String("QT_MSVC_MINOR_VERSION")).toInt(&ok));
- }
- if (ok) {
- qtEnvironment.msvcVersion.setPatchLevel(
- configVariable(qconfigContent,
- QLatin1String("QT_MSVC_PATCH_VERSION")).toInt(&ok));
- }
- if (!ok)
- qtEnvironment.msvcVersion = msvcCompilerVersionFromMkspecName(qtEnvironment.mkspecName);
- }
-
- // determine whether we have a framework build
- qtEnvironment.frameworkBuild = qtEnvironment.mkspecPath.contains(QLatin1String("macx"))
- && qtEnvironment.configItems.contains(QLatin1String("qt_framework"));
-
- // determine whether Qt is built with debug, release or both
- addQtBuildVariant(&qtEnvironment, QLatin1String("debug"));
- addQtBuildVariant(&qtEnvironment, QLatin1String("release"));
-
- if (!QFileInfo(qtEnvironment.mkspecPath).exists())
- throw ErrorInfo(tr("mkspec '%1' does not exist").arg(qtEnvironment.mkspecPath));
-
- return qtEnvironment;
+ return env;
}
static bool isToolchainProfile(const Profile &profile)
@@ -323,6 +202,12 @@ static bool isToolchainProfile(const Profile &profile)
static bool isQtProfile(const Profile &profile)
{
+ if (!profile.value(QStringLiteral("moduleProviders.Qt.qmakeFilePaths")).toStringList()
+ .empty()) {
+ return true;
+ }
+
+ // For Profiles created with setup-qt < 5.13.
const QStringList searchPaths
= profile.value(QStringLiteral("preferences.qbsSearchPaths")).toStringList();
return std::any_of(searchPaths.cbegin(), searchPaths.cend(), [] (const QString &path) {
@@ -337,39 +222,18 @@ template <typename T> bool areProfilePropertiesIncompatible(const T &set1, const
return set1.size() > 0 && set2.size() > 0 && set1 != set2;
}
-static QStringList qbsToolchainFromQtMkspec(const QtEnvironment &qtEnv)
-{
- const QString mkspec = qtEnv.mkspecName;
- if (mkspec.contains(QLatin1String("-msvc")))
- return QStringList() << QLatin1String("msvc");
- if (qtEnv.isForMinGw())
- return QStringList() << QLatin1String("mingw") << QLatin1String("gcc");
-
- if (mkspec.contains(QLatin1String("-clang")))
- return QStringList() << QLatin1String("clang") << QLatin1String("llvm")
- << QLatin1String("gcc");
- if (mkspec.contains(QLatin1String("-llvm")))
- return QStringList() << QLatin1String("llvm") << QLatin1String("gcc");
- if (mkspec.contains(QLatin1String("-g++")))
- return QStringList() << QLatin1String("gcc");
-
- // Worry about other, less common toolchains (ICC, QCC, etc.) later...
- return QStringList();
-}
-
enum Match { MatchFull, MatchPartial, MatchNone };
-static Match compatibility(const EnhancedQtEnvironment &env, const Profile &toolchainProfile)
+static Match compatibility(const QtEnvironment &env, const Profile &toolchainProfile)
{
Match match = MatchFull;
const auto toolchainNames = Internal::Set<QString>::fromList(
toolchainProfile.value(QLatin1String("qbs.toolchain")).toStringList());
- const auto mkspecToolchainNames = Internal::Set<QString>::fromList(
- qbsToolchainFromQtMkspec(env));
- if (areProfilePropertiesIncompatible(toolchainNames, mkspecToolchainNames)) {
+ const auto qtToolchainNames = Internal::Set<QString>::fromList(env.qbsToolchain);
+ if (areProfilePropertiesIncompatible(toolchainNames, qtToolchainNames)) {
auto intersection = toolchainNames;
- intersection.intersect(mkspecToolchainNames);
+ intersection.intersect(qtToolchainNames);
if (!intersection.empty())
match = MatchPartial;
else
@@ -378,7 +242,7 @@ static Match compatibility(const EnhancedQtEnvironment &env, const Profile &tool
const auto targetPlatform = toolchainProfile.value(
QLatin1String("qbs.targetPlatform")).toString();
- if (!targetPlatform.isEmpty() && targetPlatform != qbsTargetPlatformFromQtMkspec(env))
+ if (!targetPlatform.isEmpty() && targetPlatform != env.targetPlatform)
return MatchNone;
const QString toolchainArchitecture = toolchainProfile.value(QLatin1String("qbs.architecture"))
@@ -438,7 +302,7 @@ static void compressMsvcProfiles(QStringList &profiles)
}
void SetupQt::saveToQbsSettings(const QString &qtVersionName,
- const EnhancedQtEnvironment &qtEnvironment,
+ const QtEnvironment &qtEnvironment,
Settings *settings)
{
const QString cleanQtVersionName = Profile::cleanName(qtVersionName);
@@ -446,14 +310,10 @@ void SetupQt::saveToQbsSettings(const QString &qtVersionName,
.arg(cleanQtVersionName);
printf("%s\n", qPrintable(msg));
- const ErrorInfo errorInfo = setupQtProfile(cleanQtVersionName, settings, qtEnvironment);
- if (errorInfo.hasError())
- throw errorInfo;
-
- // If this profile does not specify a toolchain and we find exactly one profile that looks
- // like it might have been added by qbs-setup-toolchains, let's use that one as our
- // base profile.
Profile profile(cleanQtVersionName, settings);
+ profile.removeProfile();
+ profile.setValue(QLatin1String("moduleProviders.Qt.qmakeFilePaths"),
+ QStringList(qtEnvironment.qmakeFilePath));
if (!profile.baseProfile().isEmpty())
return;
if (isToolchainProfile(profile))
@@ -490,19 +350,14 @@ void SetupQt::saveToQbsSettings(const QString &qtVersionName,
else if (fullMatches.empty() && partialMatches.size() == 1)
bestMatch = partialMatches.front();
if (bestMatch.isEmpty()) {
- QString message = Tr::tr("You need to set up toolchain information before you can "
- "use this Qt version for building. ");
- if (fullMatches.empty() && partialMatches.empty()) {
- message += Tr::tr("However, no toolchain profile was found. Either create one "
- "using qbs-setup-toolchains and set it as this profile's "
- "base profile or add the toolchain settings manually "
- "to this profile.");
- } else {
+ QString message = Tr::tr("You may want to set up toolchain information "
+ "for the generated Qt profile. ");
+ if (!fullMatches.empty() || !partialMatches.empty()) {
message += Tr::tr("Consider setting one of these profiles as this profile's base "
"profile: %1.").arg((fullMatches + partialMatches)
.join(QLatin1String(", ")));
}
- qbsWarning() << message;
+ qbsInfo() << message;
} else {
profile.setBaseProfile(bestMatch);
qbsInfo() << Tr::tr("Setting profile '%1' as the base profile for this profile.")
@@ -510,8 +365,8 @@ void SetupQt::saveToQbsSettings(const QString &qtVersionName,
}
}
-bool SetupQt::checkIfMoreThanOneQtWithTheSameVersion(const QString &qtVersion,
- const std::vector<EnhancedQtEnvironment> &qtEnvironments)
+bool SetupQt::checkIfMoreThanOneQtWithTheSameVersion(const Version &qtVersion,
+ const std::vector<QtEnvironment> &qtEnvironments)
{
bool foundOneVersion = false;
for (const QtEnvironment &qtEnvironment : qtEnvironments) {
diff --git a/src/app/qbs-setup-qt/setupqt.h b/src/app/qbs-setup-qt/setupqt.h
index 73c0afefe..c10ae637c 100644
--- a/src/app/qbs-setup-qt/setupqt.h
+++ b/src/app/qbs-setup-qt/setupqt.h
@@ -40,8 +40,8 @@
#ifndef QBS_SETUPQT_H
#define QBS_SETUPQT_H
-#include <qtenvironment.h>
#include <tools/error.h>
+#include <tools/version.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qstringlist.h>
@@ -50,27 +50,30 @@
namespace qbs {
-class EnhancedQtEnvironment : public QtEnvironment
+class Settings;
+
+class QtEnvironment
{
public:
+ QString qmakeFilePath;
+ QStringList qbsToolchain;
+ QString architecture;
+ QString targetPlatform;
+ Version qtVersion;
Version msvcVersion;
};
-class Settings;
-
class SetupQt
{
Q_DECLARE_TR_FUNCTIONS(SetupQt)
public:
static bool isQMakePathValid(const QString &qmakePath);
- static std::vector<EnhancedQtEnvironment> fetchEnvironments();
- static void addQtBuildVariant(QtEnvironment *env, const QString &buildVariantName);
- static EnhancedQtEnvironment fetchEnvironment(const QString &qmakePath);
- static void saveToQbsSettings(const QString &qtVersionName,
- const EnhancedQtEnvironment &qtEnvironment,
+ static std::vector<QtEnvironment> fetchEnvironments();
+ static QtEnvironment fetchEnvironment(const QString &qmakePath);
+ static bool checkIfMoreThanOneQtWithTheSameVersion(const Version &qtVersion,
+ const std::vector<QtEnvironment> &qtEnvironments);
+ static void saveToQbsSettings(const QString &qtVersionName, const QtEnvironment &qtEnvironment,
Settings *settings);
- static bool checkIfMoreThanOneQtWithTheSameVersion(const QString &qtVersion,
- const std::vector<EnhancedQtEnvironment> &qtEnvironments);
};
} // namespace qbs
diff --git a/src/lib/corelib/jsextensions/utilitiesextension.cpp b/src/lib/corelib/jsextensions/utilitiesextension.cpp
index a10251c54..4cbe6ed2f 100644
--- a/src/lib/corelib/jsextensions/utilitiesextension.cpp
+++ b/src/lib/corelib/jsextensions/utilitiesextension.cpp
@@ -51,6 +51,26 @@
#include <tools/applecodesignutils.h>
#endif
+#ifdef __APPLE__
+#include <ar.h>
+#include <mach/machine.h>
+#include <mach-o/fat.h>
+#include <mach-o/loader.h>
+#ifndef FAT_MAGIC_64
+#define FAT_MAGIC_64 0xcafebabf
+#define FAT_CIGAM_64 0xbfbafeca
+struct fat_arch_64 {
+ cpu_type_t cputype;
+ cpu_subtype_t cpusubtype;
+ uint64_t offset;
+ uint64_t size;
+ uint32_t align;
+ uint32_t reserved;
+};
+#endif
+#endif
+
+
#ifdef Q_OS_WIN
#include <tools/msvcinfo.h>
#include <tools/vsenvironmentdetector.h>
@@ -58,6 +78,9 @@
#include <QtCore/qcryptographichash.h>
#include <QtCore/qdir.h>
+#include <QtCore/qendian.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qlibrary.h>
#include <QtScript/qscriptable.h>
#include <QtScript/qscriptengine.h>
@@ -91,6 +114,10 @@ public:
static QScriptValue js_qmlTypeInfo(QScriptContext *context, QScriptEngine *engine);
static QScriptValue js_builtinExtensionNames(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue js_isSharedLibrary(QScriptContext *context, QScriptEngine *engine);
+
+ static QScriptValue js_getArchitecturesFromBinary(QScriptContext *context,
+ QScriptEngine *engine);
};
QScriptValue UtilitiesExtension::js_ctor(QScriptContext *context, QScriptEngine *engine)
@@ -504,6 +531,237 @@ QScriptValue UtilitiesExtension::js_builtinExtensionNames(QScriptContext *contex
return engine->toScriptValue(JsExtensions::extensionNames());
}
+QScriptValue UtilitiesExtension::js_isSharedLibrary(QScriptContext *context, QScriptEngine *engine)
+{
+ if (context->argumentCount() == 1) {
+ const QScriptValue value = context->argument(0);
+ if (value.isString())
+ return engine->toScriptValue(QLibrary::isLibrary(value.toString()));
+ }
+ return context->throwError(QScriptContext::SyntaxError,
+ QStringLiteral("isSharedLibrary expects one argument of type string"));
+}
+
+#ifdef __APPLE__
+template <typename T = uint32_t> T readInt(QIODevice *ioDevice, bool *ok,
+ bool swap, bool peek = false) {
+ const auto bytes = peek
+ ? ioDevice->peek(sizeof(T))
+ : ioDevice->read(sizeof(T));
+ if (bytes.size() != sizeof(T)) {
+ if (ok)
+ *ok = false;
+ return T();
+ }
+ if (ok)
+ *ok = true;
+ T n = *reinterpret_cast<const T *>(bytes.constData());
+ return swap ? qbswap(n) : n;
+}
+
+static QString archName(cpu_type_t cputype, cpu_subtype_t cpusubtype)
+{
+ switch (cputype) {
+ case CPU_TYPE_X86:
+ switch (cpusubtype) {
+ case CPU_SUBTYPE_X86_ALL:
+ return QStringLiteral("i386");
+ default:
+ return QString();
+ }
+ case CPU_TYPE_X86_64:
+ switch (cpusubtype) {
+ case CPU_SUBTYPE_X86_64_ALL:
+ return QStringLiteral("x86_64");
+ case CPU_SUBTYPE_X86_64_H:
+ return QStringLiteral("x86_64h");
+ default:
+ return QString();
+ }
+ case CPU_TYPE_ARM:
+ switch (cpusubtype) {
+ case CPU_SUBTYPE_ARM_V7:
+ return QStringLiteral("armv7a");
+ case CPU_SUBTYPE_ARM_V7S:
+ return QStringLiteral("armv7s");
+ case CPU_SUBTYPE_ARM_V7K:
+ return QStringLiteral("armv7k");
+ default:
+ return QString();
+ }
+ case CPU_TYPE_ARM64:
+ switch (cpusubtype) {
+ case CPU_SUBTYPE_ARM64_ALL:
+ return QStringLiteral("arm64");
+ default:
+ return QString();
+ }
+ default:
+ return QString();
+ }
+}
+
+static QStringList detectMachOArchs(QIODevice *device)
+{
+ bool ok;
+ bool foundMachO = false;
+ qint64 pos = device->pos();
+
+ char ar_header[SARMAG];
+ if (device->read(ar_header, SARMAG) == SARMAG) {
+ if (strncmp(ar_header, ARMAG, SARMAG) == 0) {
+ while (!device->atEnd()) {
+ static_assert(sizeof(ar_hdr) == 60, "sizeof(ar_hdr) != 60");
+ ar_hdr header;
+ if (device->read(reinterpret_cast<char *>(&header),
+ sizeof(ar_hdr)) != sizeof(ar_hdr))
+ return { };
+
+ // If the file name is stored in the "extended format" manner,
+ // the real filename is prepended to the data section, so skip that many bytes
+ int filenameLength = 0;
+ if (strncmp(header.ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0) {
+ char arName[sizeof(header.ar_name)] = { 0 };
+ memcpy(arName, header.ar_name + sizeof(AR_EFMT1) - 1,
+ sizeof(header.ar_name) - (sizeof(AR_EFMT1) - 1) - 1);
+ filenameLength = strtoul(arName, nullptr, 10);
+ if (device->read(filenameLength).size() != filenameLength)
+ return { };
+ }
+
+ switch (readInt(device, nullptr, false, true)) {
+ case MH_CIGAM:
+ case MH_CIGAM_64:
+ case MH_MAGIC:
+ case MH_MAGIC_64:
+ foundMachO = true;
+ break;
+ default: {
+ // Skip the data and go to the next archive member...
+ char szBuf[sizeof(header.ar_size) + 1] = { 0 };
+ memcpy(szBuf, header.ar_size, sizeof(header.ar_size));
+ int sz = static_cast<int>(strtoul(szBuf, nullptr, 10));
+ if (sz % 2 != 0)
+ ++sz;
+ sz -= filenameLength;
+ const auto data = device->read(sz);
+ if (data.size() != sz)
+ return { };
+ }
+ }
+
+ if (foundMachO)
+ break;
+ }
+ }
+ }
+
+ // Wasn't an archive file, so try a fat file
+ if (!foundMachO && !device->seek(pos))
+ return QStringList();
+
+ pos = device->pos();
+
+ fat_header fatheader;
+ fatheader.magic = readInt(device, nullptr, false);
+ if (fatheader.magic == FAT_MAGIC || fatheader.magic == FAT_CIGAM ||
+ fatheader.magic == FAT_MAGIC_64 || fatheader.magic == FAT_CIGAM_64) {
+ const bool swap = fatheader.magic == FAT_CIGAM || fatheader.magic == FAT_CIGAM_64;
+ const bool is64bit = fatheader.magic == FAT_MAGIC_64 || fatheader.magic == FAT_CIGAM_64;
+ fatheader.nfat_arch = readInt(device, &ok, swap);
+ if (!ok)
+ return QStringList();
+
+ QStringList archs;
+
+ for (uint32_t n = 0; n < fatheader.nfat_arch; ++n) {
+ fat_arch_64 fatarch;
+ static_assert(sizeof(fat_arch_64) == 32, "sizeof(fat_arch_64) != 32");
+ static_assert(sizeof(fat_arch) == 20, "sizeof(fat_arch) != 20");
+ const qint64 expectedBytes = is64bit ? sizeof(fat_arch_64) : sizeof(fat_arch);
+ if (device->read(reinterpret_cast<char *>(&fatarch), expectedBytes) != expectedBytes)
+ return QStringList();
+
+ if (swap) {
+ fatarch.cputype = qbswap(fatarch.cputype);
+ fatarch.cpusubtype = qbswap(fatarch.cpusubtype);
+ }
+
+ const QString name = archName(fatarch.cputype, fatarch.cpusubtype);
+ if (name.isEmpty()) {
+ qWarning("Unknown cputype %d and cpusubtype %d",
+ fatarch.cputype, fatarch.cpusubtype);
+ return QStringList();
+ }
+ archs.push_back(name);
+ }
+
+ std::sort(archs.begin(), archs.end());
+ return archs;
+ }
+
+ // Wasn't a fat file, so we just read a thin Mach-O from the original offset
+ if (!device->seek(pos))
+ return QStringList();
+
+ bool swap = false;
+ mach_header header;
+ header.magic = readInt(device, nullptr, swap);
+ switch (header.magic) {
+ case MH_CIGAM:
+ case MH_CIGAM_64:
+ swap = true;
+ break;
+ case MH_MAGIC:
+ case MH_MAGIC_64:
+ break;
+ default:
+ return QStringList();
+ }
+
+ header.cputype = static_cast<cpu_type_t>(readInt(device, &ok, swap));
+ if (!ok)
+ return QStringList();
+
+ header.cpusubtype = static_cast<cpu_subtype_t>(readInt(device, &ok, swap));
+ if (!ok)
+ return QStringList();
+
+ const QString name = archName(header.cputype, header.cpusubtype);
+ if (name.isEmpty()) {
+ qWarning("Unknown cputype %d and cpusubtype %d",
+ header.cputype, header.cpusubtype);
+ return { };
+ }
+ return { name };
+}
+#endif
+
+QScriptValue UtilitiesExtension::js_getArchitecturesFromBinary(QScriptContext *context,
+ QScriptEngine *engine)
+{
+ if (context->argumentCount() != 1) {
+ return context->throwError(QScriptContext::SyntaxError,
+ QStringLiteral("getArchitecturesFromBinary expects exactly one argument"));
+ }
+ const QScriptValue arg = context->argument(0);
+ if (!arg.isString()) {
+ return context->throwError(QScriptContext::SyntaxError,
+ QStringLiteral("getArchitecturesFromBinary expects a string argument"));
+ }
+ QStringList archs;
+#ifdef __APPLE__
+ QFile file(arg.toString());
+ if (!file.open(QIODevice::ReadOnly)) {
+ return context->throwError(QScriptContext::SyntaxError,
+ QStringLiteral("Failed to open file '%1': %2")
+ .arg(file.fileName(), file.errorString()));
+ }
+ archs = detectMachOArchs(&file);
+#endif // __APPLE__
+ return engine->toScriptValue(archs);
+}
+
} // namespace Internal
} // namespace qbs
@@ -548,6 +806,10 @@ void initializeJsExtensionUtilities(QScriptValue extensionObject)
engine->newFunction(UtilitiesExtension::js_qmlTypeInfo, 0));
environmentObj.setProperty(QStringLiteral("builtinExtensionNames"),
engine->newFunction(UtilitiesExtension::js_builtinExtensionNames, 0));
+ environmentObj.setProperty(QStringLiteral("isSharedLibrary"),
+ engine->newFunction(UtilitiesExtension::js_isSharedLibrary, 1));
+ environmentObj.setProperty(QStringLiteral("getArchitecturesFromBinary"),
+ engine->newFunction(UtilitiesExtension::js_getArchitecturesFromBinary, 1));
extensionObject.setProperty(QStringLiteral("Utilities"), environmentObj);
}
diff --git a/src/lib/libs.qbs b/src/lib/libs.qbs
index 478db3286..dd21cc081 100644
--- a/src/lib/libs.qbs
+++ b/src/lib/libs.qbs
@@ -3,7 +3,6 @@ import qbs
Project {
references: [
"corelib/corelib.qbs",
- "qtprofilesetup/qtprofilesetup.qbs",
"scriptengine/scriptengine.qbs",
]
}
diff --git a/src/lib/qtprofilesetup/qtenvironment.h b/src/lib/qtprofilesetup/qtenvironment.h
deleted file mode 100644
index 72725cfae..000000000
--- a/src/lib/qtprofilesetup/qtenvironment.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qbs.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#ifndef QBS_QTENVIRONMENT_H
-#define QBS_QTENVIRONMENT_H
-
-#include <tools/qbs_export.h>
-#include <tools/version.h>
-
-#include <QtCore/qstringlist.h>
-
-namespace qbs {
-
-class QBS_EXPORT QtEnvironment {
-public:
- inline bool targetsDesktopWindows() const;
- inline bool isForMinGw() const;
-
- QString installPrefixPath;
- QString libraryPath;
- QString includePath;
- QString binaryPath;
- QString qmlPath;
- QString qmlImportPath;
- QString documentationPath;
- QString dataPath;
- QString pluginPath;
- QString qtLibInfix;
- QString qtNameSpace;
- QString mkspecPath;
- QString mkspecName;
- QString mkspecBasePath;
- QStringList entryPointLibsDebug;
- QStringList entryPointLibsRelease;
- QStringList buildVariant;
- QStringList configItems;
- QStringList qtConfigItems;
- QString architecture;
- QString qtVersion;
- QString windowsVersion;
- QString macosVersion;
- QString iosVersion;
- QString tvosVersion;
- QString watchosVersion;
- QString androidVersion;
- int qtMajorVersion;
- int qtMinorVersion;
- int qtPatchVersion;
- bool staticBuild = false;
- bool frameworkBuild = false;
-};
-
-bool QtEnvironment::targetsDesktopWindows() const
-{
- return mkspecName.startsWith(QLatin1String("win32-")) || isForMinGw();
-}
-
-bool QtEnvironment::isForMinGw() const
-{
- return mkspecName.startsWith(QLatin1String("win32-g++"))
- || mkspecName.startsWith(QLatin1String("mingw"));
-}
-
-} // namespace qbs
-
-#endif // Include guard.
diff --git a/src/lib/qtprofilesetup/qtmoduleinfo.cpp b/src/lib/qtprofilesetup/qtmoduleinfo.cpp
deleted file mode 100644
index bc3d25911..000000000
--- a/src/lib/qtprofilesetup/qtmoduleinfo.cpp
+++ /dev/null
@@ -1,839 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qbs.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#include "qtmoduleinfo.h"
-
-#include "qtenvironment.h"
-
-#include <logging/translator.h>
-#include <tools/error.h>
-#include <tools/profile.h>
-#include <tools/qttools.h>
-#include <tools/set.h>
-#include <tools/stlutils.h>
-
-#include <QtCore/qdiriterator.h>
-#include <QtCore/qfile.h>
-#include <QtCore/qhash.h>
-
-#include <algorithm>
-#include <functional>
-#include <map>
-#include <unordered_map>
-
-namespace qbs {
-namespace Internal {
-
-typedef QHash<QString, QString> NamePathHash;
-static void replaceQtLibNamesWithFilePath(const NamePathHash &namePathHash, QStringList *libList)
-{
- for (QString &lib : *libList) {
- const NamePathHash::ConstIterator it = namePathHash.find(lib);
- if (it != namePathHash.constEnd())
- lib = it.value();
- }
-}
-
-static void replaceQtLibNamesWithFilePath(QList<QtModuleInfo> *modules, const QtEnvironment &qtEnv)
-{
- // 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.
- typedef QHash<QString, QString> NamePathHash;
- NamePathHash linkerNamesToFilePathsDebug;
- NamePathHash linkerNamesToFilePathsRelease;
- for (const QtModuleInfo &m : qAsConst(*modules)) {
- linkerNamesToFilePathsDebug.insert(m.libNameForLinker(qtEnv, true), m.libFilePathDebug);
- linkerNamesToFilePathsRelease.insert(m.libNameForLinker(qtEnv, false),
- m.libFilePathRelease);
- }
- for (QtModuleInfo &module : *modules) {
- replaceQtLibNamesWithFilePath(linkerNamesToFilePathsDebug, &module.dynamicLibrariesDebug);
- replaceQtLibNamesWithFilePath(linkerNamesToFilePathsDebug, &module.staticLibrariesDebug);
- replaceQtLibNamesWithFilePath(linkerNamesToFilePathsRelease,
- &module.dynamicLibrariesRelease);
- replaceQtLibNamesWithFilePath(linkerNamesToFilePathsRelease,
- &module.staticLibrariesRelease);
- }
-}
-
-class DuplicatedDependencyLibsRemover
-{
-public:
- void apply(QList<QtModuleInfo> *modules)
- {
- setupReverseDependencies(modules);
-
- // Traverse the debug variants of modules.
- m_getLibraries = [](QtModuleInfo *module) {
- return std::vector<QStringList *>{
- &module->dynamicLibrariesDebug, &module->staticLibrariesDebug
- };
- };
- m_getLibFilePath = [](QtModuleInfo *module) {
- return module->libFilePathDebug;
- };
- const auto &rootModules = roots(modules);
- for (QtModuleInfo *module : rootModules)
- traverse(module, QStringList());
-
- // Traverse the release variants of modules.
- m_getLibraries = [](QtModuleInfo *module) {
- return std::vector<QStringList *>{
- &module->dynamicLibrariesRelease, &module->staticLibrariesRelease
- };
- };
- m_getLibFilePath = [](QtModuleInfo *module) {
- return module->libFilePathRelease;
- };
- for (QtModuleInfo *module : rootModules)
- traverse(module, QStringList());
- }
-
-private:
- void setupReverseDependencies(QList<QtModuleInfo> *modules)
- {
- std::map<QString, QtModuleInfo *> moduleByName;
- for (QtModuleInfo &module : *modules)
- moduleByName[module.qbsName] = &module;
- for (QtModuleInfo &module : *modules) {
- for (const QString &dep : module.dependencies) {
- QtModuleInfo *depmod = moduleByName[dep];
- if (!depmod)
- continue;
- m_revDeps[depmod].push_back(&module);
- }
- }
- }
-
- std::vector<QtModuleInfo *> roots(QList<QtModuleInfo> *modules)
- {
- std::vector<QtModuleInfo *> result;
- for (auto it = modules->begin(); it != modules->end(); ++it) {
- QtModuleInfo &module = *it;
- if (module.dependencies.empty())
- result.push_back(&module);
- }
- return result;
- }
-
- void traverse(QtModuleInfo *module, QStringList libs)
- {
- if (contains(m_currentPath, module))
- return;
- m_currentPath.push_back(module);
-
- auto isInLibs = [&libs](const QString &str) {
- return std::binary_search(libs.begin(), libs.end(), str);
- };
- auto moduleLibraryLists = m_getLibraries(module);
- for (QStringList *lst : moduleLibraryLists) {
- auto it = std::remove_if(lst->begin(), lst->end(), isInLibs);
- if (it != lst->end())
- lst->erase(it, lst->end());
- }
- const QString libFilePath = m_getLibFilePath(module);
- if (!libFilePath.isEmpty())
- libs.push_back(libFilePath);
- for (QStringList *lst : moduleLibraryLists)
- std::copy(lst->begin(), lst->end(), std::back_inserter(libs));
- std::sort(libs.begin(), libs.end());
-
- for (auto rdep : m_revDeps[module])
- traverse(rdep, libs);
-
- m_currentPath.pop_back();
- }
-
- std::unordered_map<QtModuleInfo *, std::vector<QtModuleInfo *>> m_revDeps;
- std::vector<QtModuleInfo *> m_currentPath;
- std::function<std::vector<QStringList *>(QtModuleInfo *)> m_getLibraries;
- std::function<QString(QtModuleInfo *)> m_getLibFilePath;
-};
-
-static void removeDuplicatedDependencyLibs(QList<QtModuleInfo> *modules)
-{
- DuplicatedDependencyLibsRemover dlr;
- dlr.apply(modules);
-}
-
-QtModuleInfo::QtModuleInfo()
- : isPrivate(false), hasLibrary(true), isStaticLibrary(false), isPlugin(false), mustExist(true)
-{
-}
-
-QtModuleInfo::QtModuleInfo(const QString &name, const QString &qbsName, const QStringList &deps)
- : name(name), qbsName(qbsName), dependencies(deps),
- isPrivate(qbsName.endsWith(QLatin1String("-private"))),
- hasLibrary(!isPrivate),
- isStaticLibrary(false),
- isPlugin(false),
- mustExist(true)
-{
- const QString coreModule = QLatin1String("core");
- if (qbsName != coreModule && !dependencies.contains(coreModule))
- dependencies.prepend(coreModule);
-}
-
-QString QtModuleInfo::moduleNameWithoutPrefix() const
-{
- if (name == QLatin1String("Phonon"))
- return QLatin1String("phonon");
- if (modulePrefix.isEmpty() && name.startsWith(QLatin1String("Qt")))
- return name.mid(2); // Strip off "Qt".
- if (name.startsWith(modulePrefix))
- return name.mid(modulePrefix.length());
- return name;
-}
-
-QString QtModuleInfo::frameworkHeadersPath(const QtEnvironment &qtEnvironment) const
-{
- return qtEnvironment.libraryPath + QLatin1Char('/') + name
- + QLatin1String(".framework/Headers");
-}
-
-QStringList QtModuleInfo::qt4ModuleIncludePaths(const QtEnvironment &qtEnvironment) const
-{
- QStringList paths;
- if (isFramework(qtEnvironment)) {
- paths << frameworkHeadersPath(qtEnvironment);
- } else {
- paths << qtEnvironment.includePath
- << qtEnvironment.includePath + QLatin1Char('/') + name;
- }
- return paths;
-}
-
-QString QtModuleInfo::libraryBaseName(const QtEnvironment &qtEnvironment,
- bool debugBuild) const
-{
- if (isPlugin)
- return libBaseName(name, debugBuild, qtEnvironment);
-
- // Some modules use a different naming scheme, so it doesn't get boring.
- const bool libNameBroken = name == QLatin1String("Enginio")
- || name == QLatin1String("DataVisualization")
- || name == QLatin1String("Phonon");
-
- QString libName = modulePrefix.isEmpty() && !libNameBroken ? QLatin1String("Qt") : modulePrefix;
- if (qtEnvironment.qtMajorVersion >= 5 && !isFramework(qtEnvironment) && !libNameBroken)
- libName += QString::number(qtEnvironment.qtMajorVersion);
- libName += moduleNameWithoutPrefix();
- libName += qtEnvironment.qtLibInfix;
- return libBaseName(libName, debugBuild, qtEnvironment);
-}
-
-QString QtModuleInfo::libNameForLinker(const QtEnvironment &qtEnvironment, bool debugBuild) const
-{
- if (!hasLibrary)
- return QString();
- QString libName = libraryBaseName(qtEnvironment, debugBuild);
- if (qtEnvironment.mkspecName.contains(QLatin1String("msvc")))
- libName += QLatin1String(".lib");
- return libName;
-}
-
-void QtModuleInfo::setupLibraries(const QtEnvironment &qtEnv,
- Internal::Set<QString> *nonExistingPrlFiles)
-{
- setupLibraries(qtEnv, true, nonExistingPrlFiles);
- setupLibraries(qtEnv, false, nonExistingPrlFiles);
-}
-
-static QStringList makeList(const QByteArray &s)
-{
- return QString::fromLatin1(s).split(QLatin1Char(' '), QString::SkipEmptyParts);
-}
-
-static QString guessLibraryFilePath(const QString &prlFilePath, const QString &libDir,
- const QtEnvironment &qtEnv)
-{
- const QString baseName = QFileInfo(prlFilePath).baseName();
- const QStringList prefixCandidates{QString(), QLatin1String("lib")};
- const QStringList suffixCandidates{QLatin1String("so.") + qtEnv.qtVersion,
- QLatin1String("so"), QLatin1String("a"), QLatin1String("lib"),
- QLatin1String("dll.a")};
- for (const QString &prefix : prefixCandidates) {
- for (const QString &suffix : suffixCandidates) {
- const QString candidate = libDir + QLatin1Char('/') + prefix + baseName
- + QLatin1Char('.') + suffix;
- if (QFile::exists(candidate))
- return candidate;
- }
- }
- return QString();
-}
-
-void QtModuleInfo::setupLibraries(const QtEnvironment &qtEnv, bool debugBuild,
- Internal::Set<QString> *nonExistingPrlFiles)
-{
- if (!hasLibrary)
- return; // Can happen for Qt4 convenience modules, like "widgets".
-
- if (debugBuild) {
- if (!qtEnv.buildVariant.contains(QLatin1String("debug")))
- return;
- const QStringList modulesNeverBuiltAsDebug = QStringList()
- << QLatin1String("bootstrap") << QLatin1String("qmldevtools");
- for (const QString &m : modulesNeverBuiltAsDebug) {
- if (qbsName == m || qbsName == m + QLatin1String("-private"))
- return;
- }
- } else if (!qtEnv.buildVariant.contains(QLatin1String("release"))) {
- return;
- }
-
- QStringList &libs = isStaticLibrary
- ? (debugBuild ? staticLibrariesDebug : staticLibrariesRelease)
- : (debugBuild ? dynamicLibrariesDebug : dynamicLibrariesRelease);
- QStringList &frameworks = debugBuild ? frameworksDebug : frameworksRelease;
- QStringList &frameworkPaths = debugBuild ? frameworkPathsDebug : frameworkPathsRelease;
- QStringList &flags = debugBuild ? linkerFlagsDebug : linkerFlagsRelease;
- QString &libFilePath = debugBuild ? libFilePathDebug : libFilePathRelease;
-
- if (qtEnv.mkspecName.contains(QLatin1String("ios")) && isStaticLibrary) {
- libs << QLatin1String("z") << QLatin1String("m");
- if (qtEnv.qtMajorVersion == 5 && qtEnv.qtMinorVersion < 8) {
- const QtModuleInfo platformSupportModule(QLatin1String("QtPlatformSupport"),
- QLatin1String("platformsupport"));
- libs << platformSupportModule.libNameForLinker(qtEnv, debugBuild);
- }
- if (name == QStringLiteral("qios")) {
- flags << QLatin1String("-force_load")
- << qtEnv.pluginPath + QLatin1String("/platforms/")
- + libBaseName(QLatin1String("libqios"), debugBuild, qtEnv)
- + QLatin1String(".a");
- }
- }
-
- QString prlFilePath = isPlugin
- ? qtEnv.pluginPath + QLatin1Char('/') + pluginData.type
- : qtEnv.libraryPath;
- prlFilePath += QLatin1Char('/');
- if (isFramework(qtEnv))
- prlFilePath.append(libraryBaseName(qtEnv, false)).append(QLatin1String(".framework/"));
- const QString libDir = prlFilePath;
- if (!qtEnv.mkspecName.startsWith(QLatin1String("win")) && !isFramework(qtEnv))
- prlFilePath += QLatin1String("lib");
- prlFilePath.append(libraryBaseName(qtEnv, debugBuild));
- const bool isNonStaticQt4OnWindows = qtEnv.mkspecName.startsWith(QLatin1String("win"))
- && !isStaticLibrary && qtEnv.qtMajorVersion < 5;
- if (isNonStaticQt4OnWindows)
- prlFilePath.chop(1); // The prl file base name does *not* contain the version number...
- prlFilePath.append(QLatin1String(".prl"));
- QFile prlFile(prlFilePath);
- if (!prlFile.open(QIODevice::ReadOnly)) {
- libFilePath = guessLibraryFilePath(prlFilePath, libDir, qtEnv);
- if (nonExistingPrlFiles->insert(prlFilePath).second) {
- if (mustExist && libFilePath.isEmpty()) {
- qDebug("Could not open prl file '%s' for module '%s' (%s), and failed to deduce "
- "the library file path. This module will likely not be usable by qbs.",
- qPrintable(prlFilePath), qPrintable(name),
- qPrintable(prlFile.errorString()));
- }
- }
- return;
- }
- const QList<QByteArray> prlLines = prlFile.readAll().split('\n');
- for (const QByteArray &line : prlLines) {
- const QByteArray simplifiedLine = line.simplified();
- const int equalsOffset = simplifiedLine.indexOf('=');
- if (equalsOffset == -1)
- continue;
- if (simplifiedLine.startsWith("QMAKE_PRL_TARGET")) {
- const bool isMingw = qtEnv.mkspecName.startsWith(QLatin1String("win"))
- && qtEnv.mkspecName.contains(QLatin1String("g++"));
- const bool isQtVersionBefore56 = qtEnv.qtMajorVersion < 5
- || (qtEnv.qtMajorVersion == 5 && qtEnv.qtMinorVersion < 6);
- libFilePath = libDir;
-
- // 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. TODO: Shoot the people responsible for this.
- if (isQtVersionBefore56 && isMingw && !isStaticLibrary)
- libFilePath += QLatin1String("lib");
-
- libFilePath += QString::fromLatin1(simplifiedLine.mid(equalsOffset + 1).trimmed());
- if (isNonStaticQt4OnWindows)
- libFilePath += QString::number(4); // This is *not* part of QMAKE_PRL_TARGET...
- if (isQtVersionBefore56) {
- if (qtEnv.mkspecName.contains(QLatin1String("msvc")))
- libFilePath += QLatin1String(".lib");
- else if (isMingw)
- libFilePath += QLatin1String(".a");
- }
- continue;
- }
- if (simplifiedLine.startsWith("QMAKE_PRL_CONFIG")) {
- config = QString::fromLatin1(simplifiedLine.mid(equalsOffset + 1).trimmed())
- .split(QLatin1Char(' '), QString::SkipEmptyParts);
- continue;
- }
- if (!simplifiedLine.startsWith("QMAKE_PRL_LIBS"))
- continue;
-
- // Assuming lib names and directories without spaces here.
- QStringList parts = QString::fromLatin1(simplifiedLine.mid(equalsOffset + 1).trimmed())
- .split(QLatin1Char(' '), QString::SkipEmptyParts);
- for (int i = 0; i < parts.size(); ++i) {
- QString part = parts.at(i);
- part.replace(QLatin1String("$$[QT_INSTALL_LIBS]"), qtEnv.libraryPath);
- if (part.startsWith(QLatin1String("-l"))) {
- libs << part.mid(2);
- } else if (part.startsWith(QLatin1String("-L"))) {
- libraryPaths << part.mid(2);
- } else if (part.startsWith(QLatin1String("-F"))) {
- frameworkPaths << part.mid(2);
- } else if (part == QLatin1String("-framework")) {
- if (++i < parts.size())
- frameworks << parts.at(i);
- } else if (part == QLatin1String("-pthread")) {
- libs << QLatin1String("pthread");
- } else if (part.startsWith(QLatin1Char('-'))) { // Some other option
- qDebug("QMAKE_PRL_LIBS contains non-library option '%s' in file '%s'",
- qPrintable(part), qPrintable(prlFilePath));
- flags << part;
- } else if (part.startsWith(QLatin1String("/LIBPATH:"))) {
- libraryPaths << part.mid(9).replace(QLatin1String("\\\\"), QLatin1String("/"));
- } else { // Assume it's a file path/name.
- libs << part.replace(QLatin1String("\\\\"), QLatin1String("/"));
- }
- }
-
- return;
- }
-}
-
-bool QtModuleInfo::isFramework(const QtEnvironment &qtEnv) const
-{
- if (!qtEnv.frameworkBuild || isStaticLibrary)
- return false;
- const QStringList modulesNeverBuiltAsFrameworks = QStringList()
- << QLatin1String("bootstrap") << QLatin1String("openglextensions")
- << QLatin1String("platformsupport") << QLatin1String("qmldevtools")
- << QLatin1String("uitools") << QLatin1String("harfbuzzng");
- return !modulesNeverBuiltAsFrameworks.contains(qbsName);
-}
-
-// We erroneously called the "testlib" module "test" for quite a while. Let's not punish users
-// for that.
-static void addTestModule(QList<QtModuleInfo> &modules)
-{
- QtModuleInfo testModule(QLatin1String("QtTest"), QLatin1String("test"),
- QStringList() << QLatin1String("testlib"));
- testModule.hasLibrary = false;
- modules.push_back(testModule);
-}
-
-// See above.
-static void addDesignerComponentsModule(QList<QtModuleInfo> &modules)
-{
- QtModuleInfo module(QLatin1String("QtDesignerComponents"),
- QLatin1String("designercomponents"),
- QStringList() << QLatin1String("designercomponents-private"));
- module.hasLibrary = false;
- modules.push_back(module);
-}
-
-
-QList<QtModuleInfo> allQt4Modules(const QtEnvironment &qtEnvironment)
-{
- // as per http://doc.qt.io/qt-4.8/modules.html + private stuff.
- QList<QtModuleInfo> modules;
-
- QtModuleInfo core(QLatin1String("QtCore"), QLatin1String("core"));
- core.compilerDefines << QLatin1String("QT_CORE_LIB");
- if (!qtEnvironment.qtNameSpace.isEmpty())
- core.compilerDefines << QLatin1String("QT_NAMESPACE=") + qtEnvironment.qtNameSpace;
-
- modules = QList<QtModuleInfo>()
- << core
- << QtModuleInfo(QLatin1String("QtCore"), QLatin1String("core-private"),
- QStringList() << QLatin1String("core"))
- << QtModuleInfo(QLatin1String("QtGui"), QLatin1String("gui"))
- << QtModuleInfo(QLatin1String("QtGui"), QLatin1String("gui-private"),
- QStringList() << QLatin1String("gui"))
- << QtModuleInfo(QLatin1String("QtMultimedia"), QLatin1String("multimedia"),
- QStringList() << QLatin1String("gui") << QLatin1String("network"))
- << QtModuleInfo(QLatin1String("QtMultimedia"), QLatin1String("multimedia-private"),
- QStringList() << QLatin1String("multimedia"))
- << QtModuleInfo(QLatin1String("QtNetwork"), QLatin1String("network"))
- << QtModuleInfo(QLatin1String("QtNetwork"), QLatin1String("network-private"),
- QStringList() << QLatin1String("network"))
- << QtModuleInfo(QLatin1String("QtOpenGL"), QLatin1String("opengl"),
- QStringList() << QLatin1String("gui"))
- << QtModuleInfo(QLatin1String("QtOpenGL"), QLatin1String("opengl-private"),
- QStringList() << QLatin1String("opengl"))
- << QtModuleInfo(QLatin1String("QtOpenVG"), QLatin1String("openvg"),
- QStringList() << QLatin1String("gui"))
- << QtModuleInfo(QLatin1String("QtScript"), QLatin1String("script"))
- << QtModuleInfo(QLatin1String("QtScript"), QLatin1String("script-private"),
- QStringList() << QLatin1String("script"))
- << QtModuleInfo(QLatin1String("QtScriptTools"), QLatin1String("scripttools"),
- QStringList() << QLatin1String("script") << QLatin1String("gui"))
- << QtModuleInfo(QLatin1String("QtScriptTools"), QLatin1String("scripttools-private"),
- QStringList() << QLatin1String("scripttools"))
- << QtModuleInfo(QLatin1String("QtSql"), QLatin1String("sql"))
- << QtModuleInfo(QLatin1String("QtSql"), QLatin1String("sql-private"),
- QStringList() << QLatin1String("sql"))
- << QtModuleInfo(QLatin1String("QtSvg"), QLatin1String("svg"),
- QStringList() << QLatin1String("gui"))
- << QtModuleInfo(QLatin1String("QtSvg"), QLatin1String("svg-private"),
- QStringList() << QLatin1String("svg"))
- << QtModuleInfo(QLatin1String("QtWebKit"), QLatin1String("webkit"),
- QStringList() << QLatin1String("gui") << QLatin1String("network"))
- << QtModuleInfo(QLatin1String("QtWebKit"), QLatin1String("webkit-private"),
- QStringList() << QLatin1String("webkit"))
- << QtModuleInfo(QLatin1String("QtXml"), QLatin1String("xml"))
- << QtModuleInfo(QLatin1String("QtXml"), QLatin1String("xml-private"),
- QStringList() << QLatin1String("xml"))
- << QtModuleInfo(QLatin1String("QtXmlPatterns"), QLatin1String("xmlpatterns"),
- QStringList() << QLatin1String("network"))
- << QtModuleInfo(QLatin1String("QtXmlPatterns"),
- QLatin1String("xmlpatterns-private"),
- QStringList() << QLatin1String("xmlpatterns"))
- << QtModuleInfo(QLatin1String("QtDeclarative"), QLatin1String("declarative"),
- QStringList() << QLatin1String("gui") << QLatin1String("script"))
- << QtModuleInfo(QLatin1String("QtDeclarative"),
- QLatin1String("declarative-private"),
- QStringList() << QLatin1String("declarative"))
- << QtModuleInfo(QLatin1String("QtDesigner"), QLatin1String("designer"),
- QStringList() << QLatin1String("gui") << QLatin1String("xml"))
- << QtModuleInfo(QLatin1String("QtDesigner"), QLatin1String("designer-private"),
- QStringList() << QLatin1String("designer"))
- << QtModuleInfo(QLatin1String("QtUiTools"), QLatin1String("uitools"))
- << QtModuleInfo(QLatin1String("QtUiTools"), QLatin1String("uitools-private"),
- QStringList() << QLatin1String("uitools"))
- << QtModuleInfo(QLatin1String("QtHelp"), QLatin1String("help"),
- QStringList() << QLatin1String("network") << QLatin1String("sql"))
- << QtModuleInfo(QLatin1String("QtHelp"), QLatin1String("help-private"),
- QStringList() << QLatin1String("help"))
- << QtModuleInfo(QLatin1String("QtTest"), QLatin1String("testlib"))
- << QtModuleInfo(QLatin1String("QtTest"), QLatin1String("testlib-private"),
- QStringList() << QLatin1String("testlib"));
-
- if (qtEnvironment.mkspecName.startsWith(QLatin1String("win"))) {
- QtModuleInfo axcontainer(QLatin1String("QAxContainer"), QLatin1String("axcontainer"));
- axcontainer.modulePrefix = QLatin1String("Q");
- axcontainer.isStaticLibrary = true;
- axcontainer.includePaths << qtEnvironment.includePath + QLatin1String("/ActiveQt");
- modules.push_back(axcontainer);
-
- QtModuleInfo axserver = axcontainer;
- axserver.name = QLatin1String("QAxServer");
- axserver.qbsName = QLatin1String("axserver");
- axserver.compilerDefines = QStringList() << QLatin1String("QAXSERVER");
- modules.push_back(axserver);
- } else {
- modules.push_back(QtModuleInfo(QLatin1String("QtDBus"), QLatin1String("dbus")));
- modules.push_back(QtModuleInfo(QLatin1String("QtDBus"), QLatin1String("dbus-private"),
- { QLatin1String("dbus") }));
- }
-
- QtModuleInfo designerComponentsPrivate(QLatin1String("QtDesignerComponents"),
- QLatin1String("designercomponents-private"),
- QStringList() << QLatin1String("gui-private") << QLatin1String("designer-private"));
- designerComponentsPrivate.hasLibrary = true;
- modules.push_back(designerComponentsPrivate);
-
- QtModuleInfo phonon(QLatin1String("Phonon"), QLatin1String("phonon"));
- phonon.includePaths = phonon.qt4ModuleIncludePaths(qtEnvironment);
- modules.push_back(phonon);
-
- // Set up include paths that haven't been set up before this point.
- for (auto &module : modules) {
- if (!module.includePaths.empty())
- continue;
- module.includePaths = module.qt4ModuleIncludePaths(qtEnvironment);
- }
-
- // Set up compiler defines haven't been set up before this point.
- for (auto &module : modules) {
- if (!module.compilerDefines.empty())
- continue;
- module.compilerDefines
- << QLatin1String("QT_") + module.qbsName.toUpper() + QLatin1String("_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.
- QtModuleInfo virtualModule;
- virtualModule.hasLibrary = false;
- virtualModule.qbsName = QLatin1String("widgets");
- virtualModule.dependencies = QStringList() << QLatin1String("core") << QLatin1String("gui");
- modules.push_back(virtualModule);
- virtualModule.qbsName = QLatin1String("quick");
- virtualModule.dependencies = QStringList() << QLatin1String("declarative");
- modules.push_back(virtualModule);
- virtualModule.qbsName = QLatin1String("concurrent");
- virtualModule.dependencies = QStringList() << QLatin1String("core");
- modules.push_back(virtualModule);
- virtualModule.qbsName = QLatin1String("printsupport");
- virtualModule.dependencies = QStringList() << QLatin1String("core") << QLatin1String("gui");
- modules.push_back(virtualModule);
-
- addTestModule(modules);
- addDesignerComponentsModule(modules);
-
- const QStringList modulesThatCanBeDisabled = QStringList() << QLatin1String("xmlpatterns")
- << QLatin1String("multimedia") << QLatin1String("phonon") << QLatin1String("svg")
- << QLatin1String("webkit") << QLatin1String("script") << QLatin1String("scripttools")
- << QLatin1String("declarative") << QLatin1String("gui") << QLatin1String("dbus")
- << QLatin1String("opengl") << QLatin1String("openvg");
- for (auto &module : modules) {
- QString name = module.qbsName;
- name.remove(QLatin1String("-private"));
- if (modulesThatCanBeDisabled.contains(name))
- module.mustExist = false;
- }
-
- Internal::Set<QString> nonExistingPrlFiles;
- for (QtModuleInfo &module : modules) {
- if (qtEnvironment.staticBuild)
- module.isStaticLibrary = true;
- module.setupLibraries(qtEnvironment, &nonExistingPrlFiles);
- }
- replaceQtLibNamesWithFilePath(&modules, qtEnvironment);
-
- return modules;
-}
-
-static QList<QByteArray> getPriFileContentsRecursively(const Profile &profile,
- const QString &priFilePath)
-{
- QFile priFile(priFilePath);
- if (!priFile.open(QIODevice::ReadOnly)) {
- throw ErrorInfo(Tr::tr("Setting up Qt profile '%1' failed: Cannot open "
- "file '%2' (%3).").arg(profile.name(), priFile.fileName(), priFile.errorString()));
- }
- QList<QByteArray> lines = priFile.readAll().split('\n');
- for (int i = 0; i < lines.size(); ++i) {
- const QByteArray includeString = "include(";
- const QByteArray &line = lines.at(i).trimmed();
- if (!line.startsWith(includeString))
- continue;
- const int offset = includeString.size();
- const int closingParenPos = line.indexOf(')', offset);
- if (closingParenPos == -1) {
- qDebug("Warning: Invalid include statement in '%s'", qPrintable(priFilePath));
- continue;
- }
- const QString includedFilePath
- = QString::fromLocal8Bit(line.mid(offset, closingParenPos - offset));
- const QList<QByteArray> &includedContents
- = getPriFileContentsRecursively(profile, includedFilePath);
- int j = i;
- for (const QByteArray &includedLine : includedContents)
- lines.insert(++j, includedLine);
- lines.removeAt(i--);
- }
- return lines;
-}
-
-static QStringList extractPaths(const QByteArray &rhs, const QString &filePath)
-{
- QStringList paths;
- int startIndex = 0;
- for (;;) {
- while (startIndex < rhs.size() && rhs.at(startIndex) == ' ')
- ++startIndex;
- if (startIndex >= rhs.size())
- break;
- int endIndex;
- if (rhs.at(startIndex) == '"') {
- ++startIndex;
- endIndex = rhs.indexOf('"', startIndex);
- if (endIndex == -1) {
- qDebug("Unmatched quote in file '%s'", qPrintable(filePath));
- break;
- }
- } else {
- endIndex = rhs.indexOf(' ', startIndex + 1);
- if (endIndex == -1)
- endIndex = rhs.size();
- }
- paths << QString::fromLocal8Bit(rhs.mid(startIndex, endIndex - startIndex));
- startIndex = endIndex + 1;
- }
- return paths;
-}
-
-QList<QtModuleInfo> allQt5Modules(const Profile &profile, const QtEnvironment &qtEnvironment)
-{
- Internal::Set<QString> nonExistingPrlFiles;
- QList<QtModuleInfo> modules;
- QDirIterator dit(qtEnvironment.mkspecBasePath + QLatin1String("/modules"));
- while (dit.hasNext()) {
- const QString moduleFileNamePrefix = QLatin1String("qt_lib_");
- const QString pluginFileNamePrefix = QLatin1String("qt_plugin_");
- const QString moduleFileNameSuffix = QLatin1String(".pri");
- dit.next();
- const bool fileHasPluginPrefix = dit.fileName().startsWith(pluginFileNamePrefix);
- if ((!fileHasPluginPrefix && !dit.fileName().startsWith(moduleFileNamePrefix))
- || !dit.fileName().endsWith(moduleFileNameSuffix)) {
- continue;
- }
- QtModuleInfo moduleInfo;
- moduleInfo.isPlugin = fileHasPluginPrefix;
- const QString fileNamePrefix
- = moduleInfo.isPlugin ? pluginFileNamePrefix : moduleFileNamePrefix;
- moduleInfo.qbsName = dit.fileName().mid(fileNamePrefix.size(),
- dit.fileName().size() - fileNamePrefix.size()
- - moduleFileNameSuffix.size());
- if (moduleInfo.isPlugin) {
- moduleInfo.name = moduleInfo.qbsName;
- moduleInfo.isStaticLibrary = true;
- }
- const QByteArray moduleKeyPrefix = QByteArray(moduleInfo.isPlugin ? "QT_PLUGIN" : "QT")
- + '.' + moduleInfo.qbsName.toLatin1() + '.';
- moduleInfo.qbsName.replace(QLatin1String("_private"), QLatin1String("-private"));
- bool hasV2 = false;
- bool hasModuleEntry = false;
- const auto lines = getPriFileContentsRecursively(profile, dit.filePath());
- for (const QByteArray &line : lines) {
- const QByteArray simplifiedLine = line.simplified();
- const int firstEqualsOffset = simplifiedLine.indexOf('=');
- if (firstEqualsOffset == -1)
- continue;
- const QByteArray key = simplifiedLine.left(firstEqualsOffset).trimmed();
- const QByteArray value = simplifiedLine.mid(firstEqualsOffset + 1).trimmed();
- if (!key.startsWith(moduleKeyPrefix) || value.isEmpty())
- continue;
- if (key.endsWith(".name")) {
- moduleInfo.name = QString::fromLocal8Bit(value);
- } else if (key.endsWith(".module")) {
- hasModuleEntry = true;
- } else if (key.endsWith(".depends")) {
- moduleInfo.dependencies = QString::fromLocal8Bit(value).split(QLatin1Char(' '));
- for (auto &dependency : moduleInfo.dependencies)
- dependency.replace(QLatin1String("_private"), QLatin1String("-private"));
- } else if (key.endsWith(".module_config")) {
- const auto elems = value.split(' ');
- for (const QByteArray &elem : elems) {
- 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, dit.filePath());
- for (auto &includePath : moduleInfo.includePaths) {
- includePath
- .replace(QLatin1String("$$QT_MODULE_INCLUDE_BASE"),
- qtEnvironment.includePath)
- .replace(QLatin1String("$$QT_MODULE_LIB_BASE"),
- qtEnvironment.libraryPath);
- }
- } else if (key.endsWith(".DEFINES")) {
- moduleInfo.compilerDefines = QString::fromLocal8Bit(value)
- .split(QLatin1Char(' '), QString::SkipEmptyParts);
- } else if (key.endsWith(".VERSION")) {
- moduleInfo.version = QString::fromLocal8Bit(value);
- } else if (key.endsWith(".plugin_types")) {
- moduleInfo.supportedPluginTypes = makeList(value);
- } else if (key.endsWith(".TYPE")) {
- moduleInfo.pluginData.type = QString::fromLatin1(value);
- } else if (key.endsWith(".EXTENDS")) {
- moduleInfo.pluginData.extends = makeList(value);
- if (moduleInfo.pluginData.extends.removeOne(QLatin1String("-")))
- moduleInfo.pluginData.autoLoad = false;
- } else if (key.endsWith(".CLASS_NAME")) {
- moduleInfo.pluginData.className = QString::fromLatin1(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 && moduleInfo.isFramework(qtEnvironment)) {
- moduleInfo.includePaths.clear();
- QString baseIncDir = moduleInfo.frameworkHeadersPath(qtEnvironment);
- if (moduleInfo.isPrivate) {
- baseIncDir += QLatin1Char('/') + moduleInfo.version;
- moduleInfo.includePaths
- << baseIncDir
- << baseIncDir + QLatin1Char('/') + moduleInfo.name;
- } else {
- moduleInfo.includePaths << baseIncDir;
- }
- }
-
- moduleInfo.setupLibraries(qtEnvironment, &nonExistingPrlFiles);
-
- modules.push_back(moduleInfo);
- if (moduleInfo.qbsName == QLatin1String("testlib"))
- addTestModule(modules);
- if (moduleInfo.qbsName == QLatin1String("designercomponents-private"))
- addDesignerComponentsModule(modules);
- }
-
- replaceQtLibNamesWithFilePath(&modules, qtEnvironment);
- removeDuplicatedDependencyLibs(&modules);
- return modules;
-}
-
-QString QtModuleInfo::libBaseName(const QString &libName, bool debugBuild,
- const QtEnvironment &qtEnvironment) const
-{
- QString name = libName;
- if (qtEnvironment.mkspecName.startsWith(QLatin1String("win"))) {
- if (debugBuild)
- name += QLatin1Char('d');
- if (!isStaticLibrary && qtEnvironment.qtMajorVersion < 5)
- name += QString::number(qtEnvironment.qtMajorVersion);
- }
- if (qtEnvironment.mkspecName.contains(QLatin1String("macx"))
- || qtEnvironment.mkspecName.contains(QLatin1String("ios"))
- || qtEnvironment.mkspecName.contains(QLatin1String("darwin"))) {
- if (!isFramework(qtEnvironment)
- && qtEnvironment.buildVariant.contains(QLatin1String("debug"))
- && (!qtEnvironment.buildVariant.contains(QLatin1String("release")) || debugBuild)) {
- name += QLatin1String("_debug");
- }
- }
- return name;
-}
-
-} // namespace Internal
-} // namespace qbs
-
diff --git a/src/lib/qtprofilesetup/qtmoduleinfo.h b/src/lib/qtprofilesetup/qtmoduleinfo.h
deleted file mode 100644
index 38a654edf..000000000
--- a/src/lib/qtprofilesetup/qtmoduleinfo.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qbs.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#ifndef QBS_QTMODULEINFO_H
-#define QBS_QTMODULEINFO_H
-
-#include <QtCore/qstringlist.h>
-
-namespace qbs {
-class QtEnvironment;
-class Profile;
-
-namespace Internal {
-
-template<typename T> class Set;
-
-class QtModuleInfo
-{
-public:
- QtModuleInfo();
- QtModuleInfo(const QString &name, const QString &qbsName,
- const QStringList &deps = QStringList());
-
- QString moduleNameWithoutPrefix() const;
- QString frameworkHeadersPath(const QtEnvironment &qtEnvironment) const;
- QStringList qt4ModuleIncludePaths(const QtEnvironment &qtEnvironment) const;
- QString libraryBaseName(const QtEnvironment &qtEnvironment, bool debugBuild) const;
- QString libBaseName(const QString &libName, bool debugBuild,
- const QtEnvironment &qtEnvironment) const;
- QString libNameForLinker(const QtEnvironment &qtEnvironment, bool debugBuild) const;
- void setupLibraries(const QtEnvironment &qtEnv, Internal::Set<QString> *nonExistingPrlFiles);
- bool isFramework(const QtEnvironment &qtEnv) const;
-
- QString modulePrefix; // default is empty and means "Qt".
- QString name; // As in the path to the headers and ".name" in the pri files.
- QString qbsName; // Lower-case version without "qt" prefix.
- QString version;
- QStringList dependencies; // qbs names.
- QStringList includePaths;
- QStringList compilerDefines;
- QStringList staticLibrariesDebug;
- QStringList staticLibrariesRelease;
- QStringList dynamicLibrariesDebug;
- QStringList dynamicLibrariesRelease;
- QStringList linkerFlagsDebug;
- QStringList linkerFlagsRelease;
- QString libFilePathDebug;
- QString libFilePathRelease;
- QStringList frameworksDebug;
- QStringList frameworksRelease;
- QStringList frameworkPathsDebug;
- QStringList frameworkPathsRelease;
- QStringList libraryPaths;
- QStringList config;
- bool isPrivate;
- bool hasLibrary;
- bool isStaticLibrary;
- bool isPlugin;
- bool mustExist;
- QStringList supportedPluginTypes;
-
- struct PluginData {
- QString type;
- QStringList extends;
- QString className;
- bool autoLoad = true;
- } pluginData;
-
-private:
- void setupLibraries(const QtEnvironment &qtEnv, bool debugBuild,
- Internal::Set<QString> *nonExistingPrlFiles);
-};
-
-QList<QtModuleInfo> allQt4Modules(const QtEnvironment &qtEnvironment);
-QList<QtModuleInfo> allQt5Modules(const Profile &profile, const QtEnvironment &qtEnvironment);
-
-} // namespace Internal
-} // namespace qbs
-
-#endif // Include guard.
diff --git a/src/lib/qtprofilesetup/qtmsvctools.cpp b/src/lib/qtprofilesetup/qtmsvctools.cpp
deleted file mode 100644
index 0c41b928c..000000000
--- a/src/lib/qtprofilesetup/qtmsvctools.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qbs.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qtmsvctools.h"
-
-namespace qbs {
-
-static const QString msvcPrefix = QLatin1String("win32-msvc");
-
-bool isMsvcQt(const QtEnvironment &env)
-{
- return env.mkspecName.startsWith(msvcPrefix);
-}
-
-static Version msvcCompilerVersionForYear(int year)
-{
- switch (year)
- {
- case 2005:
- return Version(14);
- case 2008:
- return Version(15);
- case 2010:
- return Version(16);
- case 2012:
- return Version(17);
- case 2013:
- return Version(18);
- case 2015:
- return Version(19);
- case 2017:
- return Version(19, 1);
- default:
- return Version();
- }
-}
-
-Version msvcCompilerVersionFromMkspecName(const QString &mkspecName)
-{
- return msvcCompilerVersionForYear(mkspecName.mid(msvcPrefix.size()).toInt());
-}
-
-} // namespace qbs
diff --git a/src/lib/qtprofilesetup/qtmsvctools.h b/src/lib/qtprofilesetup/qtmsvctools.h
deleted file mode 100644
index 195d0e0ec..000000000
--- a/src/lib/qtprofilesetup/qtmsvctools.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qbs.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qtenvironment.h"
-#include <tools/qbs_export.h>
-#include <tools/version.h>
-
-namespace qbs {
-
-QBS_EXPORT bool isMsvcQt(const QtEnvironment &env);
-QBS_EXPORT Version msvcCompilerVersionFromMkspecName(const QString &mkspecName);
-
-} // namespace qbs
diff --git a/src/lib/qtprofilesetup/qtprofilesetup.cpp b/src/lib/qtprofilesetup/qtprofilesetup.cpp
deleted file mode 100644
index 7fabcb5c9..000000000
--- a/src/lib/qtprofilesetup/qtprofilesetup.cpp
+++ /dev/null
@@ -1,930 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qbs.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qtprofilesetup.h"
-
-#include "qtmoduleinfo.h"
-#include "qtmsvctools.h"
-
-#include <logging/translator.h>
-#include <tools/architectures.h>
-#include <tools/error.h>
-#include <tools/hostosinfo.h>
-#include <tools/jsliterals.h>
-#include <tools/profile.h>
-#include <tools/settings.h>
-#include <tools/version.h>
-
-#include <QtCore/qdir.h>
-#include <QtCore/qdiriterator.h>
-#include <QtCore/qendian.h>
-#include <QtCore/qfile.h>
-#include <QtCore/qfileinfo.h>
-#include <QtCore/qlibrary.h>
-#include <QtCore/qregexp.h>
-#include <QtCore/qtextstream.h>
-
-#include <queue>
-#include <regex>
-
-#ifdef __APPLE__
-#include <ar.h>
-#include <mach/machine.h>
-#include <mach-o/fat.h>
-#include <mach-o/loader.h>
-#if __MAC_OS_X_VERSION_MAX_ALLOWED < 101200
-#define FAT_MAGIC_64 0xcafebabf
-#define FAT_CIGAM_64 0xbfbafeca
-struct fat_arch_64 {
- cpu_type_t cputype;
- cpu_subtype_t cpusubtype;
- uint64_t offset;
- uint64_t size;
- uint32_t align;
- uint32_t reserved;
-};
-#endif
-#endif
-
-namespace qbs {
-using namespace Internal;
-
-template <class T>
-QByteArray utf8JSLiteral(T t)
-{
- return toJSLiteral(t).toUtf8();
-}
-
-static QString pathToJSLiteral(const QString &path)
-{
- return toJSLiteral(QDir::fromNativeSeparators(path));
-}
-
-static QString defaultQpaPlugin(const Profile &profile, const QtModuleInfo &module,
- const QtEnvironment &qtEnv)
-{
- if (qtEnv.qtMajorVersion < 5)
- return QString();
-
- if (qtEnv.qtMajorVersion == 5 && qtEnv.qtMinorVersion < 8) {
- QFile qConfigPri(qtEnv.mkspecBasePath + QLatin1String("/qconfig.pri"));
- if (!qConfigPri.open(QIODevice::ReadOnly)) {
- throw ErrorInfo(Tr::tr("Setting up Qt profile '%1' failed: Cannot open "
- "file '%2' (%3).")
- .arg(profile.name(), qConfigPri.fileName(), qConfigPri.errorString()));
- }
- const QList<QByteArray> lines = qConfigPri.readAll().split('\n');
- const QByteArray magicString = "QT_DEFAULT_QPA_PLUGIN =";
- for (const QByteArray &line : lines) {
- const QByteArray simplifiedLine = line.simplified();
- if (simplifiedLine.startsWith(magicString))
- return QString::fromLatin1(simplifiedLine.mid(magicString.size()).trimmed());
- }
- } else {
- const QString qtGuiConfigHeader = (qtEnv.frameworkBuild
- ? qtEnv.libraryPath
- : qtEnv.includePath)
- + QStringLiteral("/QtGui")
- + (qtEnv.frameworkBuild ? QStringLiteral(".framework/Headers") : QString())
- + QStringLiteral("/qtgui-config.h");
- std::queue<QString> headerFiles;
- headerFiles.push(qtGuiConfigHeader);
- while (!headerFiles.empty()) {
- QFile headerFile(headerFiles.front());
- headerFiles.pop();
- if (!headerFile.open(QIODevice::ReadOnly)) {
- throw ErrorInfo(Tr::tr("Setting up Qt profile '%1' failed: Cannot open "
- "file '%2' (%3).")
- .arg(profile.name(), headerFile.fileName(),
- headerFile.errorString()));
- }
- static const std::regex regexp(
- "^#define QT_QPA_DEFAULT_PLATFORM_NAME \"(.+)\".*$");
- static const std::regex includeRegexp(
- "^#include \"(.+)\".*$");
- const QList<QByteArray> lines = headerFile.readAll().split('\n');
- for (const QByteArray &line: lines) {
- const auto lineStr = QString::fromLatin1(line.simplified()).toStdString();
- std::smatch match;
- if (std::regex_match(lineStr, match, regexp))
- return QLatin1Char('q') + QString::fromStdString(match[1]);
- if (std::regex_match(lineStr, match, includeRegexp)) {
- QString filePath = QString::fromStdString(match[1]);
- if (QFileInfo(filePath).isRelative()) {
- filePath = QDir::cleanPath(QFileInfo(headerFile.fileName()).absolutePath()
- + QLatin1Char('/') + filePath);
- }
- headerFiles.push(filePath);
- }
- }
- }
- }
-
- if (module.isStaticLibrary)
- qDebug("Warning: Could not determine default QPA plugin for static Qt.");
- return QString();
-}
-
-static QByteArray minVersionJsString(const QString &minVersion)
-{
- if (minVersion.isEmpty())
- return "original";
- return utf8JSLiteral(minVersion);
-}
-
-#ifdef __APPLE__
-template <typename T = uint32_t> T readInt(QIODevice *ioDevice, bool *ok,
- bool swap, bool peek = false) {
- const auto bytes = peek
- ? ioDevice->peek(sizeof(T))
- : ioDevice->read(sizeof(T));
- if (bytes.size() != sizeof(T)) {
- if (ok)
- *ok = false;
- return T();
- }
- if (ok)
- *ok = true;
- T n = *reinterpret_cast<const T *>(bytes.constData());
- return swap ? qbswap(n) : n;
-}
-
-static QString archName(cpu_type_t cputype, cpu_subtype_t cpusubtype)
-{
- switch (cputype) {
- case CPU_TYPE_X86:
- switch (cpusubtype) {
- case CPU_SUBTYPE_X86_ALL:
- return QStringLiteral("i386");
- default:
- return QString();
- }
- case CPU_TYPE_X86_64:
- switch (cpusubtype) {
- case CPU_SUBTYPE_X86_64_ALL:
- return QStringLiteral("x86_64");
- case CPU_SUBTYPE_X86_64_H:
- return QStringLiteral("x86_64h");
- default:
- return QString();
- }
- case CPU_TYPE_ARM:
- switch (cpusubtype) {
- case CPU_SUBTYPE_ARM_V7:
- return QStringLiteral("armv7a");
- case CPU_SUBTYPE_ARM_V7S:
- return QStringLiteral("armv7s");
- case CPU_SUBTYPE_ARM_V7K:
- return QStringLiteral("armv7k");
- default:
- return QString();
- }
- case CPU_TYPE_ARM64:
- switch (cpusubtype) {
- case CPU_SUBTYPE_ARM64_ALL:
- return QStringLiteral("arm64");
- default:
- return QString();
- }
- default:
- return QString();
- }
-}
-
-static QStringList detectMachOArchs(QIODevice *device)
-{
- bool ok;
- bool foundMachO = false;
- qint64 pos = device->pos();
-
- char ar_header[SARMAG];
- if (device->read(ar_header, SARMAG) == SARMAG) {
- if (strncmp(ar_header, ARMAG, SARMAG) == 0) {
- while (!device->atEnd()) {
- static_assert(sizeof(ar_hdr) == 60, "sizeof(ar_hdr) != 60");
- ar_hdr header;
- if (device->read(reinterpret_cast<char *>(&header),
- sizeof(ar_hdr)) != sizeof(ar_hdr))
- return { };
-
- // If the file name is stored in the "extended format" manner,
- // the real filename is prepended to the data section, so skip that many bytes
- int filenameLength = 0;
- if (strncmp(header.ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0) {
- char arName[sizeof(header.ar_name)] = { 0 };
- memcpy(arName, header.ar_name + sizeof(AR_EFMT1) - 1,
- sizeof(header.ar_name) - (sizeof(AR_EFMT1) - 1) - 1);
- filenameLength = strtoul(arName, nullptr, 10);
- if (device->read(filenameLength).size() != filenameLength)
- return { };
- }
-
- switch (readInt(device, nullptr, false, true)) {
- case MH_CIGAM:
- case MH_CIGAM_64:
- case MH_MAGIC:
- case MH_MAGIC_64:
- foundMachO = true;
- break;
- default: {
- // Skip the data and go to the next archive member...
- char szBuf[sizeof(header.ar_size) + 1] = { 0 };
- memcpy(szBuf, header.ar_size, sizeof(header.ar_size));
- int sz = static_cast<int>(strtoul(szBuf, nullptr, 10));
- if (sz % 2 != 0)
- ++sz;
- sz -= filenameLength;
- const auto data = device->read(sz);
- if (data.size() != sz)
- return { };
- }
- }
-
- if (foundMachO)
- break;
- }
- }
- }
-
- // Wasn't an archive file, so try a fat file
- if (!foundMachO && !device->seek(pos))
- return QStringList();
-
- pos = device->pos();
-
- fat_header fatheader;
- fatheader.magic = readInt(device, nullptr, false);
- if (fatheader.magic == FAT_MAGIC || fatheader.magic == FAT_CIGAM ||
- fatheader.magic == FAT_MAGIC_64 || fatheader.magic == FAT_CIGAM_64) {
- const bool swap = fatheader.magic == FAT_CIGAM || fatheader.magic == FAT_CIGAM_64;
- const bool is64bit = fatheader.magic == FAT_MAGIC_64 || fatheader.magic == FAT_CIGAM_64;
- fatheader.nfat_arch = readInt(device, &ok, swap);
- if (!ok)
- return QStringList();
-
- QStringList archs;
-
- for (uint32_t n = 0; n < fatheader.nfat_arch; ++n) {
- fat_arch_64 fatarch;
- static_assert(sizeof(fat_arch_64) == 32, "sizeof(fat_arch_64) != 32");
- static_assert(sizeof(fat_arch) == 20, "sizeof(fat_arch) != 20");
- const qint64 expectedBytes = is64bit ? sizeof(fat_arch_64) : sizeof(fat_arch);
- if (device->read(reinterpret_cast<char *>(&fatarch), expectedBytes) != expectedBytes)
- return QStringList();
-
- if (swap) {
- fatarch.cputype = qbswap(fatarch.cputype);
- fatarch.cpusubtype = qbswap(fatarch.cpusubtype);
- }
-
- const QString name = archName(fatarch.cputype, fatarch.cpusubtype);
- if (name.isEmpty()) {
- qWarning("Unknown cputype %d and cpusubtype %d",
- fatarch.cputype, fatarch.cpusubtype);
- return QStringList();
- }
- archs.push_back(name);
- }
-
- std::sort(archs.begin(), archs.end());
- return archs;
- }
-
- // Wasn't a fat file, so we just read a thin Mach-O from the original offset
- if (!device->seek(pos))
- return QStringList();
-
- bool swap = false;
- mach_header header;
- header.magic = readInt(device, nullptr, swap);
- switch (header.magic) {
- case MH_CIGAM:
- case MH_CIGAM_64:
- swap = true;
- break;
- case MH_MAGIC:
- case MH_MAGIC_64:
- break;
- default:
- return QStringList();
- }
-
- header.cputype = static_cast<cpu_type_t>(readInt(device, &ok, swap));
- if (!ok)
- return QStringList();
-
- header.cpusubtype = static_cast<cpu_subtype_t>(readInt(device, &ok, swap));
- if (!ok)
- return QStringList();
-
- const QString name = archName(header.cputype, header.cpusubtype);
- if (name.isEmpty()) {
- qWarning("Unknown cputype %d and cpusubtype %d",
- header.cputype, header.cpusubtype);
- return { };
- }
- return { name };
-}
-#endif
-
-static QStringList extractQbsArchs(const QtModuleInfo &module, const QtEnvironment &qtEnv)
-{
-#ifdef __APPLE__
- if (qtEnv.mkspecName.startsWith(QLatin1String("macx-"))) {
- QStringList archs;
- if (!module.libFilePathRelease.isEmpty()) {
- QFile file(module.libFilePathRelease);
- if (file.open(QIODevice::ReadOnly))
- archs = detectMachOArchs(&file);
- else
- qWarning("Failed to open %s for reading",
- qUtf8Printable(module.libFilePathRelease));
- if (archs.isEmpty())
- qWarning("Could not detect architectures for module %s in Qt build (%s)",
- qPrintable(module.name), qUtf8Printable(qtEnv.mkspecName));
- }
- return archs;
- }
-#else
- Q_UNUSED(module);
-#endif
- QString qbsArch = canonicalArchitecture(qtEnv.architecture);
- if (qbsArch == QLatin1String("arm") && qtEnv.mkspecPath.contains(QLatin1String("android")))
- qbsArch = QLatin1String("armv7a");
-
- // Qt4 has "QT_ARCH = windows" in qconfig.pri for both MSVC and mingw.
- if (qbsArch == QLatin1String("windows"))
- return QStringList();
-
- return QStringList { qbsArch };
-}
-
-static std::pair<int, int> findVariable(const QByteArray &content, int start)
-{
- std::pair<int, int> result = std::make_pair(-1, -1);
- result.first = content.indexOf('@', start);
- if (result.first == -1)
- return result;
- result.second = content.indexOf('@', result.first + 1);
- if (result.second == -1) {
- result.first = -1;
- return result;
- }
- for (char forbidden : {' ', '\n'}) {
- int k = content.indexOf(forbidden, result.first + 1);
- if (k != -1 && k < result.second) {
- return findVariable(content, result.first + 1);
- }
- }
- return result;
-}
-
-static QByteArray libraryFileTag(const QtEnvironment &env, const QtModuleInfo &module)
-{
- QByteArray result;
- if (module.isStaticLibrary) {
- result = "staticlibrary";
- } else {
- result = isMsvcQt(env) || env.mkspecName.startsWith(QLatin1String("win32-g++"))
- ? "dynamiclibrary_import" : "dynamiclibrary";
- }
- return result;
-}
-
-static void replaceSpecialValues(QByteArray *content, const Profile &profile,
- const QtModuleInfo &module, const QtEnvironment &qtEnvironment)
-{
- QHash<QByteArray, QByteArray> dict;
- dict.insert("archs", utf8JSLiteral(extractQbsArchs(module, qtEnvironment)));
- dict.insert("targetPlatform", utf8JSLiteral(qbsTargetPlatformFromQtMkspec(qtEnvironment)));
- dict.insert("config", utf8JSLiteral(qtEnvironment.configItems));
- dict.insert("qtConfig", utf8JSLiteral(qtEnvironment.qtConfigItems));
- dict.insert("binPath", utf8JSLiteral(qtEnvironment.binaryPath));
- dict.insert("libPath", utf8JSLiteral(qtEnvironment.libraryPath));
- dict.insert("pluginPath", utf8JSLiteral(qtEnvironment.pluginPath));
- dict.insert("incPath", utf8JSLiteral(qtEnvironment.includePath));
- dict.insert("docPath", utf8JSLiteral(qtEnvironment.documentationPath));
- dict.insert("mkspecName", utf8JSLiteral(qtEnvironment.mkspecName));
- dict.insert("mkspecPath", utf8JSLiteral(qtEnvironment.mkspecPath));
- dict.insert("version", utf8JSLiteral(qtEnvironment.qtVersion));
- dict.insert("libInfix", utf8JSLiteral(qtEnvironment.qtLibInfix));
- dict.insert("availableBuildVariants", utf8JSLiteral(qtEnvironment.buildVariant));
- dict.insert("staticBuild", utf8JSLiteral(qtEnvironment.staticBuild));
- dict.insert("frameworkBuild", utf8JSLiteral(qtEnvironment.frameworkBuild));
- dict.insert("name", utf8JSLiteral(module.moduleNameWithoutPrefix()));
- dict.insert("has_library", utf8JSLiteral(module.hasLibrary));
- dict.insert("dependencies", utf8JSLiteral(module.dependencies));
- dict.insert("includes", utf8JSLiteral(module.includePaths));
- dict.insert("staticLibsDebug", utf8JSLiteral(module.staticLibrariesDebug));
- dict.insert("staticLibsRelease", utf8JSLiteral(module.staticLibrariesRelease));
- dict.insert("dynamicLibsDebug", utf8JSLiteral(module.dynamicLibrariesDebug));
- dict.insert("dynamicLibsRelease", utf8JSLiteral(module.dynamicLibrariesRelease));
- dict.insert("linkerFlagsDebug", utf8JSLiteral(module.linkerFlagsDebug));
- dict.insert("linkerFlagsRelease", utf8JSLiteral(module.linkerFlagsRelease));
- dict.insert("libraryPaths", utf8JSLiteral(module.libraryPaths));
- dict.insert("frameworkPathsDebug", utf8JSLiteral(module.frameworkPathsDebug));
- dict.insert("frameworkPathsRelease", utf8JSLiteral(module.frameworkPathsRelease));
- dict.insert("frameworksDebug", utf8JSLiteral(module.frameworksDebug));
- dict.insert("frameworksRelease", utf8JSLiteral(module.frameworksRelease));
- dict.insert("libFilePathDebug", utf8JSLiteral(module.libFilePathDebug));
- dict.insert("libFilePathRelease", utf8JSLiteral(module.libFilePathRelease));
- dict.insert("libNameForLinkerDebug",
- utf8JSLiteral(module.libNameForLinker(qtEnvironment, true)));
- dict.insert("pluginTypes", utf8JSLiteral(module.supportedPluginTypes));
- dict.insert("moduleConfig", utf8JSLiteral(module.config));
- dict.insert("libNameForLinkerRelease",
- utf8JSLiteral(module.libNameForLinker(qtEnvironment, false)));
- dict.insert("entryPointLibsDebug", utf8JSLiteral(qtEnvironment.entryPointLibsDebug));
- dict.insert("entryPointLibsRelease", utf8JSLiteral(qtEnvironment.entryPointLibsRelease));
- dict.insert("minWinVersion", minVersionJsString(qtEnvironment.windowsVersion));
- dict.insert("minMacVersion", minVersionJsString(qtEnvironment.macosVersion));
- dict.insert("minIosVersion", minVersionJsString(qtEnvironment.iosVersion));
- dict.insert("minTvosVersion", minVersionJsString(qtEnvironment.tvosVersion));
- dict.insert("minWatchosVersion", minVersionJsString(qtEnvironment.watchosVersion));
- dict.insert("minAndroidVersion", minVersionJsString(qtEnvironment.androidVersion));
-
- QByteArray additionalContent;
- QByteArray compilerDefines = utf8JSLiteral(module.compilerDefines);
- if (module.qbsName == QLatin1String("declarative")
- || module.qbsName == QLatin1String("quick")) {
- const QByteArray debugMacro = module.qbsName == QLatin1String("declarative")
- || qtEnvironment.qtMajorVersion < 5
- ? "QT_DECLARATIVE_DEBUG" : "QT_QML_DEBUG";
-
- const QString indent = QLatin1String(" ");
- QTextStream s(&additionalContent);
- s << "property bool qmlDebugging: false" << endl;
- s << indent << "property string qmlPath";
- if (qtEnvironment.qmlPath.isEmpty())
- s << endl;
- else
- s << ": " << pathToJSLiteral(qtEnvironment.qmlPath) << endl;
-
- s << indent << "property string qmlImportsPath: "
- << pathToJSLiteral(qtEnvironment.qmlImportPath);
-
- const QByteArray baIndent(4, ' ');
- compilerDefines = "{\n"
- + baIndent + baIndent + "var result = " + compilerDefines + ";\n"
- + baIndent + baIndent + "if (qmlDebugging)\n"
- + baIndent + baIndent + baIndent + "result.push(\"" + debugMacro + "\");\n"
- + baIndent + baIndent + "return result;\n"
- + baIndent + "}";
- }
- dict.insert("defines", compilerDefines);
- if (module.qbsName == QLatin1String("gui")) {
- dict.insert("defaultQpaPlugin",
- utf8JSLiteral(defaultQpaPlugin(profile, module, qtEnvironment)));
- }
- if (module.qbsName == QLatin1String("qml"))
- dict.insert("qmlPath", pathToJSLiteral(qtEnvironment.qmlPath).toUtf8());
- if (module.isStaticLibrary && module.qbsName != QLatin1String("core")) {
- if (!additionalContent.isEmpty())
- additionalContent += "\n ";
- additionalContent += "isStaticLibrary: true";
- }
- if (module.isPlugin) {
- dict.insert("className", utf8JSLiteral(module.pluginData.className));
- dict.insert("extends", utf8JSLiteral(module.pluginData.extends));
- }
- if (module.hasLibrary && !module.isFramework(qtEnvironment)) {
- if (!additionalContent.isEmpty())
- additionalContent += "\n";
- const QByteArray indent(4, ' ');
- additionalContent += "Group {\n";
- if (module.isPlugin) {
- additionalContent += indent + indent
- + "condition: Qt[\"" + module.qbsName.toUtf8() + "\"].enableLinking\n";
- }
- additionalContent += indent + indent + "files: [Qt[\"" + module.qbsName.toUtf8() + "\"]"
- + ".libFilePath]\n"
- + indent + indent + "filesAreTargets: true\n"
- + indent + indent + "fileTags: [\"" + libraryFileTag(qtEnvironment, module)
- + "\"]\n"
- + indent + "}";
- }
- dict.insert("additionalContent", additionalContent);
-
- for (std::pair<int, int> pos = findVariable(*content, 0); pos.first != -1;
- pos = findVariable(*content, pos.first)) {
- const QByteArray &replacement = dict.value(
- content->mid(pos.first + 1, pos.second - pos.first - 1));
- content->replace(pos.first, pos.second - pos.first + 1, replacement);
- pos.first += replacement.length();
- }
-}
-
-static void copyTemplateFile(const QString &fileName, const QString &targetDirectory,
- const Profile &profile, const QtEnvironment &qtEnv, QStringList *allFiles,
- const QtModuleInfo *module = nullptr, const QVariantMap &pluginMap = QVariantMap(),
- const QStringList &nonEssentialPlugins = QStringList())
-{
- if (!QDir::root().mkpath(targetDirectory)) {
- throw ErrorInfo(Internal::Tr::tr("Setting up Qt profile '%1' failed: "
- "Cannot create directory '%2'.")
- .arg(profile.name(), targetDirectory));
- }
- QFile sourceFile(QLatin1String(":/templates/") + fileName);
- if (!sourceFile.open(QIODevice::ReadOnly)) {
- throw ErrorInfo(Internal::Tr::tr("Setting up Qt profile '%1' failed: "
- "Cannot open '%1' (%2).").arg(sourceFile.fileName(), sourceFile.errorString()));
- }
- QByteArray newContent = sourceFile.readAll();
- if (module) {
- replaceSpecialValues(&newContent, profile, *module, qtEnv);
- } else {
- newContent.replace("@allPluginsByType@", '(' + utf8JSLiteral(pluginMap) + ')');
- newContent.replace("@nonEssentialPlugins@", utf8JSLiteral(nonEssentialPlugins));
- }
- sourceFile.close();
- const QString targetPath = targetDirectory + QLatin1Char('/') + fileName;
- allFiles->push_back(QFileInfo(targetPath).absoluteFilePath());
- QFile targetFile(targetPath);
- if (targetFile.open(QIODevice::ReadOnly)) {
- if (newContent == targetFile.readAll()) // No need to overwrite anything in this case.
- return;
- targetFile.close();
- }
- if (!targetFile.open(QIODevice::WriteOnly)) {
- throw ErrorInfo(Internal::Tr::tr("Setting up Qt profile '%1' failed: "
- "Cannot open '%1' (%2).").arg(targetFile.fileName(), targetFile.errorString()));
- }
- targetFile.resize(0);
- targetFile.write(newContent);
-}
-
-static void createModules(Profile &profile, Settings *settings,
- const QtEnvironment &qtEnvironment)
-{
- const QList<QtModuleInfo> modules = qtEnvironment.qtMajorVersion < 5
- ? allQt4Modules(qtEnvironment)
- : allQt5Modules(profile, qtEnvironment);
- QVariantMap pluginsByType;
- QStringList nonEssentialPlugins;
- for (const QtModuleInfo &m : modules) {
- if (m.isPlugin) {
- QVariant &v = pluginsByType[m.pluginData.type];
- v = v.toStringList() << m.name;
- if (!m.pluginData.autoLoad)
- nonEssentialPlugins << m.name;
- }
- }
- const QString profileBaseDir = QString::fromLatin1("%1/profiles/%2")
- .arg(QFileInfo(settings->fileName()).dir().absolutePath(),
- profile.name());
- const QString qbsQtModuleBaseDir = profileBaseDir + QLatin1String("/modules/Qt");
- QStringList allFiles;
- copyTemplateFile(QLatin1String("QtModule.qbs"), qbsQtModuleBaseDir, profile, qtEnvironment,
- &allFiles);
- copyTemplateFile(QLatin1String("QtPlugin.qbs"), qbsQtModuleBaseDir, profile, qtEnvironment,
- &allFiles);
- copyTemplateFile(QLatin1String("plugin_support.qbs"),
- qbsQtModuleBaseDir + QLatin1String("/plugin_support"), profile, qtEnvironment,
- &allFiles, nullptr, pluginsByType, nonEssentialPlugins);
- for (const QtModuleInfo &module : modules) {
- const QString qbsQtModuleDir = qbsQtModuleBaseDir + QLatin1Char('/') + module.qbsName;
- QString moduleTemplateFileName;
- if (module.qbsName == QLatin1String("core")) {
- moduleTemplateFileName = QLatin1String("core.qbs");
- copyTemplateFile(QLatin1String("moc.js"), qbsQtModuleDir, profile, qtEnvironment,
- &allFiles);
- copyTemplateFile(QLatin1String("qdoc.js"), qbsQtModuleDir, profile, qtEnvironment,
- &allFiles);
- } else if (module.qbsName == QLatin1String("gui")) {
- moduleTemplateFileName = QLatin1String("gui.qbs");
- } else if (module.qbsName == QLatin1String("scxml")) {
- moduleTemplateFileName = QLatin1String("scxml.qbs");
- } else if (module.qbsName == QLatin1String("dbus")) {
- moduleTemplateFileName = QLatin1String("dbus.qbs");
- copyTemplateFile(QLatin1String("dbus.js"), qbsQtModuleDir, profile, qtEnvironment,
- &allFiles);
- } else if (module.qbsName == QLatin1String("qml")) {
- moduleTemplateFileName = QLatin1String("qml.qbs");
- copyTemplateFile(QLatin1String("qml.js"), qbsQtModuleDir, profile, qtEnvironment,
- &allFiles);
- const QString qmlcacheStr = QStringLiteral("qmlcache");
- if (QFileInfo::exists(HostOsInfo::appendExecutableSuffix(
- qtEnvironment.binaryPath + QStringLiteral("/qmlcachegen")))) {
- copyTemplateFile(qmlcacheStr + QStringLiteral(".qbs"),
- qbsQtModuleBaseDir + QLatin1Char('/') + qmlcacheStr, profile,
- qtEnvironment, &allFiles);
- }
- } else if (module.qbsName == QLatin1String("quick")) {
- moduleTemplateFileName = QLatin1String("quick.qbs");
- copyTemplateFile(QLatin1String("quick.js"), qbsQtModuleDir, profile,
- qtEnvironment, &allFiles);
- } else if (module.isPlugin) {
- moduleTemplateFileName = QLatin1String("plugin.qbs");
- } else {
- moduleTemplateFileName = QLatin1String("module.qbs");
- }
- copyTemplateFile(moduleTemplateFileName, qbsQtModuleDir, profile, qtEnvironment, &allFiles,
- &module);
- }
-
- // Note that it's not strictly necessary to copy this one, as it has no variable content.
- // But we do it anyway for consistency (and it has no impact on the project files this way).
- copyTemplateFile(QLatin1String("android_support.qbs"),
- qbsQtModuleBaseDir + QLatin1String("/android_support"), profile, qtEnvironment,
- &allFiles);
-
- QDirIterator dit(qbsQtModuleBaseDir, QDirIterator::Subdirectories);
- while (dit.hasNext()) {
- dit.next();
- const QFileInfo &fi = dit.fileInfo();
- if (!fi.isFile())
- continue;
- const QString filePath = fi.absoluteFilePath();
- if (!allFiles.contains(filePath) && !QFile::remove(filePath))
- qDebug("Warning: Failed to remove outdated file '%s'.", qPrintable(filePath));
- }
- profile.setValue(QLatin1String("preferences.qbsSearchPaths"), profileBaseDir);
-}
-
-static QString guessMinimumWindowsVersion(const QtEnvironment &qt)
-{
- if (qt.mkspecName.startsWith(QLatin1String("winrt-")))
- return QLatin1String("10.0");
-
- if (!qt.targetsDesktopWindows())
- return QString();
-
- if (qt.architecture == QLatin1String("x86_64")
- || qt.architecture == QLatin1String("ia64")) {
- return QLatin1String("5.2");
- }
-
- QRegExp rex(QLatin1String("^win32-msvc(\\d+)$"));
- if (rex.exactMatch(qt.mkspecName)) {
- int msvcVersion = rex.cap(1).toInt();
- if (msvcVersion < 2012)
- return QLatin1String("5.0");
- else
- return QLatin1String("5.1");
- }
-
- return qt.qtMajorVersion < 5 ? QLatin1String("5.0") : QLatin1String("5.1");
-}
-
-static bool checkForStaticBuild(const QtEnvironment &qt)
-{
- if (qt.qtMajorVersion >= 5)
- return qt.qtConfigItems.contains(QLatin1String("static"));
- if (qt.frameworkBuild)
- return false; // there are no Qt4 static frameworks
- const bool isWin = qt.mkspecName.startsWith(QLatin1String("win"));
- const QDir libdir(isWin ? qt.binaryPath : qt.libraryPath);
- const QStringList coreLibFiles
- = libdir.entryList(QStringList(QLatin1String("*Core*")), QDir::Files);
- if (coreLibFiles.empty())
- throw ErrorInfo(Internal::Tr::tr("Could not determine whether Qt is a static build."));
- for (const QString &fileName : coreLibFiles) {
- if (QLibrary::isLibrary(fileName))
- return false;
- }
- return true;
-}
-
-static QStringList fillEntryPointLibs(const QtEnvironment &qtEnvironment, const Version &qtVersion,
- bool debug)
-{
- QStringList result;
- const bool isMinGW = qtEnvironment.isForMinGw();
-
- // Some Linux distributions rename the qtmain library.
- QStringList qtMainCandidates(QLatin1String("qtmain"));
- if (isMinGW && qtEnvironment.qtMajorVersion == 5)
- qtMainCandidates << QLatin1String("qt5main");
-
- for (const QString &baseNameCandidate : qtMainCandidates) {
- QString qtmain = qtEnvironment.libraryPath + QLatin1Char('/');
- if (isMinGW)
- qtmain += QLatin1String("lib");
- qtmain += baseNameCandidate + qtEnvironment.qtLibInfix;
- if (debug)
- qtmain += QLatin1Char('d');
- if (isMinGW) {
- qtmain += QLatin1String(".a");
- } else {
- qtmain += QLatin1String(".lib");
- if (qtVersion >= Version(5, 4, 0))
- result << QLatin1String("Shell32.lib");
- }
- if (QFile::exists(qtmain)) {
- result << qtmain;
- break;
- }
- }
- if (result.isEmpty()) {
- qDebug("Warning: Could not find the qtmain library. "
- "You will not be able to link Qt applications.");
- }
- return result;
-}
-
-void doSetupQtProfile(const QString &profileName, Settings *settings,
- const QtEnvironment &_qtEnvironment)
-{
- QtEnvironment qtEnvironment = _qtEnvironment;
- qtEnvironment.staticBuild = checkForStaticBuild(qtEnvironment);
-
- // determine whether user apps require C++11
- if (qtEnvironment.qtConfigItems.contains(QLatin1String("c++11")) && qtEnvironment.staticBuild)
- qtEnvironment.configItems.push_back(QLatin1String("c++11"));
-
- // Set the minimum operating system versions appropriate for this Qt version
- qtEnvironment.windowsVersion = guessMinimumWindowsVersion(qtEnvironment);
- if (!qtEnvironment.windowsVersion.isEmpty()) { // Is target OS Windows?
- const Version qtVersion = Version(qtEnvironment.qtMajorVersion,
- qtEnvironment.qtMinorVersion,
- qtEnvironment.qtPatchVersion);
- if (qtEnvironment.buildVariant.contains(QLatin1String("debug"))) {
- qtEnvironment.entryPointLibsDebug = fillEntryPointLibs(qtEnvironment, qtVersion,
- true);
- }
- if (qtEnvironment.buildVariant.contains(QLatin1String("release"))) {
- qtEnvironment.entryPointLibsRelease = fillEntryPointLibs(qtEnvironment, qtVersion,
- false);
- }
- } else if (qtEnvironment.mkspecPath.contains(QLatin1String("macx"))) {
- if (qtEnvironment.qtMajorVersion >= 5) {
- QFile qmakeConf(qtEnvironment.mkspecPath + QStringLiteral("/qmake.conf"));
- if (qmakeConf.open(QIODevice::ReadOnly)) {
- static const std::regex re(
- "^QMAKE_(MACOSX|IOS|TVOS|WATCHOS)_DEPLOYMENT_TARGET\\s*=\\s*(.*)\\s*$");
- while (!qmakeConf.atEnd()) {
- std::smatch match;
- const auto line = qmakeConf.readLine().trimmed().toStdString();
- if (std::regex_match(line, match, re)) {
- const auto platform = QString::fromStdString(match[1]);
- const auto version = QString::fromStdString(match[2]);
- if (platform == QStringLiteral("MACOSX"))
- qtEnvironment.macosVersion = version;
- else if (platform == QStringLiteral("IOS"))
- qtEnvironment.iosVersion = version;
- else if (platform == QStringLiteral("TVOS"))
- qtEnvironment.tvosVersion = version;
- else if (platform == QStringLiteral("WATCHOS"))
- qtEnvironment.watchosVersion = version;
- }
- }
- }
-
- const bool isMac = qtEnvironment.mkspecName != QStringLiteral("macx-ios-clang")
- && qtEnvironment.mkspecName != QStringLiteral("macx-tvos-clang")
- && qtEnvironment.mkspecName != QStringLiteral("macx-watchos-clang");
- if (isMac) {
- // Qt 5.0.x placed the minimum version in a different file
- if (qtEnvironment.macosVersion.isEmpty()) {
- qtEnvironment.macosVersion = QLatin1String("10.6");
- }
-
- // If we're using C++11 with libc++, make sure the deployment target is >= 10.7
- if (Version::fromString(qtEnvironment.macosVersion) < Version(10, 7)
- && qtEnvironment.qtConfigItems.contains(QLatin1String("c++11")))
- qtEnvironment.macosVersion = QLatin1String("10.7");
- }
- } else if (qtEnvironment.qtMajorVersion == 4 && qtEnvironment.qtMinorVersion >= 6) {
- QDir qconfigDir;
- if (qtEnvironment.frameworkBuild) {
- qconfigDir.setPath(qtEnvironment.libraryPath);
- qconfigDir.cd(QLatin1String("QtCore.framework/Headers"));
- } else {
- qconfigDir.setPath(qtEnvironment.includePath);
- qconfigDir.cd(QLatin1String("Qt"));
- }
- QFile qconfig(qconfigDir.absoluteFilePath(QLatin1String("qconfig.h")));
- if (qconfig.open(QIODevice::ReadOnly)) {
- bool qtCocoaBuild = false;
- QTextStream ts(&qconfig);
- QString line;
- do {
- line = ts.readLine();
- if (QRegExp(QLatin1String("\\s*#define\\s+QT_MAC_USE_COCOA\\s+1\\s*"),
- Qt::CaseSensitive).exactMatch(line)) {
- qtCocoaBuild = true;
- break;
- }
- } while (!line.isNull());
-
- if (ts.status() == QTextStream::Ok) {
- qtEnvironment.macosVersion = qtCocoaBuild ? QLatin1String("10.5")
- : QLatin1String("10.4");
- }
- }
-
- if (qtEnvironment.macosVersion.isEmpty()) {
- throw ErrorInfo(Internal::Tr::tr("Error reading qconfig.h; could not determine "
- "whether Qt is using Cocoa or Carbon"));
- }
- }
- } else if (qtEnvironment.mkspecPath.contains(QLatin1String("android"))) {
- if (qtEnvironment.qtMajorVersion >= 5)
- qtEnvironment.androidVersion = QLatin1String("2.3");
- else if (qtEnvironment.qtMajorVersion == 4 && qtEnvironment.qtMinorVersion >= 8)
- qtEnvironment.androidVersion = QLatin1String("1.6"); // Necessitas
- }
-
- Profile profile(profileName, settings);
- profile.removeProfile();
- createModules(profile, settings, qtEnvironment);
-}
-
-QString qbsTargetPlatformFromQtMkspec(const QtEnvironment &qtEnv)
-{
- QString mkspec = qtEnv.mkspecName;
- int idx = mkspec.lastIndexOf(QLatin1Char('/'));
- if (idx != -1)
- mkspec = mkspec.mid(idx + 1);
- if (mkspec.startsWith(QLatin1String("aix-")))
- return QLatin1String("aix");
- if (mkspec.startsWith(QLatin1String("android-")))
- return QLatin1String("android");
- if (mkspec.startsWith(QLatin1String("cygwin-")))
- return QLatin1String("windows");
- if (mkspec.startsWith(QLatin1String("darwin-")))
- return QLatin1String("macos");
- if (mkspec.startsWith(QLatin1String("freebsd-")))
- return QLatin1String("freebsd");
- if (mkspec.startsWith(QLatin1String("haiku-")))
- return QLatin1String("haiku");
- if (mkspec.startsWith(QLatin1String("hpux-")) || mkspec.startsWith(QLatin1String("hpuxi-")))
- return QLatin1String("hpux");
- if (mkspec.startsWith(QLatin1String("hurd-")))
- return QLatin1String("hurd");
- if (mkspec.startsWith(QLatin1String("integrity-")))
- return QLatin1String("integrity");
- if (mkspec.startsWith(QLatin1String("linux-")))
- return QLatin1String("linux");
- if (mkspec.startsWith(QLatin1String("macx-"))) {
- if (mkspec.startsWith(QLatin1String("macx-ios-")))
- return QLatin1String("ios");
- if (mkspec.startsWith(QLatin1String("macx-tvos-")))
- return QLatin1String("tvos");
- if (mkspec.startsWith(QLatin1String("macx-watchos-")))
- return QLatin1String("watchos");
- return QLatin1String("macos");
- }
- if (mkspec.startsWith(QLatin1String("netbsd-")))
- return QLatin1String("netbsd");
- if (mkspec.startsWith(QLatin1String("openbsd-")))
- return QLatin1String("openbsd");
- if (mkspec.startsWith(QLatin1String("qnx-")))
- return QLatin1String("qnx");
- if (mkspec.startsWith(QLatin1String("solaris-")))
- return QLatin1String("solaris");
- if (mkspec.startsWith(QLatin1String("vxworks-")))
- return QLatin1String("vxworks");
- if (qtEnv.targetsDesktopWindows() || mkspec.startsWith(QLatin1String("winrt-")))
- return QLatin1String("windows");
- return QString();
-}
-
-ErrorInfo setupQtProfile(const QString &profileName, Settings *settings,
- const QtEnvironment &qtEnvironment)
-{
- try {
- doSetupQtProfile(profileName, settings, qtEnvironment);
- return ErrorInfo();
- } catch (const ErrorInfo &e) {
- return e;
- }
-}
-
-} // namespace qbs
diff --git a/src/lib/qtprofilesetup/qtprofilesetup.h b/src/lib/qtprofilesetup/qtprofilesetup.h
deleted file mode 100644
index f28733a1b..000000000
--- a/src/lib/qtprofilesetup/qtprofilesetup.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qbs.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#ifndef QBS_SETUPQTPROFILE_H
-#define QBS_SETUPQTPROFILE_H
-
-#include "qtenvironment.h"
-
-#include <tools/qbs_export.h>
-
-#include <QtCore/qstring.h>
-
-namespace qbs {
-class ErrorInfo;
-class Settings;
-
-QBS_EXPORT QString qbsTargetPlatformFromQtMkspec(const QtEnvironment &qtEnv);
-
-QBS_EXPORT ErrorInfo setupQtProfile(const QString &profileName, Settings *settings,
- const QtEnvironment &qtEnvironment);
-
-} // namespace qbs
-
-#endif // Include guard.
diff --git a/src/lib/qtprofilesetup/qtprofilesetup.pro b/src/lib/qtprofilesetup/qtprofilesetup.pro
deleted file mode 100644
index a32ff97aa..000000000
--- a/src/lib/qtprofilesetup/qtprofilesetup.pro
+++ /dev/null
@@ -1,31 +0,0 @@
-TARGET = qbsqtprofilesetup
-include(../library.pri)
-include(../corelib/use_corelib.pri)
-
-CONFIG -= qtquickcompiler
-
-HEADERS = \
- qtenvironment.h \
- qtmoduleinfo.h \
- qtmsvctools.h \
- qtprofilesetup.h
-
-SOURCES = \
- qtmoduleinfo.cpp \
- qtmsvctools.cpp \
- qtprofilesetup.cpp
-
-RESOURCES = templates.qrc
-
-!qbs_no_dev_install {
- header.files = \
- qtenvironment.h \
- qtmsvctools.h \
- qtprofilesetup.h
- header.path = $${QBS_INSTALL_PREFIX}/include/qbs
- use_pri.files = use_installed_qtprofilesetup.pri
- use_pri.path = $${header.path}
- INSTALLS += header use_pri
-}
-
-OTHER_FILES += templates/*
diff --git a/src/lib/qtprofilesetup/qtprofilesetup.qbs b/src/lib/qtprofilesetup/qtprofilesetup.qbs
deleted file mode 100644
index 8c8b77020..000000000
--- a/src/lib/qtprofilesetup/qtprofilesetup.qbs
+++ /dev/null
@@ -1,31 +0,0 @@
-import qbs
-
-QbsLibrary {
- name: "qbsqtprofilesetup"
- Depends { name: "qbscore" }
-
- Group {
- name: "Public API headers"
- files: [
- "qtenvironment.h",
- "qtprofilesetup.h",
- "qtmsvctools.h",
- "use_installed_qtprofilesetup.pri",
- ]
- qbs.install: qbsbuildconfig.installApiHeaders
- qbs.installDir: headerInstallPrefix
- }
-
- files: [
- "qtprofilesetup.cpp",
- "qtmoduleinfo.cpp",
- "qtmoduleinfo.h",
- "qtmsvctools.cpp",
- "templates.qrc",
- "templates/*"
- ]
-
- Export {
- Depends { name: "qbscore" }
- }
-}
diff --git a/src/lib/qtprofilesetup/templates.qrc b/src/lib/qtprofilesetup/templates.qrc
deleted file mode 100644
index 35bddf8d7..000000000
--- a/src/lib/qtprofilesetup/templates.qrc
+++ /dev/null
@@ -1,22 +0,0 @@
-<RCC>
- <qresource prefix="/">
- <file>templates/core.qbs</file>
- <file>templates/gui.qbs</file>
- <file>templates/module.qbs</file>
- <file>templates/QtModule.qbs</file>
- <file>templates/moc.js</file>
- <file>templates/plugin.qbs</file>
- <file>templates/qdoc.js</file>
- <file>templates/QtPlugin.qbs</file>
- <file>templates/dbus.js</file>
- <file>templates/dbus.qbs</file>
- <file>templates/scxml.qbs</file>
- <file>templates/qml.qbs</file>
- <file>templates/qml.js</file>
- <file>templates/qmlcache.qbs</file>
- <file>templates/quick.js</file>
- <file>templates/quick.qbs</file>
- <file>templates/plugin_support.qbs</file>
- <file>templates/android_support.qbs</file>
- </qresource>
-</RCC>
diff --git a/src/lib/qtprofilesetup/use_installed_qtprofilesetup.pri b/src/lib/qtprofilesetup/use_installed_qtprofilesetup.pri
deleted file mode 100644
index c3fa4a83d..000000000
--- a/src/lib/qtprofilesetup/use_installed_qtprofilesetup.pri
+++ /dev/null
@@ -1,20 +0,0 @@
-include(use_installed_corelib.pri)
-
-LIBNAME=qbsqtprofilesetup
-
-unix:LIBS += -l$${LIBNAME}
-
-win32 {
- CONFIG(debug, debug|release) {
- QBSQTPROFILELIB = $${LIBNAME}d$${QBSCORELIBSUFFIX}
- }
- CONFIG(release, debug|release) {
- QBSQTPROFILELIB = $${LIBNAME}$${QBSCORELIBSUFFIX}
- }
- msvc {
- QBSQTPROFILELIB = $${QBSQTPROFILELIB}.lib
- } else {
- QBSQTPROFILELIB = lib$${QBSQTPROFILELIB}
- }
- LIBS += $${QBSQTPROFILELIB}
-}
diff --git a/src/lib/qtprofilesetup/use_qtprofilesetup.pri b/src/lib/qtprofilesetup/use_qtprofilesetup.pri
deleted file mode 100644
index 87390fc10..000000000
--- a/src/lib/qtprofilesetup/use_qtprofilesetup.pri
+++ /dev/null
@@ -1,46 +0,0 @@
-include(../../../qbs_version.pri)
-include(../../library_dirname.pri)
-
-isEmpty(QBSLIBDIR) {
- QBSLIBDIR = $${OUT_PWD}/../../../$${QBS_LIBRARY_DIRNAME}
-}
-
-LIBNAME=qbsqtprofilesetup
-
-unix {
- LIBS += -L$${QBSLIBDIR} -l$${LIBNAME}
-}
-
-!qbs_disable_rpath {
- linux-*:QMAKE_LFLAGS += -Wl,-z,origin \'-Wl,-rpath,\$\$ORIGIN/../$${QBS_LIBRARY_DIRNAME}\'
- macx:QMAKE_LFLAGS += -Wl,-rpath,@loader_path/../$${QBS_LIBRARY_DIRNAME}
-}
-
-!CONFIG(static, static|shared) {
- QBSQTPROFILELIBSUFFIX = $${QBS_VERSION_MAJ}
-}
-
-win32 {
- CONFIG(debug, debug|release) {
- QBSQTPROFILELIB = $${LIBNAME}d$${QBSQTPROFILELIBSUFFIX}
- }
- CONFIG(release, debug|release) {
- QBSQTPROFILELIB = $${LIBNAME}$${QBSQTPROFILELIBSUFFIX}
- }
- msvc {
- LIBS += /LIBPATH:$$QBSLIBDIR
- QBSQTPROFILELIB = $${QBSQTPROFILELIB}.lib
- LIBS += Shell32.lib
- } else {
- LIBS += -L$${QBSLIBDIR}
- QBSQTPROFILELIB = lib$${QBSQTPROFILELIB}
- }
- LIBS += $${QBSQTPROFILELIB}
-}
-
-INCLUDEPATH += \
- $$PWD
-
-CONFIG(static, static|shared) {
- DEFINES += QBS_STATIC_LIB
-}
diff --git a/src/packages/archive/archive.qbs b/src/packages/archive/archive.qbs
index 39d762884..7deaddc3a 100644
--- a/src/packages/archive/archive.qbs
+++ b/src/packages/archive/archive.qbs
@@ -8,7 +8,6 @@ QbsProduct {
Depends { name: "qbs_processlauncher" }
Depends { name: "qbscore" }
Depends { name: "bundledqt" }
- Depends { name: "qbsqtprofilesetup" }
Depends { name: "qbs documentation" }
Depends { name: "qbs resources" }
Depends { name: "qbs man page"; condition: qbs.targetOS.contains("unix") }
diff --git a/tests/auto/blackbox/tst_blackboxqt.cpp b/tests/auto/blackbox/tst_blackboxqt.cpp
index 128c61133..4428ddb1d 100644
--- a/tests/auto/blackbox/tst_blackboxqt.cpp
+++ b/tests/auto/blackbox/tst_blackboxqt.cpp
@@ -50,15 +50,12 @@ void TestBlackboxQt::validateTestProfile()
if (profileName() != "none" && !s->profiles().contains(profileName()))
QFAIL(QByteArray("The build profile '" + profileName().toLocal8Bit() +
"' could not be found. Please set it up on your machine."));
-
- const QStringList searchPaths
- = qbs::Preferences(s.get(), profileName()).searchPaths(
- QDir::cleanPath(QCoreApplication::applicationDirPath()));
- for (const auto &searchPath : searchPaths) {
- if (QFileInfo(searchPath + "/modules/Qt").isDir())
- return;
- }
-
+ const QStringList qmakeFilePaths = Profile(profileName(), s.get())
+ .value("moduleProviders.Qt.qmakeFilePaths").toStringList();
+ if (!qmakeFilePaths.empty())
+ return;
+ if (!findExecutable(QStringList{"qmake"}).isEmpty())
+ return;
QSKIP(QByteArray("The build profile '" + profileName().toLocal8Bit() +
"' is not a valid Qt profile and Qt was not found "
"in the global search paths."));