diff options
author | Christian Kandeler <christian.kandeler@qt.io> | 2017-04-20 15:57:39 +0200 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@qt.io> | 2017-04-28 15:09:40 +0000 |
commit | b60004ea8ae2e0717e6fab2f40bfe90bac7cf6b7 (patch) | |
tree | f994c11f8f024abe56a97df6533235e21844c141 /src | |
parent | 985ed0fa89a1bdf5ced4ab0d15bf8b182e722e2d (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.cpp | 2 | ||||
-rw-r--r-- | src/lib/qtprofilesetup/templates.qrc | 1 | ||||
-rw-r--r-- | src/lib/qtprofilesetup/templates/qml.js | 65 | ||||
-rw-r--r-- | src/lib/qtprofilesetup/templates/qml.qbs | 106 |
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]; + } + } } |