aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/corelib/buildgraph/buildgraphloader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/corelib/buildgraph/buildgraphloader.cpp')
-rw-r--r--src/lib/corelib/buildgraph/buildgraphloader.cpp168
1 files changed, 86 insertions, 82 deletions
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));