diff options
Diffstat (limited to 'libbuild2/cc/link-rule.hxx')
-rw-r--r-- | libbuild2/cc/link-rule.hxx | 154 |
1 files changed, 98 insertions, 56 deletions
diff --git a/libbuild2/cc/link-rule.hxx b/libbuild2/cc/link-rule.hxx index f990415..9b491c2 100644 --- a/libbuild2/cc/link-rule.hxx +++ b/libbuild2/cc/link-rule.hxx @@ -18,11 +18,13 @@ namespace build2 { namespace cc { - class LIBBUILD2_CC_SYMEXPORT link_rule: public simple_rule, virtual common + class LIBBUILD2_CC_SYMEXPORT link_rule: public rule, virtual common { public: link_rule (data&&); + struct match_data; + struct match_result { bool seen_x = false; @@ -46,18 +48,21 @@ namespace build2 match (action, const target&, const target*, otype, bool) const; virtual bool - match (action, target&, const string&) const override; + match (action, target&, const string&, match_extra&) const override; virtual recipe - apply (action, target&) const override; + apply (action, target&, match_extra&) const override; target_state - perform_update (action, const target&) const; + perform_update (action, const target&, match_data&) const; target_state - perform_clean (action, const target&) const; + perform_clean (action, const target&, match_data&) const; - using simple_rule::match; // To make Clang happy. + virtual const target* + import (const prerequisite_key&, + const optional<string>&, + const location&) const override; public: // Library handling. @@ -81,11 +86,10 @@ namespace build2 class appended_libraries: public small_vector<appended_library, 128> { public: - // Find existing or append new entry. If appending new, use the second - // argument as the begin value. + // Find existing entry, if any. // - appended_library& - append (const file& l, size_t b) + appended_library* + find (const file& l) { auto i (find_if (begin (), end (), [&l] (const appended_library& al) @@ -93,19 +97,11 @@ namespace build2 return al.l2 == nullptr && al.l1 == &l; })); - if (i != end ()) - return *i; - - push_back (appended_library {&l, nullptr, b, appended_library::npos}); - return back (); + return i != end () ? &*i : nullptr; } - // Return NULL if no duplicate tracking can be performed for this - // library. - // appended_library* - append (const small_vector<reference_wrapper<const string>, 2>& ns, - size_t b) + find (const small_vector<reference_wrapper<const string>, 2>& ns) { size_t n (ns.size ()); @@ -125,8 +121,36 @@ namespace build2 : al.l1 == nullptr); })); - if (i != end ()) - return &*i; + return i != end () ? &*i : nullptr; + } + + // Find existing or append new entry. If appending new, use the second + // argument as the begin value. + // + appended_library& + append (const file& l, size_t b) + { + if (appended_library* r = find (l)) + return *r; + + push_back (appended_library {&l, nullptr, b, appended_library::npos}); + return back (); + } + + // Return NULL if no duplicate tracking can be performed for this + // library. + // + appended_library* + append (const small_vector<reference_wrapper<const string>, 2>& ns, + size_t b) + { + size_t n (ns.size ()); + + if (n > 2) + return nullptr; + + if (appended_library* r = find (ns)) + return r; push_back (appended_library { n == 2 ? &ns[1].get () : nullptr, &ns[0].get (), @@ -172,21 +196,19 @@ namespace build2 void append_libraries (appended_libraries&, strings&, + sha256*, bool*, timestamp, const scope&, action, const file&, bool, lflags, linfo, - bool = true, bool = true) const; - - void - append_libraries (sha256&, bool&, timestamp, - const scope&, action, - const file&, bool, lflags, linfo) const; + optional<bool>, bool = true, bool = true, + library_cache* = nullptr) const; using rpathed_libraries = small_vector<const file*, 256>; void rpath_libraries (rpathed_libraries&, strings&, const scope&, - action, const file&, bool, linfo, bool, bool) const; + action, const file&, bool, linfo, bool, bool, + library_cache* = nullptr) const; void rpath_libraries (strings&, @@ -194,12 +216,15 @@ namespace build2 const target&, linfo, bool) const; void - append_binless_modules (strings&, + append_binless_modules (strings&, sha256*, const scope&, action, const file&) const; - void - append_binless_modules (sha256&, - const scope&, action, const file&) const; + bool + deduplicate_export_libs ( + const scope&, + const vector<name>&, + names&, + vector<reference_wrapper<const name>>* = nullptr) const; optional<path> find_system_library (const strings&) const; @@ -208,9 +233,9 @@ namespace build2 static void functions (function_family&, const char*); // functions.cxx - private: - friend class install_rule; - friend class libux_install_rule; + // Implementation details. + // + public: // Shared library paths. // @@ -253,27 +278,36 @@ namespace build2 struct match_data { + explicit + match_data (const link_rule& r): rule (r) {} + // The "for install" condition is signalled to us by install_rule when // it is matched for the update operation. It also verifies that if we // have already been executed, then it was for install. // // This has an interesting implication: it means that this rule cannot - // be used to update targets during match. Specifically, we cannot be - // executed for group resolution purposes (not a problem) nor as part - // of the generated source update. The latter case can be a problem: - // imagine a code generator that itself may need to be updated before - // it can be used to re-generate some out-of-date source code. As an - // aside, note that even if we were somehow able to communicate the - // "for install" in this case, the result of such an update may not - // actually be "usable" (e.g., not runnable because of the missing + // be used to update targets to be installed during match (since we + // would notice that they are for install too late). Specifically, we + // cannot be executed for group resolution purposes (should not be a + // problem) nor as part of the generated source update. The latter + // case can be a problem: imagine a source code generator that itself + // may need to be updated before it can be used to re-generate some + // out-of-date source code (or, worse, both the generator and the + // target to be installed depend on the same library). + // + // As an aside, note that even if we were somehow able to communicate + // the "for install" in this case, the result of such an update may + // not actually be "usable" (e.g., not runnable because of the missing // rpaths). There is another prominent case where the result may not - // be usable: cross-compilation. + // be usable: cross-compilation (in fact, if you think about it, "for + // install" is quite similar to cross-compilation: we are building for + // a foreign "environment" and thus cannot execute the results of the + // build). // - // So the current (admittedly fuzzy) thinking is that a project shall - // not try to use its own build for update since it may not be usable - // (because of cross-compilations, being "for install", etc). Instead, - // it should rely on another, "usable" build of itself (this, BTW, is - // related to bpkg's build-time vs run-time dependencies). + // So the current thinking is that a project shall not try to use its + // own "for install" (or, naturally, cross-compilation) build for + // update since it may not be usable. Instead, it should rely on + // another, "usable" build. // optional<bool> for_install; @@ -281,20 +315,28 @@ namespace build2 size_t start; // Parallel prerequisites/prerequisite_targets start. link_rule::libs_paths libs_paths; + + const link_rule& rule; + + target_state + operator() (action a, const target& t) + { + return a == perform_update_id + ? rule.perform_update (a, t, *this) + : rule.perform_clean (a, t, *this); + } }; // Windows rpath emulation (windows-rpath.cxx). // + private: struct windows_dll { - const string& dll; - const string* pdb; // NULL if none. - string pdb_storage; - - bool operator< (const windows_dll& y) const {return dll < y.dll;} + reference_wrapper<const string> dll; + string pdb; // Empty if none. }; - using windows_dlls = set<windows_dll>; + using windows_dlls = vector<windows_dll>; timestamp windows_rpath_timestamp (const file&, |