aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/cc/link-rule.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2/cc/link-rule.hxx')
-rw-r--r--libbuild2/cc/link-rule.hxx154
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&,