aboutsummaryrefslogtreecommitdiff
path: root/build/bin/rule.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-04-24 12:29:20 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-04-24 12:29:20 +0200
commit2a0f9e035f673f1ee387924501a31990de37f18d (patch)
treeb8e55ab74bc88b788e99d8649219b931b80432d5 /build/bin/rule.cxx
parent4c44c914d898af53152addad5530504548175e85 (diff)
Implement lib/liba/libso{} target group, shared/static library build
Diffstat (limited to 'build/bin/rule.cxx')
-rw-r--r--build/bin/rule.cxx126
1 files changed, 126 insertions, 0 deletions
diff --git a/build/bin/rule.cxx b/build/bin/rule.cxx
new file mode 100644
index 0000000..1b887bf
--- /dev/null
+++ b/build/bin/rule.cxx
@@ -0,0 +1,126 @@
+// file : build/bin/rule.cxx -*- C++ -*-
+// copyright : Copyright (c) 2014-2015 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#include <build/bin/rule>
+
+#include <build/scope>
+#include <build/target>
+#include <build/algorithm>
+#include <build/diagnostics>
+
+#include <build/config/utility>
+
+#include <build/bin/target>
+
+using namespace std;
+
+namespace build
+{
+ namespace bin
+ {
+ // obj
+ //
+ void* obj_rule::
+ match (action a, target& t, const std::string&) const
+ {
+ fail << diag_doing (a, t) << " target group" <<
+ info << "explicitly select either obja{} or objso{} member";
+ }
+
+ recipe obj_rule::
+ apply (action, target&, void*) const {return empty_recipe;}
+
+ // lib
+ //
+ // The whole logic is pretty much as if we had our two group
+ // members as prerequisites.
+ //
+ void* lib_rule::
+ match (action, target& t, const std::string&) const
+ {
+ return &t;
+ }
+
+ recipe lib_rule::
+ apply (action a, target& xt, void*) const
+ {
+ lib& t (static_cast<lib&> (xt));
+
+ // Configure.
+ //
+ // The logic is as follows: if this library somehow knowns what
+ // it wants to be (i.e., the bin.lib is defined), then don't
+ // bother configuring the project-wide value.
+ //
+ const string* type (nullptr);
+
+ if (auto v = t["bin.lib"])
+ type = &v.as<const string&> ();
+ else
+ {
+ scope& root (*t.root_scope ());
+ type = &config::required (root, "config.bin.lib", "shared").first;
+ root.assign ("bin.lib") = *type;
+ }
+
+ bool ar (*type == "static" || *type == "both");
+ bool so (*type == "shared" || *type == "both");
+
+ if (!ar && !so)
+ fail << "unknown library type: " << *type <<
+ info << "'static', 'shared', or 'both' expected";
+
+ if (ar)
+ {
+ if (t.a == nullptr)
+ t.a = &static_cast<liba&> (search (prerequisite_key {
+ &liba::static_type, &t.dir, &t.name, &t.ext, nullptr}));
+
+ build::match (a, *t.a);
+ }
+
+ if (so)
+ {
+ if (t.so == nullptr)
+ t.so = &static_cast<libso&> (search (prerequisite_key {
+ &libso::static_type, &t.dir, &t.name, &t.ext, nullptr}));
+
+ build::match (a, *t.so);
+ }
+
+ return &perform;
+ }
+
+ target_state lib_rule::
+ perform (action a, target& xt)
+ {
+ lib& t (static_cast<lib&> (xt));
+
+ //@@ Not cool we have to do this again. Looks like we need
+ // some kind of a cache vs resolved pointer, like in
+ // prerequisite vs prerequisite_target.
+ //
+ //
+ const string& type (t["bin.lib"].as<const string&> ());
+ bool ar (type == "static" || type == "both");
+ bool so (type == "shared" || type == "both");
+
+ target* m1 (ar ? t.a : nullptr);
+ target* m2 (so ? t.so : nullptr);
+
+ if (current_mode == execution_mode::last)
+ swap (m1, m2);
+
+ target_state ts (target_state::unchanged);
+
+ if (m1 != nullptr && execute (a, *m1) == target_state::changed)
+ ts = target_state::changed;
+
+ if (m2 != nullptr && execute (a, *m2) == target_state::changed)
+ ts = target_state::changed;
+
+ return ts;
+ }
+ }
+}