diff options
119 files changed, 1115 insertions, 452 deletions
@@ -1 +1 @@ -1.12.0 +1.13.0 diff --git a/doc/reference/items/convenience/application.qdoc b/doc/reference/items/convenience/application.qdoc index de2bbae48..3c87f51f6 100644 --- a/doc/reference/items/convenience/application.qdoc +++ b/doc/reference/items/convenience/application.qdoc @@ -39,9 +39,30 @@ An Application item is a \l{Product} of the \l{Product::}{type} \c "application". - It exists for the convenience of project file authors. - \note On Android, an Application item instead builds a shared library for products whose \l{Product::}{consoleApplication} property is set to \c false. */ + +/*! + \qmlproperty bool Application::install + + If \c{true}, the executable that is produced when building the application will be installed + to \l installDir. + + \defaultvalue \c false + \since Qbs 1.13 +*/ + +/*! + \qmlproperty string Application::installDir + + Where to install the executable that is produced when building the application, if \l install + is enabled. + + The value is appended to \l{qbs::installPrefix}{qbs.installPrefix} + when constructing the actual installation directory. + + \defaultvalue \c Applications if the app is a \l{bundle::isBundle}{bundle}, \c bin otherwise. + \since Qbs 1.13 +*/ diff --git a/doc/reference/items/convenience/autotestrunner.qdoc b/doc/reference/items/convenience/autotestrunner.qdoc index f4861835b..defb2814e 100644 --- a/doc/reference/items/convenience/autotestrunner.qdoc +++ b/doc/reference/items/convenience/autotestrunner.qdoc @@ -73,6 +73,8 @@ \qmlproperty stringList AutotestRunner::arguments The list of arguments to invoke the autotest with. + A test can override this by setting the \l{autotest::arguments}{arguments} property + of the \l autotest module. \defaultvalue \c [] */ @@ -114,6 +116,8 @@ If this property is set, it will be the working directory for all invoked test executables. Otherwise, the working directory will the the parent directory of the respective executable. + A test can override this by setting the \l{autotest::workingDir}{workingDir} property + of the \l autotest module. \nodefaultvalue \since Qbs 1.12 diff --git a/doc/reference/items/convenience/dynamiclibrary.qdoc b/doc/reference/items/convenience/dynamiclibrary.qdoc index 27aa978d1..488aef3eb 100644 --- a/doc/reference/items/convenience/dynamiclibrary.qdoc +++ b/doc/reference/items/convenience/dynamiclibrary.qdoc @@ -38,7 +38,7 @@ \brief Dynamic library. A DynamicLibrary item is a \l{Product} of the \l{Product::}{type} - \c "dynamiclibrary". It exists for the convenience of project file authors. + \c "dynamiclibrary". For Android targets, the following applies: \list @@ -48,3 +48,50 @@ \endlist */ +/*! + \qmlproperty bool DynamicLibrary::install + + If \c{true}, the library will be installed to \l installDir. + + \defaultvalue \c false + \since Qbs 1.13 +*/ + +/*! + \qmlproperty string DynamicLibrary::installDir + + Where to install the library, if \l install is enabled. On Unix, the symbolic links + are also installed to this location. + + The value is appended to \l{qbs::installPrefix}{qbs.installPrefix} + when constructing the actual installation directory. + + \defaultvalue \c Library/Frameworks if the library is a \l{bundle::isBundle}{bundle}, + otherwise \c bin for Windows and \c lib for Unix-like targets. + \since Qbs 1.13 +*/ + +/*! + \qmlproperty bool DynamicLibrary::installImportLib + + If \c{true}, the import library will be installed to \l importLibInstallDir. + This property is only relevant for Windows targets. + Enable it if you want to create a development package. + + \defaultvalue \c false + \since Qbs 1.13 +*/ + +/*! + \qmlproperty string DynamicLibrary::importLibInstallDir + + Where to install the import library, if \l installImportLib is enabled. + + The value is appended to \l{qbs::installPrefix}{qbs.installPrefix} + when constructing the actual installation directory. + + This property is only relevant for Windows targets. + + \defaultvalue \c lib + \since Qbs 1.13 +*/ diff --git a/doc/reference/items/convenience/staticlibrary.qdoc b/doc/reference/items/convenience/staticlibrary.qdoc index a7a94cc43..cd459cf6e 100644 --- a/doc/reference/items/convenience/staticlibrary.qdoc +++ b/doc/reference/items/convenience/staticlibrary.qdoc @@ -37,11 +37,27 @@ \brief Static library. A StaticLibrary item is a \l{Product}{product} of the \l{Product::}{type} - \c "staticlibrary" that is normally entirely equivalent to the following: + \c "staticlibrary". +*/ + +/*! + \qmlproperty bool StaticLibrary::install + + If \c{true}, the library will be installed to \l installDir. + + \defaultvalue \c false + \since Qbs 1.13 +*/ + +/*! + \qmlproperty string StaticLibrary::installDir + + Where to install the library, if \l install is enabled. + + The value is appended to \l{qbs::installPrefix}{qbs.installPrefix} + when constructing the actual installation directory. - \code - Product { - type: "staticlibrary" - } - \endcode + \defaultvalue \c Library/Frameworks if the library is a \l{bundle::isBundle}{bundle}, + \c lib otherwise. + \since Qbs 1.13 */ diff --git a/doc/reference/modules/autotest-module.qdoc b/doc/reference/modules/autotest-module.qdoc new file mode 100644 index 000000000..ddd9e0078 --- /dev/null +++ b/doc/reference/modules/autotest-module.qdoc @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** 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$ +** +****************************************************************************/ + +/*! + \contentspage index.html + \qmltype autotest + \inqmlmodule QbsModules + \since Qbs 1.13 + + \brief Allows to fine-tune autotest execution. + + The \c autotest module provides properties that allow autotest applications to specify + how exactly they should be run. +*/ + +/*! + \qmlproperty bool autotest::allowFailure + + Autotests for which this property is \c true can return a non-zero exit code without + causing the entire \l AutotestRunner to fail. Use this for tests that are known + to be unreliable. + + \defaultvalue \c false +*/ + +/*! + \qmlproperty stringList autotest::arguments + + The list of arguments to invoke the autotest with. If not specified, then + the \l{AutotestRunner::arguments}{arguments} property of the + \l AutotestRunner that invokes the autotest is used. + + \nodefaultvalue +*/ + +/*! + \qmlproperty string autotest::workingDir + + The working directory for running the autotest. If not specified, then + the \l{AutotestRunner::workingDir}{workingDir} property of the + \l AutotestRunner that invokes the autotest is used. + + \nodefaultvalue +*/ + diff --git a/doc/reference/modules/texttemplate-module.qdoc b/doc/reference/modules/texttemplate-module.qdoc new file mode 100644 index 000000000..6d42560be --- /dev/null +++ b/doc/reference/modules/texttemplate-module.qdoc @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** 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$ +** +****************************************************************************/ + +/*! + \contentspage index.html + \qmltype texttemplate + \inqmlmodule QbsModules + \since Qbs 1.13 + + \brief Provides support for text template files + + The \c texttemplate module provides support for text template files. + + \section2 Example + + Consider the following text file \e{greeting.txt.in}. + + \code + ${greeting} ${name}! + \endcode + + This can be used in a project like this: + + \code + Product { + type: ["text"] + files: ["greeting.txt.in"] + Depends { name: "texttemplate" } + texttemplate.dict: ({ + greeting: "Hello", + name: "World" + }) + } + \endcode + + Which will create the file \e{greeting.txt}. + + \code + Hello World! + \endcode + + + \section2 Placeholder Syntax + + A placeholder \c{${foo}} is replaced by its corresponding value in + \e{texttemplate.dict}. + Placeholder names consist of alphanumeric characters only. + + The placeholder \c{${$}} is always replaced with \c{$}. + If you need a literal \c{${foo}} in your template, use \c{${$}{foo}}. + + Placeholders that are not defined in the dictionary will produce an error. + + + \section2 Relevant File Tags + \target filetags-texttemplate + + \table + \header + \li Tag + \li Auto-tagged File Names + \li Since + \li Description + \row + \li \c{"texttemplate.input"} + \li \c{*.in} + \li 1.13.0 + \li Source files with this tag serve as inputs for the text template rule. + \endtable +*/ + +/*! + \qmlproperty var texttemplate::dict + + The dictionary containing values for all keys used in the template file. + + \defaultvalue \c{{}} +*/ + +/*! + \qmlproperty string outputFileName + + The output file name that is assigned to produced artifacts. + + \defaultvalue Complete base name of the input file +*/ + +/*! + \qmlproperty string outputTag + + The output tag that is assigned to produced artifacts. + + \defaultvalue \c{"text"} +*/ diff --git a/share/qbs/imports/qbs/base/Application.qbs b/share/qbs/imports/qbs/base/Application.qbs index e16a93761..7f26279c8 100644 --- a/share/qbs/imports/qbs/base/Application.qbs +++ b/share/qbs/imports/qbs/base/Application.qbs @@ -36,4 +36,14 @@ NativeBinary { return ["dynamiclibrary", "android.nativelibrary"]; return ["application"]; } + + installDir: isBundle ? "Applications" : "bin" + + Group { + condition: install + fileTagsFilter: isBundle ? "bundle.content" : "application"; + qbs.install: true + qbs.installDir: installDir + qbs.installSourceBase: isBundle ? destinationDirectory : outer + } } diff --git a/share/qbs/imports/qbs/base/AutotestRunner.qbs b/share/qbs/imports/qbs/base/AutotestRunner.qbs index 4f175d662..3b8461167 100644 --- a/share/qbs/imports/qbs/base/AutotestRunner.qbs +++ b/share/qbs/imports/qbs/base/AutotestRunner.qbs @@ -32,7 +32,6 @@ import qbs import qbs.File import qbs.FileInfo import qbs.ModUtils -import qbs.Utilities Product { name: "autotest-runner" @@ -57,11 +56,7 @@ Product { Rule { inputsFromDependencies: "application" auxiliaryInputs: product.auxiliaryInputs - Artifact { - filePath: Utilities.getHash(input.filePath) + ".result.dummy" // Will never exist. - fileTags: "autotest-result" - alwaysUpdated: false - } + outputFileTags: "autotest-result" prepare: { // TODO: This is hacky. Possible solution: Add autotest tag to application // in autotest module and have that as inputsFromDependencies instead of application. @@ -76,14 +71,29 @@ Product { commandFilePath = ModUtils.artifactInstalledFilePath(input); if (!commandFilePath || !File.exists(commandFilePath)) commandFilePath = input.filePath; + var workingDir = product.workingDir ? product.workingDir + : FileInfo.path(commandFilePath); + var arguments = product.arguments; + var allowFailure = false; + if (input.autotest) { + // FIXME: We'd like to let the user override with an empty list, but + // qbscore turns undefined lists into empty ones at the moment. + if (input.autotest.arguments && input.autotest.arguments.length > 0) + arguments = input.autotest.arguments; + + if (input.autotest.workingDir) + workingDir = input.autotest.workingDir; + allowFailure = input.autotest.allowFailure; + } var fullCommandLine = product.wrapper .concat([commandFilePath]) - .concat(product.arguments); + .concat(arguments); var cmd = new Command(fullCommandLine[0], fullCommandLine.slice(1)); cmd.description = "Running test " + input.fileName; cmd.environment = product.environment; - cmd.workingDirectory = product.workingDir ? product.workingDir - : FileInfo.path(commandFilePath); + cmd.workingDirectory = workingDir; + if (allowFailure) + cmd.maxExitCode = 32767; return cmd; } } diff --git a/share/qbs/imports/qbs/base/DynamicLibrary.qbs b/share/qbs/imports/qbs/base/DynamicLibrary.qbs index 32d8fec41..4853b9598 100644 --- a/share/qbs/imports/qbs/base/DynamicLibrary.qbs +++ b/share/qbs/imports/qbs/base/DynamicLibrary.qbs @@ -32,4 +32,24 @@ import qbs Library { type: ["dynamiclibrary"].concat(isForAndroid ? ["android.nativelibrary"] : []) + + installDir: isBundle ? "Library/Frameworks" : qbs.targetOS.contains("windows") + ? "bin" : "lib" + property bool installImportLib: false + property string importLibInstallDir: "lib" + + Group { + condition: install + fileTagsFilter: isBundle ? "bundle.content" : ["dynamiclibrary", "dynamiclibrary_symlink"] + qbs.install: true + qbs.installDir: installDir + qbs.installSourceBase: isBundle ? destinationDirectory : outer + } + + Group { + condition: installImportLib + fileTagsFilter: "dynamiclibrary_import" + qbs.install: true + qbs.installDir: importLibInstallDir + } } diff --git a/share/qbs/imports/qbs/base/NativeBinary.qbs b/share/qbs/imports/qbs/base/NativeBinary.qbs index 0a772b60c..ce8f458f4 100644 --- a/share/qbs/imports/qbs/base/NativeBinary.qbs +++ b/share/qbs/imports/qbs/base/NativeBinary.qbs @@ -33,6 +33,10 @@ import qbs Product { property bool isForAndroid: qbs.targetOS.contains("android") property bool isForDarwin: qbs.targetOS.contains("darwin") + property bool isBundle: isForDarwin && bundle.isBundle + + property bool install: false + property string installDir Depends { name: "bundle" } diff --git a/share/qbs/imports/qbs/base/StaticLibrary.qbs b/share/qbs/imports/qbs/base/StaticLibrary.qbs index 1609bdcea..be5f7a7c4 100644 --- a/share/qbs/imports/qbs/base/StaticLibrary.qbs +++ b/share/qbs/imports/qbs/base/StaticLibrary.qbs @@ -32,4 +32,13 @@ import qbs Library { type: ["staticlibrary"] + + installDir: isBundle ? "Library/Frameworks" : "lib" + Group { + condition: install + fileTagsFilter: isBundle ? "bundle.content" : "staticlibrary"; + qbs.install: true + qbs.installDir: installDir + qbs.installSourceBase: isBundle ? destinationDirectory : outer + } } diff --git a/share/qbs/modules/autotest/autotest.qbs b/share/qbs/modules/autotest/autotest.qbs new file mode 100644 index 000000000..36029df09 --- /dev/null +++ b/share/qbs/modules/autotest/autotest.qbs @@ -0,0 +1,7 @@ +import qbs + +Module { + property stringList arguments + property bool allowFailure: false + property string workingDir +} diff --git a/share/qbs/modules/cpp/GenericGCC.qbs b/share/qbs/modules/cpp/GenericGCC.qbs index 792e8ef4c..321f3ac71 100644 --- a/share/qbs/modules/cpp/GenericGCC.qbs +++ b/share/qbs/modules/cpp/GenericGCC.qbs @@ -390,7 +390,7 @@ CppModule { || product.multiplexConfigurationId Rule { - id: dynamicLibraryLinker + name: "dynamicLibraryLinker" condition: product.cpp.shouldLink multiplex: true inputs: { @@ -452,7 +452,7 @@ CppModule { } Rule { - id: staticLibraryLinker + name: "staticLibraryLinker" condition: product.cpp.shouldLink multiplex: true inputs: ["obj", "linkerscript"] @@ -494,7 +494,7 @@ CppModule { } Rule { - id: loadableModuleLinker + name: "loadableModuleLinker" condition: product.cpp.shouldLink multiplex: true inputs: { @@ -531,7 +531,7 @@ CppModule { } Rule { - id: applicationLinker + name: "applicationLinker" condition: product.cpp.shouldLink multiplex: true inputs: { @@ -567,7 +567,7 @@ CppModule { } Rule { - id: compiler + name: "compiler" inputs: ["cpp", "c", "objcpp", "objc", "asm_cpp"] auxiliaryInputs: ["hpp"] explicitlyDependsOn: ["c_pch", "cpp_pch", "objc_pch", "objcpp_pch"] @@ -592,7 +592,7 @@ CppModule { } Rule { - id: assembler + name: "assembler" inputs: ["asm"] Artifact { diff --git a/share/qbs/modules/cpp/windows-msvc.qbs b/share/qbs/modules/cpp/windows-msvc.qbs index 3164e08b5..e86200ee3 100644 --- a/share/qbs/modules/cpp/windows-msvc.qbs +++ b/share/qbs/modules/cpp/windows-msvc.qbs @@ -170,7 +170,7 @@ CppModule { } Rule { - id: compiler + name: "compiler" inputs: ["cpp", "c"] auxiliaryInputs: ["hpp"] explicitlyDependsOn: ["c_pch", "cpp_pch"] @@ -191,7 +191,7 @@ CppModule { } Rule { - id: applicationLinker + name: "applicationLinker" multiplex: true inputs: ['obj', 'native.pe.manifest'] inputsFromDependencies: ['staticlibrary', 'dynamiclibrary_import', "debuginfo_app"] @@ -221,7 +221,7 @@ CppModule { } Rule { - id: dynamicLibraryLinker + name: "dynamicLibraryLinker" multiplex: true inputs: ['obj', 'native.pe.manifest'] inputsFromDependencies: ['staticlibrary', 'dynamiclibrary_import', "debuginfo_dll"] @@ -256,7 +256,7 @@ CppModule { } Rule { - id: libtool + name: "libtool" multiplex: true inputs: ["obj"] inputsFromDependencies: ["staticlibrary", "dynamiclibrary_import"] diff --git a/share/qbs/modules/qbs/common.qbs b/share/qbs/modules/qbs/common.qbs index 86ce27c59..4e96a320b 100644 --- a/share/qbs/modules/qbs/common.qbs +++ b/share/qbs/modules/qbs/common.qbs @@ -102,7 +102,7 @@ Module { property path installSourceBase property string installRoot: project.buildDirectory + "/install-root" property string installDir - property string installPrefix: "" + property string installPrefix: qbs.targetOS.contains("unix") ? "/usr/local" : "" property path sysroot PropertyOptions { diff --git a/share/qbs/modules/texttemplate/texttemplate.qbs b/share/qbs/modules/texttemplate/texttemplate.qbs new file mode 100644 index 000000000..c72929660 --- /dev/null +++ b/share/qbs/modules/texttemplate/texttemplate.qbs @@ -0,0 +1,64 @@ +import qbs.TextFile + +Module { + property var dict: ({}) + property string outputTag: "text" + property string outputFileName + FileTagger { + patterns: ["*.in"] + fileTags: ["texttemplate.input"] + } + Rule { + inputs: ["texttemplate.input"] + outputFileTags: [product.texttemplate.outputTag] + outputArtifacts: [ + { + fileTags: [product.texttemplate.outputTag], + filePath: input.texttemplate.outputFileName || input.completeBaseName + } + ] + prepare: { + var cmd = new JavaScriptCommand(); + cmd.silent = true; + cmd.sourceCode = function() { + try { + var src = new TextFile(input.filePath, TextFile.ReadOnly); + var dst = new TextFile(output.filePath, TextFile.WriteOnly); + var rex = /\${(\$|\w+)}/g; + var match; + while (!src.atEof()) { + rex.lastIndex = 0; + var line = src.readLine(); + var matches = []; + while (match = rex.exec(line)) + matches.push(match); + for (var i = matches.length; --i >= 0;) { + match = matches[i]; + var replacement; + if (match[1] === "$") { + replacement = "$"; + } else { + replacement = input.texttemplate.dict[match[1]]; + if (typeof replacement === "undefined") { + throw new Error("Placeholder '" + match[1] + + "' is not defined in textemplate.dict for '" + + input.fileName + "'."); + } + } + line = line.substr(0, match.index) + + replacement + + line.substr(match.index + match[0].length); + } + dst.writeLine(line); + } + } finally { + if (src) + src.close(); + if (dst) + dst.close(); + } + }; + return [cmd]; + } + } +} diff --git a/src/app/shared/logging/coloredoutput.cpp b/src/app/shared/logging/coloredoutput.cpp index 33e647d36..0f1bb26da 100644 --- a/src/app/shared/logging/coloredoutput.cpp +++ b/src/app/shared/logging/coloredoutput.cpp @@ -38,7 +38,7 @@ ****************************************************************************/ #include "coloredoutput.h" -#include <QtCore/qglobal.h> +#include <QtCore/qbytearray.h> #ifdef Q_OS_WIN32 # include <QtCore/qt_windows.h> #endif @@ -99,3 +99,13 @@ void fprintfColored(TextColor color, FILE *file, const char *str, ...) fprintfColored(color, file, str, vl); va_end(vl); } + +bool terminalSupportsColor() +{ +#if defined(Q_OS_UNIX) + const QByteArray &term = qgetenv("TERM"); + return !term.isEmpty() && term != "dumb"; +#else + return true; +#endif +} diff --git a/src/app/shared/logging/coloredoutput.h b/src/app/shared/logging/coloredoutput.h index 182d96bbe..a7b145ba5 100644 --- a/src/app/shared/logging/coloredoutput.h +++ b/src/app/shared/logging/coloredoutput.h @@ -68,5 +68,6 @@ void printfColored(TextColor color, const char *str, va_list vl); void printfColored(TextColor color, const char *str, ...); void fprintfColored(TextColor color, FILE *file, const char *str, va_list vl); void fprintfColored(TextColor color, FILE *file, const char *str, ...); +bool terminalSupportsColor(); #endif // QBS_COLOREDOUTPUT_H diff --git a/src/app/shared/logging/consolelogger.cpp b/src/app/shared/logging/consolelogger.cpp index ca270759c..7639fb111 100644 --- a/src/app/shared/logging/consolelogger.cpp +++ b/src/app/shared/logging/consolelogger.cpp @@ -91,7 +91,7 @@ void ConsoleLogSink::fprintfWrapper(TextColor color, FILE *file, const char *str { va_list vl; va_start(vl, str); - if (m_coloredOutputEnabled) + if (m_coloredOutputEnabled && terminalSupportsColor()) fprintfColored(color, file, str, vl); else vfprintf(file, str, vl); diff --git a/src/lib/corelib/buildgraph/rulesapplicator.cpp b/src/lib/corelib/buildgraph/rulesapplicator.cpp index da0e78592..4cb328f2c 100644 --- a/src/lib/corelib/buildgraph/rulesapplicator.cpp +++ b/src/lib/corelib/buildgraph/rulesapplicator.cpp @@ -65,6 +65,7 @@ #include <tools/qttools.h> #include <tools/stringconstants.h> +#include <QtCore/qcryptographichash.h> #include <QtCore/qdir.h> #include <QtScript/qscriptvalueiterator.h> @@ -218,6 +219,10 @@ void RulesApplicator::doApply(const ArtifactSet &inputArtifacts, QScriptValue &p outputArtifacts.push_back(outputArtifact); ruleArtifactArtifactMap.push_back({ ruleArtifact.get(), outputArtifact }); } + if (m_rule->artifacts.empty()) { + outputArtifacts.push_back(createOutputArtifactFromRuleArtifact(nullptr, inputArtifacts, + &outputFilePaths)); + } } if (outputArtifacts.empty()) @@ -348,18 +353,34 @@ Artifact *RulesApplicator::createOutputArtifactFromRuleArtifact( const RuleArtifactConstPtr &ruleArtifact, const ArtifactSet &inputArtifacts, Set<QString> *outputFilePaths) { - QScriptValue scriptValue = engine()->evaluate(ruleArtifact->filePath, - ruleArtifact->filePathLocation.filePath(), - ruleArtifact->filePathLocation.line()); - if (Q_UNLIKELY(engine()->hasErrorOrException(scriptValue))) - throw engine()->lastError(scriptValue, ruleArtifact->filePathLocation); - QString outputPath = FileInfo::resolvePath(m_product->buildDirectory(), scriptValue.toString()); + QString outputPath; + FileTags fileTags; + bool alwaysUpdated; + if (ruleArtifact) { + QScriptValue scriptValue = engine()->evaluate(ruleArtifact->filePath, + ruleArtifact->filePathLocation.filePath(), + ruleArtifact->filePathLocation.line()); + if (Q_UNLIKELY(engine()->hasErrorOrException(scriptValue))) + throw engine()->lastError(scriptValue, ruleArtifact->filePathLocation); + outputPath = scriptValue.toString(); + fileTags = ruleArtifact->fileTags; + alwaysUpdated = ruleArtifact->alwaysUpdated; + } else { + outputPath = QStringLiteral("__dummyoutput__"); + QByteArray hashInput = m_rule->toString().toLatin1(); + for (const Artifact * const input : inputArtifacts) + hashInput += input->filePath().toLatin1(); + outputPath += QLatin1String(QCryptographicHash::hash(hashInput, QCryptographicHash::Sha1) + .toHex().left(16)); + fileTags = m_rule->outputFileTags; + alwaysUpdated = false; + } + outputPath = FileInfo::resolvePath(m_product->buildDirectory(), outputPath); if (Q_UNLIKELY(!outputFilePaths->insert(outputPath).second)) { throw ErrorInfo(Tr::tr("Rule %1 already created '%2'.") .arg(m_rule->toString(), outputPath)); } - return createOutputArtifact(outputPath, ruleArtifact->fileTags, ruleArtifact->alwaysUpdated, - inputArtifacts); + return createOutputArtifact(outputPath, fileTags, alwaysUpdated, inputArtifacts); } Artifact *RulesApplicator::createOutputArtifact(const QString &filePath, const FileTags &fileTags, diff --git a/src/lib/corelib/language/artifactproperties.cpp b/src/lib/corelib/language/artifactproperties.cpp index 4897c6cff..dd61bf1a2 100644 --- a/src/lib/corelib/language/artifactproperties.cpp +++ b/src/lib/corelib/language/artifactproperties.cpp @@ -57,9 +57,9 @@ FileTags ArtifactProperties::extraFileTags() const return m_extraFileTags; } -void ArtifactProperties::setExtraFileTags(const FileTags &extraFileTags) +void ArtifactProperties::addExtraFileTags(const FileTags &extraFileTags) { - m_extraFileTags = extraFileTags; + m_extraFileTags.unite(extraFileTags); } bool operator==(const ArtifactProperties &ap1, const ArtifactProperties &ap2) diff --git a/src/lib/corelib/language/artifactproperties.h b/src/lib/corelib/language/artifactproperties.h index a255950d0..856aa80c7 100644 --- a/src/lib/corelib/language/artifactproperties.h +++ b/src/lib/corelib/language/artifactproperties.h @@ -59,7 +59,7 @@ public: void setPropertyMapInternal(const PropertyMapPtr &pmap) { m_propertyMap = pmap; } FileTags extraFileTags() const; - void setExtraFileTags(const FileTags &extraFileTags); + void addExtraFileTags(const FileTags &extraFileTags); template<PersistentPool::OpType opType> void completeSerializationOp(PersistentPool &pool) { diff --git a/src/lib/corelib/language/projectresolver.cpp b/src/lib/corelib/language/projectresolver.cpp index 4af79a5ce..ff74f845a 100644 --- a/src/lib/corelib/language/projectresolver.cpp +++ b/src/lib/corelib/language/projectresolver.cpp @@ -97,7 +97,7 @@ struct ProjectResolver::ProductContext ResolvedProductPtr product; QString buildDirectory; Item *item; - typedef std::pair<ArtifactPropertiesPtr, CodeLocation> ArtifactPropertiesInfo; + typedef std::pair<ArtifactPropertiesPtr, std::vector<CodeLocation>> ArtifactPropertiesInfo; QHash<QStringList, ArtifactPropertiesInfo> artifactPropertiesPerFilter; QHash<QString, CodeLocation> sourceArtifactLocations; GroupConstPtr currentGroup; @@ -692,19 +692,30 @@ void ProjectResolver::resolveGroup(Item *item, ProjectContext *projectContext) void ProjectResolver::resolveGroupFully(Item *item, ProjectResolver::ProjectContext *projectContext, bool isEnabled) { - PropertyMapPtr moduleProperties = m_productContext->currentGroup - ? m_productContext->currentGroup->properties - : m_productContext->product->moduleProperties; - const QVariantMap newModuleProperties - = resolveAdditionalModuleProperties(item, moduleProperties->value()); - if (!newModuleProperties.empty()) { - moduleProperties = PropertyMapInternal::create(); - moduleProperties->setValue(newModuleProperties); - } - AccumulatingTimer groupTimer(m_setupParams.logElapsedTime() ? &m_elapsedTimeGroups : nullptr); + const auto getGroupPropertyMap = [this, item](const ArtifactProperties *existingProps) { + PropertyMapPtr moduleProperties; + bool newPropertyMapRequired = false; + if (existingProps) + moduleProperties = existingProps->propertyMap(); + if (!moduleProperties) { + newPropertyMapRequired = true; + moduleProperties = m_productContext->currentGroup + ? m_productContext->currentGroup->properties + : m_productContext->product->moduleProperties; + } + const QVariantMap newModuleProperties + = resolveAdditionalModuleProperties(item, moduleProperties->value()); + if (!newModuleProperties.empty()) { + if (newPropertyMapRequired) + moduleProperties = PropertyMapInternal::create(); + moduleProperties->setValue(newModuleProperties); + } + return moduleProperties; + }; + QStringList files = m_evaluator->stringListValue(item, StringConstants::filesProperty()); bool fileTagsSet; const FileTags fileTags = m_evaluator->fileTagsValue(item, StringConstants::fileTagsProperty(), @@ -716,28 +727,30 @@ void ProjectResolver::resolveGroupFully(Item *item, ProjectResolver::ProjectCont throw ErrorInfo(Tr::tr("Group.files and Group.fileTagsFilters are exclusive."), item->location()); - ProductContext::ArtifactPropertiesInfo apinfo - = m_productContext->artifactPropertiesPerFilter.value(fileTagsFilter); + if (!isEnabled) + return; + + ProductContext::ArtifactPropertiesInfo &apinfo + = m_productContext->artifactPropertiesPerFilter[fileTagsFilter]; if (apinfo.first) { - if (apinfo.second.filePath() == item->location().filePath()) { + const auto it = std::find_if(apinfo.second.cbegin(), apinfo.second.cend(), + [item](const CodeLocation &loc) { + return item->location().filePath() == loc.filePath(); + }); + if (it != apinfo.second.cend()) { ErrorInfo error(Tr::tr("Conflicting fileTagsFilter in Group items.")); - error.append(Tr::tr("First item"), apinfo.second); + error.append(Tr::tr("First item"), *it); error.append(Tr::tr("Second item"), item->location()); throw error; } - - // Discard any Group with the same fileTagsFilter that was defined in a base file. - removeAll(m_productContext->product->artifactProperties, apinfo.first); + } else { + apinfo.first = ArtifactProperties::create(); + apinfo.first->setFileTagsFilter(FileTags::fromStringList(fileTagsFilter)); + m_productContext->product->artifactProperties.push_back(apinfo.first); } - if (!isEnabled) - return; - ArtifactPropertiesPtr aprops = ArtifactProperties::create(); - aprops->setFileTagsFilter(FileTags::fromStringList(fileTagsFilter)); - aprops->setExtraFileTags(fileTags); - aprops->setPropertyMapInternal(moduleProperties); - m_productContext->product->artifactProperties.push_back(aprops); - m_productContext->artifactPropertiesPerFilter.insert(fileTagsFilter, - ProductContext::ArtifactPropertiesInfo(aprops, item->location())); + apinfo.second.push_back(item->location()); + apinfo.first->setPropertyMapInternal(getGroupPropertyMap(apinfo.first.get())); + apinfo.first->addExtraFileTags(fileTags); return; } QStringList patterns; @@ -757,7 +770,7 @@ void ProjectResolver::resolveGroupFully(Item *item, ProjectResolver::ProjectCont } group->location = item->location(); group->enabled = isEnabled; - group->properties = moduleProperties; + group->properties = getGroupPropertyMap(nullptr); group->fileTags = fileTags; group->overrideTags = m_evaluator->boolValue(item, StringConstants::overrideTagsProperty()); if (group->overrideTags && fileTagsSet) { @@ -1161,19 +1174,18 @@ void ProjectResolver::resolveRule(Item *item, ProjectContext *projectContext) rule->prepareScript.initialize(scriptFunctionValue(item, StringConstants::prepareProperty())); rule->outputArtifactsScript.initialize(scriptFunctionValue( item, StringConstants::outputArtifactsProperty())); + rule->outputFileTags = m_evaluator->fileTagsValue( + item, StringConstants::outputFileTagsProperty()); if (rule->outputArtifactsScript.isValid()) { if (hasArtifactChildren) throw ErrorInfo(Tr::tr("The Rule.outputArtifacts script is not allowed in rules " "that contain Artifact items."), item->location()); - rule->outputFileTags = m_evaluator->fileTagsValue( - item, StringConstants::outputFileTagsProperty()); - if (rule->outputFileTags.empty()) - throw ErrorInfo(Tr::tr("Rule.outputFileTags must be specified if " - "Rule.outputArtifacts is specified."), - item->location()); } - + if (!hasArtifactChildren && rule->outputFileTags.empty()) { + throw ErrorInfo(Tr::tr("A rule needs to have Artifact items or a non-empty " + "outputFileTags property."), item->location()); + } rule->multiplex = m_evaluator->boolValue(item, StringConstants::multiplexProperty()); rule->alwaysRun = m_evaluator->boolValue(item, StringConstants::alwaysRunProperty()); rule->inputs = m_evaluator->fileTagsValue(item, StringConstants::inputsProperty()); diff --git a/src/lib/corelib/language/scriptengine.cpp b/src/lib/corelib/language/scriptengine.cpp index e983ae945..a1661faf4 100644 --- a/src/lib/corelib/language/scriptengine.cpp +++ b/src/lib/corelib/language/scriptengine.cpp @@ -371,6 +371,11 @@ void ScriptEngine::setEnvironment(const QProcessEnvironment &env) void ScriptEngine::importFile(const QString &filePath, QScriptValue &targetObject) { AccumulatingTimer importTimer(m_elapsedTimeImporting != -1 ? &m_elapsedTimeImporting : nullptr); + QScriptValue &evaluationResult = m_jsFileCache[filePath]; + if (evaluationResult.isValid()) { + ScriptImporter::copyProperties(evaluationResult, targetObject); + return; + } QFile file(filePath); if (Q_UNLIKELY(!file.open(QFile::ReadOnly))) throw ErrorInfo(tr("Cannot open '%1'.").arg(filePath)); @@ -379,7 +384,7 @@ void ScriptEngine::importFile(const QString &filePath, QScriptValue &targetObjec const QString sourceCode = stream.readAll(); file.close(); m_currentDirPathStack.push(FileInfo::path(filePath)); - m_scriptImporter->importSourceCode(sourceCode, filePath, targetObject); + evaluationResult = m_scriptImporter->importSourceCode(sourceCode, filePath, targetObject); m_currentDirPathStack.pop(); } diff --git a/src/lib/corelib/language/scriptengine.h b/src/lib/corelib/language/scriptengine.h index 11ed51a49..6349744e0 100644 --- a/src/lib/corelib/language/scriptengine.h +++ b/src/lib/corelib/language/scriptengine.h @@ -299,6 +299,7 @@ private: QScriptClass *m_modulePropertyScriptClass; QScriptClass *m_productPropertyScriptClass = nullptr; QHash<JsImport, QScriptValue> m_jsImportCache; + std::unordered_map<QString, QScriptValue> m_jsFileCache; bool m_propertyCacheEnabled; bool m_active; QHash<PropertyCacheKey, QVariant> m_propertyCache; diff --git a/src/lib/corelib/language/scriptimporter.cpp b/src/lib/corelib/language/scriptimporter.cpp index 6249e360e..c5dc887b7 100644 --- a/src/lib/corelib/language/scriptimporter.cpp +++ b/src/lib/corelib/language/scriptimporter.cpp @@ -120,7 +120,7 @@ ScriptImporter::ScriptImporter(ScriptEngine *scriptEngine) { } -void ScriptImporter::importSourceCode(const QString &sourceCode, const QString &filePath, +QScriptValue ScriptImporter::importSourceCode(const QString &sourceCode, const QString &filePath, QScriptValue &targetObject) { Q_ASSERT(targetObject.isObject()); @@ -146,6 +146,7 @@ void ScriptImporter::importSourceCode(const QString &sourceCode, const QString & QScriptValue result = m_engine->evaluate(code, filePath, 0); throwOnEvaluationError(m_engine, result, [&filePath] () { return CodeLocation(filePath, 0); }); copyProperties(result, targetObject); + return result; } void ScriptImporter::copyProperties(const QScriptValue &src, QScriptValue &dst) diff --git a/src/lib/corelib/language/scriptimporter.h b/src/lib/corelib/language/scriptimporter.h index 0f37038ff..8cff09382 100644 --- a/src/lib/corelib/language/scriptimporter.h +++ b/src/lib/corelib/language/scriptimporter.h @@ -53,11 +53,11 @@ class ScriptImporter { public: ScriptImporter(ScriptEngine *scriptEngine); - void importSourceCode(const QString &sourceCode, const QString &filePath, QScriptValue &targetObject); + QScriptValue importSourceCode(const QString &sourceCode, const QString &filePath, QScriptValue &targetObject); -private: static void copyProperties(const QScriptValue &src, QScriptValue &dst); +private: ScriptEngine *m_engine; QHash<QString, QString> m_sourceCodeCache; }; diff --git a/static-res.pro b/static-res.pro index b35836ece..a01b3a83b 100644 --- a/static-res.pro +++ b/static-res.pro @@ -21,6 +21,7 @@ qbsres.commands = \ -f $$shell_quote($$PWD/qbs.qbs) \ -d $$shell_quote($$builddirname) \ -p $$shell_quote("qbs resources") \ + qbs.installPrefix:undefined \ project.withCode:false \ project.withDocumentation:false \ profile:none diff --git a/tests/auto/api/testdata/build-single-file/build-single-file.qbs b/tests/auto/api/testdata/build-single-file/build-single-file.qbs index eeb38a5ff..6389713d9 100644 --- a/tests/auto/api/testdata/build-single-file/build-single-file.qbs +++ b/tests/auto/api/testdata/build-single-file/build-single-file.qbs @@ -2,6 +2,7 @@ import qbs import qbs.TextFile CppApplication { + consoleApplication: true files: ["ignored1.cpp", "ignored2.cpp", "compiled.cpp"] cpp.includePaths: [buildDirectory] @@ -10,10 +11,8 @@ CppApplication { fileTags: ["cpp_pch_src"] } - Group { - fileTagsFilter: ["application"] - qbs.install: true - } + install: true + installDir: "" Rule { multiplex: true 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 6155baf28..fb09b9a97 100644 --- a/tests/auto/api/testdata/infinite-loop-process/infinite-loop.qbs +++ b/tests/auto/api/testdata/infinite-loop-process/infinite-loop.qbs @@ -14,10 +14,7 @@ Project { Depends { name: "infinite-loop" } Rule { inputsFromDependencies: "application" - Artifact { - filePath: "dummy" - fileTags: "mytype" - } + outputFileTags: "mytype" prepare: { var cmd = new Command(inputs["application"][0].filePath); cmd.description = "Calling application that runs forever"; diff --git a/tests/auto/api/testdata/installed-artifact/installed-artifact.qbs b/tests/auto/api/testdata/installed-artifact/installed-artifact.qbs index e2d18b2ea..4a355c385 100644 --- a/tests/auto/api/testdata/installed-artifact/installed-artifact.qbs +++ b/tests/auto/api/testdata/installed-artifact/installed-artifact.qbs @@ -18,11 +18,8 @@ Project { qbs.installDir: "src" } qbs.installPrefix: "/usr" - Group { - fileTagsFilter: "application" - qbs.install: true - qbs.installDir: "bin" - } + install: true + installDir: "bin" Group { fileTagsFilter: "obj" qbs.install: true diff --git a/tests/auto/api/testdata/multi-arch/multi-arch.qbs b/tests/auto/api/testdata/multi-arch/multi-arch.qbs index d54809a41..99d9aa817 100644 --- a/tests/auto/api/testdata/multi-arch/multi-arch.qbs +++ b/tests/auto/api/testdata/multi-arch/multi-arch.qbs @@ -14,6 +14,7 @@ Project { files: "host+target.input" fileTags: "input" } + qbs.installPrefix: "" Group { fileTagsFilter: "output" qbs.install: true @@ -28,6 +29,7 @@ Project { files: "host-tool.input" fileTags: "input" } + qbs.installPrefix: "" Group { fileTagsFilter: "output" qbs.install: true diff --git a/tests/auto/api/testdata/process-result/process-result.qbs b/tests/auto/api/testdata/process-result/process-result.qbs index 2aaf0626e..24fc595bc 100644 --- a/tests/auto/api/testdata/process-result/process-result.qbs +++ b/tests/auto/api/testdata/process-result/process-result.qbs @@ -15,11 +15,7 @@ Project { property int argument Rule { inputsFromDependencies: ["application"] - Artifact { - filePath: "dummy" - fileTags: product.type - alwaysUpdated: false - } + outputFileTags: "mytype" prepare: { var cmd = new Command(inputs["application"][0].filePath, [product.argument]); if (product.redirectStdout) diff --git a/tests/auto/api/testdata/recursive-wildcards/recursive-wildcards.qbs b/tests/auto/api/testdata/recursive-wildcards/recursive-wildcards.qbs index a1970e1c4..df54577f6 100644 --- a/tests/auto/api/testdata/recursive-wildcards/recursive-wildcards.qbs +++ b/tests/auto/api/testdata/recursive-wildcards/recursive-wildcards.qbs @@ -1,4 +1,5 @@ Product { + qbs.installPrefix: "" Group { files: "dir/**" qbs.install: true diff --git a/tests/auto/api/testdata/tool-in-module/use-within-project/use-within-project.qbs b/tests/auto/api/testdata/tool-in-module/use-within-project/use-within-project.qbs index bd480fb08..bbeb29664 100644 --- a/tests/auto/api/testdata/tool-in-module/use-within-project/use-within-project.qbs +++ b/tests/auto/api/testdata/tool-in-module/use-within-project/use-within-project.qbs @@ -3,12 +3,15 @@ import qbs Project { CppApplication { name: "thetool" + consoleApplication: true files: "main.cpp" + install: true + installDir: "" + qbs.installPrefix: "" Group { fileTagsFilter: ["application"] fileTags: ["thetool.thetool"] - qbs.install: true } Export { diff --git a/tests/auto/blackbox/blackbox-android.pro b/tests/auto/blackbox/blackbox-android.pro index d27550301..7aca99e8d 100644 --- a/tests/auto/blackbox/blackbox-android.pro +++ b/tests/auto/blackbox/blackbox-android.pro @@ -16,3 +16,6 @@ for(data_dir, DATA_DIRS) { } OTHER_FILES += $$FILES + +DISTFILES += \ + testdata/texttemplate/expected-output-one.txt diff --git a/tests/auto/blackbox/testdata-apple/apple-dmg/apple-dmg.qbs b/tests/auto/blackbox/testdata-apple/apple-dmg/apple-dmg.qbs index 3bccebfd0..010e5f7c7 100644 --- a/tests/auto/blackbox/testdata-apple/apple-dmg/apple-dmg.qbs +++ b/tests/auto/blackbox/testdata-apple/apple-dmg/apple-dmg.qbs @@ -18,12 +18,7 @@ Project { targetName: "My Great App" files: ["main.c"] - Group { - fileTagsFilter: ["bundle.content"] - qbs.install: true - qbs.installDir: "/Applications" - qbs.installSourceBase: product.buildDirectory - } + install: true } AppleDiskImage { diff --git a/tests/auto/blackbox/testdata-apple/apple-multiconfig/apple-multiconfig.qbs b/tests/auto/blackbox/testdata-apple/apple-multiconfig/apple-multiconfig.qbs index ae2fcd402..ea67b6e44 100644 --- a/tests/auto/blackbox/testdata-apple/apple-multiconfig/apple-multiconfig.qbs +++ b/tests/auto/blackbox/testdata-apple/apple-multiconfig/apple-multiconfig.qbs @@ -17,11 +17,8 @@ Project { aggregate: false multiplexByQbsProperties: [] - Group { - fileTagsFilter: ["bundle.content"] - qbs.install: true - qbs.installSourceBase: product.buildDirectory - } + install: true + installDir: "" } CppApplication { @@ -38,11 +35,8 @@ Project { qbs.architectures: ["x86_64"] qbs.buildVariants: ["release"] - Group { - fileTagsFilter: ["bundle.content"] - qbs.install: true - qbs.installSourceBase: product.buildDirectory - } + install: true + installDir: "" } DynamicLibrary { @@ -58,11 +52,8 @@ Project { aggregate: false multiplexByQbsProperties: [] - Group { - fileTagsFilter: ["bundle.content"] - qbs.install: true - qbs.installSourceBase: product.buildDirectory - } + install: true + installDir: "" } CppApplication { @@ -74,11 +65,8 @@ Project { cpp.rpaths: [cpp.rpathOrigin + "/../../../"] cpp.minimumMacosVersion: "10.5" - Group { - fileTagsFilter: ["bundle.content"] - qbs.install: true - qbs.installSourceBase: product.buildDirectory - } + install: true + installDir: "" } CppApplication { @@ -91,11 +79,8 @@ Project { cpp.minimumMacosVersion: "10.5" qbs.architectures: ["x86", "x86_64"] - Group { - fileTagsFilter: ["bundle.content"] - qbs.install: true - qbs.installSourceBase: product.buildDirectory - } + install: true + installDir: "" } CppApplication { @@ -109,11 +94,8 @@ Project { qbs.architectures: ["x86", "x86_64"] qbs.buildVariants: ["debug", "profile"] - Group { - fileTagsFilter: ["bundle.content"] - qbs.install: true - qbs.installSourceBase: product.buildDirectory - } + install: true + installDir: "" } DynamicLibrary { @@ -127,11 +109,8 @@ Project { qbs.architectures: ["x86", "x86_64"] qbs.buildVariants: ["release", "debug", "profile"] - Group { - fileTagsFilter: ["bundle.content"] - qbs.install: true - qbs.installSourceBase: product.buildDirectory - } + install: true + installDir: "" } DynamicLibrary { @@ -145,11 +124,8 @@ Project { qbs.architectures: ["x86", "x86_64"] qbs.buildVariants: ["debug", "profile"] - Group { - fileTagsFilter: ["bundle.content"] - qbs.install: true - qbs.installSourceBase: product.buildDirectory - } + install: true + installDir: "" } DynamicLibrary { @@ -162,11 +138,8 @@ Project { cpp.defines: ["VARIANT=" + Utilities.cStringQuote(qbs.buildVariant)] qbs.architectures: ["x86", "x86_64"] qbs.buildVariants: ["debug", "profile"] - Group { - fileTagsFilter: ["bundle.content"] - qbs.install: true - qbs.installSourceBase: product.buildDirectory - } + install: true + installDir: "" } DynamicLibrary { Depends { name: "cpp" } @@ -177,10 +150,7 @@ Project { cpp.defines: ["VARIANT=" + Utilities.cStringQuote(qbs.buildVariant)] qbs.architectures: ["x86", "x86_64"] qbs.buildVariants: ["debug", "profile"] - Group { - fileTagsFilter: ["bundle.content"] - qbs.install: true - qbs.installSourceBase: product.buildDirectory - } + install: true + installDir: "" } } diff --git a/tests/auto/blackbox/testdata-apple/bundle-structure/bundle-structure.qbs b/tests/auto/blackbox/testdata-apple/bundle-structure/bundle-structure.qbs index a7c3e20bf..13a205730 100644 --- a/tests/auto/blackbox/testdata-apple/bundle-structure/bundle-structure.qbs +++ b/tests/auto/blackbox/testdata-apple/bundle-structure/bundle-structure.qbs @@ -17,11 +17,8 @@ Project { bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] files: ["dummy.c"] - Group { - fileTagsFilter: product.type.concat(project.bundleFileTags) - qbs.install: true - qbs.installSourceBase: product.buildDirectory - } + install: true + installDir: "" } Application { @@ -37,11 +34,8 @@ Project { bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] files: ["dummy.c"] - Group { - fileTagsFilter: product.type.concat(project.bundleFileTags) - qbs.install: true - qbs.installSourceBase: product.buildDirectory - } + install: true + installDir: "" } Application { @@ -57,11 +51,8 @@ Project { bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] files: ["dummy.c"] - Group { - fileTagsFilter: product.type.concat(project.bundleFileTags) - qbs.install: true - qbs.installSourceBase: product.buildDirectory - } + install: true + installDir: "" } DynamicLibrary { @@ -73,11 +64,8 @@ Project { bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] files: ["dummy.c"] - Group { - fileTagsFilter: product.type.concat(project.bundleFileTags) - qbs.install: true - qbs.installSourceBase: product.buildDirectory - } + install: true + installDir: "" } StaticLibrary { @@ -89,11 +77,8 @@ Project { bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] files: ["dummy.c"] - Group { - fileTagsFilter: product.type.concat(project.bundleFileTags) - qbs.install: true - qbs.installSourceBase: product.buildDirectory - } + install: true + installDir: "" } LoadableModule { @@ -105,11 +90,8 @@ Project { bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] files: ["dummy.c"] - Group { - fileTagsFilter: product.type.concat(project.bundleFileTags) - qbs.install: true - qbs.installSourceBase: product.buildDirectory - } + install: true + installDir: "" } ApplicationExtension { @@ -121,11 +103,8 @@ Project { bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] files: ["dummy.c"] - Group { - fileTagsFilter: product.type.concat(project.bundleFileTags) - qbs.install: true - qbs.installSourceBase: product.buildDirectory - } + install: true + installDir: "" } XPCService { @@ -137,11 +116,8 @@ Project { bundle.privateHeaders: ["dummy_p.h"] bundle.resources: ["resource.txt"] files: ["dummy.c"] - Group { - fileTagsFilter: product.type.concat(project.bundleFileTags) - qbs.install: true - qbs.installSourceBase: product.buildDirectory - } + install: true + installDir: "" } Product { diff --git a/tests/auto/blackbox/testdata-apple/embedInfoPlist/embedInfoPlist.qbs b/tests/auto/blackbox/testdata-apple/embedInfoPlist/embedInfoPlist.qbs index c0d77aefd..87f6c1750 100644 --- a/tests/auto/blackbox/testdata-apple/embedInfoPlist/embedInfoPlist.qbs +++ b/tests/auto/blackbox/testdata-apple/embedInfoPlist/embedInfoPlist.qbs @@ -13,10 +13,8 @@ Project { bundle.infoPlist: ({ "QBS": "org.qt-project.qbs.testdata.embedInfoPlist" }) - Group { - fileTagsFilter: product.type - qbs.install: true - } + install: true + installDir: "" } DynamicLibrary { @@ -30,10 +28,8 @@ Project { bundle.infoPlist: ({ "QBS": "org.qt-project.qbs.testdata.embedInfoPlist.dylib" }) - Group { - fileTagsFilter: product.type - qbs.install: true - } + install: true + installDir: "" } LoadableModule { diff --git a/tests/auto/blackbox/testdata-java/java/vehicles.qbs b/tests/auto/blackbox/testdata-java/java/vehicles.qbs index 86d1f7d32..4051bb6e4 100644 --- a/tests/auto/blackbox/testdata-java/java/vehicles.qbs +++ b/tests/auto/blackbox/testdata-java/java/vehicles.qbs @@ -14,10 +14,9 @@ Project { name: "native" files: ["engine.c"] - Group { - fileTagsFilter: ["dynamiclibrary"] - qbs.install: true - } + qbs.installPrefix: "" + install: true + installDir: "" } JavaClassCollection { @@ -44,6 +43,7 @@ Project { name: "random_stuff" files: ["RandomStuff.java"] + qbs.installPrefix: "" Group { fileTagsFilter: ["java.jar"] qbs.install: true @@ -78,6 +78,7 @@ Project { java.manifestClassPath: [product.targetName + ".jar"] } + qbs.installPrefix: "" Group { fileTagsFilter: ["java.jar"] qbs.install: true @@ -98,6 +99,7 @@ Project { return mf; } + qbs.installPrefix: "" Group { fileTagsFilter: ["java.jar"] qbs.install: true diff --git a/tests/auto/blackbox/testdata-qt/cached-qml/cached-qml.qbs b/tests/auto/blackbox/testdata-qt/cached-qml/cached-qml.qbs index 5117557e1..397c2a691 100644 --- a/tests/auto/blackbox/testdata-qt/cached-qml/cached-qml.qbs +++ b/tests/auto/blackbox/testdata-qt/cached-qml/cached-qml.qbs @@ -3,9 +3,13 @@ import qbs.Utilities CppApplication { name: "app" + consoleApplication: true Depends { name: "Qt.core" } Depends { name: "Qt.quick" } Depends { name: "Qt.qml" } + install: true + installDir: "" + qbs.installPrefix: "" Qt.qml.generateCacheFiles: true Qt.qml.cacheFilesInstallDir: "data" @@ -16,11 +20,6 @@ CppApplication { "stuff.js" ] - Group { - fileTagsFilter: ["application"] - qbs.install: true - } - // Install the C++ sources to tell the blackbox test that Qt.qmlcache is not available. Group { condition: !Qt.qml.cachingEnabled diff --git a/tests/auto/blackbox/testdata-qt/qtscxml/qtscxml.qbs b/tests/auto/blackbox/testdata-qt/qtscxml/qtscxml.qbs index e010e76e6..4a26550b7 100644 --- a/tests/auto/blackbox/testdata-qt/qtscxml/qtscxml.qbs +++ b/tests/auto/blackbox/testdata-qt/qtscxml/qtscxml.qbs @@ -29,10 +29,7 @@ Project { Depends { name: "app" } Rule { inputsFromDependencies: ["application"] - Artifact { - filePath: "dummy" - fileTags: ["runner"] - } + outputFileTags: ["runner"] prepare: { var cmd = new Command(input.filePath); cmd.description = "running " + input.filePath; diff --git a/tests/auto/blackbox/testdata/QTBUG-51237/qtbug-51237.qbs b/tests/auto/blackbox/testdata/QTBUG-51237/qtbug-51237.qbs index 6edea9dc6..33539a5a1 100644 --- a/tests/auto/blackbox/testdata/QTBUG-51237/qtbug-51237.qbs +++ b/tests/auto/blackbox/testdata/QTBUG-51237/qtbug-51237.qbs @@ -5,10 +5,7 @@ Product { Depends { name: "mymodule" } Rule { multiplex: true - Artifact { - filePath: "dummy.custom" - fileTags: ["custom"] - } + outputFileTags: ["custom"] prepare: { var theProperty = product.mymodule.theProperty; if (!theProperty) diff --git a/tests/auto/blackbox/testdata/artifacts-map-race-condition/artifacts-map-race-condition.qbs b/tests/auto/blackbox/testdata/artifacts-map-race-condition/artifacts-map-race-condition.qbs index 0ab4cea88..af568ae45 100644 --- a/tests/auto/blackbox/testdata/artifacts-map-race-condition/artifacts-map-race-condition.qbs +++ b/tests/auto/blackbox/testdata/artifacts-map-race-condition/artifacts-map-race-condition.qbs @@ -5,7 +5,7 @@ Product { type: ["custom1", "custom2", "custom3", "custom4", "custom5"] Rule { multiplex: true - Artifact { filePath: "dummy"; fileTags: "custom1" } + outputFileTags: "custom1" prepare: { var cmd = new JavaScriptCommand(); cmd.description = "reader1"; @@ -24,7 +24,7 @@ Product { } Rule { multiplex: true - Artifact { filePath: "helperdummy"; fileTags: "helper" } + outputFileTags: "helper" prepare: { var cmd = new JavaScriptCommand(); cmd.description = "helper"; @@ -55,7 +55,7 @@ Product { } Rule { multiplex: true - Artifact { filePath: "dummy2"; fileTags: "custom5" } + outputFileTags: "custom5" prepare: { var cmd = new JavaScriptCommand(); cmd.description = "reader2"; 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 6850ee138..682b4c029 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 @@ -6,18 +6,18 @@ Project { name: "helper-app" type: ["application", "test-helper"] consoleApplication: true + install: true files: "helper-main.cpp" cpp.executableSuffix: ".exe" Group { fileTagsFilter: "application" fileTags: "test-helper" - qbs.install: true - qbs.installDir: "bin" } } CppApplication { name: "test-app" type: ["application", "autotest"] + Depends { name: "autotest" } files: "test-main.cpp" } diff --git a/tests/auto/blackbox/testdata/autotests/autotests.qbs b/tests/auto/blackbox/testdata/autotests/autotests.qbs new file mode 100644 index 000000000..b08bc425c --- /dev/null +++ b/tests/auto/blackbox/testdata/autotests/autotests.qbs @@ -0,0 +1,6 @@ +import qbs + +Project { + references: ["test1", "test2", "test3"] + AutotestRunner {} +} diff --git a/tests/auto/blackbox/testdata/autotests/test1/test1.cpp b/tests/auto/blackbox/testdata/autotests/test1/test1.cpp new file mode 100644 index 000000000..08d9d4782 --- /dev/null +++ b/tests/auto/blackbox/testdata/autotests/test1/test1.cpp @@ -0,0 +1,12 @@ +#include <cstdlib> +#include <iostream> + +int main(int argc, char *[]) +{ + if (argc != 2) { + std::cerr << "This test needs exactly one argument" << std::endl; + std::cerr << "FAIL" << std::endl; + return EXIT_FAILURE; + } + std::cout << "PASS" << std::endl; +} diff --git a/tests/auto/blackbox/testdata/autotests/test1/test1.qbs b/tests/auto/blackbox/testdata/autotests/test1/test1.qbs new file mode 100644 index 000000000..78326994d --- /dev/null +++ b/tests/auto/blackbox/testdata/autotests/test1/test1.qbs @@ -0,0 +1,11 @@ +import qbs + +CppApplication { + name: "test1" + type: base.concat("autotest") + + Depends { name: "autotest" } + autotest.arguments: "--dummy" + + files: "test1.cpp" +} diff --git a/tests/auto/blackbox/testdata/autotests/test2/test2-resource.txt b/tests/auto/blackbox/testdata/autotests/test2/test2-resource.txt new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/auto/blackbox/testdata/autotests/test2/test2-resource.txt diff --git a/tests/auto/blackbox/testdata/autotests/test2/test2.cpp b/tests/auto/blackbox/testdata/autotests/test2/test2.cpp new file mode 100644 index 000000000..dcc3d270a --- /dev/null +++ b/tests/auto/blackbox/testdata/autotests/test2/test2.cpp @@ -0,0 +1,13 @@ +#include <cstdlib> +#include <fstream> +#include <iostream> + +int main() +{ + std::ifstream input("test2-resource.txt"); + if (!input.is_open()) { + std::cerr << "Test resource not found"; + return EXIT_FAILURE; + } + std::cout << "PASS" << std::endl; +} diff --git a/tests/auto/blackbox/testdata/autotests/test2/test2.qbs b/tests/auto/blackbox/testdata/autotests/test2/test2.qbs new file mode 100644 index 000000000..0f110e1e7 --- /dev/null +++ b/tests/auto/blackbox/testdata/autotests/test2/test2.qbs @@ -0,0 +1,11 @@ +import qbs + +CppApplication { + name: "test2" + type: base.concat("autotest") + + Depends { name: "autotest" } + autotest.workingDir: sourceDirectory + + files: "test2.cpp" +} diff --git a/tests/auto/blackbox/testdata/autotests/test3/test3.cpp b/tests/auto/blackbox/testdata/autotests/test3/test3.cpp new file mode 100644 index 000000000..2ce7e2bf6 --- /dev/null +++ b/tests/auto/blackbox/testdata/autotests/test3/test3.cpp @@ -0,0 +1,9 @@ +#include <cstdlib> +#include <iostream> + +int main() +{ + std::cerr << "I am an awful test"; + std::cerr << "FAIL" << std::endl; + return EXIT_FAILURE; +} diff --git a/tests/auto/blackbox/testdata/autotests/test3/test3.qbs b/tests/auto/blackbox/testdata/autotests/test3/test3.qbs new file mode 100644 index 000000000..3c7b734e3 --- /dev/null +++ b/tests/auto/blackbox/testdata/autotests/test3/test3.qbs @@ -0,0 +1,11 @@ +import qbs + +CppApplication { + name: "test3" + type: base.concat("autotest") + + Depends { name: "autotest" } + autotest.allowFailure: true + + files: "test3.cpp" +} diff --git a/tests/auto/blackbox/testdata/build-directories/build-directories.qbs b/tests/auto/blackbox/testdata/build-directories/build-directories.qbs index dd8fc6c05..60a4e76dd 100644 --- a/tests/auto/blackbox/testdata/build-directories/build-directories.qbs +++ b/tests/auto/blackbox/testdata/build-directories/build-directories.qbs @@ -6,10 +6,7 @@ Project { type: "blubb1" Rule { multiplex: true - Artifact { - filePath: "dummy1.txt" - fileTags: product.type - } + outputFileTags: "blubb1" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; @@ -26,10 +23,7 @@ Project { Depends { name: "p1" } Rule { inputsFromDependencies: "blubb1" - Artifact { - filePath: "dummy2.txt" - fileTags: product.type - } + outputFileTags: "blubb2" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; diff --git a/tests/auto/blackbox/testdata/choose-module-instance/gerbil.txt.in b/tests/auto/blackbox/testdata/choose-module-instance/gerbil.txt.in index 53b91dbcd..4722829a3 100644 --- a/tests/auto/blackbox/testdata/choose-module-instance/gerbil.txt.in +++ b/tests/auto/blackbox/testdata/choose-module-instance/gerbil.txt.in @@ -1,5 +1,5 @@ I once had a gerbil named Bobby, Who had an unusual hobby. -He $DID on a $THING, -and now -- oh my $IDOL, +He ${DID} on a ${THING}, +and now -- oh my ${IDOL}, now all that's left is a blobby. diff --git a/tests/auto/blackbox/testdata/choose-module-instance/modules/texttemplate/texttemplate.qbs b/tests/auto/blackbox/testdata/choose-module-instance/modules/texttemplate/texttemplate.qbs deleted file mode 100644 index aca755373..000000000 --- a/tests/auto/blackbox/testdata/choose-module-instance/modules/texttemplate/texttemplate.qbs +++ /dev/null @@ -1,49 +0,0 @@ -import qbs.TextFile - -Module { - property var dict: ({}) - FileTagger { - patterns: ["*.in"] - fileTags: ["texttemplate.input"] - } - Rule { - inputs: ["texttemplate.input"] - Artifact { - fileTags: ["text"] - filePath: input.completeBaseName - } - prepare: { - var cmd = new JavaScriptCommand(); - cmd.silent = true; - cmd.sourceCode = function() { - try { - var src = new TextFile(input.filePath, TextFile.ReadOnly); - var dst = new TextFile(output.filePath, TextFile.WriteOnly); - var rex = /\$([A-Z]+)/g; - while (!src.atEof()) { - rex.lastIndex = 0; - var line = src.readLine(); - while (true) { - var result = rex.exec(line); - if (!result) - break; - var replacement = input.texttemplate.dict[result[1]]; - if (replacement) { - line = line.substr(0, result.index) - + replacement - + line.substr(result.index + result[0].length); - } - } - dst.writeLine(line); - } - } finally { - if (src) - src.close(); - if (dst) - dst.close(); - } - }; - return [cmd]; - } - } -} diff --git a/tests/auto/blackbox/testdata/concurrent-executor/concurrent-executor.qbs b/tests/auto/blackbox/testdata/concurrent-executor/concurrent-executor.qbs index 9031890bd..99fec93f2 100644 --- a/tests/auto/blackbox/testdata/concurrent-executor/concurrent-executor.qbs +++ b/tests/auto/blackbox/testdata/concurrent-executor/concurrent-executor.qbs @@ -52,10 +52,7 @@ Product { } Rule { inputs: ["intermediate"] - Artifact { - filePath: "dummy2.final" - fileTags: ["final2"] - } + outputFileTags: "final2" prepare: { do Utils.sleep(6000); diff --git a/tests/auto/blackbox/testdata/discard-unused-data/discard-unused-data.qbs b/tests/auto/blackbox/testdata/discard-unused-data/discard-unused-data.qbs index 6f433cf63..b7cca4fa8 100644 --- a/tests/auto/blackbox/testdata/discard-unused-data/discard-unused-data.qbs +++ b/tests/auto/blackbox/testdata/discard-unused-data/discard-unused-data.qbs @@ -14,10 +14,7 @@ CppApplication { Rule { multiplex: true - Artifact { - filePath: "dummy.txt" - fileTags: ["custom"] - } + outputFileTags: "custom" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; diff --git a/tests/auto/blackbox/testdata/dynamic-library-in-module/Dll.qbs b/tests/auto/blackbox/testdata/dynamic-library-in-module/Dll.qbs index 0f897df67..565402a31 100644 --- a/tests/auto/blackbox/testdata/dynamic-library-in-module/Dll.qbs +++ b/tests/auto/blackbox/testdata/dynamic-library-in-module/Dll.qbs @@ -9,8 +9,9 @@ DynamicLibrary { cpp.minimumMacosVersion: "10.5" // For -rpath } - Group { - fileTagsFilter: ["dynamiclibrary", "dynamiclibrary_import"] - qbs.install: true - } + install: true + installImportLib: true + qbs.installPrefix: "" + installDir: "" + importLibInstallDir: "" } diff --git a/tests/auto/blackbox/testdata/env-merging/env-merging.qbs b/tests/auto/blackbox/testdata/env-merging/env-merging.qbs index 7f3f73550..884dc4745 100644 --- a/tests/auto/blackbox/testdata/env-merging/env-merging.qbs +++ b/tests/auto/blackbox/testdata/env-merging/env-merging.qbs @@ -12,10 +12,7 @@ Project { Depends { name: "tool" } Rule { inputsFromDependencies: "application" - Artifact { - filePath: "dummy" - fileTags: "custom" - } + outputFileTags: "custom" prepare: { var cmd = new Command(input.filePath, []); cmd.description = "running tool"; diff --git a/tests/auto/blackbox/testdata/erroneous/texttemplate-unknown-placeholder/boom.txt.in b/tests/auto/blackbox/testdata/erroneous/texttemplate-unknown-placeholder/boom.txt.in new file mode 100644 index 000000000..359e856ec --- /dev/null +++ b/tests/auto/blackbox/testdata/erroneous/texttemplate-unknown-placeholder/boom.txt.in @@ -0,0 +1 @@ +Boom! shake-shake-shake the ${what}! diff --git a/tests/auto/blackbox/testdata/erroneous/texttemplate-unknown-placeholder/texttemplate-unknown-placeholder.qbs b/tests/auto/blackbox/testdata/erroneous/texttemplate-unknown-placeholder/texttemplate-unknown-placeholder.qbs new file mode 100644 index 000000000..3ad31a609 --- /dev/null +++ b/tests/auto/blackbox/testdata/erroneous/texttemplate-unknown-placeholder/texttemplate-unknown-placeholder.qbs @@ -0,0 +1,8 @@ +import qbs + +Product { + type: ["text"] + Depends { name: "texttemplate" } + texttemplate.dict: ({ wat: "room" }) // typo in key name + files: [ "boom.txt.in" ] +} diff --git a/tests/auto/blackbox/testdata/exports-pkgconfig/exports-pkgconfig.qbs b/tests/auto/blackbox/testdata/exports-pkgconfig/exports-pkgconfig.qbs index 7934dc3c9..674f78c94 100644 --- a/tests/auto/blackbox/testdata/exports-pkgconfig/exports-pkgconfig.qbs +++ b/tests/auto/blackbox/testdata/exports-pkgconfig/exports-pkgconfig.qbs @@ -85,6 +85,8 @@ Project { Depends { name: "cpp" } cpp.defines: ["SECONDLIB"] + qbs.installPrefix: "" + Depends { name: "TheFirstLib" } Export { diff --git a/tests/auto/blackbox/testdata/exports-qbs/lib.qbs b/tests/auto/blackbox/testdata/exports-qbs/lib.qbs index 6ae0885d5..54f524c23 100644 --- a/tests/auto/blackbox/testdata/exports-qbs/lib.qbs +++ b/tests/auto/blackbox/testdata/exports-qbs/lib.qbs @@ -28,11 +28,9 @@ DynamicLibrary { qbs.install: true qbs.installDir: headersInstallDir } - Group { - fileTagsFilter: ["dynamiclibrary", "dynamiclibrary_import"] - qbs.install: true - qbs.installDir: "lib" - } + install: true + installImportLib: true + installDir: "lib" Group { fileTagsFilter: ["Exporter.qbs.module"] qbs.install: true diff --git a/tests/auto/blackbox/testdata/exports-qbs/tool.qbs b/tests/auto/blackbox/testdata/exports-qbs/tool.qbs index b0078a75c..01521405f 100644 --- a/tests/auto/blackbox/testdata/exports-qbs/tool.qbs +++ b/tests/auto/blackbox/testdata/exports-qbs/tool.qbs @@ -11,6 +11,7 @@ CppApplication { Depends { name: "Exporter.qbs" } Exporter.qbs.artifactTypes: ["installable", "blubb"] files: ["tool.cpp"] + install: true qbs.installPrefix: project.installPrefix Group { files: ["helper.js"] @@ -25,8 +26,6 @@ CppApplication { Group { fileTagsFilter: ["application"] - qbs.install: true - qbs.installDir: "bin" fileTags: toolTags } Group { diff --git a/tests/auto/blackbox/testdata/filetagsfilter-merging/MyApplication.qbs b/tests/auto/blackbox/testdata/filetagsfilter-merging/MyApplication.qbs new file mode 100644 index 000000000..1bd215cc6 --- /dev/null +++ b/tests/auto/blackbox/testdata/filetagsfilter-merging/MyApplication.qbs @@ -0,0 +1,11 @@ +import qbs + +CppApplication { + consoleApplication: true + Group { + fileTagsFilter: "application" + qbs.install:true + qbs.installPrefix: product.name + qbs.installDir: "wrong" + } +} diff --git a/tests/auto/blackbox/testdata/filetagsfilter-merging/filetagsfilter-merging.qbs b/tests/auto/blackbox/testdata/filetagsfilter-merging/filetagsfilter-merging.qbs new file mode 100644 index 000000000..ae1342bff --- /dev/null +++ b/tests/auto/blackbox/testdata/filetagsfilter-merging/filetagsfilter-merging.qbs @@ -0,0 +1,29 @@ +import qbs +import qbs.TextFile + +MyApplication { + name: "myapp" + type: base.concat("extra-output") + files: "main.cpp" + Group { + fileTagsFilter: "application" + qbs.installDir: "binDir" + fileTags: "extra-input" + } + Rule { + inputs: "extra-input" + Artifact { + filePath: input.baseName + ".txt" + fileTags: "extra-output" + } + prepare: { + var cmd = new JavaScriptCommand(); + cmd.description = "creating " + output.fileName; + cmd.sourceCode = function() { + var f = new TextFile(output.filePath, TextFile.WriteOnly); + f.close(); + } + return cmd; + } + } +} diff --git a/tests/auto/blackbox/testdata/filetagsfilter-merging/main.cpp b/tests/auto/blackbox/testdata/filetagsfilter-merging/main.cpp new file mode 100644 index 000000000..237c8ce18 --- /dev/null +++ b/tests/auto/blackbox/testdata/filetagsfilter-merging/main.cpp @@ -0,0 +1 @@ +int main() {} diff --git a/tests/auto/blackbox/testdata/install-locations/install-locations.qbs b/tests/auto/blackbox/testdata/install-locations/install-locations.qbs new file mode 100644 index 000000000..7bdb3f396 --- /dev/null +++ b/tests/auto/blackbox/testdata/install-locations/install-locations.qbs @@ -0,0 +1,28 @@ +import qbs + +Project { + property bool dummy: { + if (qbs.targetOS.contains("windows")) + console.info("is windows"); + else if (qbs.targetOS.contains("macos")) + console.info("is mac"); + else + console.info("is unix"); + } + CppApplication { + name: "theapp" + install: true + files: "main.cpp" + Group { + fileTagsFilter: "application" + fileTags: "some-tag" + } + } + DynamicLibrary { + name: "thelib" + install: true + installImportLib: true + Depends { name: "cpp" } + files: "thelib.cpp" + } +} diff --git a/tests/auto/blackbox/testdata/install-locations/main.cpp b/tests/auto/blackbox/testdata/install-locations/main.cpp new file mode 100644 index 000000000..237c8ce18 --- /dev/null +++ b/tests/auto/blackbox/testdata/install-locations/main.cpp @@ -0,0 +1 @@ +int main() {} diff --git a/tests/auto/blackbox/testdata/install-locations/thelib.cpp b/tests/auto/blackbox/testdata/install-locations/thelib.cpp new file mode 100644 index 000000000..d3877db26 --- /dev/null +++ b/tests/auto/blackbox/testdata/install-locations/thelib.cpp @@ -0,0 +1,3 @@ +#include "../dllexport.h" + +DLL_EXPORT void libFunc() {} diff --git a/tests/auto/blackbox/testdata/install-tree/install-tree.qbs b/tests/auto/blackbox/testdata/install-tree/install-tree.qbs index cbd7300d6..69571d58a 100644 --- a/tests/auto/blackbox/testdata/install-tree/install-tree.qbs +++ b/tests/auto/blackbox/testdata/install-tree/install-tree.qbs @@ -2,6 +2,7 @@ import qbs CppApplication { files: ["main.cpp"] + qbs.installPrefix: "" Group { files: ["data/**/*.txt"] qbs.install: true diff --git a/tests/auto/blackbox/testdata/installable-as-auxiliary-input/installable-as-auxiliary-input.qbs b/tests/auto/blackbox/testdata/installable-as-auxiliary-input/installable-as-auxiliary-input.qbs index 822473157..75ff10c80 100644 --- a/tests/auto/blackbox/testdata/installable-as-auxiliary-input/installable-as-auxiliary-input.qbs +++ b/tests/auto/blackbox/testdata/installable-as-auxiliary-input/installable-as-auxiliary-input.qbs @@ -34,6 +34,7 @@ Project { property string installDir: "include" + qbs.installPrefix: "" Group { fileTagsFilter: "header" qbs.install: true diff --git a/tests/auto/blackbox/testdata/installable/installable.qbs b/tests/auto/blackbox/testdata/installable/installable.qbs index 7ce41867b..eeb0875ad 100644 --- a/tests/auto/blackbox/testdata/installable/installable.qbs +++ b/tests/auto/blackbox/testdata/installable/installable.qbs @@ -5,15 +5,14 @@ Project { CppApplication { type: ["application"] name: "app" + consoleApplication: true Group { files: ["main.cpp"] qbs.install: true } - Group { - fileTagsFilter: ["application"] - qbs.install: true - } + install: true + installDir: "" } Product { diff --git a/tests/auto/blackbox/testdata/installed-source-files/installed-source-files.qbs b/tests/auto/blackbox/testdata/installed-source-files/installed-source-files.qbs index 1aa564553..fca3fcca3 100644 --- a/tests/auto/blackbox/testdata/installed-source-files/installed-source-files.qbs +++ b/tests/auto/blackbox/testdata/installed-source-files/installed-source-files.qbs @@ -3,6 +3,7 @@ import qbs CppApplication { consoleApplication: true files: ["main.cpp"] + qbs.installPrefix: "" Group { fileTagsFilter: ["cpp"] qbs.install: true diff --git a/tests/auto/blackbox/testdata/installed-transformer-output/qbs668.qbs b/tests/auto/blackbox/testdata/installed-transformer-output/qbs668.qbs index 99acc5585..244f80abe 100644 --- a/tests/auto/blackbox/testdata/installed-transformer-output/qbs668.qbs +++ b/tests/auto/blackbox/testdata/installed-transformer-output/qbs668.qbs @@ -4,6 +4,7 @@ import qbs.TextFile Product { name: "install-test" type: ["text"] + qbs.installPrefix: "" Group { qbs.install: true qbs.installDir: "textfiles" diff --git a/tests/auto/blackbox/testdata/invalid-install-dir/invalid-install-dir.qbs b/tests/auto/blackbox/testdata/invalid-install-dir/invalid-install-dir.qbs index f4a608904..ffa92dabb 100644 --- a/tests/auto/blackbox/testdata/invalid-install-dir/invalid-install-dir.qbs +++ b/tests/auto/blackbox/testdata/invalid-install-dir/invalid-install-dir.qbs @@ -3,9 +3,7 @@ import qbs CppApplication { consoleApplication: true files: ["main.cpp"] - Group { - fileTagsFilter: ["application"] - qbs.install: true - qbs.installDir: "../whatever" - } + qbs.installPrefix: "" + install: true + installDir: "../whatever" } diff --git a/tests/auto/blackbox/testdata/jsextensions-binaryfile/binaryfile.qbs b/tests/auto/blackbox/testdata/jsextensions-binaryfile/binaryfile.qbs index 7d3ada851..bf6d4a4cf 100644 --- a/tests/auto/blackbox/testdata/jsextensions-binaryfile/binaryfile.qbs +++ b/tests/auto/blackbox/testdata/jsextensions-binaryfile/binaryfile.qbs @@ -5,10 +5,7 @@ Product { type: ["dummy"] Rule { multiplex: true - Artifact { - filePath: "dummy.dat" - fileTags: ["dummy"] - } + outputFileTags: "dummy" prepare: { var commands = []; var cmd = new JavaScriptCommand(); diff --git a/tests/auto/blackbox/testdata/jsextensions-file/file.qbs b/tests/auto/blackbox/testdata/jsextensions-file/file.qbs index 2b0ec8de1..93b61d38d 100644 --- a/tests/auto/blackbox/testdata/jsextensions-file/file.qbs +++ b/tests/auto/blackbox/testdata/jsextensions-file/file.qbs @@ -7,10 +7,7 @@ Product { type: ["dummy"] Rule { multiplex: true - Artifact { - filePath: "dummy.txt" - fileTags: ["dummy"] - } + outputFileTags: "dummy" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; diff --git a/tests/auto/blackbox/testdata/jsextensions-fileinfo/fileinfo.qbs b/tests/auto/blackbox/testdata/jsextensions-fileinfo/fileinfo.qbs index cf28b4014..99d872b19 100644 --- a/tests/auto/blackbox/testdata/jsextensions-fileinfo/fileinfo.qbs +++ b/tests/auto/blackbox/testdata/jsextensions-fileinfo/fileinfo.qbs @@ -6,10 +6,7 @@ Product { type: ["dummy"] Rule { multiplex: true - Artifact { - filePath: "dummy.txt" - fileTags: ["dummy"] - } + outputFileTags: "dummy" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; diff --git a/tests/auto/blackbox/testdata/jsextensions-process/process.qbs b/tests/auto/blackbox/testdata/jsextensions-process/process.qbs index c9c832ba4..730468b3a 100644 --- a/tests/auto/blackbox/testdata/jsextensions-process/process.qbs +++ b/tests/auto/blackbox/testdata/jsextensions-process/process.qbs @@ -13,10 +13,7 @@ Project { Rule { multiplex: true inputs: ["application"] - Artifact { - filePath: "dummy.txt" - fileTags: ["dummy"] - } + outputFileTags: "dummy" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; diff --git a/tests/auto/blackbox/testdata/jsextensions-textfile/textfile.qbs b/tests/auto/blackbox/testdata/jsextensions-textfile/textfile.qbs index ef433a1e4..44c142745 100644 --- a/tests/auto/blackbox/testdata/jsextensions-textfile/textfile.qbs +++ b/tests/auto/blackbox/testdata/jsextensions-textfile/textfile.qbs @@ -5,10 +5,7 @@ Product { type: ["dummy"] Rule { multiplex: true - Artifact { - filePath: "dummy.txt" - fileTags: ["dummy"] - } + outputFileTags: "dummy" prepare: { var commands = []; var cmd = new JavaScriptCommand(); diff --git a/tests/auto/blackbox/testdata/linkerscripts/linkerscripts.qbs b/tests/auto/blackbox/testdata/linkerscripts/linkerscripts.qbs index 42b3884ea..1601baf3c 100644 --- a/tests/auto/blackbox/testdata/linkerscripts/linkerscripts.qbs +++ b/tests/auto/blackbox/testdata/linkerscripts/linkerscripts.qbs @@ -12,10 +12,7 @@ DynamicLibrary { Rule { multiplex: true - Artifact { - filePath: "dummy.txt" - fileTags: ["custom"] - } + outputFileTags: "custom" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; @@ -26,8 +23,7 @@ DynamicLibrary { } } - Group { - fileTagsFilter: ["dynamiclibrary"] - qbs.install: true - } + qbs.installPrefix: "" + install: true + installDir: "" } diff --git a/tests/auto/blackbox/testdata/list-properties-with-outer/modules/lower/lower.qbs b/tests/auto/blackbox/testdata/list-properties-with-outer/modules/lower/lower.qbs index 3d5824bc2..6f9597788 100644 --- a/tests/auto/blackbox/testdata/list-properties-with-outer/modules/lower/lower.qbs +++ b/tests/auto/blackbox/testdata/list-properties-with-outer/modules/lower/lower.qbs @@ -5,10 +5,7 @@ Module { Rule { inputs: ["intype"] - Artifact { - filePath: "dummy.out" - fileTags: ["outtype"] - } + outputFileTags: "outtype" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; diff --git a/tests/auto/blackbox/testdata/makefile-generator/app.qbs b/tests/auto/blackbox/testdata/makefile-generator/app.qbs index 103f71ecf..c0f423d5c 100644 --- a/tests/auto/blackbox/testdata/makefile-generator/app.qbs +++ b/tests/auto/blackbox/testdata/makefile-generator/app.qbs @@ -14,9 +14,5 @@ CppApplication { files: "main.cpp" qbs.installPrefix: "/usr/local" - Group { - fileTagsFilter: "application" - qbs.install: true - qbs.installDir: "bin" - } + install: true } diff --git a/tests/auto/blackbox/testdata/nested-properties/modules/lowerlevel/lower-level.qbs b/tests/auto/blackbox/testdata/nested-properties/modules/lowerlevel/lower-level.qbs index 6b2d00587..60ddc219b 100644 --- a/tests/auto/blackbox/testdata/nested-properties/modules/lowerlevel/lower-level.qbs +++ b/tests/auto/blackbox/testdata/nested-properties/modules/lowerlevel/lower-level.qbs @@ -7,10 +7,7 @@ Module { Rule { inputs: ["dummy-input"] - Artifact { - filePath: "dummy.out" - fileTags: "mytype" - } + outputFileTags: "mytype" prepare: { var cmd = new JavaScriptCommand(); cmd.sourceCode = function() { }; diff --git a/tests/auto/blackbox/testdata/new-output-artifact/new-output-artifact.qbs b/tests/auto/blackbox/testdata/new-output-artifact/new-output-artifact.qbs index 10e0e4305..fa70aee8d 100644 --- a/tests/auto/blackbox/testdata/new-output-artifact/new-output-artifact.qbs +++ b/tests/auto/blackbox/testdata/new-output-artifact/new-output-artifact.qbs @@ -9,6 +9,7 @@ Product { files: ["input.txt"] fileTags: ["input"] } + qbs.installPrefix: "" Group { fileTagsFilter: product.type qbs.install: true diff --git a/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/modules/themodule/themodule.qbs b/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/modules/themodule/themodule.qbs index 2b33922a2..ecbfd6c9d 100644 --- a/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/modules/themodule/themodule.qbs +++ b/tests/auto/blackbox/testdata/pkg-config-probe-sysroot/modules/themodule/themodule.qbs @@ -11,10 +11,7 @@ Module { Rule { multiplex: true - Artifact { - filePath: "dummy.out" - fileTags: ["theType"] - } + outputFileTags: "theType" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; diff --git a/tests/auto/blackbox/testdata/pkg-config-probe/modules/themodule/themodule.qbs b/tests/auto/blackbox/testdata/pkg-config-probe/modules/themodule/themodule.qbs index 81dfa955f..8edd218c3 100644 --- a/tests/auto/blackbox/testdata/pkg-config-probe/modules/themodule/themodule.qbs +++ b/tests/auto/blackbox/testdata/pkg-config-probe/modules/themodule/themodule.qbs @@ -18,10 +18,7 @@ Module { Rule { multiplex: true - Artifact { - filePath: "dummy.out" - fileTags: ["theType"] - } + outputFileTags: "theType" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; diff --git a/tests/auto/blackbox/testdata/probe-in-exported-module/modules/depmodule/depmodule.qbs b/tests/auto/blackbox/testdata/probe-in-exported-module/modules/depmodule/depmodule.qbs index b880d6dac..a9a27edb4 100644 --- a/tests/auto/blackbox/testdata/probe-in-exported-module/modules/depmodule/depmodule.qbs +++ b/tests/auto/blackbox/testdata/probe-in-exported-module/modules/depmodule/depmodule.qbs @@ -6,10 +6,7 @@ Module { Rule { inputs: ["dep-in"] - Artifact { - filePath: "dummy.txt" - fileTags: ["dep-out"] - } + outputFileTags: "dep-out" prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Creating dep-out artifact"; diff --git a/tests/auto/blackbox/testdata/probe-in-exported-module/modules/mymodule/mymodule.qbs b/tests/auto/blackbox/testdata/probe-in-exported-module/modules/mymodule/mymodule.qbs index 9f3657f34..622dcf0ec 100644 --- a/tests/auto/blackbox/testdata/probe-in-exported-module/modules/mymodule/mymodule.qbs +++ b/tests/auto/blackbox/testdata/probe-in-exported-module/modules/mymodule/mymodule.qbs @@ -12,10 +12,7 @@ Module { Rule { inputs: ["in"] - Artifact { - filePath: "dummy2.txt" - fileTags: ["out"] - } + outputFileTags: "out" prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Creating out artifact"; diff --git a/tests/auto/blackbox/testdata/probes-and-array-properties/modules/mymodule/mymodule.qbs b/tests/auto/blackbox/testdata/probes-and-array-properties/modules/mymodule/mymodule.qbs index 6479bdfac..b76cffa00 100644 --- a/tests/auto/blackbox/testdata/probes-and-array-properties/modules/mymodule/mymodule.qbs +++ b/tests/auto/blackbox/testdata/probes-and-array-properties/modules/mymodule/mymodule.qbs @@ -15,11 +15,7 @@ Module { Rule { multiplex: true - alwaysRun: true - Artifact { - filePath: "dummy" - fileTags: ["the-output"] - } + outputFileTags: "the-output" prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating dummy"; diff --git a/tests/auto/blackbox/testdata/property-precedence/modules/leaf/leaf.qbs b/tests/auto/blackbox/testdata/property-precedence/modules/leaf/leaf.qbs index 1ccc95939..741174eb2 100644 --- a/tests/auto/blackbox/testdata/property-precedence/modules/leaf/leaf.qbs +++ b/tests/auto/blackbox/testdata/property-precedence/modules/leaf/leaf.qbs @@ -6,11 +6,7 @@ Module { Rule { inputs: ["rule-input"] - Artifact { - filePath: "dummy" - fileTags: ["rule-output"] - alwaysUpdated: false - } + outputFileTags: "rule-output" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; diff --git a/tests/auto/blackbox/testdata/recursive_renaming/recursive_renaming.qbs b/tests/auto/blackbox/testdata/recursive_renaming/recursive_renaming.qbs index 5c2c4ec48..0ed6fa72f 100644 --- a/tests/auto/blackbox/testdata/recursive_renaming/recursive_renaming.qbs +++ b/tests/auto/blackbox/testdata/recursive_renaming/recursive_renaming.qbs @@ -1,6 +1,7 @@ import qbs 1.0 Product { + qbs.installPrefix: "" Group { qbs.install: true qbs.installSourceBase: "." diff --git a/tests/auto/blackbox/testdata/recursive_wildcards/recursive_wildcards.qbs b/tests/auto/blackbox/testdata/recursive_wildcards/recursive_wildcards.qbs index 703a65e0e..dc993ae23 100644 --- a/tests/auto/blackbox/testdata/recursive_wildcards/recursive_wildcards.qbs +++ b/tests/auto/blackbox/testdata/recursive_wildcards/recursive_wildcards.qbs @@ -3,6 +3,7 @@ import qbs.TextFile Product { type: ["txt.out"] + qbs.installPrefix: "" Group { files: "dir/**" qbs.install: true diff --git a/tests/auto/blackbox/testdata/response-files/response-files.qbs b/tests/auto/blackbox/testdata/response-files/response-files.qbs index 73eb720fe..1e1e75314 100644 --- a/tests/auto/blackbox/testdata/response-files/response-files.qbs +++ b/tests/auto/blackbox/testdata/response-files/response-files.qbs @@ -13,6 +13,7 @@ Project { type: ["text"] Depends { name: "cpp" } Depends { name: "cat-response-file" } + qbs.installPrefix: "" Group { fileTagsFilter: ["text"] qbs.install: true 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 9f841effd..8a5312d75 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 @@ -8,12 +8,11 @@ Project { files: ["lib1.cpp"] - Group { - condition: !qbs.targetOS.contains("darwin") - fileTagsFilter: ["dynamiclibrary", "dynamiclibrary_import"] - qbs.install: true - qbs.installDir: "/lib1" - } + install: !qbs.targetOS.contains("darwin") + installImportLib: true + installDir: "lib1" + importLibInstallDir: installDir + Group { condition: qbs.targetOS.contains("darwin") fileTagsFilter: ["bundle.content"] @@ -41,16 +40,15 @@ Project { files: ["lib3.cpp"] - Properties { + Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } - Group { - fileTagsFilter: ["dynamiclibrary", "dynamiclibrary_import"] - qbs.install: true - qbs.installDir: "/lib3" - } + install: true + installImportLib: true + installDir: "lib3" + importLibInstallDir: installDir } DynamicLibrary { // Non-dependency, referred to by name @@ -59,16 +57,15 @@ Project { files: ["lib4.cpp"] - Properties { + Properties { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false } - Group { - fileTagsFilter: ["dynamiclibrary", "dynamiclibrary_import"] - qbs.install: true - qbs.installDir: "/lib4" - } + install: true + installImportLib: true + installDir: "lib4" + importLibInstallDir: installDir } DynamicLibrary { // Recursive product dependency diff --git a/tests/auto/blackbox/testdata/suspicious-calls/copy-command.qbs b/tests/auto/blackbox/testdata/suspicious-calls/copy-command.qbs index e01435fc0..f913a8efb 100644 --- a/tests/auto/blackbox/testdata/suspicious-calls/copy-command.qbs +++ b/tests/auto/blackbox/testdata/suspicious-calls/copy-command.qbs @@ -9,10 +9,7 @@ Product { } Rule { inputs: ["in"] - Artifact { - filePath: "dummy.txt" - fileTags: ["out"] - } + outputFileTags: "out" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; diff --git a/tests/auto/blackbox/testdata/suspicious-calls/copy-prepare.qbs b/tests/auto/blackbox/testdata/suspicious-calls/copy-prepare.qbs index b6098e8de..b3d402062 100644 --- a/tests/auto/blackbox/testdata/suspicious-calls/copy-prepare.qbs +++ b/tests/auto/blackbox/testdata/suspicious-calls/copy-prepare.qbs @@ -9,10 +9,7 @@ Product { } Rule { inputs: ["in"] - Artifact { - filePath: "dummy.txt" - fileTags: ["out"] - } + outputFileTags: "out" prepare: { File.copy(input.filePath, output.filePath); var cmd = new JavaScriptCommand(); diff --git a/tests/auto/blackbox/testdata/suspicious-calls/direntries-command.qbs b/tests/auto/blackbox/testdata/suspicious-calls/direntries-command.qbs index d15351c25..bb96aa1dc 100644 --- a/tests/auto/blackbox/testdata/suspicious-calls/direntries-command.qbs +++ b/tests/auto/blackbox/testdata/suspicious-calls/direntries-command.qbs @@ -9,10 +9,7 @@ Product { } Rule { inputs: ["in"] - Artifact { - filePath: "dummy.txt" - fileTags: ["out"] - } + outputFileTags: "out" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; diff --git a/tests/auto/blackbox/testdata/suspicious-calls/direntries-prepare.qbs b/tests/auto/blackbox/testdata/suspicious-calls/direntries-prepare.qbs index 6f7320110..bc439125e 100644 --- a/tests/auto/blackbox/testdata/suspicious-calls/direntries-prepare.qbs +++ b/tests/auto/blackbox/testdata/suspicious-calls/direntries-prepare.qbs @@ -9,10 +9,7 @@ Product { } Rule { inputs: ["in"] - Artifact { - filePath: "dummy.txt" - fileTags: ["out"] - } + outputFileTags: "out" prepare: { var dummy = File.directoryEntries(product.sourceDirectory, File.Files); var cmd = new JavaScriptCommand(); diff --git a/tests/auto/blackbox/testdata/symlink-removal/symlink-removal.qbs b/tests/auto/blackbox/testdata/symlink-removal/symlink-removal.qbs index fc47c450f..a2f450082 100644 --- a/tests/auto/blackbox/testdata/symlink-removal/symlink-removal.qbs +++ b/tests/auto/blackbox/testdata/symlink-removal/symlink-removal.qbs @@ -5,10 +5,7 @@ Product { type: "removal" Rule { multiplex: true - Artifact { - filePath: "dummy" - fileTags: product.type - } + outputFileTags: "removal" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; diff --git a/tests/auto/blackbox/testdata/system-run-paths/system-run-paths.qbs b/tests/auto/blackbox/testdata/system-run-paths/system-run-paths.qbs index 81778d6f7..7f9fa3000 100644 --- a/tests/auto/blackbox/testdata/system-run-paths/system-run-paths.qbs +++ b/tests/auto/blackbox/testdata/system-run-paths/system-run-paths.qbs @@ -6,6 +6,7 @@ Project { name: "theLib" type: ["dynamiclibrary"] Depends { name: "cpp" } + qbs.installPrefix: "" Group { fileTagsFilter: product.type qbs.install: true diff --git a/tests/auto/blackbox/testdata/texttemplate/cdefgabc.txt.in b/tests/auto/blackbox/testdata/texttemplate/cdefgabc.txt.in new file mode 100644 index 000000000..9e3a753bc --- /dev/null +++ b/tests/auto/blackbox/testdata/texttemplate/cdefgabc.txt.in @@ -0,0 +1 @@ +${c} ${d} ${e} ${f} ${g} ${a} ${b} ${c} diff --git a/tests/auto/blackbox/testdata/texttemplate/expected/lalala.txt b/tests/auto/blackbox/testdata/texttemplate/expected/lalala.txt new file mode 100644 index 000000000..c47434717 --- /dev/null +++ b/tests/auto/blackbox/testdata/texttemplate/expected/lalala.txt @@ -0,0 +1 @@ +do re mi fa so la ti do diff --git a/tests/auto/blackbox/testdata/texttemplate/expected/output.txt b/tests/auto/blackbox/testdata/texttemplate/expected/output.txt new file mode 100644 index 000000000..5c4b1a82a --- /dev/null +++ b/tests/auto/blackbox/testdata/texttemplate/expected/output.txt @@ -0,0 +1,12 @@ +foo bar baz +fu bar baz +foo BAR baz +foo bar buzz +fu BAR baz +fu bar buzz +fu BAR buzz +fooBARbaz +foo\BARbaz +foo\\BARbaz +foo\\\BARbaz +foo${bar}baz diff --git a/tests/auto/blackbox/testdata/texttemplate/output.txt.in b/tests/auto/blackbox/testdata/texttemplate/output.txt.in new file mode 100644 index 000000000..f5f645b73 --- /dev/null +++ b/tests/auto/blackbox/testdata/texttemplate/output.txt.in @@ -0,0 +1,12 @@ +foo bar baz +${foo} bar baz +foo ${bar} baz +foo bar ${baz} +${foo} ${bar} baz +${foo} bar ${baz} +${foo} ${bar} ${baz} +foo${bar}baz +foo\${bar}baz +foo\\${bar}baz +foo\\\${bar}baz +foo${$}{bar}baz diff --git a/tests/auto/blackbox/testdata/texttemplate/texttemplatetest.qbs b/tests/auto/blackbox/testdata/texttemplate/texttemplatetest.qbs new file mode 100644 index 000000000..8b312e7c6 --- /dev/null +++ b/tests/auto/blackbox/testdata/texttemplate/texttemplatetest.qbs @@ -0,0 +1,26 @@ +import qbs + +Product { + name: "one" + type: ["text"] + files: ["output.txt.in"] + Depends { name: "texttemplate" } + texttemplate.dict: ({ + foo: "fu", + bar: "BAR", + baz: "buzz", + }) + Group { + files: ["cdefgabc.txt.in"] + texttemplate.outputFileName: "lalala.txt" + texttemplate.dict: ({ + c: "do", + d: "re", + e: "mi", + f: "fa", + g: "so", + a: "la", + b: "ti", + }) + } +} diff --git a/tests/auto/blackbox/testdata/variant-suffix/variant-suffix.qbs b/tests/auto/blackbox/testdata/variant-suffix/variant-suffix.qbs index b919f84eb..a1dff378e 100644 --- a/tests/auto/blackbox/testdata/variant-suffix/variant-suffix.qbs +++ b/tests/auto/blackbox/testdata/variant-suffix/variant-suffix.qbs @@ -22,11 +22,8 @@ StaticLibrary { cpp.staticLibraryPrefix: "lib" cpp.staticLibrarySuffix: ".ext" - Group { - fileTagsFilter: ["staticlibrary"] - qbs.install: true - qbs.installDir: "lib" - } + qbs.installPrefix: "" + install: true Depends { name: "cpp" } diff --git a/tests/auto/blackbox/testdata/versionscript/versionscript.qbs b/tests/auto/blackbox/testdata/versionscript/versionscript.qbs index 0309d3e06..5af798f5f 100644 --- a/tests/auto/blackbox/testdata/versionscript/versionscript.qbs +++ b/tests/auto/blackbox/testdata/versionscript/versionscript.qbs @@ -12,10 +12,7 @@ DynamicLibrary { Rule { multiplex: true - Artifact { - filePath: "dummy.txt" - fileTags: ["custom"] - } + outputFileTags: "custom" prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; @@ -26,8 +23,7 @@ DynamicLibrary { } } - Group { - fileTagsFilter: ["dynamiclibrary"] - qbs.install: true - } + qbs.installPrefix: "" + install: true + installDir: "" } diff --git a/tests/auto/blackbox/testdata/wildcard_renaming/wildcard_renaming.qbs b/tests/auto/blackbox/testdata/wildcard_renaming/wildcard_renaming.qbs index 4cb2c071c..68043f991 100644 --- a/tests/auto/blackbox/testdata/wildcard_renaming/wildcard_renaming.qbs +++ b/tests/auto/blackbox/testdata/wildcard_renaming/wildcard_renaming.qbs @@ -1,6 +1,7 @@ import qbs 1.0 Product { + qbs.installPrefix: "" Group { qbs.install: true files: "*" diff --git a/tests/auto/blackbox/tst_blackbox.cpp b/tests/auto/blackbox/tst_blackbox.cpp index 6987ae662..9022bd975 100644 --- a/tests/auto/blackbox/tst_blackbox.cpp +++ b/tests/auto/blackbox/tst_blackbox.cpp @@ -258,6 +258,19 @@ void TestBlackbox::tar() QCOMPARE(listContents.readAllStandardOutput(), listFile.readAll()); } +void TestBlackbox::textTemplate() +{ + QVERIFY(QDir::setCurrent(testDataDir + "/texttemplate")); + rmDirR(relativeBuildDir()); + QCOMPARE(runQbs(), 0); + QString outputFilePath = relativeProductBuildDir("one") + "/output.txt"; + QString expectedOutputFilePath = QFINDTESTDATA("expected/output.txt"); + TEXT_FILE_COMPARE(outputFilePath, expectedOutputFilePath); + outputFilePath = relativeProductBuildDir("one") + "/lalala.txt"; + expectedOutputFilePath = QFINDTESTDATA("expected/lalala.txt"); + TEXT_FILE_COMPARE(outputFilePath, expectedOutputFilePath); +} + static QStringList sortedFileList(const QByteArray &ba) { auto list = QString::fromUtf8(ba).split(QRegExp("[\r\n]"), QString::SkipEmptyParts); @@ -460,11 +473,7 @@ void TestBlackbox::artifactsMapInvalidation() const QString projectDir = testDataDir + "/artifacts-map-invalidation"; QDir::setCurrent(projectDir); QCOMPARE(runQbs(), 0); - QFile sourceFile("file.in"); - QVERIFY2(sourceFile.open(QIODevice::ReadOnly), qPrintable(sourceFile.errorString())); - QFile generatedFile(relativeProductBuildDir("p") + "/myfile.out"); - QVERIFY2(generatedFile.open(QIODevice::ReadOnly), qPrintable(generatedFile.errorString())); - QCOMPARE(sourceFile.readAll(), generatedFile.readAll()); + TEXT_FILE_COMPARE(relativeProductBuildDir("p") + "/myfile.out", "file.in"); } void TestBlackbox::artifactsMapRaceCondition() @@ -3155,6 +3164,8 @@ void TestBlackbox::erroneousFiles_data() << "Error in Rule\\.outputArtifacts\\[0\\]\n\r?" "Property fileTags for artifact 'outputArtifacts-missing-fileTags\\.txt' " "must be a non-empty string list\\."; + QTest::newRow("texttemplate-unknown-placeholder") + << "Placeholder 'what' is not defined in textemplate.dict for 'boom.txt.in'"; } void TestBlackbox::erroneousFiles() @@ -3373,12 +3384,8 @@ void TestBlackbox::exportsPkgconfig() QCOMPARE(generatedPcFile.readAll().replace("\r", ""), sourcePcFile.readAll().replace("\r", "")); sourcePcFile.close(); generatedPcFile.close(); - sourcePcFile.setFileName("TheSecondLib.pc"); - generatedPcFilePath = relativeProductBuildDir("TheSecondLib") + "/TheSecondLib.pc"; - generatedPcFile.setFileName(generatedPcFilePath); - QVERIFY2(sourcePcFile.open(QIODevice::ReadOnly), qPrintable(sourcePcFile.errorString())); - QVERIFY2(generatedPcFile.open(QIODevice::ReadOnly), qPrintable(generatedPcFile.errorString())); - QCOMPARE(generatedPcFile.readAll(), sourcePcFile.readAll()); + TEXT_FILE_COMPARE(relativeProductBuildDir("TheSecondLib") + "/TheSecondLib.pc", + "TheSecondLib.pc"); } void TestBlackbox::exportsQbs() @@ -3486,6 +3493,17 @@ void TestBlackbox::fileDependencies() QVERIFY(!m_qbsStdout.contains("compiling zort.cpp")); } +void TestBlackbox::fileTagsFilterMerging() +{ + QDir::setCurrent(testDataDir + "/filetagsfilter-merging"); + QCOMPARE(runQbs(QStringList{"-f", "filetagsfilter-merging.qbs"}), 0); + const QString installedApp = defaultInstallRoot + "/myapp/binDir/" + + QFileInfo(relativeExecutableFilePath("myapp")).fileName(); + QVERIFY2(QFile::exists(installedApp), qPrintable(installedApp)); + const QString otherOutput = relativeProductBuildDir("myapp") + "/myapp.txt"; + QVERIFY2(QFile::exists(otherOutput), qPrintable(otherOutput)); +} + void TestBlackbox::installedTransformerOutput() { QDir::setCurrent(testDataDir + "/installed-transformer-output"); @@ -3494,6 +3512,59 @@ void TestBlackbox::installedTransformerOutput() QVERIFY2(QFile::exists(installedFilePath), qPrintable(installedFilePath)); } +void TestBlackbox::installLocations_data() +{ + QTest::addColumn<QString>("binDir"); + QTest::addColumn<QString>("dllDir"); + QTest::addColumn<QString>("libDir"); + QTest::newRow("explicit values") << QString("bindir") << QString("dlldir") << QString("libdir"); + QTest::newRow("default values") << QString() << QString() << QString(); +} + +void TestBlackbox::installLocations() +{ + QDir::setCurrent(testDataDir + "/install-locations"); + QFETCH(QString, binDir); + QFETCH(QString, dllDir); + QFETCH(QString, libDir); + QbsRunParameters params("resolve"); + if (!binDir.isEmpty()) + params.arguments.push_back("products.theapp.installDir:" + binDir); + if (!dllDir.isEmpty()) + params.arguments.push_back("products.thelib.installDir:" + dllDir); + if (!libDir.isEmpty()) + params.arguments.push_back("products.thelib.importLibInstallDir:" + libDir); + QCOMPARE(runQbs(params), 0); + const bool isWindows = m_qbsStdout.contains("is windows"); + const bool isMac = m_qbsStdout.contains("is mac"); + const bool isUnix = m_qbsStdout.contains("is unix"); + QVERIFY(isWindows || isMac || isUnix); + QCOMPARE(runQbs(QbsRunParameters(QStringList("--clean-install-root"))), 0); + const QString dllFileName = isWindows ? "thelib.dll" : isMac ? "thelib" : "libthelib.so"; + const QString appFileName = isWindows ? "theapp.exe" : "theapp"; + if (binDir.isEmpty()) + binDir = isMac ? "/Applications" : "/bin"; + if (dllDir.isEmpty()) + dllDir = isMac ? "/Library/Frameworks" : isWindows ? "/bin" : "/lib"; + if (libDir.isEmpty()) + libDir = "/lib"; + if (isMac) { + binDir += "/theapp.app/Contents/MacOS"; + dllDir += "/thelib.framework"; + } + const QString installRoot = QDir::currentPath() + "/default/install-root"; + const QString installPrefix = isWindows ? QString() : "/usr/local"; + const QString fullInstallPrefix = installRoot + '/' + installPrefix + '/'; + const QString appFilePath = fullInstallPrefix + binDir + '/' + appFileName; + QVERIFY2(QFile::exists(appFilePath), qPrintable(appFilePath)); + const QString dllFilePath = fullInstallPrefix + dllDir + '/' + dllFileName; + QVERIFY2(QFile::exists(dllFilePath), qPrintable(dllFilePath)); + if (isWindows) { + const QString libFilePath = fullInstallPrefix + libDir + "/thelib.lib"; + QVERIFY2(QFile::exists(libFilePath), qPrintable(libFilePath)); + } +} + void TestBlackbox::inputsFromDependencies() { QDir::setCurrent(testDataDir + "/inputs-from-dependencies"); @@ -3898,7 +3969,7 @@ void TestBlackbox::symbolLinkMode() QbsRunParameters params; params.command = "run"; const QStringList commonArgs{"-p", "driver", "--setup-run-env-config", - "ignore-lib-dependencies"}; + "ignore-lib-dependencies", "qbs.installPrefix:''"}; rmDirR(relativeBuildDir()); params.arguments = QStringList() << commonArgs << "project.shouldInstallLibrary:true"; @@ -3930,7 +4001,7 @@ void TestBlackbox::linkerMode() QSKIP("only applies on Unix"); QDir::setCurrent(testDataDir + "/linkerMode"); - QCOMPARE(runQbs(), 0); + QCOMPARE(runQbs(QbsRunParameters(QStringList("qbs.installPrefix:''"))), 0); auto testCondition = [&](const QString &lang, const std::function<bool(const QByteArray &)> &condition) { @@ -5082,6 +5153,44 @@ void TestBlackbox::autotestWithDependencies() && m_qbsStdout.contains("i am the helper"), m_qbsStdout.constData()); } +void TestBlackbox::autotests_data() +{ + QTest::addColumn<QString>("evilPropertySpec"); + QTest::addColumn<QByteArray>("expectedErrorMessage"); + QTest::newRow("missing arguments") << QString("products.test1.autotest.arguments:[]") + << QByteArray("This test needs exactly one argument"); + QTest::newRow("missing working dir") << QString("products.test2.autotest.workingDir:''") + << QByteArray("Test resource not found"); + QTest::newRow("missing flaky specifier") + << QString("products.test3.autotest.allowFailure:false") + << QByteArray("I am an awful test"); + QTest::newRow("everything's fine") << QString() << QByteArray(); +} + +void TestBlackbox::autotests() +{ + QDir::setCurrent(testDataDir + "/autotests"); + QFETCH(QString, evilPropertySpec); + QFETCH(QByteArray, expectedErrorMessage); + QbsRunParameters resolveParams("resolve"); + if (!evilPropertySpec.isEmpty()) + resolveParams.arguments << evilPropertySpec; + QCOMPARE(runQbs(resolveParams), 0); + QbsRunParameters testParams(QStringList{"-p", "autotest-runner"}); + if (!evilPropertySpec.isEmpty()) + testParams.expectFailure = true; + QCOMPARE(runQbs(testParams) == 0, !testParams.expectFailure); + if (testParams.expectFailure) { + QVERIFY2(m_qbsStderr.contains(expectedErrorMessage), m_qbsStderr.constData()); + return; + } + QVERIFY2(m_qbsStdout.contains("Running test test1") + && m_qbsStdout.contains("Running test test2") + && m_qbsStdout.contains("Running test test3"), m_qbsStdout.constData()); + QCOMPARE(m_qbsStdout.count("PASS"), 2); + QCOMPARE(m_qbsStderr.count("FAIL"), 1); +} + void TestBlackbox::auxiliaryInputsFromDependencies() { QDir::setCurrent(testDataDir + "/aux-inputs-from-deps"); diff --git a/tests/auto/blackbox/tst_blackbox.h b/tests/auto/blackbox/tst_blackbox.h index 35ba2c5b7..a2c021140 100644 --- a/tests/auto/blackbox/tst_blackbox.h +++ b/tests/auto/blackbox/tst_blackbox.h @@ -48,6 +48,8 @@ private slots: void artifactScanning(); void assembly(); void autotestWithDependencies(); + void autotests_data(); + void autotests(); void auxiliaryInputsFromDependencies(); void badInterpreter(); void bomSources(); @@ -111,6 +113,7 @@ private slots: void exportsQbs(); void externalLibs(); void fileDependencies(); + void fileTagsFilterMerging(); void generatedArtifactAsInputToDynamicRule(); void generator(); void generator_data(); @@ -133,6 +136,8 @@ private slots: void installDuplicatesNoError(); void installedSourceFiles(); void installedTransformerOutput(); + void installLocations_data(); + void installLocations(); void installPackage(); void installRootFromProjectFile(); void installTree(); @@ -248,6 +253,7 @@ private slots: void systemRunPaths(); void systemRunPaths_data(); void tar(); + void textTemplate(); void toolLookup(); void topLevelSearchPath(); void trackAddFile(); diff --git a/tests/auto/blackbox/tst_blackboxapple.cpp b/tests/auto/blackbox/tst_blackboxapple.cpp index 6fc526cd8..64aca99f1 100644 --- a/tests/auto/blackbox/tst_blackboxapple.cpp +++ b/tests/auto/blackbox/tst_blackboxapple.cpp @@ -77,7 +77,7 @@ void TestBlackboxApple::initTestCase() void TestBlackboxApple::appleMultiConfig() { QDir::setCurrent(testDataDir + "/apple-multiconfig"); - QCOMPARE(runQbs(), 0); + QCOMPARE(runQbs(QbsRunParameters(QStringList{"qbs.installPrefix:''"})), 0); QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp.app/Contents/MacOS/singleapp").isExecutable()); QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp.app/Contents/Info.plist").isRegularFile()); @@ -285,7 +285,7 @@ void TestBlackboxApple::bundleStructure() QFETCH(bool, isShallow); QDir::setCurrent(testDataDir + "/bundle-structure"); - QbsRunParameters params; + QbsRunParameters params(QStringList{"qbs.installPrefix:''"}); params.arguments << "project.buildableProducts:" + productName; if (isShallow) { // Coerce shallow bundles - don't set bundle.isShallow directly because we want to test the @@ -624,7 +624,7 @@ void TestBlackboxApple::embedInfoPlist() { QDir::setCurrent(testDataDir + QLatin1String("/embedInfoPlist")); - QbsRunParameters params; + QbsRunParameters params(QStringList{"qbs.installPrefix:''"}); QCOMPARE(runQbs(params), 0); QVERIFY(!getEmbeddedBinaryPlist(defaultInstallRoot + "/app").isEmpty()); diff --git a/tests/auto/language/testdata/erroneous/rule-without-output-tags.qbs b/tests/auto/language/testdata/erroneous/rule-without-output-tags.qbs new file mode 100644 index 000000000..316448858 --- /dev/null +++ b/tests/auto/language/testdata/erroneous/rule-without-output-tags.qbs @@ -0,0 +1,13 @@ +import qbs + +Product { + Rule { + inputs: "input-tag" + prepare: { + var cmd = new JavaScriptCommand; + cmd.silent = true; + cmd.sourceCode = function() {}; + return cmd; + } + } +} diff --git a/tests/auto/language/tst_language.cpp b/tests/auto/language/tst_language.cpp index f52c6ec9c..f3c510049 100644 --- a/tests/auto/language/tst_language.cpp +++ b/tests/auto/language/tst_language.cpp @@ -830,6 +830,9 @@ void TestLanguage::erroneousFiles_data() QTest::newRow("original-in-product-property") << "original-in-product-property.qbs" ":4:21.*The special value 'original' can only be used with module properties."; + QTest::newRow("rule-without-output-tags") + << "rule-without-output-tags.qbs:4:5.*A rule needs to have Artifact items or " + "a non-empty outputFileTags property."; QTest::newRow("mismatching-multiplex-dependency") << "mismatching-multiplex-dependency.qbs:9:5.*Dependency from product " "'b \\{\"architecture\":\"mips\"\\}' to product 'a \\{\"architecture\":\"mips\"\\}'" diff --git a/tests/auto/shared.h b/tests/auto/shared.h index b7a3e2b11..e049511ab 100644 --- a/tests/auto/shared.h +++ b/tests/auto/shared.h @@ -32,8 +32,10 @@ #include <tools/profile.h> #include <tools/settings.h> +#include <QtCore/qbytearray.h> #include <QtCore/qcryptographichash.h> #include <QtCore/qdatetime.h> +#include <QtCore/qdebug.h> #include <QtCore/qdir.h> #include <QtCore/qfile.h> #include <QtCore/qfileinfo.h> @@ -103,6 +105,79 @@ inline bool directoryExists(const QString &dirPath) return fi.exists() && fi.isDir(); } +struct ReadFileContentResult +{ + QByteArray content; + QString errorString; +}; + +inline ReadFileContentResult readFileContent(const QString &filePath) +{ + ReadFileContentResult result; + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly)) { + result.errorString = file.errorString(); + return result; + } + result.content = file.readAll(); + return result; +} + +inline QByteArray diffText(const QByteArray &actual, const QByteArray &expected) +{ + QByteArray result; + QList<QByteArray> actualLines = actual.split('\n'); + QList<QByteArray> expectedLines = expected.split('\n'); + int n = 1; + while (!actualLines.isEmpty() && !expectedLines.isEmpty()) { + QByteArray actualLine = actualLines.takeFirst(); + QByteArray expectedLine = expectedLines.takeFirst(); + if (actualLine != expectedLine) { + result += QStringLiteral("%1: actual: %2\n%1:expected: %3\n") + .arg(n, 2) + .arg(QString::fromUtf8(actualLine)) + .arg(QString::fromUtf8(expectedLine)) + .toUtf8(); + } + n++; + } + auto addLines = [&result, &n] (const QList<QByteArray> &lines) { + for (const QByteArray &line : qAsConst(lines)) { + result += QStringLiteral("%1: %2\n").arg(n).arg(QString::fromUtf8(line)); + n++; + } + }; + if (!actualLines.isEmpty()) { + result += "Extra unexpected lines:\n"; + addLines(actualLines); + } + if (!expectedLines.isEmpty()) { + result += "Missing expected lines:\n"; + addLines(expectedLines); + } + return result; +} + +#define READ_TEXT_FILE(filePath, contentVariable) \ + QByteArray contentVariable; \ + { \ + auto c = readFileContent(filePath); \ + QVERIFY2(c.errorString.isEmpty(), \ + qUtf8Printable(QStringLiteral("Cannot open file %1. %2") \ + .arg(filePath, c.errorString))); \ + contentVariable = std::move(c.content); \ + } + +#define TEXT_FILE_COMPARE(actualFilePath, expectedFilePath) \ + { \ + READ_TEXT_FILE(actualFilePath, ba1); \ + READ_TEXT_FILE(expectedFilePath, ba2); \ + if (ba1 != ba2) { \ + QByteArray msg = "File contents differ:\n" + diffText(ba1, ba2); \ + QFAIL(msg.constData()); \ + } \ + } + template <typename T> inline QString prefixedIfNonEmpty(const T &prefix, const QString &str) { |