diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2024-02-22 09:28:16 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2024-02-22 09:28:16 +0200 |
commit | 626bd6434662436423d0c5cd9689149076ebed07 (patch) | |
tree | 69a5e42736594580857c8f79ba61e2b7f57691f1 /libbuild2 | |
parent | 13840225f01b5000e726b27ad2cca1f4837e0a4d (diff) |
Detect non-cc::link_rule libraries not marked with cc.type=cc
Fixes GH issue #368.
Diffstat (limited to 'libbuild2')
-rw-r--r-- | libbuild2/cc/link-rule.cxx | 15 | ||||
-rw-r--r-- | libbuild2/target.hxx | 27 |
2 files changed, 36 insertions, 6 deletions
diff --git a/libbuild2/cc/link-rule.cxx b/libbuild2/cc/link-rule.cxx index d705eb5..704fb47 100644 --- a/libbuild2/cc/link-rule.cxx +++ b/libbuild2/cc/link-rule.cxx @@ -2261,14 +2261,21 @@ namespace build2 *type != "cc" && type->compare (0, 3, "cc,") != 0) { - auto& md (l->data<link_rule::match_data> (d.a)); - assert (md.for_install); // Must have been executed. + auto* md (l->try_data<link_rule::match_data> (d.a)); + + if (md == nullptr) + fail << "library " << *l << " is not built with cc module-based " + << "link rule" << + info << "mark it as generic with cc.type=cc target-specific " + << "variable"; + + assert (md->for_install); // Must have been executed. // The user will get the target name from the context info. // - if (*md.for_install != *d.for_install) + if (*md->for_install != *d.for_install) fail << "incompatible " << *l << " build" << - info << "library is built " << (*md.for_install ? "" : "not ") + info << "library is built " << (*md->for_install ? "" : "not ") << "for install"; } diff --git a/libbuild2/target.hxx b/libbuild2/target.hxx index 0d4eece..20cd32d 100644 --- a/libbuild2/target.hxx +++ b/libbuild2/target.hxx @@ -1219,13 +1219,28 @@ namespace build2 } template <typename T> - typename std::enable_if<!data_invocable<T>::value, T&>::type& + typename std::enable_if<!data_invocable<T>::value, T&>::type data (action a) const { using V = typename std::remove_cv<T>::type; return state[a].recipe.target<data_wrapper<V>> ()->d; } + // Return NULL if there is no data or the data is of a different type. + // + template <typename T> + typename std::enable_if<!data_invocable<T>::value, T*>::type + try_data (action a) const + { + using V = typename std::remove_cv<T>::type; + + if (auto& r = state[a].recipe) + if (auto* t = r.target<data_wrapper<V>> ()) + return &t->d; + + return nullptr; + } + // Note that in this case we don't strip const (the expectation is that we // move the recipe in/out of data). // @@ -1250,12 +1265,20 @@ namespace build2 } template <typename T> - typename std::enable_if<data_invocable<T>::value, T&>::type& + typename std::enable_if<data_invocable<T>::value, T&>::type data (action a) const { return *state[a].recipe.target<T> (); } + template <typename T> + typename std::enable_if<data_invocable<T>::value, T*>::type + try_data (action a) const + { + auto& r = state[a].recipe; + return r ? r.target<T> () : nullptr; + } + // Target type info and casting. // public: |