diff options
Diffstat (limited to 'build/bin/rule.cxx')
-rw-r--r-- | build/bin/rule.cxx | 126 |
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; + } + } +} |