diff options
| author | Christian Kandeler <christian.kandeler@digia.com> | 2013-09-10 16:08:37 +0200 |
|---|---|---|
| committer | Joerg Bornemann <joerg.bornemann@digia.com> | 2013-09-11 08:20:47 +0200 |
| commit | 58a907db9a96b4a21c1ead744a04529a4641b708 (patch) | |
| tree | 50cd3cf16db5859cb2780bfe37d824fa8891116f /src/lib/buildgraph/buildgraphloader.cpp | |
| parent | 49ebbc396cc0276dace901b67b9e974750b50f81 (diff) | |
| download | qbs-58a907db9a96b4a21c1ead744a04529a4641b708.tar.gz | |
Fix a number of bugs uncovered by a recent leak fix (ff5b33b82b).
To name just a few:
- Product removal, adaptation and re-resolving/swapping build data
was done in the wrong order, resulting in outdated information still
being present and necessary new one not being there yet.
- Outdated artifacts were deleted too early, so that look-ups into
the old project build data would cause undefined behavior.
- The list of products whose file list was changed could contain the
same entry twice, causing asserts when the same code was run again for
the same product.
Change-Id: I0c318fb18d5a8293d863ea6802203200941b9b7b
Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
Diffstat (limited to 'src/lib/buildgraph/buildgraphloader.cpp')
| -rw-r--r-- | src/lib/buildgraph/buildgraphloader.cpp | 93 |
1 files changed, 50 insertions, 43 deletions
diff --git a/src/lib/buildgraph/buildgraphloader.cpp b/src/lib/buildgraph/buildgraphloader.cpp index 4082b77f1..da3ca97c8 100644 --- a/src/lib/buildgraph/buildgraphloader.cpp +++ b/src/lib/buildgraph/buildgraphloader.cpp @@ -55,6 +55,11 @@ BuildGraphLoader::BuildGraphLoader(const QProcessEnvironment &env, const Logger { } +BuildGraphLoader::~BuildGraphLoader() +{ + qDeleteAll(m_objectsToDelete); +} + static bool isConfigCompatible(const QVariantMap &cfg1, const QVariantMap &cfg2) { if (cfg1.count() != cfg2.count()) @@ -198,7 +203,7 @@ void BuildGraphLoader::trackProjectChanges(const SetupProjectParameters ¶met productsWithChangedFiles); QSharedPointer<ProjectBuildData> oldBuildData; - if (!changedProducts.isEmpty()) { + if (!changedProducts.isEmpty() || !productsWithChangedFiles.isEmpty()) { oldBuildData = QSharedPointer<ProjectBuildData>( new ProjectBuildData(restoredProject->buildData.data())); } @@ -215,15 +220,6 @@ void BuildGraphLoader::trackProjectChanges(const SetupProjectParameters ¶met productsWithChangedFiles.removeOne(product); } - // For products where only the list of files has changed, we adapt the existing build data - // so we won't recompile existing files just because new ones have been added. - foreach (const ResolvedProductPtr &product, productsWithChangedFiles) { - ResolvedProductPtr freshProduct = freshProductsByName.value(product->name); - if (!freshProduct) - continue; - onProductFileListChanged(product, freshProduct); - } - // Move over restored build data to newly resolved project. m_result.newlyResolvedProject->buildData.swap(restoredProject->buildData); QBS_CHECK(m_result.newlyResolvedProject->buildData); @@ -249,6 +245,12 @@ void BuildGraphLoader::trackProjectChanges(const SetupProjectParameters ¶met } } + // Products still left in the list do not exist anymore. + foreach (const ResolvedProductPtr &removedProduct, allRestoredProducts) { + onProductRemoved(removedProduct, m_result.newlyResolvedProject->buildData.data()); + productsWithChangedFiles.removeOne(removedProduct); + } + // Products still left in the list need resolving, either because they are new // or because they are newly enabled. if (!allNewlyResolvedProducts.isEmpty()) { @@ -257,9 +259,14 @@ void BuildGraphLoader::trackProjectChanges(const SetupProjectParameters ¶met allNewlyResolvedProducts); } - // Products still left in the list do not exist anymore. - foreach (const ResolvedProductPtr &removedProduct, allRestoredProducts) - onProductRemoved(removedProduct, m_result.newlyResolvedProject->buildData.data()); + // For products where only the list of files has changed, we adapt the existing build data + // so we won't recompile existing files just because new ones have been added. + foreach (const ResolvedProductPtr &product, productsWithChangedFiles) { + ResolvedProductPtr freshProduct = freshProductsByName.value(product->name); + if (!freshProduct) + continue; + onProductFileListChanged(product, freshProduct, oldBuildData.data()); + } foreach (const ResolvedProductConstPtr &changedProduct, changedProducts) { rescueOldBuildData(changedProduct, freshProductsByName.value(changedProduct->name), @@ -311,7 +318,7 @@ bool BuildGraphLoader::hasProductFileChanged(const QList<ResolvedProductPtr> &re } else if (referenceTime < pfi.lastModified()) { m_logger.qbsDebug() << "A product was changed, must re-resolve project"; hasChanged = true; - } else { + } else if (!productsWithChangedFiles.contains(product)) { foreach (const GroupPtr &group, product->groups) { if (!group->wildcards) continue; @@ -357,8 +364,9 @@ void BuildGraphLoader::checkAllProductsForChanges(const QList<ResolvedProductPtr = newlyResolvedProductsByName.value(restoredProduct->name); if (!newlyResolvedProduct) continue; - if (!sourceArtifactListsAreEqual(restoredProduct->allFiles(), - newlyResolvedProduct->allFiles())) { + if (!productsWithChangedFiles.contains(restoredProduct) + && !sourceArtifactListsAreEqual(restoredProduct->allFiles(), + newlyResolvedProduct->allFiles())) { m_logger.qbsDebug() << "File list of product '" << restoredProduct->name << "' was changed."; productsWithChangedFiles += restoredProduct; @@ -408,42 +416,42 @@ void BuildGraphLoader::onProductRemoved(const ResolvedProductPtr &product, m_logger.qbsDebug() << "[BG] product '" << product->name << "' removed."; product->project->products.removeOne(product); - if (product->buildData) { foreach (Artifact *artifact, product->buildData->artifacts) projectBuildData->removeArtifact(artifact, m_logger, removeArtifactsFromDisk, false); } } -void BuildGraphLoader::onProductFileListChanged(const ResolvedProductPtr &product, - const ResolvedProductPtr &changedProduct) +void BuildGraphLoader::onProductFileListChanged(const ResolvedProductPtr &restoredProduct, + const ResolvedProductPtr &newlyResolvedProduct, const ProjectBuildData *oldBuildData) { - m_logger.qbsDebug() << "[BG] product '" << product->name << "' changed."; + m_logger.qbsDebug() << "[BG] product '" << restoredProduct->name << "' changed."; ArtifactsPerFileTagMap artifactsPerFileTag; QList<Artifact *> addedArtifacts; ArtifactList artifactsToRemove; QHash<QString, SourceArtifactConstPtr> oldArtifacts, newArtifacts; - const QList<SourceArtifactPtr> oldProductAllFiles = product->allEnabledFiles(); - foreach (const SourceArtifactConstPtr &a, oldProductAllFiles) + const QList<SourceArtifactPtr> restoredProductAllFiles = restoredProduct->allEnabledFiles(); + foreach (const SourceArtifactConstPtr &a, restoredProductAllFiles) oldArtifacts.insert(a->absoluteFilePath, a); - foreach (const SourceArtifactPtr &a, changedProduct->allEnabledFiles()) { + foreach (const SourceArtifactPtr &a, newlyResolvedProduct->allEnabledFiles()) { newArtifacts.insert(a->absoluteFilePath, a); if (!oldArtifacts.contains(a->absoluteFilePath)) { // artifact added m_logger.qbsDebug() << "[BG] artifact '" << a->absoluteFilePath - << "' added to product " << product->name; - Artifact *newArtifact = lookupArtifact(product, a->absoluteFilePath); + << "' added to product " << restoredProduct->name; + Artifact *newArtifact = lookupArtifact(newlyResolvedProduct, oldBuildData, + a->absoluteFilePath, true); if (newArtifact) { // User added a source file that was a generated artifact in the previous // build, e.g. a C++ source file that was generated and now is a non-generated // source file. newArtifact->artifactType = Artifact::SourceFile; } else { - newArtifact = createArtifact(product, a, m_logger); + newArtifact = createArtifact(newlyResolvedProduct, a, m_logger); foreach (FileResourceBase *oldArtifactLookupResult, - product->topLevelProject()->buildData->lookupFiles(newArtifact->filePath())) { + oldBuildData->lookupFiles(newArtifact->filePath())) { if (oldArtifactLookupResult == newArtifact) continue; FileDependency *oldFileDependency @@ -454,7 +462,7 @@ void BuildGraphLoader::onProductFileListChanged(const ResolvedProductPtr &produc } // User added a source file that was recognized as file dependency in the // previous build, e.g. a C++ header file. - replaceFileDependencyWithArtifact(product, + replaceFileDependencyWithArtifact(newlyResolvedProduct, oldFileDependency, newArtifact); } @@ -463,13 +471,14 @@ void BuildGraphLoader::onProductFileListChanged(const ResolvedProductPtr &produc } } - foreach (const SourceArtifactPtr &a, oldProductAllFiles) { + foreach (const SourceArtifactPtr &a, restoredProductAllFiles) { const SourceArtifactConstPtr changedArtifact = newArtifacts.value(a->absoluteFilePath); if (!changedArtifact) { // artifact removed m_logger.qbsDebug() << "[BG] artifact '" << a->absoluteFilePath - << "' removed from product " << product->name; - Artifact *artifact = lookupArtifact(product, a->absoluteFilePath); + << "' removed from product " << restoredProduct->name; + Artifact *artifact + = lookupArtifact(restoredProduct, oldBuildData, a->absoluteFilePath, true); QBS_CHECK(artifact); removeArtifactAndExclusiveDependents(artifact, &artifactsToRemove); continue; @@ -481,7 +490,8 @@ void BuildGraphLoader::onProductFileListChanged(const ResolvedProductPtr &produc m_logger.qbsDebug() << "[BG] filetags have changed for artifact '" << a->absoluteFilePath << "' from " << a->fileTags << " to " << changedArtifact->fileTags; - Artifact *artifact = lookupArtifact(product, a->absoluteFilePath); + Artifact *artifact + = lookupArtifact(restoredProduct, oldBuildData, a->absoluteFilePath, true); QBS_CHECK(artifact); // handle added filetags @@ -503,30 +513,27 @@ void BuildGraphLoader::onProductFileListChanged(const ResolvedProductPtr &produc } } - // Discard groups of the old product. Use the groups of the new one. - product->groups = changedProduct->groups; - product->properties = changedProduct->properties; - if (!product->enabled) + if (!newlyResolvedProduct->enabled) return; // apply rules for new artifacts foreach (Artifact *artifact, addedArtifacts) foreach (const FileTag &ft, artifact->fileTags) artifactsPerFileTag[ft] += artifact; - RulesApplicator(product, artifactsPerFileTag, m_logger).applyAllRules(); + RulesApplicator(newlyResolvedProduct, artifactsPerFileTag, m_logger).applyAllRules(); - addTargetArtifacts(product, artifactsPerFileTag, m_logger); + addTargetArtifacts(newlyResolvedProduct, artifactsPerFileTag, m_logger); // parents of removed artifacts must update their transformers foreach (Artifact *removedArtifact, artifactsToRemove) foreach (Artifact *parent, removedArtifact->parents) - product->topLevelProject()->buildData->artifactsThatMustGetNewTransformers += parent; - product->topLevelProject()->buildData->updateNodesThatMustGetNewTransformer(m_logger); + newlyResolvedProduct->topLevelProject()->buildData->artifactsThatMustGetNewTransformers += parent; + newlyResolvedProduct->topLevelProject()->buildData->updateNodesThatMustGetNewTransformer(m_logger); // delete all removed artifacts physically from the disk foreach (Artifact *artifact, artifactsToRemove) { removeGeneratedArtifactFromDisk(artifact, m_logger); - delete artifact; + m_objectsToDelete << artifact; } } @@ -642,7 +649,7 @@ void BuildGraphLoader::replaceFileDependencyWithArtifact(const ResolvedProductPt } fileDepProduct->topLevelProject()->buildData->fileDependencies.remove(filedep); fileDepProduct->topLevelProject()->buildData->removeFromLookupTable(filedep); - delete filedep; + m_objectsToDelete << filedep; } static bool commandsEqual(const TransformerConstPtr &t1, const TransformerConstPtr &t2) @@ -679,7 +686,7 @@ void BuildGraphLoader::rescueOldBuildData(const ResolvedProductConstPtr &restore } Artifact * const oldArtifact = lookupArtifact(restoredProduct, oldBuildData, - artifact->dirPath(), artifact->fileName()); + artifact->dirPath(), artifact->fileName(), true); if (!oldArtifact || !oldArtifact->transformer) { if (m_logger.traceEnabled()) m_logger.qbsTrace() << QString::fromLocal8Bit("[BG] no transformer data"); |
