From bcfcc38538af8bb896551c9e5730767807ad7a67 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 7 Feb 2017 10:05:47 +0200 Subject: Tighten code that operates during both search/match and execute --- build2/cc/common.cxx | 166 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 99 insertions(+), 67 deletions(-) (limited to 'build2/cc/common.cxx') diff --git a/build2/cc/common.cxx b/build2/cc/common.cxx index 62a4ab2..654ff53 100644 --- a/build2/cc/common.cxx +++ b/build2/cc/common.cxx @@ -422,15 +422,16 @@ namespace build2 // dir_path out; prerequisite_key pk {n.proj, {tt, &n.dir, &out, &n.value, ext}, &s}; - xt = search_library (sysd, usrd, pk); //@@ TM const + xt = search_library_existing (sysd, usrd, pk); if (xt == nullptr) { if (n.qualified ()) - xt = &import (pk); //@@ TM const - else - fail << "unable to find library " << pk; + xt = import_existing (pk); } + + if (xt == nullptr) + fail << "unable to find library " << pk; } // If this is lib{}, pick appropriate member. @@ -448,7 +449,8 @@ namespace build2 target* common:: search_library (const dir_paths& sysd, optional& usrd, - const prerequisite_key& p) const + const prerequisite_key& p, + bool exist) const { tracer trace (x, "search_library"); @@ -544,11 +546,31 @@ namespace build2 path f; // Reuse the buffer. const dir_path* pd (nullptr); + // Insert a target verifying that it already exists if requested. + // + auto insert = [&name, exist, &trace] (auto*& r, + const dir_path& d, + optional ext) + { + using T = typename std::remove_reference::type; + + auto p (targets.insert (T::static_type, + d, + dir_path (), + name, + move (ext), + true, // Implied. + trace)); + + assert (!exist || !p.second); + r = static_cast (&p.first); + }; + auto search =[&a, &s, &an, &ae, &sn, &se, &name, ext, - &p, &f, &trace, this] (const dir_path& d) -> bool + &p, &f, &insert, exist, this] (const dir_path& d) -> bool { timestamp mt; @@ -571,17 +593,17 @@ namespace build2 // if (tclass == "windows") { - s = &targets.insert (d, dir_path (), name, nullopt, trace); + insert (s, d, nullopt); if (s->member == nullptr) { - libi& i ( - targets.insert (d, dir_path (), name, se, trace)); + libi* i; + insert (i, d, se); - if (i.path ().empty ()) - i.path (move (f)); + if (i->path ().empty ()) + i->path (move (f)); - i.mtime (mt); + i->mtime (mt); // Presumably there is a DLL somewhere, we just don't know // where (and its possible we might have to look for one if we @@ -590,12 +612,12 @@ namespace build2 // but valid timestamp (aka "trust me, it's there"). // s->mtime (mt); - s->member = &i; + s->member = i; } } else { - s = &targets.insert (d, dir_path (), name, se, trace); + insert (s, d, se); if (s->path ().empty ()) s->path (move (f)); @@ -617,7 +639,7 @@ namespace build2 if (mt != timestamp_nonexistent) { - s = &targets.insert (d, dir_path (), name, se, trace); + insert (s, d, se); if (s->path ().empty ()) s->path (move (f)); @@ -644,7 +666,7 @@ namespace build2 // Note that this target is outside any project which we treat // as out trees. // - a = &targets.insert (d, dir_path (), name, ae, trace); + insert (a, d, ae); if (a->path ().empty ()) a->path (move (f)); @@ -661,10 +683,10 @@ namespace build2 const process_path& ld (cast (rs["bin.ld.path"])); if (s == nullptr && !sn.empty ()) - s = msvc_search_shared (ld, d, p); + s = msvc_search_shared (ld, d, p, exist); if (a == nullptr && !an.empty ()) - a = msvc_search_static (ld, d, p); + a = msvc_search_static (ld, d, p, exist); } return a != nullptr || s != nullptr; @@ -705,6 +727,62 @@ namespace build2 if (pd == nullptr) return nullptr; + // Enter (or find) the lib{} target group. Note that we must be careful + // here since its possible we have already imported some of its members. + // + lib* lt; + insert (lt, *pd, l ? p.tk.ext : nullopt); + + // It should automatically link-up to the members we have found. + // + assert (a == nullptr || lt->a == a); + assert (s == nullptr || lt->s == s); + + // Update the bin.lib variable to indicate what's available. Assume + // already done if existing. + // + if (!exist) + { + const char* bl (lt->a != nullptr + ? (lt->s != nullptr ? "both" : "static") + : "shared"); + lt->assign (var_pool["bin.lib"]) = bl; + } + + target* r (l ? lt : (p.is_a () ? static_cast (a) : s)); + + // Mark as a "cc" library (unless already marked) and set the system + // flag. + // + auto mark_cc = [sys, this] (target& t) -> bool + { + auto p (t.vars.insert (c_type)); + + if (p.second) + { + p.first.get () = string ("cc"); + + if (sys) + t.vars.assign (c_system) = true; + } + + return p.second; + }; + + // If the library already has cc.type, then assume it was either already + // imported or was matched by a rule. + // + // Assume already done if existing. + // + if (!exist) + { + if (a != nullptr && !mark_cc (*a)) + a = nullptr; + + if (s != nullptr && !mark_cc (*s)) + s = nullptr; + } + // Add the "using static/shared library" macro (used, for example, to // handle DLL export). The absence of either of these macros would mean // some other build system that cannot distinguish between the two (and @@ -754,55 +832,9 @@ namespace build2 } }; - // Enter (or find) the lib{} target group. Note that we must be careful - // here since its possible we have already imported some of its members. - // - lib& lt ( - targets.insert ( - *pd, dir_path (), name, l ? p.tk.ext : nullopt, trace)); - - // It should automatically link-up to the members we have found. - // - assert (a == nullptr || lt.a == a); - assert (s == nullptr || lt.s == s); - - // Update the bin.lib variable to indicate what's available. - // - const char* bl (lt.a != nullptr - ? (lt.s != nullptr ? "both" : "static") - : "shared"); - lt.assign (var_pool["bin.lib"]) = bl; - - target* r (l ? < : (p.is_a () ? static_cast (a) : s)); - - // Mark as a "cc" library (unless already marked) and set the system - // flag. - // - auto mark_cc = [sys, this] (target& t) -> bool - { - auto p (t.vars.insert (c_type)); - - if (p.second) - { - p.first.get () = string ("cc"); - - if (sys) - t.vars.assign (c_system) = true; - } - - return p.second; - }; - - // If the library already has cc.type, then assume it was either already - // imported or was matched by a rule. + // Assume already done if existing. // - if (a != nullptr && !mark_cc (*a)) - a = nullptr; - - if (s != nullptr && !mark_cc (*s)) - s = nullptr; - - if (a != nullptr || s != nullptr) + if (!exist && (a != nullptr || s != nullptr)) { // Try to extract library information from pkg-config. We only add the // default macro if we could not extract more precise information. The @@ -810,7 +842,7 @@ namespace build2 // macros (or custom ones) from *.export.poptions. // if (pkgconfig == nullptr || - !pkgconfig_extract (*p.scope, lt, a, s, p.proj, name, *pd, sysd)) + !pkgconfig_extract (*p.scope, *lt, a, s, p.proj, name, *pd, sysd)) { if (a != nullptr) add_macro (*a, "STATIC"); if (s != nullptr) add_macro (*s, "SHARED"); -- cgit v1.1