diff options
Diffstat (limited to 'src/lib/corelib/buildgraph')
21 files changed, 219 insertions, 199 deletions
diff --git a/src/lib/corelib/buildgraph/abstractcommandexecutor.cpp b/src/lib/corelib/buildgraph/abstractcommandexecutor.cpp index 16c3621b6..ee82de43d 100644 --- a/src/lib/corelib/buildgraph/abstractcommandexecutor.cpp +++ b/src/lib/corelib/buildgraph/abstractcommandexecutor.cpp @@ -60,13 +60,12 @@ AbstractCommandExecutor::AbstractCommandExecutor(Logger logger, QObject *parent) , m_logger(std::move(logger)) { m_watchdog.setSingleShot(true); - connect(&m_watchdog, &QTimer::timeout, - this, [this]() { - cancel(ErrorInfo{Tr::tr("Command cancelled because it exceeded the timeout.")}); + connect(&m_watchdog, &QTimer::timeout, this, [this]() { + cancel(ErrorInfo{Tr::tr("Command cancelled because it exceeded the timeout: %1") + .arg(m_command->descriptionForCancelMessage( + m_transformer->product()->fullDisplayName()))}); }); - connect(this, &AbstractCommandExecutor::finished, - &m_watchdog, &QTimer::stop); - + connect(this, &AbstractCommandExecutor::finished, &m_watchdog, &QTimer::stop); } void AbstractCommandExecutor::start(Transformer *transformer, AbstractCommand *cmd) diff --git a/src/lib/corelib/buildgraph/artifactsscriptvalue.cpp b/src/lib/corelib/buildgraph/artifactsscriptvalue.cpp index 6a470bc17..6d0ea738f 100644 --- a/src/lib/corelib/buildgraph/artifactsscriptvalue.cpp +++ b/src/lib/corelib/buildgraph/artifactsscriptvalue.cpp @@ -135,7 +135,7 @@ static int getArtifactsPropertyNames(JSContext *ctx, JSPropertyEnum **ptab, uint if (!tags.isEmpty()) { *ptab = reinterpret_cast<JSPropertyEnum *>(js_malloc(ctx, *plen * sizeof **ptab)); JSPropertyEnum *entry = *ptab; - for (const QString &tag : qAsConst(tags)) { + for (const QString &tag : std::as_const(tags)) { entry->atom = JS_NewAtom(ctx, tag.toUtf8().constData()); entry->is_enumerable = 1; ++entry; diff --git a/src/lib/corelib/buildgraph/artifactvisitor.cpp b/src/lib/corelib/buildgraph/artifactvisitor.cpp index 22c987572..885292f06 100644 --- a/src/lib/corelib/buildgraph/artifactvisitor.cpp +++ b/src/lib/corelib/buildgraph/artifactvisitor.cpp @@ -55,7 +55,7 @@ void ArtifactVisitor::visitProduct(const ResolvedProductConstPtr &product) { if (!product->buildData) return; - for (BuildGraphNode *node : qAsConst(product->buildData->allNodes())) + for (BuildGraphNode *node : std::as_const(product->buildData->allNodes())) node->accept(this); } diff --git a/src/lib/corelib/buildgraph/buildgraph.cpp b/src/lib/corelib/buildgraph/buildgraph.cpp index df3301d57..10aae5991 100644 --- a/src/lib/corelib/buildgraph/buildgraph.cpp +++ b/src/lib/corelib/buildgraph/buildgraph.cpp @@ -283,7 +283,7 @@ private: } else { productDeps = product->dependencies; } - for (const ResolvedProductPtr &dependency : qAsConst(productDeps)) { + for (const ResolvedProductPtr &dependency : std::as_const(productDeps)) { setupBaseProductScriptValue(engine, dependency.get()); JSValue obj = JS_NewObjectClass(engine->context(), engine->productPropertyScriptClass()); @@ -520,7 +520,7 @@ bool findPath(BuildGraphNode *u, BuildGraphNode *v, QList<BuildGraphNode *> &pat return true; } - for (BuildGraphNode * const childNode : qAsConst(u->children)) { + for (BuildGraphNode * const childNode : std::as_const(u->children)) { if (findPath(childNode, v, path)) { path.prepend(u); return true; @@ -710,7 +710,7 @@ void updateArtifactFromSourceArtifact(const ResolvedProductPtr &product, const QVariantMap oldModuleProperties = artifact->properties->value(); setArtifactData(artifact, sourceArtifact); if (oldFileTags != artifact->fileTags() - || oldModuleProperties != artifact->properties->value()) { + || !qVariantMapsEqual(oldModuleProperties, artifact->properties->value())) { invalidateArtifactAsRuleInputIfNecessary(artifact); } } @@ -766,7 +766,7 @@ void updateGeneratedArtifacts(ResolvedProduct *product) provideFullFileTagsAndProperties(artifact); applyPerArtifactProperties(artifact); if (oldFileTags != artifact->fileTags() - || oldModuleProperties != artifact->properties->value()) { + || !qVariantMapsEqual(oldModuleProperties, artifact->properties->value())) { invalidateArtifactAsRuleInputIfNecessary(artifact); } } @@ -809,17 +809,17 @@ static void doSanityChecksForProduct(const ResolvedProductConstPtr &product, QBS_CHECK(buildData); if (!product->buildData) return; - for (BuildGraphNode * const node : qAsConst(buildData->rootNodes())) { + for (BuildGraphNode * const node : std::as_const(buildData->rootNodes())) { qCDebug(lcBuildGraph).noquote() << "Checking root node" << node->toString(); QBS_CHECK(buildData->allNodes().contains(node)); } Set<QString> filePaths; - for (BuildGraphNode * const node : qAsConst(buildData->allNodes())) { + for (BuildGraphNode * const node : std::as_const(buildData->allNodes())) { qCDebug(lcBuildGraph).noquote() << "Sanity checking node" << node->toString(); QBS_CHECK(node->product == product); - for (const BuildGraphNode * const parent : qAsConst(node->parents)) + for (const BuildGraphNode * const parent : std::as_const(node->parents)) QBS_CHECK(parent->children.contains(node)); - for (BuildGraphNode * const child : qAsConst(node->children)) { + for (BuildGraphNode * const child : std::as_const(node->children)) { QBS_CHECK(child->parents.contains(node)); QBS_CHECK(!child->product.expired()); QBS_CHECK(child->product->buildData); @@ -846,7 +846,7 @@ static void doSanityChecksForProduct(const ResolvedProductConstPtr &product, !filePaths.contains(artifact->filePath())); filePaths << artifact->filePath(); - for (Artifact * const child : qAsConst(artifact->childrenAddedByScanner)) + for (Artifact * const child : std::as_const(artifact->childrenAddedByScanner)) QBS_CHECK(artifact->children.contains(child)); const TransformerConstPtr transformer = artifact->transformer; if (artifact->artifactType == Artifact::SourceFile) @@ -865,7 +865,7 @@ static void doSanityChecksForProduct(const ResolvedProductConstPtr &product, qCDebug(lcBuildGraph) << "The transformer has" << transformer->outputs.size() << "outputs."; ArtifactSet transformerOutputChildren; - for (const Artifact * const output : qAsConst(transformer->outputs)) { + for (const Artifact * const output : std::as_const(transformer->outputs)) { QBS_CHECK(output->transformer == transformer); transformerOutputChildren.unite(ArtifactSet::filtered(output->children)); for (const Artifact *a : filterByType<Artifact>(output->children)) { @@ -883,14 +883,14 @@ static void doSanityChecksForProduct(const ResolvedProductConstPtr &product, } if (lcBuildGraph().isDebugEnabled()) { qCDebug(lcBuildGraph) << "The transformer output children are:"; - for (const Artifact * const a : qAsConst(transformerOutputChildren)) + for (const Artifact * const a : std::as_const(transformerOutputChildren)) qCDebug(lcBuildGraph) << "\t" << a->fileName(); qCDebug(lcBuildGraph) << "The transformer inputs are:"; - for (const Artifact * const a : qAsConst(transformer->inputs)) + for (const Artifact * const a : std::as_const(transformer->inputs)) qCDebug(lcBuildGraph) << "\t" << a->fileName(); } QBS_CHECK(transformer->inputs.size() <= transformerOutputChildren.size()); - for (Artifact * const transformerInput : qAsConst(transformer->inputs)) + for (Artifact * const transformerInput : std::as_const(transformer->inputs)) QBS_CHECK(transformerOutputChildren.contains(transformerInput)); transformer->artifactsMapRequestedInPrepareScript.doSanityChecks(); transformer->artifactsMapRequestedInCommands.doSanityChecks(); @@ -902,7 +902,7 @@ static void doSanityChecks(const ResolvedProjectPtr &project, const Logger &logger) { logger.qbsDebug() << "Sanity checking project '" << project->name << "'"; - for (const ResolvedProjectPtr &subProject : qAsConst(project->subProjects)) + for (const ResolvedProjectPtr &subProject : std::as_const(project->subProjects)) doSanityChecks(subProject, allProducts, productNames, logger); for (const auto &product : project->products) { diff --git a/src/lib/corelib/buildgraph/buildgraphloader.cpp b/src/lib/corelib/buildgraph/buildgraphloader.cpp index 9d65f42e4..ffae52ab2 100644 --- a/src/lib/corelib/buildgraph/buildgraphloader.cpp +++ b/src/lib/corelib/buildgraph/buildgraphloader.cpp @@ -39,21 +39,20 @@ #include "buildgraphloader.h" #include "buildgraph.h" -#include "cycledetector.h" #include "emptydirectoriesremover.h" #include "productbuilddata.h" #include "projectbuilddata.h" #include "rulenode.h" #include "rulecommands.h" -#include "rulesevaluationcontext.h" #include "transformer.h" +#include <buildgraph/rulesevaluationcontext.h> #include <language/artifactproperties.h> #include <language/language.h> -#include <language/loader.h> #include <language/propertymapinternal.h> #include <language/qualifiedid.h> #include <language/resolvedfilecontext.h> +#include <loader/projectresolver.h> #include <logging/categories.h> #include <logging/translator.h> #include <tools/buildgraphlocker.h> @@ -95,7 +94,7 @@ static void restoreBackPointers(const ResolvedProjectPtr &project) product->project = project; if (!product->buildData) continue; - for (BuildGraphNode * const n : qAsConst(product->buildData->allNodes())) { + for (BuildGraphNode * const n : std::as_const(product->buildData->allNodes())) { if (n->type() == BuildGraphNode::ArtifactNodeType) { project->topLevelProject()->buildData ->insertIntoLookupTable(static_cast<Artifact *>(n)); @@ -103,7 +102,7 @@ static void restoreBackPointers(const ResolvedProjectPtr &project) } } - for (const ResolvedProjectPtr &subProject : qAsConst(project->subProjects)) { + for (const ResolvedProjectPtr &subProject : std::as_const(project->subProjects)) { subProject->parentProject = project; restoreBackPointers(subProject); } @@ -129,7 +128,7 @@ BuildGraphLoadResult BuildGraphLoader::load(const TopLevelProjectPtr &existingPr if (!m_result.loadedProject) return m_result; if (parameters.restoreBehavior() == SetupProjectParameters::RestoreOnly) { - for (const ErrorInfo &e : qAsConst(m_result.loadedProject->warningsEncountered)) + for (const ErrorInfo &e : std::as_const(m_result.loadedProject->warningsEncountered)) m_logger.printWarning(e); return m_result; } @@ -220,7 +219,7 @@ bool BuildGraphLoader::checkBuildGraphCompatibility(const TopLevelProjectConstPt if (m_parameters.projectFilePath().isEmpty()) m_parameters.setProjectFilePath(project->location.filePath()); else - Loader::setupProjectFilePath(m_parameters); + m_parameters.finalizeProjectFilePath(); if (QFileInfo(project->location.filePath()) == QFileInfo(m_parameters.projectFilePath())) return true; QString message = Tr::tr("Stored build graph at '%1' is for project file '%2', but " @@ -244,7 +243,7 @@ static bool checkProductForChangedDependency(std::vector<ResolvedProductPtr> &ch return false; if (contains(changedProducts, product)) return true; - for (const ResolvedProductPtr &dep : qAsConst(product->dependencies)) { + for (const ResolvedProductPtr &dep : std::as_const(product->dependencies)) { if (checkProductForChangedDependency(changedProducts, seenProducts, dep)) { changedProducts << product; return true; @@ -269,14 +268,14 @@ static void makeChangedProductsListComplete(std::vector<ResolvedProductPtr> &cha static void updateProductAndRulePointers(const ResolvedProductPtr &newProduct) { std::unordered_map<RuleConstPtr, RuleConstPtr> ruleMap; - for (BuildGraphNode *node : qAsConst(newProduct->buildData->allNodes())) { + for (BuildGraphNode *node : std::as_const(newProduct->buildData->allNodes())) { node->product = newProduct; const auto findNewRule = [&ruleMap, &newProduct] (const RuleConstPtr &oldRule) -> RuleConstPtr { const auto it = ruleMap.find(oldRule); if (it != ruleMap.cend()) return it->second; - for (const auto &r : qAsConst(newProduct->rules)) { + for (const auto &r : std::as_const(newProduct->rules)) { if (*r == *oldRule) { ruleMap.insert(std::make_pair(oldRule, r)); return r; @@ -308,8 +307,10 @@ void BuildGraphLoader::trackProjectChanges() std::vector<ResolvedProductPtr> allRestoredProducts = restoredProject->allProducts(); std::vector<ResolvedProductPtr> changedProducts; bool reResolvingNecessary = false; - if (!checkConfigCompatibility()) + if (!checkConfigCompatibility()) { + m_logger.qbsInfo() << Tr::tr("One or more properties have changed."); reResolvingNecessary = true; + } if (hasProductFileChanged(allRestoredProducts, restoredProject->lastStartResolveTime, buildSystemFiles, changedProducts)) { reResolvingNecessary = true; @@ -330,33 +331,41 @@ void BuildGraphLoader::trackProjectChanges() } if (!reResolvingNecessary) { - for (const ErrorInfo &e : qAsConst(restoredProject->warningsEncountered)) + for (const ErrorInfo &e : std::as_const(restoredProject->warningsEncountered)) m_logger.printWarning(e); return; } + for (const QString &file : m_changedProjectFiles) { + m_logger.qbsInfo() << Tr::tr("Project file '%1' has changed.") + .arg(QDir::toNativeSeparators(file)); + } + for (const QString &file : m_removedProjectFiles) { + m_logger.qbsInfo() << Tr::tr("Project file '%1' was removed.") + .arg(QDir::toNativeSeparators(file)); + } + restoredProject->buildData->setDirty(); markTransformersForChangeTracking(allRestoredProducts); if (!m_parameters.overrideBuildGraphData()) m_parameters.setEnvironment(restoredProject->environment); - Loader ldr(m_evalContext->engine(), m_logger); - ldr.setSearchPaths(m_parameters.searchPaths()); - ldr.setProgressObserver(m_evalContext->observer()); - ldr.setOldProjectProbes(restoredProject->probes); + ProjectResolver resolver(m_parameters, m_evalContext->engine(), m_logger); + resolver.setProgressObserver(m_evalContext->observer()); + resolver.setOldProjectProbes(restoredProject->probes); if (!m_parameters.forceProbeExecution()) - ldr.setStoredModuleProviderInfo(restoredProject->moduleProviderInfo); - ldr.setLastResolveTime(restoredProject->lastStartResolveTime); + resolver.setStoredModuleProviderInfo(restoredProject->moduleProviderInfo); + resolver.setLastResolveTime(restoredProject->lastStartResolveTime); QHash<QString, std::vector<ProbeConstPtr>> restoredProbes; - for (const auto &restoredProduct : qAsConst(allRestoredProducts)) + for (const auto &restoredProduct : std::as_const(allRestoredProducts)) restoredProbes.insert(restoredProduct->uniqueName(), restoredProduct->probes); - ldr.setOldProductProbes(restoredProbes); + resolver.setOldProductProbes(restoredProbes); if (!m_parameters.overrideBuildGraphData()) - ldr.setStoredProfiles(restoredProject->profileConfigs); - m_result.newlyResolvedProject = ldr.loadProject(m_parameters); + resolver.setStoredProfiles(restoredProject->profileConfigs); + m_result.newlyResolvedProject = resolver.resolve(); std::vector<ResolvedProductPtr> allNewlyResolvedProducts = m_result.newlyResolvedProject->allProducts(); - for (const ResolvedProductPtr &cp : qAsConst(allNewlyResolvedProducts)) + for (const ResolvedProductPtr &cp : std::as_const(allNewlyResolvedProducts)) m_freshProductsByName.insert(cp->uniqueName(), cp); checkAllProductsForChanges(allRestoredProducts, changedProducts); @@ -365,7 +374,7 @@ void BuildGraphLoader::trackProjectChanges() ChildListHash childLists; if (!changedProducts.empty()) { oldBuildData = std::make_shared<ProjectBuildData>(restoredProject->buildData.get()); - for (const auto &product : qAsConst(allRestoredProducts)) { + for (const auto &product : std::as_const(allRestoredProducts)) { if (!product->buildData) continue; @@ -384,7 +393,7 @@ void BuildGraphLoader::trackProjectChanges() // mean that artifacts will have to get rebuilt; whether this is necesessary will be decided // an a per-artifact basis by the Executor on the next build. QHash<QString, AllRescuableArtifactData> rescuableArtifactData; - for (const ResolvedProductPtr &product : qAsConst(changedProducts)) { + for (const ResolvedProductPtr &product : std::as_const(changedProducts)) { const QString name = product->uniqueName(); m_changedSourcesByProduct.erase(name); m_productsWhoseArtifactsNeedUpdate.remove(name); @@ -428,7 +437,7 @@ void BuildGraphLoader::trackProjectChanges() } // Products still left in the list do not exist anymore. - for (const ResolvedProductPtr &removedProduct : qAsConst(allRestoredProducts)) { + for (const ResolvedProductPtr &removedProduct : std::as_const(allRestoredProducts)) { removeOne(changedProducts, removedProduct); onProductRemoved(removedProduct, m_result.newlyResolvedProject->buildData.get()); } @@ -454,7 +463,7 @@ void BuildGraphLoader::trackProjectChanges() updateGeneratedArtifacts(product.get()); } - for (const auto &changedProduct : qAsConst(changedProducts)) { + for (const auto &changedProduct : std::as_const(changedProducts)) { rescueOldBuildData(changedProduct, m_freshProductsByName.value(changedProduct->uniqueName()), childLists, rescuableArtifactData.value(changedProduct->uniqueName())); @@ -463,7 +472,7 @@ void BuildGraphLoader::trackProjectChanges() EmptyDirectoriesRemover(m_result.newlyResolvedProject.get(), m_logger) .removeEmptyParentDirectories(m_artifactsRemovedFromDisk); - for (FileResourceBase * const f : qAsConst(m_objectsToDelete)) { + for (FileResourceBase * const f : std::as_const(m_objectsToDelete)) { if (f->fileType() == FileResourceBase::FileTypeArtifact) static_cast<Artifact *>(f)->product.reset(); // To help with the sanity checks. } @@ -499,9 +508,11 @@ bool BuildGraphLoader::hasEnvironmentChanged(const TopLevelProjectConstPtr &rest newEnv.remove(ldPreloadEnvVar); if (oldEnv != newEnv) { - qCDebug(lcBuildGraph) << "Set of environment variables changed. Must re-resolve project." - << "\nold:" << restoredProject->environment.toStringList() - << "\nnew:" << m_parameters.adjustedEnvironment().toStringList(); + m_logger.qbsInfo() << Tr::tr("Environment changed."); + m_logger.qbsDebug() << Tr::tr("old: %1").arg( + restoredProject->environment.toStringList().join(QLatin1Char('\n'))); + m_logger.qbsDebug() << Tr::tr("new: %2").arg( + m_parameters.adjustedEnvironment().toStringList().join(QLatin1Char('\n'))); return true; } return false; @@ -512,8 +523,8 @@ bool BuildGraphLoader::hasCanonicalFilePathResultChanged(const TopLevelProjectCo for (auto it = restoredProject->canonicalFilePathResults.constBegin(); it != restoredProject->canonicalFilePathResults.constEnd(); ++it) { if (QFileInfo(it.key()).canonicalFilePath() != it.value()) { - qCDebug(lcBuildGraph) << "Canonical file path for file" << it.key() - << "changed, must re-resolve project."; + m_logger.qbsInfo() << Tr::tr("Canonical file path for file '%1' changed.") + .arg(QDir::toNativeSeparators(it.key())); return true; } } @@ -526,8 +537,8 @@ bool BuildGraphLoader::hasFileExistsResultChanged(const TopLevelProjectConstPtr for (QHash<QString, bool>::ConstIterator it = restoredProject->fileExistsResults.constBegin(); it != restoredProject->fileExistsResults.constEnd(); ++it) { if (FileInfo(it.key()).exists() != it.value()) { - qCDebug(lcBuildGraph) << "Existence check for file" << it.key() - << "changed, must re-resolve project."; + m_logger.qbsInfo() << Tr::tr("Existence check for file '%1' changed.") + .arg(QDir::toNativeSeparators(it.key())); return true; } } @@ -541,9 +552,8 @@ bool BuildGraphLoader::hasDirectoryEntriesResultChanged(const TopLevelProjectCon it != restoredProject->directoryEntriesResults.constEnd(); ++it) { if (QDir(it.key().first).entryList(static_cast<QDir::Filters>(it.key().second), QDir::Name) != it.value()) { - qCDebug(lcBuildGraph) << "Entry list for directory" << it.key().first - << static_cast<QDir::Filters>(it.key().second) - << "changed, must re-resolve project."; + m_logger.qbsInfo() << Tr::tr("Entry list for directory '%1' changed.") + .arg(QDir::toNativeSeparators(it.key().first)); return true; } } @@ -557,8 +567,8 @@ bool BuildGraphLoader::hasFileLastModifiedResultChanged(const TopLevelProjectCon = restoredProject->fileLastModifiedResults.constBegin(); it != restoredProject->fileLastModifiedResults.constEnd(); ++it) { if (FileInfo(it.key()).lastModified() != it.value()) { - qCDebug(lcBuildGraph) << "Timestamp for file" << it.key() - << "changed, must re-resolve project."; + m_logger.qbsInfo() << Tr::tr("Timestamp for file '%1' has changed.") + .arg(QDir::toNativeSeparators(it.key())); return true; } } @@ -576,17 +586,18 @@ bool BuildGraphLoader::hasProductFileChanged(const std::vector<ResolvedProductPt const FileInfo pfi(filePath); remainingBuildSystemFiles.remove(filePath); if (!pfi.exists()) { - qCDebug(lcBuildGraph) << "A product was removed, must re-resolve project"; + m_removedProjectFiles << filePath; hasChanged = true; } else if (referenceTime < pfi.lastModified()) { - qCDebug(lcBuildGraph) << "A product was changed, must re-resolve project"; + m_changedProjectFiles << filePath; hasChanged = true; } else if (!contains(changedProducts, product)) { bool foundMissingSourceFile = false; - for (const QString &file : qAsConst(product->missingSourceFiles)) { + for (const QString &file : std::as_const(product->missingSourceFiles)) { if (FileInfo(file).exists()) { - qCDebug(lcBuildGraph) << "Formerly missing file" << file << "in product" - << product->name << "exists now, must re-resolve project"; + m_logger.qbsInfo() + << Tr::tr("Formerly missing file '%1' in product '%2' exists now.") + .arg(QDir::toNativeSeparators(filePath), product->fullDisplayName()); foundMissingSourceFile = true; break; } @@ -600,25 +611,14 @@ bool BuildGraphLoader::hasProductFileChanged(const std::vector<ResolvedProductPt AccumulatingTimer wildcardTimer(m_parameters.logElapsedTime() ? &m_wildcardExpansionEffort : nullptr); for (const GroupPtr &group : product->groups) { - if (!group->wildcards) - continue; - const bool reExpansionRequired = Internal::any_of(group->wildcards->dirTimeStamps, - [](const std::pair<QString, FileTime> &pair) { - return FileInfo(pair.first).lastModified() > pair.second; - }); - if (!reExpansionRequired) - continue; - const Set<QString> files = group->wildcards->expandPatterns(group, - FileInfo::path(group->location.filePath()), - product->topLevelProject()->buildDirectory); - Set<QString> wcFiles; - for (const auto &sourceArtifact : group->wildcards->files) - wcFiles += sourceArtifact->absoluteFilePath; - if (files == wcFiles) - continue; - hasChanged = true; - changedProducts.push_back(product); - break; + if (group->wildcards && group->wildcards->hasChangedSinceExpansion()) { + m_logger.qbsInfo() + << Tr::tr("Must re-expand wildcards for group '%1' in product '%2'.") + .arg(group->name, product->fullDisplayName()); + hasChanged = true; + changedProducts.push_back(product); + break; + } } } } @@ -632,8 +632,7 @@ bool BuildGraphLoader::hasBuildSystemFileChanged(const Set<QString> &buildSystem for (const QString &file : buildSystemFiles) { const FileInfo fi(file); if (!fi.exists()) { - qCDebug(lcBuildGraph) << "Project file" << file - << "no longer exists, must re-resolve project."; + m_removedProjectFiles << file; return true; } const auto generatedChecker = [&file, restoredProject](const ModuleProviderInfo &mpi) { @@ -644,7 +643,7 @@ bool BuildGraphLoader::hasBuildSystemFileChanged(const Set<QString> &buildSystem const FileTime referenceTime = fileWasCreatedByModuleProvider ? restoredProject->lastEndResolveTime : restoredProject->lastStartResolveTime; if (referenceTime < fi.lastModified()) { - qCDebug(lcBuildGraph) << "Project file" << file << "changed, must re-resolve project."; + m_changedProjectFiles << file; return true; } } @@ -739,9 +738,9 @@ static bool dependenciesAreEqual(const ResolvedProductConstPtr &p1, return false; Set<QString> names1; Set<QString> names2; - for (const auto &dep : qAsConst(p1->dependencies)) + for (const auto &dep : std::as_const(p1->dependencies)) names1 << dep->uniqueName(); - for (const auto &dep : qAsConst(p2->dependencies)) + for (const auto &dep : std::as_const(p2->dependencies)) names2 << dep->uniqueName(); return names1 == names2; } @@ -771,10 +770,11 @@ bool BuildGraphLoader::checkProductForInstallInfoChanges(const ResolvedProductPt << StringConstants::installDirProperty() << StringConstants::installPrefixProperty() << StringConstants::installRootProperty(); for (const QString &key : specialProperties) { - if (restoredProduct->moduleProperties->qbsPropertyValue(key) - != newlyResolvedProduct->moduleProperties->qbsPropertyValue(key)) { + if (!qVariantsEqual( + restoredProduct->moduleProperties->qbsPropertyValue(key), + newlyResolvedProduct->moduleProperties->qbsPropertyValue(key))) { qCDebug(lcBuildGraph).noquote().nospace() - << "Product property 'qbs." << key << "' changed."; + << "Product property 'qbs." << key << "' changed."; return true; } } @@ -820,7 +820,7 @@ void BuildGraphLoader::onProductRemoved(const ResolvedProductPtr &product, removeOne(product->project->products, product); if (product->buildData) { - for (BuildGraphNode * const node : qAsConst(product->buildData->allNodes())) { + for (BuildGraphNode * const node : std::as_const(product->buildData->allNodes())) { if (node->type() == BuildGraphNode::ArtifactNodeType) { const auto artifact = static_cast<Artifact *>(node); projectBuildData->removeArtifact(artifact, m_logger, removeArtifactsFromDisk, @@ -828,10 +828,10 @@ void BuildGraphLoader::onProductRemoved(const ResolvedProductPtr &product, if (removeArtifactsFromDisk && artifact->artifactType == Artifact::Generated) m_artifactsRemovedFromDisk << artifact->filePath(); } else { - for (BuildGraphNode * const parent : qAsConst(node->parents)) + for (BuildGraphNode * const parent : std::as_const(node->parents)) parent->children.remove(node); node->parents.clear(); - for (BuildGraphNode * const child : qAsConst(node->children)) + for (BuildGraphNode * const child : std::as_const(node->children)) child->parents.remove(node); node->children.clear(); } @@ -860,11 +860,14 @@ void BuildGraphLoader::replaceFileDependencyWithArtifact(const ResolvedProductPt bool BuildGraphLoader::checkConfigCompatibility() { const TopLevelProjectConstPtr restoredProject = m_result.loadedProject; - if (m_parameters.topLevelProfile().isEmpty()) + if (m_parameters.topLevelProfile().isEmpty()) { m_parameters.setTopLevelProfile(restoredProject->profile()); + m_parameters.expandBuildConfiguration(); + } if (!m_parameters.overrideBuildGraphData()) { if (!m_parameters.overriddenValues().empty() - && m_parameters.overriddenValues() != restoredProject->overriddenValues) { + && !qVariantMapsEqual( + m_parameters.overriddenValues(), restoredProject->overriddenValues)) { const auto toUserOutput = [](const QVariantMap &propMap) { QString o; for (auto it = propMap.begin(); it != propMap.end(); ++it) { @@ -882,7 +885,7 @@ bool BuildGraphLoader::checkConfigCompatibility() "you really want to rebuild with the new properties.") .arg(toUserOutput(restoredProject->overriddenValues), toUserOutput(m_parameters.overriddenValues()))); - } + } m_parameters.setOverriddenValues(restoredProject->overriddenValues); if (m_parameters.topLevelProfile() != restoredProject->profile()) { throw ErrorInfo(Tr::tr("The current profile is '%1', but profile '%2' was used " @@ -897,11 +900,12 @@ bool BuildGraphLoader::checkConfigCompatibility() } if (!m_parameters.overrideBuildGraphData()) return true; - if (m_parameters.finalBuildConfigurationTree() != restoredProject->buildConfiguration()) + if (!qVariantMapsEqual( + m_parameters.finalBuildConfigurationTree(), restoredProject->buildConfiguration())) return false; Settings settings(m_parameters.settingsDirectory()); - for (QVariantMap::ConstIterator it = restoredProject->profileConfigs.constBegin(); - it != restoredProject->profileConfigs.constEnd(); ++it) { + const QVariantMap profileConfigsTree = restoredProject->fullProfileConfigsTree(); + for (auto it = profileConfigsTree.begin(); it != profileConfigsTree.end(); ++it) { const Profile profile(it.key(), &settings); const QVariantMap buildConfig = SetupProjectParameters::expandedBuildConfiguration( profile, m_parameters.configurationName()); @@ -967,7 +971,7 @@ void BuildGraphLoader::rescueOldBuildData(const ResolvedProductConstPtr &restore rad.lastPrepareScriptExecutionTime = oldArtifact->transformer->lastPrepareScriptExecutionTime; const ChildrenInfo &childrenInfo = childLists.value(oldArtifact); - for (Artifact * const child : qAsConst(childrenInfo.children)) { + for (Artifact * const child : std::as_const(childrenInfo.children)) { rad.children.emplace_back(child->product->name, child->product->multiplexConfigurationId, child->filePath(), childrenInfo.childrenAddedByScanner.contains(child)); diff --git a/src/lib/corelib/buildgraph/buildgraphloader.h b/src/lib/corelib/buildgraph/buildgraphloader.h index c62ba7fa7..02b00e29d 100644 --- a/src/lib/corelib/buildgraph/buildgraphloader.h +++ b/src/lib/corelib/buildgraph/buildgraphloader.h @@ -46,6 +46,7 @@ #include <language/forward_decls.h> #include <logging/logger.h> +#include <tools/set.h> #include <tools/setupprojectparameters.h> #include <QtCore/qprocess.h> @@ -140,6 +141,8 @@ private: Logger m_logger; QStringList m_artifactsRemovedFromDisk; std::unordered_map<QString, std::vector<SourceArtifactConstPtr>> m_changedSourcesByProduct; + Set<QString> m_changedProjectFiles; + Set<QString> m_removedProjectFiles; Set<QString> m_productsWhoseArtifactsNeedUpdate; qint64 m_wildcardExpansionEffort = 0; qint64 m_propertyComparisonEffort = 0; diff --git a/src/lib/corelib/buildgraph/buildgraphnode.cpp b/src/lib/corelib/buildgraph/buildgraphnode.cpp index 7d011d50c..cb19ee95c 100644 --- a/src/lib/corelib/buildgraph/buildgraphnode.cpp +++ b/src/lib/corelib/buildgraph/buildgraphnode.cpp @@ -56,9 +56,9 @@ BuildGraphNode::BuildGraphNode() : buildState(Untouched) BuildGraphNode::~BuildGraphNode() { - for (BuildGraphNode *p : qAsConst(parents)) + for (BuildGraphNode *p : std::as_const(parents)) p->children.remove(this); - for (BuildGraphNode *c : qAsConst(children)) + for (BuildGraphNode *c : std::as_const(children)) c->parents.remove(this); } @@ -69,7 +69,7 @@ void BuildGraphNode::onChildDisconnected(BuildGraphNode *child) void BuildGraphNode::acceptChildren(BuildGraphVisitor *visitor) { - for (BuildGraphNode *child : qAsConst(children)) + for (BuildGraphNode *child : std::as_const(children)) child->accept(visitor); } diff --git a/src/lib/corelib/buildgraph/cycledetector.cpp b/src/lib/corelib/buildgraph/cycledetector.cpp index 5daed55fd..3a1c43cd1 100644 --- a/src/lib/corelib/buildgraph/cycledetector.cpp +++ b/src/lib/corelib/buildgraph/cycledetector.cpp @@ -91,7 +91,7 @@ bool CycleDetector::visitNode(BuildGraphNode *node) m_nodesInCurrentPath += node; m_parent = node; - for (BuildGraphNode * const child : qAsConst(node->children)) + for (BuildGraphNode * const child : std::as_const(node->children)) child->accept(this); m_nodesInCurrentPath -= node; m_allNodes += node; diff --git a/src/lib/corelib/buildgraph/environmentscriptrunner.cpp b/src/lib/corelib/buildgraph/environmentscriptrunner.cpp index c4810f621..0fbb3ab19 100644 --- a/src/lib/corelib/buildgraph/environmentscriptrunner.cpp +++ b/src/lib/corelib/buildgraph/environmentscriptrunner.cpp @@ -137,7 +137,7 @@ void EnvironmentScriptRunner::setupEnvironment() QHash<const ResolvedModule*, QList<const ResolvedModule*> > moduleParents; QHash<const ResolvedModule*, QList<const ResolvedModule*> > moduleChildren; for (const auto &module : m_product->modules) { - for (const QString &moduleName : qAsConst(module->moduleDependencies)) { + for (const QString &moduleName : std::as_const(module->moduleDependencies)) { const ResolvedModule * const depmod = moduleMap.value(moduleName); QBS_ASSERT(depmod, return); moduleParents[depmod].push_back(module.get()); diff --git a/src/lib/corelib/buildgraph/executor.cpp b/src/lib/corelib/buildgraph/executor.cpp index 72ee9d7ba..2b8232a0a 100644 --- a/src/lib/corelib/buildgraph/executor.cpp +++ b/src/lib/corelib/buildgraph/executor.cpp @@ -204,7 +204,7 @@ private: { if (!m_seenProducts.insert(product).second) return; - for (const ResolvedProductPtr &dependency : qAsConst(product->dependencies)) + for (const ResolvedProductPtr &dependency : std::as_const(product->dependencies)) traverse(dependency); if (!product->buildData) return; @@ -263,6 +263,7 @@ void Executor::doBuild() QBS_CHECK(!m_project->buildData->evaluationContext); m_project->buildData->evaluationContext = std::make_shared<RulesEvaluationContext>(m_logger); m_evalContext = m_project->buildData->evaluationContext; + m_progressObserver->addScriptEngine(m_evalContext->engine()); m_elapsedTimeRules = m_elapsedTimeScanners = m_elapsedTimeInstalling = 0; m_evalContext->engine()->enableProfiling(m_buildOptions.logElapsedTime()); @@ -328,7 +329,7 @@ void Executor::updateLeaves(BuildGraphNode *node, NodeSet &seenNodes) } bool isLeaf = true; - for (BuildGraphNode *child : qAsConst(node->children)) { + for (BuildGraphNode *child : std::as_const(node->children)) { if (child->buildState != BuildGraphNode::Built) { isLeaf = false; updateLeaves(child, seenNodes); @@ -451,7 +452,7 @@ bool Executor::isUpToDate(Artifact *artifact) const return false; } - for (FileDependency *fileDependency : qAsConst(artifact->fileDependencies)) { + for (FileDependency *fileDependency : std::as_const(artifact->fileDependencies)) { if (!fileDependency->timestamp().isValid()) { qCDebug(lcUpToDateCheck) << "file dependency doesn't exist" << fileDependency->filePath(); @@ -478,7 +479,7 @@ bool Executor::mustExecuteTransformer(const TransformerPtr &transformer) const bool hasAlwaysUpdatedArtifacts = false; bool hasUpToDateNotAlwaysUpdatedArtifacts = false; - for (Artifact *artifact : qAsConst(transformer->outputs)) { + for (Artifact *artifact : std::as_const(transformer->outputs)) { if (isUpToDate(artifact)) { if (artifact->alwaysUpdated) hasAlwaysUpdatedArtifacts = true; @@ -567,7 +568,7 @@ void Executor::finishJob(ExecutorJob *job, bool success) updateJobCounts(transformer.get(), -1); if (success) { m_project->buildData->setDirty(); - for (Artifact * const artifact : qAsConst(transformer->outputs)) { + for (Artifact * const artifact : std::as_const(transformer->outputs)) { if (artifact->alwaysUpdated) { artifact->setTimestamp(FileTime::currentTime()); for (Artifact * const parent : artifact->parentArtifacts()) @@ -626,7 +627,7 @@ static bool allChildrenBuilt(BuildGraphNode *node) void Executor::finishNode(BuildGraphNode *leaf) { leaf->buildState = BuildGraphNode::Built; - for (BuildGraphNode * const parent : qAsConst(leaf->parents)) { + for (BuildGraphNode * const parent : std::as_const(leaf->parents)) { if (parent->buildState != BuildGraphNode::Buildable) { qCDebug(lcExec).noquote() << "parent" << parent->toString() << "build state:" << toString(parent->buildState); @@ -679,7 +680,7 @@ bool Executor::transformerHasMatchingInputFiles(const TransformerConstPtr &trans return false; if (transformer->inputs.empty()) return true; - for (const Artifact * const input : qAsConst(transformer->inputs)) { + for (const Artifact * const input : std::as_const(transformer->inputs)) { const auto files = m_buildOptions.filesToConsider(); for (const QString &filePath : files) { if (input->filePath() == filePath @@ -695,7 +696,7 @@ bool Executor::transformerHasMatchingInputFiles(const TransformerConstPtr &trans void Executor::setupJobLimits() { Settings settings(m_buildOptions.settingsDirectory()); - for (const auto &p : qAsConst(m_productsToBuild)) { + for (const auto &p : std::as_const(m_productsToBuild)) { const Preferences prefs(&settings, p->profile()); const JobLimits &jobLimitsFromSettings = prefs.jobLimits(); JobLimits effectiveJobLimits; @@ -732,7 +733,7 @@ void Executor::setupProgressObserver() if (!m_progressObserver) return; int totalEffort = 1; // For the effort after the last rule application; - for (const auto &product : qAsConst(m_productsToBuild)) { + for (const auto &product : std::as_const(m_productsToBuild)) { QBS_CHECK(product->buildData); const auto filtered = filterByType<RuleNode>(product->buildData->allNodes()); totalEffort += std::distance(filtered.begin(), filtered.end()); @@ -744,7 +745,7 @@ void Executor::doSanityChecks() { QBS_CHECK(m_project); QBS_CHECK(!m_productsToBuild.empty()); - for (const auto &product : qAsConst(m_productsToBuild)) { + for (const auto &product : std::as_const(m_productsToBuild)) { QBS_CHECK(product->buildData); QBS_CHECK(product->topLevelProject() == m_project.get()); } @@ -915,7 +916,7 @@ bool Executor::checkForUnbuiltDependencies(Artifact *artifact) { bool buildingDependenciesFound = false; NodeSet unbuiltDependencies; - for (BuildGraphNode * const dependency : qAsConst(artifact->children)) { + for (BuildGraphNode * const dependency : std::as_const(artifact->children)) { switch (dependency->buildState) { case BuildGraphNode::Untouched: case BuildGraphNode::Buildable: @@ -946,7 +947,7 @@ bool Executor::checkForUnbuiltDependencies(Artifact *artifact) void Executor::potentiallyRunTransformer(const TransformerPtr &transformer) { - for (Artifact * const output : qAsConst(transformer->outputs)) { + for (Artifact * const output : std::as_const(transformer->outputs)) { // Rescuing build data can introduce new dependencies, potentially delaying execution of // this transformer. bool childrenAddedDueToRescue; @@ -969,7 +970,7 @@ void Executor::potentiallyRunTransformer(const TransformerPtr &transformer) const bool mustExecute = mustExecuteTransformer(transformer); if (mustExecute || m_buildOptions.forceTimestampCheck()) { - for (Artifact * const output : qAsConst(transformer->outputs)) { + for (Artifact * const output : std::as_const(transformer->outputs)) { // Scan all input artifacts. If new dependencies were found during scanning, delay // execution of this transformer. InputArtifactScanner scanner(output, m_inputArtifactScanContext, m_logger); @@ -1000,7 +1001,7 @@ void Executor::runTransformer(const TransformerPtr &transformer) // create the output directories if (!m_buildOptions.dryRun()) { - for (Artifact * const output : qAsConst(transformer->outputs)) { + for (Artifact * const output : std::as_const(transformer->outputs)) { QDir outDir = QFileInfo(output->filePath()).absoluteDir(); if (!outDir.exists() && !outDir.mkpath(StringConstants::dot())) { throw ErrorInfo(tr("Failed to create directory '%1'.") @@ -1011,7 +1012,7 @@ void Executor::runTransformer(const TransformerPtr &transformer) QBS_CHECK(!m_availableJobs.empty()); ExecutorJob *job = m_availableJobs.takeFirst(); - for (Artifact * const artifact : qAsConst(transformer->outputs)) + for (Artifact * const artifact : std::as_const(transformer->outputs)) artifact->buildState = BuildGraphNode::Building; m_processingJobs.insert(job, transformer); updateJobCounts(transformer.get(), 1); @@ -1021,7 +1022,7 @@ void Executor::runTransformer(const TransformerPtr &transformer) void Executor::finishTransformer(const TransformerPtr &transformer) { transformer->markedForRerun = false; - for (Artifact * const artifact : qAsConst(transformer->outputs)) { + for (Artifact * const artifact : std::as_const(transformer->outputs)) { possiblyInstallArtifact(artifact); finishArtifact(artifact); } @@ -1082,9 +1083,9 @@ void Executor::checkForUnbuiltProducts() if (m_buildOptions.executeRulesOnly()) return; std::vector<ResolvedProductPtr> unbuiltProducts; - for (const ResolvedProductPtr &product : qAsConst(m_productsToBuild)) { + for (const ResolvedProductPtr &product : std::as_const(m_productsToBuild)) { bool productBuilt = true; - for (BuildGraphNode *rootNode : qAsConst(product->buildData->rootNodes())) { + for (BuildGraphNode *rootNode : std::as_const(product->buildData->rootNodes())) { if (rootNode->buildState != BuildGraphNode::Built) { productBuilt = false; unbuiltProducts.push_back(product); @@ -1198,11 +1199,11 @@ void Executor::prepareAllNodes() for (const ResolvedProductPtr &product : m_allProducts) { if (product->enabled) { QBS_CHECK(product->buildData); - for (BuildGraphNode * const node : qAsConst(product->buildData->allNodes())) + for (BuildGraphNode * const node : std::as_const(product->buildData->allNodes())) node->buildState = BuildGraphNode::Untouched; } } - for (const ResolvedProductPtr &product : qAsConst(m_productsToBuild)) { + for (const ResolvedProductPtr &product : std::as_const(m_productsToBuild)) { QBS_CHECK(product->buildData); for (Artifact * const artifact : filterByType<Artifact>(product->buildData->allNodes())) prepareArtifact(artifact); @@ -1286,7 +1287,7 @@ void Executor::setupForBuildingSelectedFiles(const BuildGraphNode *node) */ void Executor::prepareReachableNodes() { - for (BuildGraphNode * const root : qAsConst(m_roots)) + for (BuildGraphNode * const root : std::as_const(m_roots)) prepareReachableNodes_impl(root); } @@ -1298,7 +1299,7 @@ void Executor::prepareReachableNodes_impl(BuildGraphNode *node) return; node->buildState = BuildGraphNode::Buildable; - for (BuildGraphNode *child : qAsConst(node->children)) + for (BuildGraphNode *child : std::as_const(node->children)) prepareReachableNodes_impl(child); } @@ -1306,7 +1307,7 @@ void Executor::prepareProducts() { ProductPrioritySetter prioritySetter(m_allProducts); prioritySetter.apply(); - for (const ResolvedProductPtr &product : qAsConst(m_productsToBuild)) { + for (const ResolvedProductPtr &product : std::as_const(m_productsToBuild)) { EnvironmentScriptRunner(product.get(), m_evalContext.get(), m_project->environment) .setupForBuild(); } @@ -1315,7 +1316,7 @@ void Executor::prepareProducts() void Executor::setupRootNodes() { m_roots.clear(); - for (const ResolvedProductPtr &product : qAsConst(m_productsToBuild)) + for (const ResolvedProductPtr &product : std::as_const(m_productsToBuild)) m_roots += product->buildData->rootNodes(); } diff --git a/src/lib/corelib/buildgraph/inputartifactscanner.cpp b/src/lib/corelib/buildgraph/inputartifactscanner.cpp index 05bbc0d4b..0c73f599f 100644 --- a/src/lib/corelib/buildgraph/inputartifactscanner.cpp +++ b/src/lib/corelib/buildgraph/inputartifactscanner.cpp @@ -103,9 +103,14 @@ static void resolveDepencency(const RawScannedDependency &dependency, } // prioritize found artifacts - if ((result->file = dependencyInProduct) - || (result->file = dependencyInOtherProduct) - || (result->file = fileDependencyArtifact)) { + if (dependencyInProduct) + result->file = dependencyInProduct; + else if (dependencyInOtherProduct) + result->file = dependencyInOtherProduct; + else + result->file = fileDependencyArtifact; + + if (result->file) { result->filePath = result->file->filePath(); if (result->file == dependencyInOtherProduct && !productOfDependencyIsDependency) { @@ -158,7 +163,7 @@ void InputArtifactScanner::scan() for (Artifact * const dependency : childrenAddedByScanner) disconnect(m_artifact, dependency); - for (Artifact * const inputArtifact : qAsConst(m_artifact->transformer->inputs)) + for (Artifact * const inputArtifact : std::as_const(m_artifact->transformer->inputs)) scanForFileDependencies(inputArtifact); } @@ -224,7 +229,7 @@ Set<DependencyScanner *> InputArtifactScanner::scannersForArtifact(const Artifac } } } - for (const DependencyScannerPtr &scanner : qAsConst(cache.scanners)) + for (const DependencyScannerPtr &scanner : std::as_const(cache.scanners)) scanners += scanner.get(); } return scanners; @@ -243,21 +248,16 @@ void InputArtifactScanner::scanForScannerFileDependencies(DependencyScanner *sca cache.searchPaths = scanner->collectSearchPaths(inputArtifact); } qCDebug(lcDepScan) << "include paths (cache" << (cacheHit ? "hit)" : "miss)"); - for (const QString &s : qAsConst(cache.searchPaths)) + for (const QString &s : std::as_const(cache.searchPaths)) qCDebug(lcDepScan) << " " << s; const QString &filePathToBeScanned = fileToBeScanned->filePath(); RawScanResults::ScanData &scanData = m_rawScanResults.findScanData(fileToBeScanned, scanner, m_artifact->properties); if (scanData.lastScanTime < fileToBeScanned->timestamp()) { - try { - qCDebug(lcDepScan) << "scanning" << FileInfo::fileName(filePathToBeScanned); - scanWithScannerPlugin(scanner, inputArtifact, fileToBeScanned, &scanData.rawScanResult); - scanData.lastScanTime = FileTime::currentTime(); - } catch (const ErrorInfo &error) { - m_logger.printWarning(error); - return; - } + qCDebug(lcDepScan) << "scanning" << FileInfo::fileName(filePathToBeScanned); + scanWithScannerPlugin(scanner, inputArtifact, fileToBeScanned, &scanData.rawScanResult); + scanData.lastScanTime = FileTime::currentTime(); } resolveScanResultDependencies(inputArtifact, scanData.rawScanResult, filesToScan, cache); @@ -289,7 +289,7 @@ void InputArtifactScanner::resolveScanResultDependencies(const Artifact *inputAr } // try include paths - for (const QString &includePath : qAsConst(cache.searchPaths)) { + for (const QString &includePath : std::as_const(cache.searchPaths)) { resolveDepencency(dependency, inputArtifact->product.get(), &resolvedDependency, includePath); if (resolvedDependency.isValid()) diff --git a/src/lib/corelib/buildgraph/nodetreedumper.cpp b/src/lib/corelib/buildgraph/nodetreedumper.cpp index 8475a46cf..6ad597c70 100644 --- a/src/lib/corelib/buildgraph/nodetreedumper.cpp +++ b/src/lib/corelib/buildgraph/nodetreedumper.cpp @@ -120,7 +120,7 @@ bool NodeTreeDumper::doVisit(BuildGraphNode *node, const QString &nodeRepr) QByteArray NodeTreeDumper::indentation() const { - return QByteArray(m_indentation, ' '); + return {m_indentation, ' '}; } } // namespace Internal diff --git a/src/lib/corelib/buildgraph/processcommandexecutor.cpp b/src/lib/corelib/buildgraph/processcommandexecutor.cpp index 0058b940e..52a8fe75d 100644 --- a/src/lib/corelib/buildgraph/processcommandexecutor.cpp +++ b/src/lib/corelib/buildgraph/processcommandexecutor.cpp @@ -291,7 +291,7 @@ void ProcessCommandExecutor::getProcessOutput(bool stdOut, ProcessResult &result } else { if (!contentString.isEmpty() && contentString.endsWith(QLatin1Char('\n'))) contentString.chop(1); - *target = contentString.split(QLatin1Char('\n'), QBS_SKIP_EMPTY_PARTS); + *target = contentString.split(QLatin1Char('\n'), Qt::SkipEmptyParts); } } @@ -398,7 +398,7 @@ void ProcessCommandExecutor::doReportCommandDescription(const QString &productNa if (m_echoMode == CommandEchoModeCommandLineWithEnvironment) { QStringList keys = m_commandEnvironment.keys(); keys.sort(); - for (const QString &key : qAsConst(keys)) + for (const QString &key : std::as_const(keys)) fullInvocation += environmentVariableString(key, m_commandEnvironment.value(key)); } fullInvocation += m_shellInvocation; diff --git a/src/lib/corelib/buildgraph/productinstaller.cpp b/src/lib/corelib/buildgraph/productinstaller.cpp index 80a76d7f5..f757c8a85 100644 --- a/src/lib/corelib/buildgraph/productinstaller.cpp +++ b/src/lib/corelib/buildgraph/productinstaller.cpp @@ -96,7 +96,7 @@ void ProductInstaller::install() removeInstallRoot(); QList<const Artifact *> artifactsToInstall; - for (const auto &product : qAsConst(m_products)) { + for (const auto &product : std::as_const(m_products)) { QBS_CHECK(product->buildData); for (const Artifact *artifact : filterByType<Artifact>(product->buildData->allNodes())) { if (artifact->properties->qbsPropertyValue(StringConstants::installProperty()).toBool()) @@ -105,7 +105,7 @@ void ProductInstaller::install() } m_observer->initialize(Tr::tr("Installing"), artifactsToInstall.size()); - for (const Artifact * const a : qAsConst(artifactsToInstall)) { + for (const Artifact * const a : std::as_const(artifactsToInstall)) { copyFile(a); m_observer->incrementProgressValue(); } diff --git a/src/lib/corelib/buildgraph/projectbuilddata.cpp b/src/lib/corelib/buildgraph/projectbuilddata.cpp index c229a6171..36ac75331 100644 --- a/src/lib/corelib/buildgraph/projectbuilddata.cpp +++ b/src/lib/corelib/buildgraph/projectbuilddata.cpp @@ -157,7 +157,7 @@ void ProjectBuildData::insertFileDependency(FileDependency *dependency) static void disconnectArtifactChildren(Artifact *artifact) { qCDebug(lcBuildGraph) << "disconnect children of" << relativeArtifactFileName(artifact); - for (BuildGraphNode * const child : qAsConst(artifact->children)) + for (BuildGraphNode * const child : std::as_const(artifact->children)) child->parents.remove(artifact); artifact->children.clear(); artifact->childrenAddedByScanner.clear(); @@ -166,7 +166,7 @@ static void disconnectArtifactChildren(Artifact *artifact) static void disconnectArtifactParents(Artifact *artifact) { qCDebug(lcBuildGraph) << "disconnect parents of" << relativeArtifactFileName(artifact); - for (BuildGraphNode * const parent : qAsConst(artifact->parents)) { + for (BuildGraphNode * const parent : std::as_const(artifact->parents)) { parent->children.remove(artifact); if (parent->type() != BuildGraphNode::ArtifactNodeType) continue; @@ -257,7 +257,7 @@ void ProjectBuildData::setClean() void ProjectBuildData::load(PersistentPool &pool) { serializationOp<PersistentPool::Load>(pool); - for (FileDependency * const dep : qAsConst(fileDependencies)) + for (FileDependency * const dep : std::as_const(fileDependencies)) insertIntoLookupTable(dep); m_isDirty = false; } @@ -337,7 +337,7 @@ private: { if (!m_rulesOnPath.insert(rule.get()).second) { QString pathstr; - for (const Rule *r : qAsConst(m_rulePath)) { + for (const Rule *r : std::as_const(m_rulePath)) { pathstr += QLatin1Char('\n') + r->toString() + QLatin1Char('\t') + r->prepareScript.location().toString(); } @@ -394,7 +394,7 @@ void BuildDataResolver::resolveProductBuildData(const ResolvedProductPtr &produc product->buildData = std::make_unique<ProductBuildData>(); ArtifactSetByFileTag artifactsPerFileTag; - for (const auto &dependency : qAsConst(product->dependencies)) { + for (const auto &dependency : std::as_const(product->dependencies)) { QBS_CHECK(dependency->enabled); resolveProductBuildData(dependency); } diff --git a/src/lib/corelib/buildgraph/rulecommands.cpp b/src/lib/corelib/buildgraph/rulecommands.cpp index 6acd1d68c..be90c2fd5 100644 --- a/src/lib/corelib/buildgraph/rulecommands.cpp +++ b/src/lib/corelib/buildgraph/rulecommands.cpp @@ -99,15 +99,11 @@ AbstractCommand::~AbstractCommand() = default; bool AbstractCommand::equals(const AbstractCommand *other) const { - return type() == other->type() - && m_description == other->m_description - && m_extendedDescription == other->m_extendedDescription - && m_highlight == other->m_highlight - && m_ignoreDryRun == other->m_ignoreDryRun - && m_silent == other->m_silent - && m_jobPool == other->m_jobPool - && m_timeout == other->m_timeout - && m_properties == other->m_properties; + return type() == other->type() && m_description == other->m_description + && m_extendedDescription == other->m_extendedDescription + && m_highlight == other->m_highlight && m_ignoreDryRun == other->m_ignoreDryRun + && m_silent == other->m_silent && m_jobPool == other->m_jobPool + && m_timeout == other->m_timeout && qVariantMapsEqual(m_properties, other->m_properties); } void AbstractCommand::fillFromScriptValue(JSContext *ctx, const JSValue *scriptValue, @@ -139,6 +135,11 @@ QString AbstractCommand::fullDescription(const QString &productName) const return description() + QLatin1String(" [") + productName + QLatin1Char(']'); } +QString AbstractCommand::descriptionForCancelMessage(const QString &productName) const +{ + return fullDescription(productName); +} + void AbstractCommand::load(PersistentPool &pool) { serializationOp<PersistentPool::Load>(pool); @@ -339,6 +340,12 @@ void ProcessCommand::fillFromScriptValue(JSContext *ctx, const JSValue *scriptVa applyCommandProperties(ctx, scriptValue); } +QString ProcessCommand::descriptionForCancelMessage(const QString &productName) const +{ + return description() + QLatin1String(" (") + QDir::toNativeSeparators(m_program) + + QLatin1String(") [") + productName + QLatin1Char(']'); +} + QStringList ProcessCommand::relevantEnvVars() const { QStringList vars = m_relevantEnvVars; diff --git a/src/lib/corelib/buildgraph/rulecommands.h b/src/lib/corelib/buildgraph/rulecommands.h index 7b08d1015..4296146d2 100644 --- a/src/lib/corelib/buildgraph/rulecommands.h +++ b/src/lib/corelib/buildgraph/rulecommands.h @@ -78,6 +78,7 @@ public: virtual bool equals(const AbstractCommand *other) const; virtual void fillFromScriptValue(JSContext *ctx, const JSValue *scriptValue, const CodeLocation &codeLocation); + virtual QString descriptionForCancelMessage(const QString &productName) const; QString fullDescription(const QString &productName) const; const QString description() const { return m_description; } @@ -129,6 +130,7 @@ public: bool equals(const AbstractCommand *otherAbstractCommand) const override; void fillFromScriptValue(JSContext *ctx, const JSValue *scriptValue, const CodeLocation &codeLocation) override; + QString descriptionForCancelMessage(const QString &productName) const override; const QString program() const { return m_program; } const QStringList arguments() const { return m_arguments; } const QString workingDir() const { return m_workingDir; } diff --git a/src/lib/corelib/buildgraph/rulegraph.cpp b/src/lib/corelib/buildgraph/rulegraph.cpp index 3f9a4fcb5..2acc2a97e 100644 --- a/src/lib/corelib/buildgraph/rulegraph.cpp +++ b/src/lib/corelib/buildgraph/rulegraph.cpp @@ -61,11 +61,11 @@ void RuleGraph::build(const std::vector<RulePtr> &rules, const FileTags &product m_parents.resize(rules.size()); m_children.resize(rules.size()); - for (const auto &rule : qAsConst(m_rules)) { + for (const auto &rule : std::as_const(m_rules)) { FileTags inFileTags = rule->inputs; inFileTags += rule->auxiliaryInputs; inFileTags += rule->explicitlyDependsOn; - for (const FileTag &fileTag : qAsConst(inFileTags)) { + for (const FileTag &fileTag : std::as_const(inFileTags)) { inputFileTagToRule[fileTag].push_back(rule.get()); for (const Rule * const producingRule : m_outputFileTagToRule.value(fileTag)) { if (!producingRule->collectedOutputFileTags().intersects( @@ -82,14 +82,14 @@ void RuleGraph::build(const std::vector<RulePtr> &rules, const FileTags &product productRules << rules; //### check: the rule graph must be a in valid shape! } - for (const Rule *r : qAsConst(productRules)) + for (const Rule *r : std::as_const(productRules)) m_rootRules += r->ruleGraphId; } void RuleGraph::accept(RuleGraphVisitor *visitor) const { const RuleConstPtr nullParent; - for (int rootIndex : qAsConst(m_rootRules)) + for (int rootIndex : std::as_const(m_rootRules)) traverse(visitor, nullParent, m_rules.at(rootIndex)); } @@ -98,10 +98,10 @@ void RuleGraph::dump() const QByteArray indent; std::printf("---rule graph dump:\n"); Set<int> rootRules; - for (const auto &rule : qAsConst(m_rules)) + for (const auto &rule : std::as_const(m_rules)) if (m_parents[rule->ruleGraphId].empty()) rootRules += rule->ruleGraphId; - for (int idx : qAsConst(rootRules)) + for (int idx : std::as_const(rootRules)) dump_impl(indent, idx); } @@ -113,7 +113,7 @@ void RuleGraph::dump_impl(QByteArray &indent, int rootIndex) const std::printf("\n"); indent.append(" "); - for (int childIndex : qAsConst(m_children[rootIndex])) + for (int childIndex : std::as_const(m_children[rootIndex])) dump_impl(indent, childIndex); indent.chop(2); } diff --git a/src/lib/corelib/buildgraph/rulenode.cpp b/src/lib/corelib/buildgraph/rulenode.cpp index 0558ba144..8568e4098 100644 --- a/src/lib/corelib/buildgraph/rulenode.cpp +++ b/src/lib/corelib/buildgraph/rulenode.cpp @@ -229,7 +229,7 @@ int RuleNode::transformerCount() const ArtifactSet RuleNode::currentInputArtifacts() const { ArtifactSet s; - for (const FileTag &t : qAsConst(m_rule->inputs)) { + for (const FileTag &t : std::as_const(m_rule->inputs)) { for (Artifact *artifact : product->lookupArtifactsByFileTag(t)) { if (artifact->isTargetOfModule()) continue; @@ -246,7 +246,7 @@ ArtifactSet RuleNode::currentInputArtifacts() const if (m_rule->inputsFromDependencies.empty()) return s; - for (const FileTag &t : qAsConst(m_rule->inputsFromDependencies)) { + for (const FileTag &t : std::as_const(m_rule->inputsFromDependencies)) { for (Artifact *artifact : product->lookupArtifactsByFileTag(t)) { if (!artifact->isTargetOfModule()) continue; @@ -258,7 +258,7 @@ ArtifactSet RuleNode::currentInputArtifacts() const } } - for (const auto &dep : qAsConst(product->dependencies)) { + for (const auto &dep : std::as_const(product->dependencies)) { if (!dep->buildData) continue; for (Artifact * const a : filterByType<Artifact>(dep->buildData->allNodes())) { diff --git a/src/lib/corelib/buildgraph/rulesapplicator.cpp b/src/lib/corelib/buildgraph/rulesapplicator.cpp index 84956d123..94cee0c62 100644 --- a/src/lib/corelib/buildgraph/rulesapplicator.cpp +++ b/src/lib/corelib/buildgraph/rulesapplicator.cpp @@ -146,7 +146,7 @@ void RulesApplicator::handleRemovedRuleOutputs(const ArtifactSet &inputArtifacts project->buildData->removeArtifactAndExclusiveDependents(removedArtifact, logger, true, &artifactsToRemove); } - for (Artifact * const artifact : qAsConst(artifactsToRemove)) { + for (Artifact * const artifact : std::as_const(artifactsToRemove)) { QBS_CHECK(!inputArtifacts.contains(artifact)); removedArtifacts << artifact->filePath(); delete artifact; @@ -247,8 +247,8 @@ void RulesApplicator::doApply(const ArtifactSet &inputArtifacts, JSValue prepare if (outputArtifacts.empty()) return; - for (Artifact * const outputArtifact : qAsConst(outputArtifacts)) { - for (Artifact * const dependency : qAsConst(m_transformer->explicitlyDependsOn)) + for (Artifact * const outputArtifact : std::as_const(outputArtifacts)) { + for (Artifact * const dependency : std::as_const(m_transformer->explicitlyDependsOn)) connect(outputArtifact, dependency); } @@ -293,8 +293,9 @@ void RulesApplicator::doApply(const ArtifactSet &inputArtifacts, JSValue prepare } outputArtifact->properties->setValue(artifactModulesCfg); if (!outputInfo.newlyCreated - && (outputArtifact->fileTags() != outputInfo.oldFileTags - || outputArtifact->properties->value() != outputInfo.oldProperties)) { + && (outputArtifact->fileTags() != outputInfo.oldFileTags + || !qVariantMapsEqual( + outputArtifact->properties->value(), outputInfo.oldProperties))) { invalidateArtifactAsRuleInputIfNecessary(outputArtifact); } } @@ -313,7 +314,7 @@ void RulesApplicator::doApply(const ArtifactSet &inputArtifacts, JSValue prepare || m_oldTransformer->commands != m_transformer->commands || commandsNeedRerun(m_transformer.get(), m_product.get(), m_productsByName, m_projectsByName)) { - for (Artifact * const output : qAsConst(outputArtifacts)) { + for (Artifact * const output : std::as_const(outputArtifacts)) { output->clearTimestamp(); m_invalidatedArtifacts += output; } @@ -419,11 +420,7 @@ RulesApplicator::OutputArtifactInfo RulesApplicator::createOutputArtifactFromRul RulesApplicator::OutputArtifactInfo RulesApplicator::createOutputArtifact(const QString &filePath, const FileTags &fileTags, bool alwaysUpdated, const ArtifactSet &inputArtifacts) { - QString outputPath = filePath; - // don't let the output artifact "escape" its build dir - outputPath.replace(StringConstants::dotDot(), QStringLiteral("dotdot")); - outputPath = resolveOutPath(outputPath); - + const QString outputPath = resolveOutPath(filePath); if (m_rule->isDynamic()) { const Set<FileTag> undeclaredTags = fileTags - m_rule->collectedOutputFileTags(); if (!undeclaredTags.empty()) { @@ -664,8 +661,10 @@ Artifact *RulesApplicator::createOutputArtifactFromScriptValue(const JSValue &ob connect(outputInfo.artifact, dependency); } ArtifactBindingsExtractor().apply(engine(), outputInfo.artifact, obj); - if (!outputInfo.newlyCreated && (outputInfo.artifact->fileTags() != outputInfo.oldFileTags - || outputInfo.artifact->properties->value() != outputInfo.oldProperties)) { + if (!outputInfo.newlyCreated + && (outputInfo.artifact->fileTags() != outputInfo.oldFileTags + || !qVariantMapsEqual( + outputInfo.artifact->properties->value(), outputInfo.oldProperties))) { invalidateArtifactAsRuleInputIfNecessary(outputInfo.artifact); } return outputInfo.artifact; @@ -673,9 +672,14 @@ Artifact *RulesApplicator::createOutputArtifactFromScriptValue(const JSValue &ob QString RulesApplicator::resolveOutPath(const QString &path) const { - QString buildDir = m_product->topLevelProject()->buildDirectory; - QString result = FileInfo::resolvePath(buildDir, path); - result = QDir::cleanPath(result); + const QString buildDir = m_product->topLevelProject()->buildDirectory; + QString result = QDir::cleanPath(FileInfo::resolvePath(buildDir, path)); + if (!result.startsWith(buildDir + QLatin1Char('/'))) { + throw ErrorInfo( + Tr::tr("Refusing to create artifact '%1' outside of build directory '%2'.") + .arg(QDir::toNativeSeparators(result), QDir::toNativeSeparators(buildDir)), + m_rule->prepareScript.location()); + } return result; } diff --git a/src/lib/corelib/buildgraph/transformerchangetracking.cpp b/src/lib/corelib/buildgraph/transformerchangetracking.cpp index 710590654..ae43e8219 100644 --- a/src/lib/corelib/buildgraph/transformerchangetracking.cpp +++ b/src/lib/corelib/buildgraph/transformerchangetracking.cpp @@ -158,7 +158,7 @@ bool TrafoChangeTracker::checkForPropertyChange(const Property &restoredProperty case Property::PropertyInArtifact: QBS_CHECK(false); } - if (restoredProperty.value != v) { + if (!qVariantsEqual(restoredProperty.value, v)) { qCDebug(lcBuildGraph).noquote().nospace() << "Value for property '" << restoredProperty.moduleName << "." << restoredProperty.propertyName << "' has changed.\n" @@ -257,7 +257,7 @@ const ResolvedProduct *TrafoChangeTracker::getProduct(const QString &name) const bool TrafoChangeTracker::prepareScriptNeedsRerun() const { - for (const Property &property : qAsConst(m_transformer->propertiesRequestedInPrepareScript)) { + for (const Property &property : std::as_const(m_transformer->propertiesRequestedInPrepareScript)) { if (checkForPropertyChange(property, propertyMapByKind(property))) return true; } @@ -269,7 +269,7 @@ bool TrafoChangeTracker::prepareScriptNeedsRerun() const for (auto it = m_transformer->propertiesRequestedFromArtifactInPrepareScript.constBegin(); it != m_transformer->propertiesRequestedFromArtifactInPrepareScript.constEnd(); ++it) { - for (const Property &property : qAsConst(it.value())) { + for (const Property &property : std::as_const(it.value())) { const Artifact * const artifact = getArtifact(it.key(), property.productName); if (!artifact) return true; @@ -297,14 +297,14 @@ bool TrafoChangeTracker::prepareScriptNeedsRerun() const bool TrafoChangeTracker::commandsNeedRerun() const { - for (const Property &property : qAsConst(m_transformer->propertiesRequestedInCommands)) { + for (const Property &property : std::as_const(m_transformer->propertiesRequestedInCommands)) { if (checkForPropertyChange(property, propertyMapByKind(property))) return true; } for (auto it = m_transformer->propertiesRequestedFromArtifactInCommands.cbegin(); it != m_transformer->propertiesRequestedFromArtifactInCommands.cend(); ++it) { - for (const Property &property : qAsConst(it.value())) { + for (const Property &property : std::as_const(it.value())) { const Artifact * const artifact = getArtifact(it.key(), property.productName); if (!artifact) return true; @@ -331,7 +331,7 @@ bool TrafoChangeTracker::commandsNeedRerun() const return true; // TODO: Also track env access in JS commands and prepare scripts - for (const AbstractCommandPtr &c : qAsConst(m_transformer->commands.commands())) { + for (const AbstractCommandPtr &c : std::as_const(m_transformer->commands.commands())) { if (c->type() != AbstractCommand::ProcessCommandType) continue; const ProcessCommandPtr &processCmd = std::static_pointer_cast<ProcessCommand>(c); |