aboutsummaryrefslogtreecommitdiff
path: root/libbuild2
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2024-02-22 09:28:16 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2024-02-22 09:28:16 +0200
commit626bd6434662436423d0c5cd9689149076ebed07 (patch)
tree69a5e42736594580857c8f79ba61e2b7f57691f1 /libbuild2
parent13840225f01b5000e726b27ad2cca1f4837e0a4d (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.cxx15
-rw-r--r--libbuild2/target.hxx27
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: