diff options
author | Christian Kandeler <christian.kandeler@qt.io> | 2018-06-08 14:55:29 +0200 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@qt.io> | 2018-06-08 15:13:47 +0200 |
commit | 073fda0ab536b5610ff1b9191db582791552509e (patch) | |
tree | 16f0bbacc116e93778e9490ba2c2d9efff738d35 /share/qbs/modules | |
parent | 9349866b37118db9179d1f0689e872ca1260f040 (diff) | |
parent | 5f71b2220f9ff6838799c407972309bff1e8fc96 (diff) |
Merge 1.12 into master
Change-Id: I0c914674c0728a7f7bc70fd9608914b95ef55a30
Diffstat (limited to 'share/qbs/modules')
-rw-r--r-- | share/qbs/modules/Exporter/pkgconfig/pkgconfig.js | 228 | ||||
-rw-r--r-- | share/qbs/modules/Exporter/pkgconfig/pkgconfig.qbs | 91 | ||||
-rw-r--r-- | share/qbs/modules/cpp/GenericGCC.qbs | 2 |
3 files changed, 320 insertions, 1 deletions
diff --git a/share/qbs/modules/Exporter/pkgconfig/pkgconfig.js b/share/qbs/modules/Exporter/pkgconfig/pkgconfig.js new file mode 100644 index 000000000..a3109d61d --- /dev/null +++ b/share/qbs/modules/Exporter/pkgconfig/pkgconfig.js @@ -0,0 +1,228 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qbs. +** +** 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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://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 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +var FileInfo = require("qbs.FileInfo"); +var ModUtils = require("qbs.ModUtils"); + +function quote(value) +{ + if (value.contains(" ") || value.contains("'") || value.contains('"')) { + return '"' + value.replace(/(["'\\])/g, "\\$1") + '"'; + } + return value; +} + +function writeEntry(product, file, key, propertyName, required, additionalValues) +{ + var value = product.Exporter.pkgconfig[propertyName]; + if (additionalValues && additionalValues.length > 0) + value = (value || []).concat(additionalValues); + var valueIsNotEmpty = value && (!Array.isArray(value) || value.length > 0); + if (valueIsNotEmpty) { + if (Array.isArray(value)) + value = value.join(' '); + file.writeLine(key + ": " + value); + } else if (required) { + throw "Failure creating " + FileInfo.fileName(file.filePath()) + ": The entry '" + key + + "' is required, but property Exporter.pkgconfig." + + propertyName + " is not set."; + } +} + +function collectAutodetectedData(topLevelProduct) +{ + var data = { + libs: [], + cflags: [], + requires: [], + requiresPrivate: [] + }; + if (!topLevelProduct.Exporter.pkgconfig.autoDetect) + return data; + + var excludedDeps = topLevelProduct.Exporter.pkgconfig.excludedDependencies || []; + var explicitRequires = topLevelProduct.Exporter.pkgconfig.requiresEntry || []; + var explicitRequiresPrivate = topLevelProduct.Exporter.pkgconfig.requiresPrivateEntry || []; + + var transformFunc = topLevelProduct.Exporter.pkgconfig.transformFunction; + + // Make use of the "prefix" convenience variable if applicable. + function quoteAndPrefixify(value) + { + var quotedValue = quote(value); + var installPrefix = topLevelProduct.qbs.installPrefix || ""; + if (!topLevelProduct.Exporter.pkgconfig._usePrefix || typeof value !== "string" + || !value.startsWith(installPrefix) + || (value.length > installPrefix.length && value[installPrefix.length] !== '/')) { + return quotedValue; + } + return quotedValue.replace(product.qbs.installPrefix, "${prefix}"); + } + + function transformedValue(product, moduleName, propertyName) + { + var originalValue = product.exports[moduleName][propertyName]; + var value = transformFunc + ? eval("(" + transformFunc + ")(product, moduleName, propertyName, originalValue)") + : originalValue; + if (Array.isArray(value)) + value.forEach(function(v, i, a) { a[i] = quoteAndPrefixify(v); }); + else if (value) + value = quoteAndPrefixify(value); + return value; + } + + function collectLibs(productOrModule) + { + var libs = []; + var libArtifacts; + var isProduct = !productOrModule.present; + var considerDynamicLibs = !isProduct || (productOrModule.type + && productOrModule.type.contains("dynamiclibrary")); + if (considerDynamicLibs) { + libArtifacts = productOrModule.artifacts.dynamiclibrary; + } else { + var considerStaticLibs = !isProduct || (productOrModule.type + && productOrModule.type.contains("staticlibrary")); + if (considerStaticLibs) + libArtifacts = productOrModule.artifacts.staticlibrary; + } + for (var i = 0; i < (libArtifacts || []).length; ++i) { + var libArtifact = libArtifacts[i]; + if (libArtifact.qbs.install) { + var installDir = FileInfo.path(ModUtils.artifactInstalledFilePath(libArtifact)); + installDir = installDir.slice(libArtifact.qbs.installRoot.length); + libs.push("-L" + quoteAndPrefixify(FileInfo.cleanPath(installDir)), + "-l" + quote(productOrModule.targetName)); + } + } + if (!productOrModule.exports.cpp) + return libs; + var libPaths = transformedValue(productOrModule, "cpp", "libraryPaths"); + if (libPaths) + libs.push.apply(libs, libPaths.map(function(p) { return "-L" + p; })); + function libNamesToLibEntries(libNames) { + return libNames.map(function(libName) { return "-l" + libName; }); + }; + var dlls = transformedValue(productOrModule, "cpp", "dynamicLibraries"); + if (dlls) + libs.push.apply(libs, libNamesToLibEntries(dlls)); + var staticLibs = transformedValue(productOrModule, "cpp", "staticLibraries"); + if (staticLibs) + libs.push.apply(libs, libNamesToLibEntries(staticLibs)); + var lFlags = transformedValue(productOrModule, "cpp", "linkerFlags"); + if (lFlags) + libs.push.apply(libs, lFlags); + lFlags = transformedValue(productOrModule, "cpp", "driverFlags"); + if (lFlags) + libs.push.apply(libs, lFlags); + lFlags = transformedValue(productOrModule, "cpp", "driverLinkerFlags"); + if (lFlags) + libs.push.apply(libs, lFlags); + return libs; + } + + function collectCFlags(productOrModule) + { + if (!productOrModule.exports.cpp) + return []; + var flags = []; + var defs = transformedValue(productOrModule, "cpp", "defines"); + if (defs) + flags.push.apply(flags, defs.map(function(d) { return "-D" + d; })); + var incPaths = transformedValue(productOrModule, "cpp", "includePaths"); + if (incPaths) + flags.push.apply(flags, incPaths.map(function(p) { return "-I" + p; })); + var cflags = transformedValue(productOrModule, "cpp", "commonCompilerFlags"); + if (cflags) + flags.push.apply(flags, cflags); + cflags = transformedValue(productOrModule, "cpp", "driverFlags"); + if (cflags) + flags.push.apply(flags, cflags); + cflags = transformedValue(productOrModule, "cpp", "cxxFlags") + || transformedValue(productOrModule, "cpp", "cFlags"); + if (cflags) + flags.push.apply(flags, cflags); + return flags; + } + + function collectAutodetectedDataRecursive(productOrModule, privateContext) + { + if (!privateContext) { + data.libs.push.apply(data.libs, collectLibs(productOrModule)); + data.cflags.push.apply(data.cflags, collectCFlags(productOrModule)); + } + var exportedDeps = productOrModule.exports ? productOrModule.exports.dependencies : []; + var exportedDepNames = []; + var privateDeps = []; + for (var i = 0; i < exportedDeps.length; ++i) + exportedDepNames.push(exportedDeps[i].name); + for (i = 0; i < (productOrModule.dependencies || []).length; ++i) { + var dep = productOrModule.dependencies[i]; + if (exportedDepNames.contains(dep.name)) + continue; + privateDeps.push(dep); + } + + function gatherData(dep) { + if (dep.name === "Exporter.pkgconfig") + return; + var depHasPkgConfig = dep.Exporter && dep.Exporter.pkgconfig; + if (depHasPkgConfig) { + var entry = FileInfo.completeBaseName(dep.Exporter.pkgconfig.fileName); + if (excludedDeps.contains(entry)) + return; + if (isPrivateDep && !data.requiresPrivate.contains(entry) + && !explicitRequiresPrivate.contains(entry)) { + data.requiresPrivate.push(entry); + } + if (!isPrivateDep && !data.requires.contains(entry) + && !explicitRequires.contains(entry)) { + data.requires.push(entry); + } + } else { + if (excludedDeps.contains(dep.name)) + return; + if (isPrivateDep && explicitRequiresPrivate.contains(dep.name)) + return; + if (!isPrivateDep && explicitRequires.contains(dep.name)) + return; + collectAutodetectedDataRecursive(dep, isPrivateDep); + } + } + var isPrivateDep = privateContext; + exportedDeps.forEach(gatherData); + isPrivateDep = true; + privateDeps.forEach(gatherData); + } + + collectAutodetectedDataRecursive(topLevelProduct, false); + return data; +} diff --git a/share/qbs/modules/Exporter/pkgconfig/pkgconfig.qbs b/share/qbs/modules/Exporter/pkgconfig/pkgconfig.qbs new file mode 100644 index 000000000..5fbda2bf4 --- /dev/null +++ b/share/qbs/modules/Exporter/pkgconfig/pkgconfig.qbs @@ -0,0 +1,91 @@ +import qbs +import qbs.FileInfo +import qbs.TextFile + +import "pkgconfig.js" as HelperFunctions + +Module { + property string fileName: product.targetName + ".pc" + property bool autoDetect: true + property var transformFunction // function(product, moduleName, propertyName, valueElement) + property stringList excludedDependencies + + property string nameEntry: product.name + property string descriptionEntry: product.name + property string versionEntry: product.version + property string urlEntry + property stringList cflagsEntry: [] + property stringList libsEntry: [] + property stringList libsPrivateEntry: [] + property stringList requiresEntry: [] + property stringList requiresPrivateEntry: [] + property stringList conflictsEntry: [] + + property var customVariables + + property bool _usePrefix: autoDetect && qbs.installPrefix + + additionalProductTypes: ["Exporter.pkgconfig.pc"] + + Rule { + multiplex: true + requiresInputs: false + + // Make sure all relevant library artifacts have been created by the time we run. + inputsFromDependencies: autoDetect + ? ["Exporter.pkgconfig.pc", "staticlibrary", "dynamiclibrary"] + : [] + inputs: { + if (!product.Exporter.pkgconfig.autoDetect) + return undefined; + if (product.type.contains("staticlibrary")) + return ["staticlibrary"]; + if (product.type.contains("dynamiclibrary")) + return ["dynamiclibrary"]; + } + + Artifact { + filePath: product.Exporter.pkgconfig.fileName + fileTags: ["Exporter.pkgconfig.pc"] + } + prepare: { + var cmd = new JavaScriptCommand(); + cmd.description = "Creating " + output.fileName; + cmd.sourceCode = function() { + var f = new TextFile(output.filePath, TextFile.WriteOnly); + if (product.Exporter.pkgconfig._usePrefix) + f.writeLine("prefix=" + product.qbs.installPrefix + "\n"); + var customVariables = product.Exporter.pkgconfig.customVariables; + if (customVariables) { + for (var customVar in customVariables) + f.writeLine(customVar + "=" + customVariables[customVar]); + f.writeLine(""); + } + var autoDetectedData = HelperFunctions.collectAutodetectedData(product); + HelperFunctions.writeEntry(product, f, "Name", "nameEntry", true); + HelperFunctions.writeEntry(product, f, "Description", "descriptionEntry", true); + HelperFunctions.writeEntry(product, f, "Version", "versionEntry", true); + HelperFunctions.writeEntry(product, f, "URL", "urlEntry"); + HelperFunctions.writeEntry(product, f, "Cflags", "cflagsEntry", false, + autoDetectedData.cflags); + HelperFunctions.writeEntry(product, f, "Libs", "libsEntry", false, + autoDetectedData.libs); + HelperFunctions.writeEntry(product, f, "Libs.private", "libsPrivateEntry"); + HelperFunctions.writeEntry(product, f, "Requires", "requiresEntry", false, + autoDetectedData.requires); + HelperFunctions.writeEntry(product, f, "Requires.private", "requiresPrivateEntry", + false, autoDetectedData.requiresPrivate); + HelperFunctions.writeEntry(product, f, "Conflicts", "conflictsEntry"); + }; + return [cmd]; + } + } + + validate: { + if (requiresEntry && excludedDependencies + && requiresEntry.containsAny(excludedDependencies)) { + throw "The contents of Export.pkgconfig.requiresEntry and " + + "Export.pkgconfig.excludedDependencies must not overlap."; + } + } +} diff --git a/share/qbs/modules/cpp/GenericGCC.qbs b/share/qbs/modules/cpp/GenericGCC.qbs index 5676d62e0..792e8ef4c 100644 --- a/share/qbs/modules/cpp/GenericGCC.qbs +++ b/share/qbs/modules/cpp/GenericGCC.qbs @@ -456,7 +456,7 @@ CppModule { condition: product.cpp.shouldLink multiplex: true inputs: ["obj", "linkerscript"] - inputsFromDependencies: ["dynamiclibrary", "staticlibrary"] + inputsFromDependencies: ["dynamiclibrary_symbols", "staticlibrary"] outputFileTags: ["bundle.input", "staticlibrary", "c_staticlibrary", "cpp_staticlibrary"] outputArtifacts: { |