aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@qt.io>2018-01-19 10:58:43 +0100
committerChristian Kandeler <christian.kandeler@qt.io>2018-01-19 10:58:43 +0100
commit13e8c5371709c9e1c337c664062aec19930c306b (patch)
tree5cf5ad7eeffbf136f0bfcb17375a118d8160f584 /src
parent8ba1aa806bdb313161acad22d9b16c33b295e607 (diff)
parentd3e137c20248f6852a91341782011ca58534ed21 (diff)
Merge 1.10 into 1.11
Diffstat (limited to 'src')
-rw-r--r--src/lib/corelib/language/item.h1
-rw-r--r--src/lib/corelib/language/moduleloader.cpp62
2 files changed, 44 insertions, 19 deletions
diff --git a/src/lib/corelib/language/item.h b/src/lib/corelib/language/item.h
index b86c50a3c..97ca3ad91 100644
--- a/src/lib/corelib/language/item.h
+++ b/src/lib/corelib/language/item.h
@@ -164,7 +164,6 @@ private:
};
inline bool operator<(const Item::Module &m1, const Item::Module &m2) { return m1.name < m2.name; }
-inline bool operator==(const Item::Module &m1, const Item::Module &m2) { return m1.item == m2.item; }
} // namespace Internal
} // namespace qbs
diff --git a/src/lib/corelib/language/moduleloader.cpp b/src/lib/corelib/language/moduleloader.cpp
index 81d1088b5..35d0636b6 100644
--- a/src/lib/corelib/language/moduleloader.cpp
+++ b/src/lib/corelib/language/moduleloader.cpp
@@ -1000,17 +1000,42 @@ void ModuleLoader::setupProductDependencies(ProductContext *productContext)
productContext->project->result->productInfos.insert(item, productContext->info);
}
-// Non-dependencies first.
+// Leaf modules first.
static void createSortedModuleList(const Item::Module &parentModule, Item::Modules &modules)
{
- if (contains(modules, parentModule))
+ if (std::find_if(modules.cbegin(), modules.cend(),
+ [parentModule](const Item::Module &m) { return m.name == parentModule.name;})
+ != modules.cend()) {
return;
+ }
for (const Item::Module &dep : parentModule.item->modules())
createSortedModuleList(dep, modules);
modules.push_back(parentModule);
return;
}
+static Item::Modules modulesSortedByDependency(const Item *productItem)
+{
+ QBS_CHECK(productItem->type() == ItemType::Product);
+ Item::Modules sortedModules;
+ const Item::Modules &unsortedModules = productItem->modules();
+ for (const Item::Module &module : unsortedModules)
+ createSortedModuleList(module, sortedModules);
+ QBS_CHECK(sortedModules.size() == unsortedModules.size());
+
+ // Make sure the top-level items stay the same.
+ for (Item::Module &s : sortedModules) {
+ for (const Item::Module &u : unsortedModules) {
+ if (s.name == u.name) {
+ s.item = u.item;
+ break;
+ }
+ }
+ }
+ return sortedModules;
+}
+
+
template<typename T> bool insertIntoSet(Set<T> &set, const T &value)
{
const auto insertionResult = set.insert(value);
@@ -1045,21 +1070,22 @@ void ModuleLoader::handleProduct(ModuleLoader::ProductContext *productContext)
Item * const item = productContext->item;
- Item::Modules mergedModules;
- for (const Item::Module &module : Item::Modules(item->modules())) {
- Item::Module mergedModule = module;
- ModuleMerger(m_logger, item, mergedModule).start();
- mergedModules << mergedModule;
- }
- item->setModules(mergedModules);
-
- // Must happen after all modules have been merged, so needs to be a second loop.
- Item::Modules sortedModules;
- for (const Item::Module &module : item->modules())
- createSortedModuleList(module, sortedModules);
- QBS_CHECK(sortedModules.size() == item->modules().size());
-
- for (const Item::Module &module : qAsConst(sortedModules)) {
+ // It is important that dependent modules are merged after their dependency, because
+ // the dependent module's merger potentially needs to replace module items that were
+ // set by the dependency module's merger (namely, scopes of defining items; see
+ // ModuleMerger::replaceItemInScopes()).
+ Item::Modules topSortedModules = modulesSortedByDependency(item);
+ for (Item::Module &module : topSortedModules)
+ ModuleMerger(m_logger, item, module).start();
+
+ // Re-sort the modules by name. This is more stable; see QBS-818.
+ // The list of modules in the product now has the same order as before,
+ // only the items have been replaced by their merged counterparts.
+ Item::Modules lexicographicallySortedModules = topSortedModules;
+ std::sort(lexicographicallySortedModules.begin(), lexicographicallySortedModules.end());
+ item->setModules(lexicographicallySortedModules);
+
+ for (const Item::Module &module : topSortedModules) {
if (!module.item->isPresentModule())
continue;
try {
@@ -1101,7 +1127,7 @@ void ModuleLoader::handleProduct(ModuleLoader::ProductContext *productContext)
// Module validation must happen in an extra pass, after all Probes have been resolved.
EvalCacheEnabler cacheEnabler(m_evaluator);
- for (const Item::Module &module : qAsConst(sortedModules)) {
+ for (const Item::Module &module : topSortedModules) {
if (!module.item->isPresentModule())
continue;
try {