aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Weickelt <richard@weickelt.de>2019-07-08 01:49:19 +0200
committerRichard Weickelt <richard@weickelt.de>2019-10-10 08:05:15 +0000
commit905ee49fabe197bfe4537c1f10df9d7c48f731c2 (patch)
tree57acb908ac5449be8ddb84e01e00e52d7ce07755
parent73ed687cf11cb2d4e7f263ef5754039b96b69aaa (diff)
Bundle Qt libraries on all platforms
This patch allows us to deploy a self-containing Qbs package on all host platforms that are supported by the official Qt binary packages. Although not all (Linux) distributions make use of it, this will be helpful to - provide at least some binary convenience packages for the most important distributions, - perform building and testing in different environments, for instance build Qbs in one stage and then run autotests for desktop, iOS, android in parallel on multiple machines, - avoid windeployqt which does not work when cross-building for Windows on a Linux hosts. Change-Id: I63de4ea2240b37d8bd465cbbf4ddff3d01eeac7e Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
-rw-r--r--qbs-resources/imports/QbsAutotest.qbs6
-rw-r--r--qbs-resources/modules/qbsbuildconfig/qbsbuildconfig.qbs2
-rw-r--r--src/lib/corelib/corelib.qbs1
-rw-r--r--src/packages/archive/archive.qbs115
-rw-r--r--src/shared/bundledqt/bundledqt.qbs181
5 files changed, 144 insertions, 161 deletions
diff --git a/qbs-resources/imports/QbsAutotest.qbs b/qbs-resources/imports/QbsAutotest.qbs
index 78db72d11..5d4143a41 100644
--- a/qbs-resources/imports/QbsAutotest.qbs
+++ b/qbs-resources/imports/QbsAutotest.qbs
@@ -7,6 +7,7 @@ QtApplication {
consoleApplication: true
property string testName
name: "tst_" + testName
+ property string targetInstallDir: qbsbuildconfig.appInstallDir
Depends { name: "Qt.testlib" }
Depends { name: "qbscore" }
Depends { name: "qbsbuildconfig" }
@@ -28,13 +29,14 @@ QtApplication {
"consolelogger.h"
]
}
- cpp.rpaths: [FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix, qbsbuildconfig.libDirName)]
+ cpp.rpaths: qbsbuildconfig.libRPaths
+
qbs.commonRunEnvironment: ({
"QBS_INSTALL_DIR": FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix)
})
Group {
fileTagsFilter: product.type
qbs.install: true
- qbs.installDir: qbsbuildconfig.appInstallDir
+ qbs.installDir: targetInstallDir
}
}
diff --git a/qbs-resources/modules/qbsbuildconfig/qbsbuildconfig.qbs b/qbs-resources/modules/qbsbuildconfig/qbsbuildconfig.qbs
index c2db0189f..7fe735ad9 100644
--- a/qbs-resources/modules/qbsbuildconfig/qbsbuildconfig.qbs
+++ b/qbs-resources/modules/qbsbuildconfig/qbsbuildconfig.qbs
@@ -12,7 +12,7 @@ Module {
property bool enableProjectFileUpdates: false
property bool enableRPath: true
property bool installApiHeaders: true
- property bool enableBundledQt: true
+ property bool enableBundledQt: false
property bool useBundledQtScript: false
property bool staticBuild: false
property string libDirName: "lib"
diff --git a/src/lib/corelib/corelib.qbs b/src/lib/corelib/corelib.qbs
index 019d9aa51..bd44ac3ed 100644
--- a/src/lib/corelib/corelib.qbs
+++ b/src/lib/corelib/corelib.qbs
@@ -3,7 +3,6 @@ import qbs.Utilities
QbsLibrary {
Depends { name: "cpp" }
- Depends { name: "bundledqt" }
Depends { name: "Qt"; submodules: ["core-private", "network", "xml"] }
Depends {
name: "Qt.script"
diff --git a/src/packages/archive/archive.qbs b/src/packages/archive/archive.qbs
index 0e0663090..468606368 100644
--- a/src/packages/archive/archive.qbs
+++ b/src/packages/archive/archive.qbs
@@ -7,7 +7,7 @@ import qbs.TextFile
QbsProduct {
Depends { name: "qbs_processlauncher" }
Depends { name: "qbscore" }
- Depends { name: "bundledqt" }
+ Depends { name: "bundledqt"; required: false }
Depends { name: "qbs documentation"; condition: project.withDocumentation }
Depends { name: "qbs resources" }
Depends {
@@ -18,25 +18,8 @@ QbsProduct {
Depends { name: "archiver" }
- property stringList windeployqtArgs: [
- "--no-svg",
- "--no-system-d3d-compiler",
- "--no-angle",
- "--no-compiler-runtime",
- "--no-opengl-sw",
- ]
-
- // List of path prefixes to be excluded from the generated archive
- property stringList excludedPathPrefixes: [
- "bin/icudt",
- "bin/icuin",
- "bin/icuuc",
- "bin/iconengines/",
- "bin/imageformats/",
- ]
property bool includeTopLevelDir: false
- condition: qbs.targetOS.containsAny(["windows", "macos"])
builtByDefault: false
name: "qbs archive"
type: ["archiver.archive"]
@@ -64,65 +47,8 @@ QbsProduct {
}
Rule {
- condition: qbs.targetOS.contains("windows")
multiplex: true
- inputsFromDependencies: ["installable"]
-
- Artifact {
- filePath: "windeployqt.json"
- fileTags: ["dependencies.json"]
- }
-
- prepare: {
- var cmd = new JavaScriptCommand();
- cmd.description = "windeployqt";
- cmd.outputFilePath = output.filePath;
- cmd.installRoot = product.moduleProperty("qbs", "installRoot");
- cmd.windeployqtArgs = product.windeployqtArgs;
- cmd.binaryFilePaths = inputs.installable.filter(function (artifact) {
- return artifact.fileTags.contains("application")
- || artifact.fileTags.contains("dynamiclibrary");
- }).map(function(a) { return ModUtils.artifactInstalledFilePath(a); });
- cmd.binaryFilePaths.sort(function(a1, a2) {
- if (a1.contains("qbs.exe"))
- return -1;
- if (a2.contains("qbs.exe"))
- return 1;
- return 0;
- });
- cmd.extendedDescription = FileInfo.joinPaths(
- product.moduleProperty("Qt.core", "binPath"), "windeployqt") + ".exe " +
- ["--json"].concat(cmd.windeployqtArgs).concat(cmd.binaryFilePaths).join(" ");
- cmd.sourceCode = function () {
- var out;
- var process;
- try {
- process = new Process();
- process.exec(FileInfo.joinPaths(product.moduleProperty("Qt.core", "binPath"),
- "windeployqt"), ["--json"]
- .concat(windeployqtArgs).concat(binaryFilePaths), true);
- out = process.readStdOut();
- } finally {
- if (process)
- process.close();
- }
-
- var tf;
- try {
- tf = new TextFile(outputFilePath, TextFile.WriteOnly);
- tf.write(out);
- } finally {
- if (tf)
- tf.close();
- }
- };
- return [cmd];
- }
- }
-
- Rule {
- multiplex: true
- inputs: ["dependencies.json", "installable"]
+ inputs: ["installable"]
inputsFromDependencies: ["installable"]
Artifact {
@@ -140,46 +66,13 @@ QbsProduct {
cmd.outputFilePath = output.filePath;
cmd.baseDirectory = product.moduleProperty("archiver", "workingDirectory");
cmd.sourceCode = function() {
- var tf;
- for (var i = 0; i < (inputs["dependencies.json"] || []).length; ++i) {
- try {
- tf = new TextFile(inputs["dependencies.json"][i].filePath,
- TextFile.ReadOnly);
- inputFilePaths = inputFilePaths.concat(
- JSON.parse(tf.readAll())["files"].map(function (obj) {
- return FileInfo.joinPaths(
- FileInfo.fromWindowsSeparators(obj.target),
- FileInfo.fileName(
- FileInfo.fromWindowsSeparators(
- obj.source)));
- }));
- } finally {
- if (tf)
- tf.close();
- }
- }
-
inputFilePaths.sort();
-
+ var tf;
try {
tf = new TextFile(outputFilePath, TextFile.ReadWrite);
for (var i = 0; i < inputFilePaths.length; ++i) {
- var ignore = false;
var relativePath = FileInfo.relativePath(baseDirectory, inputFilePaths[i]);
- for (var j = 0; j < excludedPathPrefixes.length; ++j) {
- if (relativePath.startsWith(excludedPathPrefixes[j])) {
- ignore = true;
- break;
- }
- }
-
- // QTBUG-65916
- var fileName = FileInfo.fileName(inputFilePaths[i]);
- if (fileName.endsWith(".qm") && !fileName.startsWith("qt_"))
- ignore = true;
-
- if (!ignore)
- tf.writeLine(relativePath);
+ tf.writeLine(relativePath);
}
} finally {
if (tf)
diff --git a/src/shared/bundledqt/bundledqt.qbs b/src/shared/bundledqt/bundledqt.qbs
index 6e9b744ab..5995ae4d6 100644
--- a/src/shared/bundledqt/bundledqt.qbs
+++ b/src/shared/bundledqt/bundledqt.qbs
@@ -1,18 +1,29 @@
import qbs
+import qbs.File
import qbs.FileInfo
Product {
Depends { name: "qbsbuildconfig" }
- Depends { name: "Qt"; submodules:
- ["core", "gui", "network", "printsupport", "widgets", "xml"] }
- Depends { name: "Qt.script"; required: false }
+ Depends { name: "Qt"; submodules: ["core", "gui", "network", "printsupport", "widgets", "xml"] }
+ Depends { name: "Qt.test"; condition: project.withTests === true }
+ Depends { name: "Qt.script"; condition: !qbsbuildconfig.useBundledQtScript; required: false }
+ Depends {
+ name: "Qt";
+ submodules: [ "dbus", "xcb_qpa_lib-private" ];
+ required: false
+ }
- property bool deployQt: qbsbuildconfig.enableBundledQt && qbs.targetOS.contains("macos")
- && Qt.core.qtConfig.contains("rpath")
- property bool deployDebugLibraries: qbs.buildVariant === "debug"
- || (qbs.buildVariants && qbs.buildVariants.contains("debug"))
+ condition: {
+ if (!qbsbuildconfig.enableBundledQt)
+ return false;
+ if (Qt.core.staticBuild)
+ throw("Cannot bundle static Qt libraries");
+ return true;
+ }
readonly property string qtDebugLibrarySuffix: {
+ if (Qt.core.qtBuildVariant !== "debug")
+ return "";
if (qbs.targetOS.contains("windows"))
return "d";
if (qbs.targetOS.contains("darwin"))
@@ -21,7 +32,6 @@ Product {
}
Group {
- condition: deployQt && !Qt.core.staticBuild
name: "qt.conf"
files: ["qt.conf"]
qbs.install: true
@@ -29,56 +39,135 @@ Product {
}
Group {
- condition: deployQt
name: "Qt libraries"
- files: !Qt.core.staticBuild ? Array.prototype.concat.apply(
- [], Object.getOwnPropertyNames(Qt).map(function(mod) {
- if (mod === "script" && !Qt[mod].present)
- return [];
- if (!Qt[mod].hasLibrary)
- return [];
- var fp = Qt[mod].libFilePathRelease;
- var fpd = Qt.core.frameworkBuild ? fp + qtDebugLibrarySuffix : Qt[mod].libFilePathDebug;
-
- var list = [fp];
- if (deployDebugLibraries && qtDebugLibrarySuffix)
- list.push(fpd);
-
- if (Qt.core.frameworkBuild) {
- var suffix = ".framework/";
- var frameworkPath = fp.substr(0, fp.lastIndexOf(suffix) + suffix.length - 1);
- var versionsPath = frameworkPath + "/Versions";
- var versionPath = versionsPath + "/" + Qt.core.versionMajor;
- list.push(frameworkPath + "/Resources");
- list.push(versionPath + "/Resources/Info.plist");
- list.push(versionPath + "/" + FileInfo.fileName(fp));
- if (deployDebugLibraries && qtDebugLibrarySuffix)
- list.push(versionPath + "/" + FileInfo.fileName(fpd));
- if (qbsbuildconfig.installApiHeaders) {
- list.push(frameworkPath + "/Headers");
- list.push(versionPath + "/Headers/**");
+ files: {
+ function getLibsForQtModule(mod) {
+ if (mod === "script" && !Qt[mod].present)
+ return [];
+ if ((mod !== "core") && !Qt[mod].hasLibrary)
+ return [];
+ if (Qt[mod].isStaticLibrary)
+ return [];
+
+ var list = [];
+ if (qbs.targetOS.contains("windows")) {
+ var basename = FileInfo.baseName(Qt[mod].libNameForLinker);
+ var dir = Qt.core.binPath;
+ list.push(dir + "/" + basename + ".dll");
+
+ } else if (qbs.targetOS.contains("linux")) {
+ var fp = Qt[mod].libFilePath;
+ var basename = FileInfo.baseName(fp);
+ var dir = FileInfo.path(fp);
+ list.push(dir + "/" + basename + ".so");
+ list.push(dir + "/" + basename + ".so." + Qt.core.versionMajor);
+ list.push(dir + "/" + basename + ".so." + Qt.core.versionMajor + "." + Qt.core.versionMinor);
+ list.push(fp);
+
+ } else if (Qt.core.frameworkBuild) {
+ var fp = Qt[mod].libFilePathRelease;
+ var fpd = fp + "_debug";
+
+ if (qtDebugLibrarySuffix)
+ list.push(fpd);
+
+ var suffix = ".framework/";
+ var frameworkPath = fp.substr(0, fp.lastIndexOf(suffix) + suffix.length - 1);
+ var versionsPath = frameworkPath + "/Versions";
+ var versionPath = versionsPath + "/" + Qt.core.versionMajor;
+ list.push(frameworkPath + "/Resources");
+ list.push(versionPath + "/Resources/Info.plist");
+ list.push(versionPath + "/" + FileInfo.fileName(fp));
+ if (qtDebugLibrarySuffix)
+ list.push(versionPath + "/" + FileInfo.fileName(fpd));
+ if (qbsbuildconfig.installApiHeaders) {
+ list.push(frameworkPath + "/Headers");
+ list.push(versionPath + "/Headers/**");
+ }
}
+ return list;
+ }
+
+ var qtModules = Object.getOwnPropertyNames(Qt);
+ var libraries = Array.prototype.concat.apply([], qtModules.map(getLibsForQtModule));
+
+ // Qt might be bundled with additional libraries
+ if (qbs.targetOS.contains("linux")) {
+ var dir = FileInfo.path(Qt.core.libFilePathRelease);
+ var addons = [ "libicui18n", "libicuuc", "libicudata" ];
+ addons.forEach(function(lib) {
+ var fp = dir + "/" + lib + ".so";
+ if (File.exists(fp))
+ libraries.push(fp + "*");
+ });
}
- return list;
- })) : []
+ return libraries;
+ }
+
qbs.install: true
qbs.installDir: qbsbuildconfig.libInstallDir
- qbs.installSourceBase: Qt.core.libPath
+ qbs.installSourceBase: qbs.targetOS.contains("windows") ? Qt.core.binPath : Qt.core.libPath
}
Group {
- condition: deployQt
+ name: "Windows Plugins"
+ condition: qbs.targetOS.contains("windows")
prefix: Qt.core.pluginPath + "/"
- name: "QPA plugin"
- files: !Qt.core.staticBuild ? Array.prototype.concat.apply([], [""].concat(
- deployDebugLibraries && qtDebugLibrarySuffix ? [qtDebugLibrarySuffix] : []).map(
- function(suffix) {
- return ["platforms/" + cpp.dynamicLibraryPrefix + (Qt.gui.defaultQpaPlugin || "qcocoa")
- + suffix + cpp.dynamicLibrarySuffix];
- })) : []
+ files: [
+ "platforms/qwindows" + qtDebugLibrarySuffix + cpp.dynamicLibrarySuffix,
+ "styles/qwindowsvistastyle" + qtDebugLibrarySuffix + cpp.dynamicLibrarySuffix
+ ]
qbs.install: true
qbs.installDir: "plugins"
qbs.installSourceBase: prefix
}
+
+ Group {
+ name: "macOS Plugins"
+ condition: qbs.targetOS.contains("darwin")
+ prefix: Qt.core.pluginPath + "/"
+ files: [
+ "platforms/libqcocoa" + qtDebugLibrarySuffix + cpp.dynamicLibrarySuffix,
+ "styles/libqmacstyle" + qtDebugLibrarySuffix + cpp.dynamicLibrarySuffix
+ ]
+ qbs.install: true
+ qbs.installDir: "plugins"
+ qbs.installSourceBase: prefix
+ }
+
+ Group {
+ name: "Linux Plugins"
+ condition: qbs.targetOS.contains("linux")
+ prefix: Qt.core.pluginPath + "/"
+ files: [
+ "platforms/libqxcb" + cpp.dynamicLibrarySuffix,
+ "platformthemes/libqgtk3" + cpp.dynamicLibrarySuffix
+ ]
+ qbs.install: true
+ qbs.installDir: "plugins"
+ qbs.installSourceBase: prefix
+ }
+
+ Group {
+ name: "MinGW Runtime DLLs"
+ condition: qbs.targetOS.contains("windows") && qbs.toolchain.contains("mingw")
+
+ files: {
+ var libFileGlobs = [
+ "*libgcc_s*.dll",
+ "*libstdc++-6.dll",
+ "*libwinpthread-1.dll"
+ ];
+ var searchPaths = cpp.compilerLibraryPaths;
+ return Array.prototype.concat.apply([], searchPaths.map(function(path) {
+ return libFileGlobs.map(function(glob) {
+ return path + "/" + glob;
+ });
+ }));
+ }
+
+ qbs.install: true
+ qbs.installDir: "bin"
+ }
}