diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2022-04-20 08:55:59 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2022-04-20 08:55:59 +0200 |
commit | dca10cb2cc9ae928edf945274b5860d5bbc9dea3 (patch) | |
tree | 1fdcadeac9599c4bd5db53fab700dfc8fdef6008 | |
parent | 9034f7c51ef6437ce9d4547ba5bde217b4740fb2 (diff) |
Add import cache
-rw-r--r-- | libbuild2/context.hxx | 20 | ||||
-rw-r--r-- | libbuild2/file.cxx | 59 |
2 files changed, 77 insertions, 2 deletions
diff --git a/libbuild2/context.hxx b/libbuild2/context.hxx index 9083556..6eb85f7 100644 --- a/libbuild2/context.hxx +++ b/libbuild2/context.hxx @@ -540,6 +540,26 @@ namespace build2 build2::meta_operation_table meta_operation_table; build2::operation_table operation_table; + // Import cache (see import_load()). + // + struct import_key + { + dir_path out_root; // Imported project's out root. + name target; // Imported target (unqualified). + uint64_t metadata; // Metadata version (0 if none). + + friend bool + operator< (const import_key& x, const import_key& y) + { + int r; + return ((r = x.out_root.compare (y.out_root)) != 0 ? r < 0 : + (r = x.target.compare (y.target)) != 0 ? r < 0 : + x.metadata < y.metadata); + } + }; + + map<import_key, pair<names, const scope&>> import_cache; + // The old/new src_root remapping for subprojects. // dir_path old_src_root; diff --git a/libbuild2/file.cxx b/libbuild2/file.cxx index 31db943..47b8c4f 100644 --- a/libbuild2/file.cxx +++ b/libbuild2/file.cxx @@ -1522,6 +1522,10 @@ namespace build2 // path f (src_root / root.root_extra->root_file); + // @@ What if no root.build (like an amalgamation)? Also, why create + // a path to check? Maybe just have a flag in root_extra? Also why + // not put buildfiles in root_extra? + // if (root.buildfiles.find (f) != root.buildfiles.end ()) return; @@ -2413,6 +2417,8 @@ namespace build2 { tracer trace ("import_load"); + uint64_t metav (meta ? 1 : 0); // Metadata version. + // We end up here in two cases: Ad hoc import, in which case name is // unqualified and absolute and path is a base, not necessarily root. And // normal import, in which case name must be project-qualified and path is @@ -2475,14 +2481,51 @@ namespace build2 } } + // First check the cache. + // + using import_key = context::import_key; + + auto cache_find = [&ctx, &tgt, metav] (dir_path& out_root) -> + const pair<names, const scope&>* + { + import_key k {move (out_root), move (tgt), metav}; + + auto i (ctx.import_cache.find (k)); + if (i != ctx.import_cache.end ()) + return &i->second; + + out_root = move (k.out_root); + tgt = move (k.target); + + return nullptr; + }; + + if (proj) + { + if (const auto* r = cache_find (out_root)) + return *r; + } + + dir_path cache_out_root; + // Clear current project's environment. // auto_project_env penv (nullptr); + // Note: this loop does at most two iterations. + // for (const scope* proot (nullptr); ; proot = root) { bool top (proot == nullptr); + // Check the cache for the subproject. + // + if (!top && proj) + { + if (const auto* r = cache_find (out_root)) + return *r; + } + root = create_root (ctx, out_root, src_root)->second.front (); bool bstrapped (bootstrapped (*root)); @@ -2561,6 +2604,8 @@ namespace build2 if (i != ps->end ()) { + cache_out_root = move (out_root); + const dir_path& d ((*i).second); altn = nullopt; out_root = root->out_path () / d; @@ -2589,6 +2634,9 @@ namespace build2 // "Pass" the imported project's roots to the stub. // + if (cache_out_root.empty ()) + cache_out_root = out_root; + ts.assign (ctx.var_out_root) = move (out_root); ts.assign (ctx.var_src_root) = move (src_root); @@ -2604,7 +2652,7 @@ namespace build2 // Pass the metadata compatibility version in import.metadata. // if (meta) - ts.assign (ctx.var_import_metadata) = uint64_t (1); + ts.assign (ctx.var_import_metadata) = metav; // Load the export stub. Note that it is loaded in the context of the // importing project, not the imported one. The export stub will @@ -2640,7 +2688,14 @@ namespace build2 fail (loc) << "target " << tgt << " is not exported by project " << *proj; - return pair<names, const scope&> (move (v), *root); + pair<names, const scope&> r (move (v), *root); + + // Cache. + // + ctx.import_cache.emplace ( + import_key {move (cache_out_root), move (tgt), metav}, r); + + return r; } catch (const io_error& e) { |