diff options
author | Ivan Komissarov <abbapoh@gmail.com> | 2021-05-14 00:55:15 +0200 |
---|---|---|
committer | Ivan Komissarov <ABBAPOH@gmail.com> | 2021-10-14 10:03:50 +0000 |
commit | 3187199a17e013882b0d0ea7aff9c7b9411e4cd1 (patch) | |
tree | 5e82271f0702e037898c723bcdaf6ab426eba342 | |
parent | e7cc3a2cf13db0f786727ce2469f7c66324f35a2 (diff) | |
download | qbs-3187199a17e013882b0d0ea7aff9c7b9411e4cd1.tar.gz |
Implement eager pkg-config provider
This implements provider that generates modules based on all .pc files
present in system. This allows to get rid of the multi-shot providers
such as fallback provider.
Fixes: QBS-1614
Change-Id: Icf87ac609bc34bd26e8ed94ae547a7e649835a3a
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
-rw-r--r-- | doc/qbs.qdoc | 1 | ||||
-rw-r--r-- | doc/reference/module-providers/qbspkgconfig-module-provider.qdoc | 99 | ||||
-rw-r--r-- | doc/reference/reference.qdoc | 6 | ||||
-rw-r--r-- | examples/pkgconfig-provider/main.c | 137 | ||||
-rw-r--r-- | examples/pkgconfig-provider/pkgconfig-provider.qbs | 60 | ||||
-rw-r--r-- | share/qbs/module-providers/qbspkgconfig.qbs | 216 | ||||
-rw-r--r-- | share/share.qbs | 2 | ||||
-rw-r--r-- | tests/auto/blackbox/testdata/qbspkgconfig-module-provider/libdir/libA.pc | 6 | ||||
-rw-r--r-- | tests/auto/blackbox/testdata/qbspkgconfig-module-provider/libs/libA.cpp | 14 | ||||
-rw-r--r-- | tests/auto/blackbox/testdata/qbspkgconfig-module-provider/libs/libA.h | 21 | ||||
-rw-r--r-- | tests/auto/blackbox/testdata/qbspkgconfig-module-provider/libs/libs.qbs | 29 | ||||
-rw-r--r-- | tests/auto/blackbox/testdata/qbspkgconfig-module-provider/main.cpp | 11 | ||||
-rw-r--r-- | tests/auto/blackbox/testdata/qbspkgconfig-module-provider/qbspkgconfig-module-provider.qbs | 6 | ||||
-rw-r--r-- | tests/auto/blackbox/tst_blackbox.cpp | 22 | ||||
-rw-r--r-- | tests/auto/blackbox/tst_blackbox.h | 1 |
15 files changed, 630 insertions, 1 deletions
diff --git a/doc/qbs.qdoc b/doc/qbs.qdoc index ac7bf20c2..f297ea2cf 100644 --- a/doc/qbs.qdoc +++ b/doc/qbs.qdoc @@ -81,6 +81,7 @@ \li \l{List of Built-in Services} \li \l{Command-Line Interface} \li \l{List of Modules} + \li \l{List of Module Providers} \li \l{Command and JavaScriptCommand} \endlist diff --git a/doc/reference/module-providers/qbspkgconfig-module-provider.qdoc b/doc/reference/module-providers/qbspkgconfig-module-provider.qdoc new file mode 100644 index 000000000..80afe3667 --- /dev/null +++ b/doc/reference/module-providers/qbspkgconfig-module-provider.qdoc @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com) +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \qmltype qbspkgconfig + \inqmlmodule QbsModuleProviders + \since 1.20 + + \brief Module provider based on the qbspkg-config library. + + \QBS uses a built-in parser of the \c{*.pc} files and does not require the presence of the + \c pkg-config tool in the system. However, if the \c pkg-config tool is present, \QBS will + use the same libDirs as the system pkg-config uses by default; otherwise, a built-in list of + paths is used. + + In order to enable usage of this provider in your Product, set the + \l{Product::qbsModuleProviders}{qbsModuleProviders} property as shown in the example below: + \snippet ../examples/pkgconfig-provider/pkgconfig-provider.qbs 0 +*/ + +/*! + \qmlproperty string qbspkgconfig::executableFilePath + + The path to the \c {pkg-config} executable. If not set, the pkg-config from PATH is used. + + \defaultvalue undefined +*/ + +/*! + \qmlproperty stringList qbspkgconfig::libDirs + + Set this if you need to overwrite the default search directories. + \note You do not need to set this for cross-compilation in order to point + to the sysroot. \QBS does that for you. + + This property is the equivalent of the \c{PKG_CONFIG_PATH} / \c{PKG_CONFIG_LIBDIR} variables + for the \c{pkg-config} tool. + + \nodefaultvalue +*/ + +/*! + \qmlproperty bool qbspkgconfig::staticMode + + If this property is \c true, then \QBS will include "private" libs and dependencies of the + package. This property is the equivalent of the + \c{--static} option for the \c{pkg-config} tool. + + Set this if your product is to be linked statically. + + \defaultvalue \c false +*/ + +/*! + \qmlproperty path qbspkgconfig::sysroot + + Set this property if you need to overwrite the default search sysroot path used by + \c pkg-config. + + This can be useful if \c pkg-config files are located in the directory other than qbs.sysroot. + This is the case on macOS platform - all XCode profiles are sysrooted to the SDK + directory, but \c pkg-config is typically intalled using Brew and resides in the + \c /usr/local directory. + + Setting this property to \c undefined or empty (\c "") value will use pkg-config's default + search paths: + \code + qbs build module-providers.pkgconfig.sysroot:undefined + \endcode + + This property is the equivalent of the \c{PKG_CONFIG_SYSROOT_DIR} variable for the + \c{pkg-config} tool. + + \defaultvalue \c "" on macOS, \c qbs.sysroot on other platforms +*/ diff --git a/doc/reference/reference.qdoc b/doc/reference/reference.qdoc index 63b8c187d..f2992b287 100644 --- a/doc/reference/reference.qdoc +++ b/doc/reference/reference.qdoc @@ -75,6 +75,12 @@ */ /*! + \qmlmodule QbsModuleProviders + \title List of Module Providers + These are the module providers shipped with \QBS. +*/ + +/*! \group list-of-items \title List of All Items diff --git a/examples/pkgconfig-provider/main.c b/examples/pkgconfig-provider/main.c new file mode 100644 index 000000000..398b06842 --- /dev/null +++ b/examples/pkgconfig-provider/main.c @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** MIT License + +** Copyright (c) 2017 Aleksander Alekseev + +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +** copies of the Software, and to permit persons to whom the Software is +** furnished to do so, subject to the following conditions: + +** The above copyright notice and this permission notice shall be included in all +** copies or substantial portions of the Software. + +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +** SOFTWARE. +** +****************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdint.h> +#include <errno.h> +#include <limits.h> +#include <zlib.h> + +int main(int argc, char* argv[]) +{ + int res; + + if (argc < 2) + { + fprintf(stderr, "Usage: %s <fname>\n", argv[0]); + return 1; + } + + char* fname = argv[1]; + + struct stat file_stat; + res = stat(fname, &file_stat); + if (res == -1) + { + fprintf(stderr, "stat(...) failed, errno = %d\n", errno); + return 1; + } + + size_t temp_file_size = (size_t)file_stat.st_size; + if (temp_file_size >= INT_MAX) + { + fprintf(stderr, "Error: filze_size >= INT_MAX (%d)\n", INT_MAX); + return 1; + } + + int file_size = (int)temp_file_size; + int buff_size = file_size + 1; + void* file_buff = malloc(buff_size); + if (file_buff == NULL) + { + fprintf(stderr, "malloc(buff_size) failed, buff_size = %d\n", + file_size); + return 1; + } + + int fid = open(fname, O_RDONLY); + if (fid == -1) + { + fprintf(stderr, "open(...) failed, errno = %d\n", errno); + free(file_buff); + return 1; + } + + if (read(fid, file_buff, file_size) != file_size) + { + fprintf(stderr, "read(...) failed, errno = %d\n", errno); + free(file_buff); + close(fid); + return 1; + } + + close(fid); + + uLongf compress_buff_size = compressBound(file_size); + void* compress_buff = malloc(compress_buff_size); + if (compress_buff == NULL) + { + fprintf(stderr, + "malloc(compress_buff_size) failed, " + "compress_buff_size = %lu\n", + compress_buff_size); + free(file_buff); + return 1; + } + + uLongf compressed_size = compress_buff_size; + res = compress(compress_buff, &compressed_size, file_buff, file_size); + if (res != Z_OK) + { + fprintf(stderr, "compress(...) failed, res = %d\n", res); + free(compress_buff); + free(file_buff); + return 1; + } + + memset(file_buff, 0, buff_size); + uLongf decompressed_size = (uLongf)file_size; + res = uncompress(file_buff, &decompressed_size, + compress_buff, compressed_size); + if (res != Z_OK) + { + fprintf(stderr, "uncompress(...) failed, res = %d\n", res); + free(compress_buff); + free(file_buff); + return 1; + } + + printf( + "%s\n----------------\n" + "File size: %d, compress_buff_size: %lu, compressed_size: %lu, " + "decompressed_size: %lu\n", + (char*)file_buff, file_size, compress_buff_size, compressed_size, + decompressed_size); + + free(compress_buff); + free(file_buff); +} diff --git a/examples/pkgconfig-provider/pkgconfig-provider.qbs b/examples/pkgconfig-provider/pkgconfig-provider.qbs new file mode 100644 index 000000000..34ba32d03 --- /dev/null +++ b/examples/pkgconfig-provider/pkgconfig-provider.qbs @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com) +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of Qbs. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [0] +CppApplication { + consoleApplication: true + Depends { name: "zlib"; required: false } + condition: zlib.present + name: "PkgConfigProviderExample" + files: "main.c" + qbsModuleProviders: ["qbspkgconfig"] +} +//! [0] diff --git a/share/qbs/module-providers/qbspkgconfig.qbs b/share/qbs/module-providers/qbspkgconfig.qbs new file mode 100644 index 000000000..ad6d64027 --- /dev/null +++ b/share/qbs/module-providers/qbspkgconfig.qbs @@ -0,0 +1,216 @@ +/**************************************************************************** +** +** Copyright (C) 2021 Ivan Komissarov (abbapoh@gmail.com) +** 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$ +** +****************************************************************************/ + +import qbs.Environment +import qbs.File +import qbs.FileInfo +import qbs.ModUtils +import qbs.PkgConfig +import qbs.Process +import qbs.TextFile + +ModuleProvider { + property string executableFilePath + property stringList libDirs + property bool staticMode: false + property path sysroot: { + if (qbs.targetOS.contains("macos")) + return ""; + return qbs.sysroot; + } + + relativeSearchPaths: { + + // we need Probes in Providers... + function getPkgConfigExecutable(qbs) { + function splitNonEmpty(s, c) { return s.split(c).filter(function(e) { return e; }) } + function exeSuffix(qbs) { return qbs.hostOS.contains("windows") ? ".exe" : ""; } + + var pathValue = Environment.getEnv("PATH"); + if (!pathValue) + return undefined; + var dirs = splitNonEmpty(pathValue, qbs.pathListSeparator); + var suffix = exeSuffix(qbs); + var filePaths = []; + for (var i = 0; i < dirs.length; ++i) { + var candidate = FileInfo.joinPaths(dirs[i], "pkg-config" + suffix); + var canonicalCandidate = FileInfo.canonicalPath(candidate); + if (!canonicalCandidate || !File.exists(canonicalCandidate)) + continue; + return canonicalCandidate; + } + return undefined; + } + + function getModuleInfo(pkg, staticMode) { + var result = {}; + + var mapper = function(flag) { return flag.value; } + var typeFilter = function(type) { + return function(flag) { return flag.type === type; } + } + + function getLibsInfo(libs) { + var result = {}; + result.dynamicLibraries = libs.filter(typeFilter(PkgConfig.LibraryName)).map(mapper); + result.staticLibraries = + libs.filter(typeFilter(PkgConfig.StaticLibraryName)).map(mapper); + result.libraryPaths = libs.filter(typeFilter(PkgConfig.LibraryPath)).map(mapper); + result.frameworks = libs.filter(typeFilter(PkgConfig.Framework)).map(mapper); + result.frameworkPaths = + libs.filter(typeFilter(PkgConfig.FrameworkPath)).map(mapper); + result.driverLinkerFlags = + libs.filter(typeFilter(PkgConfig.LinkerFlag)).map(mapper); + return result; + } + + result.version = pkg.version; + result.includePaths = pkg.cflags.filter(typeFilter(PkgConfig.IncludePath)).map(mapper); + result.systemIncludePaths = + pkg.cflags.filter(typeFilter(PkgConfig.SystemIncludePath)).map(mapper); + result.defines = pkg.cflags.filter(typeFilter(PkgConfig.Define)).map(mapper); + result.commonCompilerFlags = + pkg.cflags.filter(typeFilter(PkgConfig.CompilerFlag)).map(mapper); + + var libsInfo = !staticMode ? getLibsInfo(pkg.libs) : getLibsInfo(pkg.libsPrivate); + for (var key in libsInfo) { + result[key] = libsInfo[key]; + } + + return result; + } + + function getModuleName(packageName) { return packageName.replace('.', '-'); } + + function getModuleDependencies(pkg, staticMode) { + var mapper = function(p) { + var result = {}; + for (var key in p) + result[key] = p[key]; + result.name = getModuleName(result.name); + return result; + } + var result = pkg.requires.map(mapper); + if (staticMode) + result = result.concat(pkg.requiresPrivate.map(mapper)); + return result; + } + + console.debug("Running pkgconfig provider.") + + var outputDir = FileInfo.joinPaths(outputBaseDir, "modules"); + File.makePath(outputDir); + + var options = {}; + options.searchPaths = libDirs; + options.sysroot = sysroot; + if (options.sysroot && !options.searchPaths) { + options.searchPaths = [ + sysroot + "/usr/lib/pkgconfig", + sysroot + "/usr/share/pkgconfig" + ]; + } + if (!options.searchPaths) { + // if we have pkg-config installed, let's ask it for its search paths (since + // built-in search paths can differ between platforms) + var executable = executableFilePath ? executableFilePath : getPkgConfigExecutable(qbs); + if (executable) { + var p = new Process() + if (p.exec(executable, ['pkg-config', '--variable=pc_path']) === 0) { + var stdout = p.readStdOut().trim(); + // TODO: qbs.pathListSeparator? depends on what pkg-config prints on Windows + options.searchPaths = stdout ? stdout.split(':'): []; + } + } + } + + var pkgConfig = new PkgConfig(options); + var brokenPackages = pkgConfig.brokenPackages(); + if (brokenPackages.length !== 0) { + console.warn("Failed to load some pkg-config packages:"); + for (var i = 0; i < brokenPackages.length; ++i) { + console.warn(" " + brokenPackages[i].filePath + + ": " + brokenPackages[i].errorText); + } + } + var packages = pkgConfig.packages(); + for (var packageName in packages) { + var moduleName = getModuleName(packageName); + var moduleInfo = getModuleInfo(packages[packageName], staticMode); + var deps = getModuleDependencies(packages[packageName], staticMode); + + var moduleDir = FileInfo.joinPaths(outputDir, moduleName); + File.makePath(moduleDir); + var module = + new TextFile(FileInfo.joinPaths(moduleDir, "module.qbs"), TextFile.WriteOnly); + module.writeLine("Module {"); + module.writeLine(" version: " + ModUtils.toJSLiteral(moduleInfo.version)); + module.writeLine(" Depends { name: 'cpp' }"); + deps.forEach(function(dep) { + module.write(" Depends { name: '" + dep.name + "'"); + for (var k in dep) { + if (k === "name") + continue; + module.write("; " + k + ": " + ModUtils.toJSLiteral(dep[k])); + } + module.writeLine(" }"); + }) + function writeProperty(propertyName) { + var value = moduleInfo[propertyName]; + if (value.length !== 0) { // skip empty props for simplicity of the module file + module.writeLine( + " cpp." + propertyName + ":" + ModUtils.toJSLiteral(value)); + } + } + writeProperty("includePaths"); + writeProperty("systemIncludePaths"); + writeProperty("defines"); + writeProperty("commonCompilerFlags"); + writeProperty("dynamicLibraries"); + writeProperty("staticLibraries"); + writeProperty("libraryPaths"); + writeProperty("frameworks"); + writeProperty("frameworkPaths"); + writeProperty("driverLinkerFlags"); + module.writeLine("}"); + module.close(); + } + return ""; + } +} diff --git a/share/share.qbs b/share/share.qbs index b02e971f6..c5cf6893e 100644 --- a/share/share.qbs +++ b/share/share.qbs @@ -56,7 +56,7 @@ Product { Group { name: "Module providers" - files: ["qbs/module-providers/**/*"] + files: ["qbs/module-providers/*", "qbs/module-providers/**/*"] fileTags: ["qbs resources"] qbs.install: true qbs.installDir: qbsbuildconfig.resourcesInstallDir + "/share" diff --git a/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/libdir/libA.pc b/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/libdir/libA.pc new file mode 100644 index 000000000..077a05893 --- /dev/null +++ b/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/libdir/libA.pc @@ -0,0 +1,6 @@ +Name: libA +Description: just a test +Version: 0.0.1 + +Cflags: -DTHE_MAGIC_DEFINE -I/usr/local/include +Libs: -L/usr/local/lib -llibA diff --git a/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/libs/libA.cpp b/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/libs/libA.cpp new file mode 100644 index 000000000..0c5274415 --- /dev/null +++ b/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/libs/libA.cpp @@ -0,0 +1,14 @@ +#include "libA.h" + +#include <iostream> + +void foo() +{ + std::cout << "hello from foo: "; +#ifdef MYLIB_FRAMEWORK + std::cout << "bundled: yes"; +#else + std::cout << "bundled: no"; +#endif + std::cout << std::endl; +} diff --git a/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/libs/libA.h b/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/libs/libA.h new file mode 100644 index 000000000..ddaaf1609 --- /dev/null +++ b/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/libs/libA.h @@ -0,0 +1,21 @@ +#pragma once + +#if defined(_WIN32) || defined(WIN32) +# define DECL_EXPORT __declspec(dllexport) +# define DECL_IMPORT __declspec(dllimport) +#else +# define DECL_EXPORT __attribute__((visibility("default"))) +# define DECL_IMPORT __attribute__((visibility("default"))) +# endif + +#if defined(LIBA_STATIC_LIBRARY) +# define LIBA_EXPORT +#else +# if defined(MYLIB_LIBRARY) +# define LIBA_EXPORT DECL_EXPORT +# else +# define LIBA_EXPORT DECL_IMPORT +# endif +#endif + +LIBA_EXPORT void foo(); diff --git a/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/libs/libs.qbs b/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/libs/libs.qbs new file mode 100644 index 000000000..9d482415b --- /dev/null +++ b/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/libs/libs.qbs @@ -0,0 +1,29 @@ +import qbs.FileInfo + +Project { + property bool isBundle: false + + DynamicLibrary { + Depends { name: "cpp" } + Depends { name: "bundle" } + name: "libA" + bundle.isBundle: project.isBundle + bundle.publicHeaders: ["libA.h"] + files: "libA.cpp" + cpp.defines: { + var result = []; + if (project.isBundle) + result.push("MYLIB_FRAMEWORK"); + return result; + } + qbs.installPrefix: "" + install: true + installImportLib: true + installDir: "lib" + Group { + files: ["libA.h"] + qbs.install: !project.isBundle + qbs.installDir: FileInfo.joinPaths("include", product.name) + } + } +} diff --git a/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/main.cpp b/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/main.cpp new file mode 100644 index 000000000..5fa0f7eed --- /dev/null +++ b/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/main.cpp @@ -0,0 +1,11 @@ +#include <libA/libA.h> + +#ifndef THE_MAGIC_DEFINE +#error "missing the magic define" +#endif + +int main() +{ + foo(); + return 0; +} diff --git a/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/qbspkgconfig-module-provider.qbs b/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/qbspkgconfig-module-provider.qbs new file mode 100644 index 000000000..d2b3654ae --- /dev/null +++ b/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/qbspkgconfig-module-provider.qbs @@ -0,0 +1,6 @@ +CppApplication { + name: "p" + Depends { name: "libA" } + files: "main.cpp" + qbsModuleProviders: "qbspkgconfig" +} diff --git a/tests/auto/blackbox/tst_blackbox.cpp b/tests/auto/blackbox/tst_blackbox.cpp index 3cacd67e9..44026fc86 100644 --- a/tests/auto/blackbox/tst_blackbox.cpp +++ b/tests/auto/blackbox/tst_blackbox.cpp @@ -6144,6 +6144,28 @@ void TestBlackbox::qbsModuleProvidersCompatibility_data() QTest::newRow("named") << QStringList("project.qbsModuleProviders:named_provider") << "from_named_provider"; } +void TestBlackbox::qbspkgconfigModuleProvider() +{ + QDir::setCurrent(testDataDir + "/qbspkgconfig-module-provider/libs"); + + const auto commonParams = QbsRunParameters(QStringLiteral("install"), { + QStringLiteral("qbs.installPrefix:/usr/local"), + QStringLiteral("--install-root"), + QStringLiteral("install-root") + }); + auto dynamicParams = commonParams; + dynamicParams.arguments << "config:library" << "projects.libs.isBundle:false"; + QCOMPARE(runQbs(dynamicParams), 0); + + QDir::setCurrent(testDataDir + "/qbspkgconfig-module-provider"); + + QbsRunParameters params; + params.arguments + << "moduleProviders.qbspkgconfig.libDirs:libdir" + << "moduleProviders.qbspkgconfig.sysroot:" + QDir::currentPath() + "/libs/install-root"; + QCOMPARE(runQbs(params), 0); +} + static QJsonObject getNextSessionPacket(QProcess &session, QByteArray &data) { int totalSize = -1; diff --git a/tests/auto/blackbox/tst_blackbox.h b/tests/auto/blackbox/tst_blackbox.h index 8728f2b10..2f443f681 100644 --- a/tests/auto/blackbox/tst_blackbox.h +++ b/tests/auto/blackbox/tst_blackbox.h @@ -265,6 +265,7 @@ private slots: void qbsModuleProvidersCliOverride_data(); void qbsModuleProvidersCompatibility(); void qbsModuleProvidersCompatibility_data(); + void qbspkgconfigModuleProvider(); void qbsSession(); void qbsVersion(); void qtBug51237(); |