aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@qt.io>2017-04-20 15:57:39 +0200
committerChristian Kandeler <christian.kandeler@qt.io>2017-04-28 15:09:40 +0000
commitb60004ea8ae2e0717e6fab2f40bfe90bac7cf6b7 (patch)
treef994c11f8f024abe56a97df6533235e21844c141 /src
parent985ed0fa89a1bdf5ced4ab0d15bf8b182e722e2d (diff)
Qt.qml: Link against QML plugins when using a static Qt
Task-number: QBS-1121 Change-Id: Id1da9786d4535a350eed72062848c2745cf8a73b Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/lib/qtprofilesetup/qtprofilesetup.cpp2
-rw-r--r--src/lib/qtprofilesetup/templates.qrc1
-rw-r--r--src/lib/qtprofilesetup/templates/qml.js65
-rw-r--r--src/lib/qtprofilesetup/templates/qml.qbs106
4 files changed, 171 insertions, 3 deletions
diff --git a/src/lib/qtprofilesetup/qtprofilesetup.cpp b/src/lib/qtprofilesetup/qtprofilesetup.cpp
index 9f9462a38..6b09c4e8a 100644
--- a/src/lib/qtprofilesetup/qtprofilesetup.cpp
+++ b/src/lib/qtprofilesetup/qtprofilesetup.cpp
@@ -277,6 +277,8 @@ static void createModules(Profile &profile, Settings *settings,
&allFiles);
} else if (module.qbsName == QLatin1String("qml")) {
moduleTemplateFileName = QLatin1String("qml.qbs");
+ copyTemplateFile(QLatin1String("qml.js"), qbsQtModuleDir, profile, qtEnvironment,
+ &allFiles);
} else if (module.qbsName == QLatin1String("phonon")) {
moduleTemplateFileName = QLatin1String("phonon.qbs");
} else if (module.isPlugin) {
diff --git a/src/lib/qtprofilesetup/templates.qrc b/src/lib/qtprofilesetup/templates.qrc
index 9c0310750..d65582a1c 100644
--- a/src/lib/qtprofilesetup/templates.qrc
+++ b/src/lib/qtprofilesetup/templates.qrc
@@ -13,5 +13,6 @@
<file>templates/dbus.qbs</file>
<file>templates/scxml.qbs</file>
<file>templates/qml.qbs</file>
+ <file>templates/qml.js</file>
</qresource>
</RCC>
diff --git a/src/lib/qtprofilesetup/templates/qml.js b/src/lib/qtprofilesetup/templates/qml.js
new file mode 100644
index 000000000..640f2e072
--- /dev/null
+++ b/src/lib/qtprofilesetup/templates/qml.js
@@ -0,0 +1,65 @@
+var File = require("qbs.File");
+var FileInfo = require("qbs.FileInfo");
+var Process = require("qbs.Process");
+var TextFile = require("qbs.TextFile");
+
+function scannerData(scannerFilePath, qmlFiles, qmlPath)
+{
+ var p;
+ try {
+ p = new Process();
+ p.exec(scannerFilePath, ["-qmlFiles"].concat(qmlFiles).concat(["-importPath", qmlPath]),
+ true);
+ return JSON.parse(p.readStdOut());
+ } finally {
+ if (p)
+ p.close();
+ }
+}
+
+function getPrlRhs(line)
+{
+ return line.split('=')[1].trim();
+}
+
+function getLibsForPlugin(pluginData, buildVariant, targetOS, toolchain)
+{
+ if (!pluginData.path)
+ return "";
+ var prlFileName = "";
+ if (!targetOS.contains("windows"))
+ prlFileName += "lib";
+ prlFileName += pluginData.plugin;
+ if (buildVariant === "debug" && targetOS.contains("windows"))
+ prlFileName += "d";
+ prlFileName += ".prl";
+ var prlFilePath = FileInfo.joinPaths(pluginData.path, prlFileName);
+ if (!File.exists(prlFilePath)) {
+ console.warn("prl file for QML plugin '" + pluginData.plugin + "' not present at '"
+ + prlFilePath + "'. Linking may fail.");
+ return "";
+ }
+ var prlFile = new TextFile(prlFilePath, TextFile.ReadOnly);
+ try {
+ var pluginLib;
+ var otherLibs = "";
+ var line;
+ while (line = prlFile.readLine()) {
+ if (line.startsWith("QMAKE_PRL_TARGET"))
+ pluginLib = FileInfo.joinPaths(pluginData.path, getPrlRhs(line));
+ if (line.startsWith("QMAKE_PRL_LIBS")) {
+ var otherLibsLine = ' ' + getPrlRhs(line);
+ if (toolchain.contains("msvc")) {
+ otherLibsLine = otherLibsLine.replace(/ -L/g, " /LIBPATH:");
+ otherLibsLine = otherLibsLine.replace(/-l([^ ]+)/g, "$1" + ".lib");
+ }
+ otherLibs += otherLibsLine;
+ }
+ }
+ if (!pluginLib)
+ throw "Malformed prl file '" + prlFilePath + "'.";
+ return pluginLib + ' ' + otherLibs;
+ } finally {
+ prlFile.close();
+ }
+}
diff --git a/src/lib/qtprofilesetup/templates/qml.qbs b/src/lib/qtprofilesetup/templates/qml.qbs
index 36f086add..cea3ab85a 100644
--- a/src/lib/qtprofilesetup/templates/qml.qbs
+++ b/src/lib/qtprofilesetup/templates/qml.qbs
@@ -1,15 +1,22 @@
-import qbs 1.0
+import qbs
+import qbs.TextFile
import '../QtModule.qbs' as QtModule
+import "qml.js" as Qml
QtModule {
qtModuleName: "Qml"
Depends { name: "Qt"; submodules: @dependencies@}
+ property string qmlImportScannerName: "qmlimportscanner"
+ property string qmlImportScannerFilePath: Qt.core.binPath + '/' + qmlImportScannerName
property string qmlPath: @qmlPath@
+ readonly property string pluginListFilePathDebug: product.buildDirectory + "/plugins.list.d"
+ readonly property string pluginListFilePathRelease: product.buildDirectory + "/plugins.list"
+
hasLibrary: @has_library@
- staticLibsDebug: @staticLibsDebug@
- staticLibsRelease: @staticLibsRelease@
+ staticLibsDebug: (isStaticLibrary ? ['@' + pluginListFilePathDebug] : []).concat(@staticLibsDebug@)
+ staticLibsRelease: (isStaticLibrary ? ['@' + pluginListFilePathRelease] : []).concat(@staticLibsRelease@)
dynamicLibsDebug: @dynamicLibsDebug@
dynamicLibsRelease: @dynamicLibsRelease@
linkerFlagsDebug: @linkerFlagsDebug@
@@ -26,4 +33,97 @@ QtModule {
cpp.includePaths: @includes@
cpp.libraryPaths: @libraryPaths@
@special_properties@
+
+ FileTagger {
+ patterns: ["*.qml"]
+ fileTags: ["qt.qml.qml"]
+ }
+
+ // This is needed for the case that there are no QML files in the project.
+ Rule {
+ condition: isStaticLibrary
+ multiplex: true
+ Artifact {
+ filePath: "qml_plugin_import.dummy"
+ fileTags: ["qt.qml.import_dummy"]
+ }
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ cmd.silent = true;
+ cmd.sourceCode = function() {
+ var f = new TextFile(output.filePath, TextFile.WriteOnly);
+ f.close();
+ }
+ return [cmd];
+ }
+ }
+
+ Rule {
+ condition: isStaticLibrary
+ multiplex: true
+ inputs: ["qt.qml.qml", "qt.qml.import_dummy"]
+ outputFileTags: ["cpp", "qt.qml.pluginlist"]
+ outputArtifacts: {
+ var list = [];
+ if (inputs["qt.qml.qml"])
+ list.push({ filePath: "qml_plugin_import.cpp", fileTags: ["cpp"] });
+ list.push({
+ filePath: product.Qt.core.qtBuildVariant === "debug"
+ ? product.Qt.qml.pluginListFilePathDebug
+ : product.Qt.qml.pluginListFilePathRelease,
+ fileTags: ["qt.qml.pluginlist"]
+ });
+ return list;
+ }
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ if (inputs["qt.qml.qml"])
+ cmd.description = "Creating " + outputs["cpp"][0].fileName;
+ else
+ cmd.silent = true;
+ cmd.sourceCode = function() {
+ var qmlInputs = inputs["qt.qml.qml"];
+ if (!qmlInputs)
+ qmlInputs = [];
+ var scannerData = Qml.scannerData(product.Qt.qml.qmlImportScannerFilePath,
+ qmlInputs.map(function(inp) { return inp.filePath; }),
+ product.Qt.qml.qmlPath);
+ var cppFile;
+ var listFile;
+ try {
+ if (qmlInputs.length > 0)
+ cppFile = new TextFile(outputs["cpp"][0].filePath, TextFile.WriteOnly);
+ listFile = new TextFile(outputs["qt.qml.pluginlist"][0].filePath,
+ TextFile.WriteOnly);
+ if (cppFile)
+ cppFile.writeLine("#include <QtPlugin>");
+ var plugins = { };
+ for (var p in scannerData) {
+ var plugin = scannerData[p].plugin;
+ if (!plugin || plugins[plugin])
+ continue;
+ plugins[plugin] = true;
+ var className = scannerData[p].classname;
+ if (!className) {
+ throw "QML plugin '" + plugin + "' is missing a classname entry. " +
+ "Please add one to the qmldir file.";
+ }
+ if (cppFile)
+ cppFile.writeLine("Q_IMPORT_PLUGIN(" + className + ")");
+ var libs = Qml.getLibsForPlugin(scannerData[p],
+ product.Qt.core.qtBuildVariant,
+ product.qbs.targetOS,
+ product.qbs.toolchain);
+ listFile.write(libs + ' ');
+ }
+ } finally {
+ if (cppFile)
+ cppFile.close();
+ if (listFile)
+ listFile.close();
+ };
+ };
+ return [cmd];
+ }
+ }
}