diff options
21 files changed, 454 insertions, 159 deletions
diff --git a/share/qbs/module-providers/Qt/templates/core.qbs b/share/qbs/module-providers/Qt/templates/core.qbs index 98bc0c4d3..8e990db22 100644 --- a/share/qbs/module-providers/Qt/templates/core.qbs +++ b/share/qbs/module-providers/Qt/templates/core.qbs @@ -105,6 +105,10 @@ Module { condition: moduleConfig.contains("use_gold_linker") cpp.linkerVariant: "gold" } + Properties { + condition: !moduleConfig.contains("use_gold_linker") && qbs.toolchain.contains("gcc") + cpp.linkerVariant: original + } cpp.cxxLanguageVersion: Utilities.versionCompare(version, "5.7.0") >= 0 ? "c++11" : original cpp.enableCompilerDefinesByLanguage: ["cpp"].concat( diff --git a/share/qbs/modules/cpp/GenericGCC.qbs b/share/qbs/modules/cpp/GenericGCC.qbs index f9537884e..3b775c9fa 100644 --- a/share/qbs/modules/cpp/GenericGCC.qbs +++ b/share/qbs/modules/cpp/GenericGCC.qbs @@ -135,14 +135,14 @@ CppModule { : undefined property string binutilsPath: binutilsProbe.found ? binutilsProbe.path : toolchainInstallPath - assemblerName: 'as' + assemblerName: 'as' + compilerExtension compilerName: cxxCompilerName - linkerName: 'ld' - property string archiverName: 'ar' - property string nmName: 'nm' - property string objcopyName: "objcopy" - property string stripName: "strip" - property string dsymutilName: "dsymutil" + linkerName: 'ld' + compilerExtension + property string archiverName: 'ar' + compilerExtension + property string nmName: 'nm' + compilerExtension + property string objcopyName: "objcopy" + compilerExtension + property string stripName: "strip" + compilerExtension + property string dsymutilName: "dsymutil" + compilerExtension property string lipoName property string sysroot: qbs.sysroot property string syslibroot: sysroot @@ -429,7 +429,7 @@ CppModule { + PathTools.bundleExecutableFilePath(product) } }]; - if (product.qbs.toolchain.contains("mingw")) { + if (product.cpp.imageFormat === "pe") { artifacts.push({ fileTags: ["dynamiclibrary_import"], filePath: FileInfo.joinPaths(product.destinationDirectory, diff --git a/share/qbs/modules/cpp/MingwBaseModule.qbs b/share/qbs/modules/cpp/MingwBaseModule.qbs new file mode 100644 index 000000000..60ad28b08 --- /dev/null +++ b/share/qbs/modules/cpp/MingwBaseModule.qbs @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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. +** +****************************************************************************/ + +import qbs.TextFile +import qbs.Utilities +import qbs.WindowsUtils + +import "setuprunenv.js" as SetupRunEnv + +GenericGCC { + condition: false + + staticLibraryPrefix: "lib" + staticLibrarySuffix: ".a" + dynamicLibrarySuffix: ".dll" + executableSuffix: ".exe" + debugInfoSuffix: ".debug" + imageFormat: "pe" + windowsApiCharacterSet: "unicode" + platformDefines: base.concat(WindowsUtils.characterSetDefines(windowsApiCharacterSet)) + .concat("WIN32") + + Properties { + condition: product.multiplexByQbsProperties.contains("buildVariants") + && qbs.buildVariants && qbs.buildVariants.length > 1 + && qbs.buildVariant !== "release" + && product.type.containsAny(["staticlibrary", "dynamiclibrary"]) + variantSuffix: "d" + } + + FileTagger { + patterns: ["*.manifest"] + fileTags: ["native.pe.manifest"] + } + + FileTagger { + patterns: ["*.rc"] + fileTags: ["rc"] + } + + Rule { + inputs: ["native.pe.manifest"] + multiplex: true + + outputFileTags: ["rc"] + outputArtifacts: { + if (product.type.containsAny(["application", "dynamiclibrary"])) { + return [{ + filePath: input.completeBaseName + ".rc", + fileTags: ["rc"] + }]; + } + return []; + } + + prepare: { + var inputList = inputs["native.pe.manifest"]; + // TODO: Emulate manifest merging like Microsoft's mt.exe tool does + if (inputList.length !== 1) { + throw("The MinGW toolchain does not support manifest merging; " + + "you may only specify a single manifest file to embed into your assembly."); + } + + var cmd = new JavaScriptCommand(); + cmd.silent = true; + cmd.productType = product.type; + cmd.inputFilePath = inputList[0].filePath; + cmd.outputFilePath = output.filePath; + cmd.sourceCode = function() { + var tf; + try { + tf = new TextFile(outputFilePath, TextFile.WriteOnly); + if (productType.contains("application")) + tf.write("1 "); // CREATEPROCESS_MANIFEST_RESOURCE_ID + else if (productType.contains("dynamiclibrary")) + tf.write("2 "); // ISOLATIONAWARE_MANIFEST_RESOURCE_ID + tf.write("24 "); // RT_MANIFEST + tf.writeLine(Utilities.cStringQuote(inputFilePath)); + } finally { + if (tf) + tf.close(); + } + }; + return [cmd]; + } + } +} + diff --git a/share/qbs/modules/cpp/gcc.js b/share/qbs/modules/cpp/gcc.js index 6936beb5e..f1cee8231 100644 --- a/share/qbs/modules/cpp/gcc.js +++ b/share/qbs/modules/cpp/gcc.js @@ -78,7 +78,7 @@ function collectLibraryDependencies(product, isDarwin) { var publicDeps = {}; var objects = []; var objectByFilePath = {}; - var tagForLinkingAgainstSharedLib = product.qbs.toolchain.contains("mingw") + var tagForLinkingAgainstSharedLib = product.cpp.imageFormat === "pe" ? "dynamiclibrary_import" : "dynamiclibrary"; function addObject(obj, addFunc) { @@ -283,7 +283,7 @@ function linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPat args.push("-current_version", internalVersion); escapableLinkerFlags.push("-install_name", UnixUtils.soname(product, primaryOutput.fileName)); - } else { + } else if (product.cpp.imageFormat === "elf") { escapableLinkerFlags.push("-soname=" + UnixUtils.soname(product, primaryOutput.fileName)); } @@ -295,7 +295,7 @@ function linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPat if (primaryOutput.fileTags.containsAny(["dynamiclibrary", "loadablemodule"])) { if (isDarwin) escapableLinkerFlags.push("-headerpad_max_install_names"); - else + else if (product.cpp.imageFormat === "elf") escapableLinkerFlags.push("--as-needed"); } @@ -344,13 +344,15 @@ function linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPat return rpath; } - function isNotSystemRunPath(p) { - return !FileInfo.isAbsolutePath(p) || (!systemRunPaths.contains(p) - && !canonicalSystemRunPaths.contains(File.canonicalFilePath(p))); - }; - for (i in rpaths) { - if (isNotSystemRunPath(rpaths[i])) - escapableLinkerFlags.push("-rpath", fixupRPath(rpaths[i])); + if (!product.qbs.targetOS.contains("windows")) { + function isNotSystemRunPath(p) { + return !FileInfo.isAbsolutePath(p) || (!systemRunPaths.contains(p) + && !canonicalSystemRunPaths.contains(File.canonicalFilePath(p))); + }; + for (i in rpaths) { + if (isNotSystemRunPath(rpaths[i])) + escapableLinkerFlags.push("-rpath", fixupRPath(rpaths[i])); + } } if (product.cpp.entryPoint) @@ -854,7 +856,7 @@ function compilerFlags(project, product, input, output, explicitlyDependsOn) { } var positionIndependentCode = input.cpp.positionIndependentCode; - if (positionIndependentCode && !product.qbs.toolchain.contains("mingw")) + if (positionIndependentCode && !product.qbs.targetOS.contains("windows")) args.push('-fPIC'); var cppFlags = input.cpp.cppFlags; @@ -1035,7 +1037,7 @@ function linkerEnvVars(config, inputs) function setResponseFileThreshold(command, product) { - if (product.qbs.toolchain.contains("mingw") && product.qbs.hostOS.contains("windows")) + if (product.qbs.targetOS.contains("windows") && product.qbs.hostOS.contains("windows")) command.responseFileThreshold = 10000; } diff --git a/share/qbs/modules/cpp/msvc.js b/share/qbs/modules/cpp/msvc.js index 9deffa064..02facf30a 100644 --- a/share/qbs/modules/cpp/msvc.js +++ b/share/qbs/modules/cpp/msvc.js @@ -542,3 +542,46 @@ function prepareLinker(project, product, inputs, outputs, input, output) { return commands; } +function createRcCommand(binary, input, output, logo) { + var platformDefines = input.cpp.platformDefines; + var defines = input.cpp.defines; + var includePaths = input.cpp.includePaths; + var systemIncludePaths = input.cpp.systemIncludePaths; + + var args = []; + if (logo === "can-suppress-logo") + args.push("/nologo"); + for (i in platformDefines) { + args.push("/d"); + args.push(platformDefines[i]); + } + for (i in defines) { + args.push("/d"); + args.push(defines[i]); + } + for (i in includePaths) { + args.push("/I"); + args.push(includePaths[i]); + } + for (i in systemIncludePaths) { + args.push("/I"); + args.push(systemIncludePaths[i]); + } + args = args.concat(["/FO", output.filePath, input.filePath]); + var cmd = new Command(binary, args); + cmd.description = 'compiling ' + input.fileName; + cmd.highlight = 'compiler'; + cmd.jobPool = "compiler"; + + if (logo === "always-shows-logo") { + // Remove the first two lines of stdout. That's the logo. + cmd.stdoutFilterFunction = function(output) { + var idx = 0; + for (var i = 0; i < 3; ++i) + idx = output.indexOf('\n', idx + 1); + return output.substr(idx + 1); + } + } + + return cmd; +} diff --git a/share/qbs/modules/cpp/windows-clang-mingw.qbs b/share/qbs/modules/cpp/windows-clang-mingw.qbs new file mode 100644 index 000000000..8389dbf2e --- /dev/null +++ b/share/qbs/modules/cpp/windows-clang-mingw.qbs @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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. +** +****************************************************************************/ + +import qbs.File +import qbs.FileInfo +import qbs.ModUtils +import qbs.Utilities +import "msvc.js" as MSVC + +import "setuprunenv.js" as SetupRunEnv + +MingwBaseModule { + condition: qbs.targetOS.contains("windows") && + qbs.toolchain && qbs.toolchain.contains("clang") + priority: 0 + + // llvm-as and llvm-objopy are not shipped with the official binaries on Windows at the + // moment (8.0). We fall back to using the mingw versions in that case. + assemblerName: "llvm-as" + compilerExtension + assemblerPath: { + if (File.exists(base)) + return base; + if (qbs.sysroot) + return FileInfo.joinPaths(qbs.sysroot, "bin", "as" + compilerExtension); + } + objcopyName: "llvm-objcopy" + compilerExtension + objcopyPath: { + if (File.exists(base)) + return base; + if (qbs.sysroot) + return FileInfo.joinPaths(qbs.sysroot, "bin", "objcopy" + compilerExtension); + } + + archiverName: "llvm-ar" + compilerExtension + + linkerVariant: "lld" + targetVendor: "pc" + targetSystem: "windows" + targetAbi: "gnu" + property string rcFilePath: FileInfo.joinPaths(toolchainInstallPath, + "llvm-rc" + compilerExtension) + + setupBuildEnvironment: { + if (product.qbs.hostOS.contains("windows") && product.qbs.sysroot) { + var v = new ModUtils.EnvironmentVariable("PATH", product.qbs.pathListSeparator, true); + v.prepend(FileInfo.joinPaths(product.qbs.sysroot, "bin")); + v.set(); + } + } + + setupRunEnvironment: { + if (product.qbs.hostOS.contains("windows") && product.qbs.sysroot) { + var v = new ModUtils.EnvironmentVariable("PATH", product.qbs.pathListSeparator, true); + v.prepend(FileInfo.joinPaths(product.qbs.sysroot, "bin")); + v.set(); + SetupRunEnv.setupRunEnvironment(product, config); + } + } + + Rule { + inputs: ["rc"] + auxiliaryInputs: ["hpp"] + + Artifact { + filePath: Utilities.getHash(input.baseDir) + "/" + input.completeBaseName + ".res" + fileTags: ["obj"] + } + + prepare: MSVC.createRcCommand(product.cpp.rcFilePath, input, output); + } +} diff --git a/share/qbs/modules/cpp/windows-mingw.qbs b/share/qbs/modules/cpp/windows-mingw.qbs index 27382742f..fe9fd4bf8 100644 --- a/share/qbs/modules/cpp/windows-mingw.qbs +++ b/share/qbs/modules/cpp/windows-mingw.qbs @@ -28,39 +28,28 @@ ** ****************************************************************************/ +import qbs.File +import qbs.FileInfo import qbs.ModUtils -import qbs.TextFile import qbs.Utilities -import qbs.WindowsUtils import "setuprunenv.js" as SetupRunEnv -GenericGCC { +MingwBaseModule { condition: qbs.targetOS.contains("windows") && qbs.toolchain && qbs.toolchain.contains("mingw") priority: 0 - staticLibraryPrefix: "lib" - staticLibrarySuffix: ".a" - dynamicLibrarySuffix: ".dll" - executableSuffix: ".exe" - debugInfoSuffix: ".debug" - imageFormat: "pe" - windowsApiCharacterSet: "unicode" - platformDefines: base.concat(WindowsUtils.characterSetDefines(windowsApiCharacterSet)) - .concat("WIN32") + probeEnv: buildEnv - Properties { - condition: product.multiplexByQbsProperties.contains("buildVariants") - && qbs.buildVariants && qbs.buildVariants.length > 1 - && qbs.buildVariant !== "release" - && product.type.containsAny(["staticlibrary", "dynamiclibrary"]) - variantSuffix: "d" + property string windresName: "windres" + compilerExtension + property path windresPath: { + var filePath = toolchainPrefix + windresName; + if (!File.exists(filePath)) + filePath = FileInfo.joinPaths(toolchainInstallPath, windresName); + return filePath; } - property string windresName: 'windres' - property path windresPath: { return toolchainPathPrefix + windresName } - setupBuildEnvironment: { var v = new ModUtils.EnvironmentVariable("PATH", product.qbs.pathListSeparator, true); v.prepend(product.cpp.toolchainInstallPath); @@ -74,63 +63,6 @@ GenericGCC { SetupRunEnv.setupRunEnvironment(product, config); } - FileTagger { - patterns: ["*.manifest"] - fileTags: ["native.pe.manifest"] - } - - Rule { - inputs: ["native.pe.manifest"] - multiplex: true - - outputFileTags: ["rc"] - outputArtifacts: { - if (product.type.containsAny(["application", "dynamiclibrary"])) { - return [{ - filePath: input.completeBaseName + ".rc", - fileTags: ["rc"] - }]; - } - return []; - } - - prepare: { - var inputList = inputs["native.pe.manifest"]; - // TODO: Emulate manifest merging like Microsoft's mt.exe tool does - if (inputList.length !== 1) { - throw("The MinGW toolchain does not support manifest merging; " + - "you may only specify a single manifest file to embed into your assembly."); - } - - var cmd = new JavaScriptCommand(); - cmd.silent = true; - cmd.productType = product.type; - cmd.inputFilePath = inputList[0].filePath; - cmd.outputFilePath = output.filePath; - cmd.sourceCode = function() { - var tf; - try { - tf = new TextFile(outputFilePath, TextFile.WriteOnly); - if (productType.contains("application")) - tf.write("1 "); // CREATEPROCESS_MANIFEST_RESOURCE_ID - else if (productType.contains("dynamiclibrary")) - tf.write("2 "); // ISOLATIONAWARE_MANIFEST_RESOURCE_ID - tf.write("24 "); // RT_MANIFEST - tf.writeLine(Utilities.cStringQuote(inputFilePath)); - } finally { - if (tf) - tf.close(); - } - }; - return [cmd]; - } - } - - FileTagger { - patterns: ["*.rc"] - fileTags: ["rc"] - } - Rule { inputs: ["rc"] auxiliaryInputs: ["hpp"] diff --git a/share/qbs/modules/cpp/windows-msvc-base.qbs b/share/qbs/modules/cpp/windows-msvc-base.qbs index d36daa99f..ae105abe2 100644 --- a/share/qbs/modules/cpp/windows-msvc-base.qbs +++ b/share/qbs/modules/cpp/windows-msvc-base.qbs @@ -291,50 +291,10 @@ CppModule { } prepare: { - var platformDefines = input.cpp.platformDefines; - var defines = input.cpp.defines; - var includePaths = input.cpp.includePaths; - var systemIncludePaths = input.cpp.systemIncludePaths; - var args = []; - var i; - var hasNoLogo = product.cpp.compilerVersionMajor >= 16; // 2010 - if (hasNoLogo) - args.push("/nologo"); - - for (i in platformDefines) { - args.push('/d'); - args.push(platformDefines[i]); - } - for (i in defines) { - args.push('/d'); - args.push(defines[i]); - } - for (i in includePaths) { - args.push('/i'); - args.push(includePaths[i]); - } - for (i in systemIncludePaths) { - args.push('/i'); - args.push(systemIncludePaths[i]); - } - - args = args.concat(['/fo', output.filePath, input.filePath]); - var cmd = new Command('rc', args); - cmd.description = 'compiling ' + input.fileName; - cmd.highlight = 'compiler'; - cmd.jobPool = "compiler"; - - if (!hasNoLogo) { - // Remove the first two lines of stdout. That's the logo. - cmd.stdoutFilterFunction = function(output) { - var idx = 0; - for (var i = 0; i < 3; ++i) - idx = output.indexOf('\n', idx + 1); - return output.substr(idx + 1); - } - } - - return cmd; + // From MSVC 2010 on, the logo can be suppressed. + var logo = product.cpp.compilerVersionMajor >= 16 + ? "can-suppress-logo" : "always-shows-logo"; + return MSVC.createRcCommand("rc", input, output, logo); } } diff --git a/src/app/qbs-setup-toolchains/gccprobe.cpp b/src/app/qbs-setup-toolchains/gccprobe.cpp index e979acf59..a8482f8d0 100644 --- a/src/app/qbs-setup-toolchains/gccprobe.cpp +++ b/src/app/qbs-setup-toolchains/gccprobe.cpp @@ -46,11 +46,14 @@ #include <tools/hostosinfo.h> #include <tools/profile.h> +#include <tools/settings.h> #include <tools/toolchains.h> #include <QtCore/qdir.h> #include <QtCore/qprocess.h> +#include <algorithm> + using namespace qbs; using Internal::HostOsInfo; using Internal::Tr; @@ -395,6 +398,31 @@ Profile createGccProfile(const QFileInfo &compiler, Settings *settings, setCommonProperties(profile, compiler, toolchainTypes, details); + if (HostOsInfo::isWindowsHost() && toolchainTypes.contains(QLatin1String("clang"))) { + const QStringList profileNames = settings->profiles(); + bool foundMingw = false; + for (const QString &profileName : profileNames) { + const Profile otherProfile(profileName, settings); + if (otherProfile.value(QLatin1String("qbs.toolchainType")).toString() + == QLatin1String("mingw") + || otherProfile.value(QLatin1String("qbs.toolchain")) + .toStringList().contains(QLatin1String("mingw"))) { + const QFileInfo tcDir(otherProfile.value(QLatin1String("cpp.toolchainInstallPath")) + .toString()); + if (!tcDir.fileName().isEmpty() && tcDir.exists()) { + profile.setValue(QLatin1String("qbs.sysroot"), tcDir.path()); + foundMingw = true; + break; + } + } + } + if (!foundMingw) { + qbsWarning() << Tr::tr("Using clang on Windows requires a mingw installation. " + "Please set qbs.sysroot accordingly for profile '%1'.") + .arg(profile.name()); + } + } + if (!toolchainTypes.contains(QLatin1String("clang"))) { // Check whether auxiliary tools reside within the toolchain's install path. // This might not be the case when using icecc or another compiler wrapper. @@ -466,6 +494,16 @@ void gccProbe(Settings *settings, QList<Profile> &profiles, const QString &compi return; } + // Sort candidates so that mingw comes first. Information from mingw profiles is potentially + // used for setting up clang profiles. + if (HostOsInfo::isWindowsHost()) { + std::sort(candidates.begin(), candidates.end(), + [](const QFileInfo &fi1, const QFileInfo &fi2) { + return fi1.absoluteFilePath().contains(QLatin1String("mingw")) + && !fi2.absoluteFilePath().contains(QLatin1String("mingw")); + }); + } + for (const auto &candidate : qAsConst(candidates)) { const QStringList toolchainTypes = toolchainTypeFromCompilerName( candidate.baseName()); diff --git a/src/lib/corelib/language/evaluatorscriptclass.cpp b/src/lib/corelib/language/evaluatorscriptclass.cpp index 55a9e1aac..375954133 100644 --- a/src/lib/corelib/language/evaluatorscriptclass.cpp +++ b/src/lib/corelib/language/evaluatorscriptclass.cpp @@ -205,7 +205,18 @@ private: result.second = false; return result; } - SVConverter converter(scriptClass, object, item->property(*propertyName), item, + const ValuePtr v = item->property(*propertyName); + + // This can happen when resolving shadow products. The error will be ignored + // in that case. + if (!v) { + const QString errorMessage = Tr::tr("Error setting up 'original'."); + extraScope = engine->currentContext()->throwError(errorMessage); + result.second = false; + return result; + } + + SVConverter converter(scriptClass, object, v, item, propertyName, data, &originalValue); converter.start(); } else { diff --git a/tests/auto/api/testdata/infinite-loop-process/infinite-loop.qbs b/tests/auto/api/testdata/infinite-loop-process/infinite-loop.qbs index f0de12df1..f4ea8bf83 100644 --- a/tests/auto/api/testdata/infinite-loop-process/infinite-loop.qbs +++ b/tests/auto/api/testdata/infinite-loop-process/infinite-loop.qbs @@ -4,12 +4,21 @@ Project { consoleApplication: true // suppress bundle generation files: "main.cpp" name: "infinite-loop" + cpp.cxxLanguageVersion: "c++11" + Properties { + condition: qbs.toolchain.contains("gcc") + cpp.driverFlags: "-pthread" + } } Product { type: "mytype" name: "caller" Depends { name: "infinite-loop" } + Depends { + name: "cpp" // Make sure build environment is set up properly. + condition: qbs.hostOS.contains("windows") && qbs.toolchain.contains("gcc") + } Rule { inputsFromDependencies: "application" outputFileTags: "mytype" diff --git a/tests/auto/api/testdata/link-staticlibs-dynamiclibs/link-staticlibs-dynamiclibs.qbs b/tests/auto/api/testdata/link-staticlibs-dynamiclibs/link-staticlibs-dynamiclibs.qbs index eade97126..d7ed6c862 100644 --- a/tests/auto/api/testdata/link-staticlibs-dynamiclibs/link-staticlibs-dynamiclibs.qbs +++ b/tests/auto/api/testdata/link-staticlibs-dynamiclibs/link-staticlibs-dynamiclibs.qbs @@ -11,6 +11,13 @@ Project { files: [ "static1.cpp" ] Depends { name: "cpp" } Depends { name: "dynamic1" } + + Probe { + id: osCheck + property bool isNormalUnix: qbs.targetOS.contains("unix") + && !qbs.targetOS.contains("darwin") + configure: { console.info("is normal unix: " + (isNormalUnix ? "yes" : "no")); } + } } DynamicLibrary { diff --git a/tests/auto/api/testdata/timeout-process/timeout.qbs b/tests/auto/api/testdata/timeout-process/timeout.qbs index 3f79dce96..bdf6833fd 100644 --- a/tests/auto/api/testdata/timeout-process/timeout.qbs +++ b/tests/auto/api/testdata/timeout-process/timeout.qbs @@ -5,12 +5,20 @@ Project { files: "main.cpp" name: "infinite-loop" cpp.cxxLanguageVersion: "c++11" + Properties { + condition: qbs.toolchain.contains("gcc") + cpp.driverFlags: "-pthread" + } } Product { type: "product-under-test" name: "caller" Depends { name: "infinite-loop" } + Depends { + name: "cpp" // Make sure build environment is set up properly. + condition: qbs.hostOS.contains("windows") && qbs.toolchain.contains("gcc") + } Rule { inputsFromDependencies: "application" outputFileTags: "product-under-test" diff --git a/tests/auto/api/tst_api.cpp b/tests/auto/api/tst_api.cpp index 1a98f5f21..36a98fdaa 100644 --- a/tests/auto/api/tst_api.cpp +++ b/tests/auto/api/tst_api.cpp @@ -1556,9 +1556,13 @@ void TestApi::linkStaticAndDynamicLibs() BuildDescriptionReceiver bdr; qbs::BuildOptions options; options.setEchoMode(qbs::CommandEchoModeCommandLine); + m_logSink->output.clear(); const qbs::ErrorInfo errorInfo = doBuildProject("link-staticlibs-dynamiclibs", &bdr, nullptr, nullptr, options); VERIFY_NO_ERROR(errorInfo); + const bool isNormalUnix = m_logSink->output.contains("is normal unix: yes"); + const bool isNotNormalUnix = m_logSink->output.contains("is normal unix: no"); + QVERIFY2(isNormalUnix != isNotNormalUnix, qPrintable(m_logSink->output)); // The dependencies libdynamic1.so and libstatic2.a must not appear in the link command for the // executable. The -rpath-link line for libdynamic1.so must be there. @@ -1575,12 +1579,7 @@ void TestApi::linkStaticAndDynamicLibs() } } QVERIFY(!appLinkCmd.isEmpty()); - std::string targetPlatform = buildProfile.value("qbs.targetPlatform") - .toString().toStdString(); - std::vector<std::string> targetOS = qbs::Internal::HostOsInfo::canonicalOSIdentifiers( - targetPlatform); - if (!qbs::Internal::contains(targetOS, "darwin") - && !qbs::Internal::contains(targetOS, "windows")) { + if (isNormalUnix) { const std::regex rpathLinkRex("-rpath-link=\\S*/" + relativeProductBuildDir("dynamic2").toStdString()); const auto ln = appLinkCmd.toStdString(); @@ -2861,7 +2860,7 @@ void TestApi::timeout() QVERIFY(waitForFinished(buildJob.get(), testTimeoutInMsecs())); QVERIFY(buildJob->error().hasError()); const auto errorString = buildJob->error().toString(); - QVERIFY(errorString.contains("cancel")); + QVERIFY2(errorString.contains("cancel"), qPrintable(errorString)); QVERIFY(errorString.contains("timeout")); } diff --git a/tests/auto/blackbox/testdata/autotest-timeout/autotests-timeout.qbs b/tests/auto/blackbox/testdata/autotest-timeout/autotests-timeout.qbs index 270fc9eaf..d4f01895f 100644 --- a/tests/auto/blackbox/testdata/autotest-timeout/autotests-timeout.qbs +++ b/tests/auto/blackbox/testdata/autotest-timeout/autotests-timeout.qbs @@ -4,7 +4,16 @@ Project { type: ["application", "autotest"] Depends { name: "autotest" } cpp.cxxLanguageVersion: "c++11" + Properties { + condition: qbs.toolchain.contains("gcc") + cpp.driverFlags: "-pthread" + } files: "test-main.cpp" } - AutotestRunner {} + AutotestRunner { + Depends { + name: "cpp" // Make sure build environment is set up properly. + condition: qbs.hostOS.contains("windows") && qbs.toolchain.contains("gcc") + } + } } diff --git a/tests/auto/blackbox/testdata/autotest-with-dependencies/autotest-with-dependencies.qbs b/tests/auto/blackbox/testdata/autotest-with-dependencies/autotest-with-dependencies.qbs index 92d5ec6dd..7ae6cef73 100644 --- a/tests/auto/blackbox/testdata/autotest-with-dependencies/autotest-with-dependencies.qbs +++ b/tests/auto/blackbox/testdata/autotest-with-dependencies/autotest-with-dependencies.qbs @@ -21,6 +21,10 @@ Project { } AutotestRunner { + Depends { + name: "cpp" // Make sure build environment is set up properly. + condition: qbs.hostOS.contains("windows") && qbs.toolchain.contains("gcc") + } arguments: FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix, "bin") auxiliaryInputs: "test-helper" } diff --git a/tests/auto/blackbox/testdata/autotests/autotests.qbs b/tests/auto/blackbox/testdata/autotests/autotests.qbs index a2c2646dc..10334156e 100644 --- a/tests/auto/blackbox/testdata/autotests/autotests.qbs +++ b/tests/auto/blackbox/testdata/autotests/autotests.qbs @@ -1,4 +1,9 @@ Project { references: ["test1", "test2", "test3"] - AutotestRunner {} + AutotestRunner { + Depends { + name: "cpp" // Make sure build environment is set up properly. + condition: qbs.hostOS.contains("windows") && qbs.toolchain.contains("gcc") + } + } } diff --git a/tests/auto/blackbox/testdata/lexyacc/one-grammar/one-grammar.qbs b/tests/auto/blackbox/testdata/lexyacc/one-grammar/one-grammar.qbs index 61f76f4be..6cd334247 100644 --- a/tests/auto/blackbox/testdata/lexyacc/one-grammar/one-grammar.qbs +++ b/tests/auto/blackbox/testdata/lexyacc/one-grammar/one-grammar.qbs @@ -8,6 +8,23 @@ CppApplication { cpp.cxxLanguageVersion: "c++11" cpp.minimumMacosVersion: "10.7" consoleApplication: true + Probe { + id: pathCheck + property string theDir: { + if (qbs.targetOS.contains("windows")) { + if (qbs.toolchain.contains("mingw")) + return cpp.toolchainInstallPath; + if (qbs.toolchain.contains("clang") && qbs.sysroot) + return qbs.sysroot + "/bin"; + } + } + configure: { + if (theDir) + console.info("add to PATH: " + theDir); + found = true; + } + } + files: [ "lexer.l", "parser.y", diff --git a/tests/auto/blackbox/testdata/separate-debug-info/separate-debug-info.qbs b/tests/auto/blackbox/testdata/separate-debug-info/separate-debug-info.qbs index 48bdff904..0b16d1984 100644 --- a/tests/auto/blackbox/testdata/separate-debug-info/separate-debug-info.qbs +++ b/tests/auto/blackbox/testdata/separate-debug-info/separate-debug-info.qbs @@ -4,6 +4,15 @@ Project { type: ["application"] files: ["main.cpp"] cpp.separateDebugInformation: true + + Probe { + id: osProbe + property stringList targetOS: qbs.targetOS + configure: { + console.info("is windows: " + (targetOS.contains("windows") ? "yes" : "no")); + console.info("is darwin: " + (targetOS.contains("darwin") ? "yes" : "no")); + } + } } DynamicLibrary { Depends { name: "cpp" } diff --git a/tests/auto/blackbox/testdata/setup-run-environment/setup-run-environment.qbs b/tests/auto/blackbox/testdata/setup-run-environment/setup-run-environment.qbs index b5ac8b289..d2d47b767 100644 --- a/tests/auto/blackbox/testdata/setup-run-environment/setup-run-environment.qbs +++ b/tests/auto/blackbox/testdata/setup-run-environment/setup-run-environment.qbs @@ -61,6 +61,16 @@ Project { bundle.isBundle: false } + // Testing shows that clang (8.0) does not find dynamic libraries via + // the -L<dir> and -l<libname> mechanism unless the name is "lib<libname>.a". + Properties { + condition: qbs.hostOS.contains("windows") && qbs.toolchain.contains("clang") + cpp.dynamicLibraryPrefix: "lib" + cpp.dynamicLibraryImportSuffix: ".a" + } + cpp.dynamicLibraryPrefix: original + cpp.dynamicLibraryImportSuffix: original + install: true installImportLib: true installDir: "lib4" @@ -91,8 +101,9 @@ Project { property string fullInstallPrefix: FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix) property string lib3FilePath: FileInfo.joinPaths(fullInstallPrefix, "lib3", - cpp.dynamicLibraryPrefix + "lib3" + (qbs.toolchain.contains("msvc") - ? ".lib" : cpp.dynamicLibrarySuffix)) + cpp.dynamicLibraryPrefix + "lib3" + (qbs.targetOS.contains("windows") + ? cpp.dynamicLibraryImportSuffix + : cpp.dynamicLibrarySuffix)) cpp.dynamicLibraries: [lib3FilePath, "lib4"] cpp.libraryPaths: FileInfo.joinPaths(fullInstallPrefix, "lib4") } diff --git a/tests/auto/blackbox/tst_blackbox.cpp b/tests/auto/blackbox/tst_blackbox.cpp index edc2b51c8..31a5a92ae 100644 --- a/tests/auto/blackbox/tst_blackbox.cpp +++ b/tests/auto/blackbox/tst_blackbox.cpp @@ -1806,14 +1806,17 @@ void TestBlackbox::separateDebugInfo() { QDir::setCurrent(testDataDir + "/separate-debug-info"); QCOMPARE(runQbs(QbsRunParameters(QStringList("qbs.debugInformation:true"))), 0); + const bool isWindows = m_qbsStdout.contains("is windows: yes"); + const bool isNotWindows = m_qbsStdout.contains("is windows: no"); + QVERIFY(isWindows != isNotWindows); + const bool isDarwin = m_qbsStdout.contains("is darwin: yes"); + const bool isNotDarwin = m_qbsStdout.contains("is darwin: no"); + QVERIFY(isDarwin != isNotDarwin); const SettingsPtr s = settings(); Profile buildProfile(profileName(), s.get()); QStringList toolchain = buildProfile.value("qbs.toolchain").toStringList(); - std::string targetPlatform = buildProfile.value("qbs.targetPlatform").toString().toStdString(); - std::vector<std::string> targetOS = HostOsInfo::canonicalOSIdentifiers(targetPlatform); - if (qbs::Internal::contains(targetOS, "darwin") - || (targetPlatform.empty() && HostOsInfo::isMacosHost())) { + if (isDarwin) { QVERIFY(directoryExists(relativeProductBuildDir("app1") + "/app1.app.dSYM")); QVERIFY(regularFileExists(relativeProductBuildDir("app1") + "/app1.app.dSYM/Contents/Info.plist")); @@ -1878,7 +1881,6 @@ void TestBlackbox::separateDebugInfo() .entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).size(), 1); QVERIFY(regularFileExists(relativeProductBuildDir("bar5") + "/bar5.bundle.dwarf")); } else if (toolchain.contains("gcc")) { - const bool isWindows = qbs::Internal::contains(targetOS, "windows"); const QString exeSuffix = isWindows ? ".exe" : ""; const QString dllPrefix = isWindows ? "" : "lib"; const QString dllSuffix = isWindows ? ".dll" : ".so"; @@ -4354,6 +4356,18 @@ void TestBlackbox::lexyacc() QCOMPARE(runQbs(), 0); const QString parserBinary = relativeExecutableFilePath("one-grammar"); QProcess p; + const QByteArray magicString = "add to PATH: "; + const int magicStringIndex = m_qbsStdout.indexOf(magicString); + if (magicStringIndex != -1) { + const int newLineIndex = m_qbsStdout.indexOf('\n', magicStringIndex); + QVERIFY(newLineIndex != -1); + const int dirIndex = magicStringIndex + magicString.length(); + const QString dir = QString::fromLocal8Bit(m_qbsStdout.mid(dirIndex, + newLineIndex - dirIndex)); + QProcessEnvironment env; + env.insert("PATH", dir); + p.setProcessEnvironment(env); + } p.start(parserBinary); QVERIFY2(p.waitForStarted(), qPrintable(p.errorString())); p.write("a && b || c && !d"); |