From 9fb791e9fad6c63fc1dac49f4d05ae63b8a3db9b Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 5 Jan 2016 11:55:15 +0200 Subject: Rename build directory/namespace to build2 --- build2/bin/module | 23 ++++++ build2/bin/module.cxx | 188 +++++++++++++++++++++++++++++++++++++++++++++++++ build2/bin/rule | 39 +++++++++++ build2/bin/rule.cxx | 145 ++++++++++++++++++++++++++++++++++++++ build2/bin/target | 99 ++++++++++++++++++++++++++ build2/bin/target.cxx | 190 ++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 684 insertions(+) create mode 100644 build2/bin/module create mode 100644 build2/bin/module.cxx create mode 100644 build2/bin/rule create mode 100644 build2/bin/rule.cxx create mode 100644 build2/bin/target create mode 100644 build2/bin/target.cxx (limited to 'build2/bin') diff --git a/build2/bin/module b/build2/bin/module new file mode 100644 index 0000000..85be444 --- /dev/null +++ b/build2/bin/module @@ -0,0 +1,23 @@ +// file : build2/bin/module -*- C++ -*- +// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BUILD2_BIN_MODULE +#define BUILD2_BIN_MODULE + +#include +#include + +#include + +namespace build2 +{ + namespace bin + { + extern "C" bool + bin_init ( + scope&, scope&, const location&, unique_ptr&, bool, bool); + } +} + +#endif // BUILD2_BIN_MODULE diff --git a/build2/bin/module.cxx b/build2/bin/module.cxx new file mode 100644 index 0000000..624a8d3 --- /dev/null +++ b/build2/bin/module.cxx @@ -0,0 +1,188 @@ +// file : build2/bin/module.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include + +#include +#include +#include + +#include +#include + +#include +#include + +using namespace std; + +namespace build2 +{ + namespace bin + { + static obj_rule obj_; + static lib_rule lib_; + + // Default config.bin.*.lib values. + // + static const strings exe_lib {"shared", "static"}; + static const strings liba_lib {"static"}; + static const strings libso_lib {"shared"}; + + extern "C" bool + bin_init (scope& r, + scope& b, + const location&, + std::unique_ptr&, + bool first, + bool) + { + tracer trace ("bin::init"); + level5 ([&]{trace << "for " << b.out_path ();}); + + // Enter module variables. + // + if (first) + { + auto& v (var_pool); + + v.find ("config.bin.lib", string_type); + v.find ("config.bin.exe.lib", strings_type); + v.find ("config.bin.liba.lib", strings_type); + v.find ("config.bin.libso.lib", strings_type); + v.find ("config.bin.rpath", strings_type); //@@ VAR paths_type + + v.find ("bin.lib", string_type); + v.find ("bin.exe.lib", strings_type); + v.find ("bin.liba.lib", strings_type); + v.find ("bin.libso.lib", strings_type); + v.find ("bin.rpath", strings_type); //@@ VAR paths_type + + v.find ("bin.libprefix", string_type); + } + + // Register target types. + // + { + auto& t (b.target_types); + + t.insert (); + t.insert (); + t.insert (); + t.insert (); + t.insert (); + t.insert (); + t.insert (); + } + + // Register rules. + // + { + auto& r (b.rules); + + r.insert (perform_update_id, "bin.obj", obj_); + r.insert (perform_clean_id, "bin.obj", obj_); + + r.insert (perform_update_id, "bin.lib", lib_); + r.insert (perform_clean_id, "bin.lib", lib_); + + // Configure member. + // + r.insert (configure_update_id, "bin.lib", lib_); + + //@@ Should we check if the install module was loaded + // (by checking if install operation is registered + // for this project)? If we do that, then install + // will have to be loaded before bin. Perhaps we + // should enforce loading of all operation-defining + // modules before all others? + // + r.insert (perform_install_id, "bin.lib", lib_); + } + + // Configure. + // + using config::required; + + // The idea here is as follows: if we already have one of + // the bin.* variables set, then we assume this is static + // project configuration and don't bother setting the + // corresponding config.bin.* variable. + // + //@@ Need to validate the values. Would be more efficient + // to do it once on assignment than every time on query. + // Custom var type? + // + + // config.bin.lib + // + { + value& v (b.assign ("bin.lib")); + if (!v) + v = required (r, "config.bin.lib", "both").first; + } + + // config.bin.exe.lib + // + { + value& v (b.assign ("bin.exe.lib")); + if (!v) + v = required (r, "config.bin.exe.lib", exe_lib).first; + } + + // config.bin.liba.lib + // + { + value& v (b.assign ("bin.liba.lib")); + if (!v) + v = required (r, "config.bin.liba.lib", liba_lib).first; + } + + // config.bin.libso.lib + // + { + value& v (b.assign ("bin.libso.lib")); + if (!v) + v = required (r, "config.bin.libso.lib", libso_lib).first; + } + + // config.bin.rpath + // + // This one is optional and we merge it into bin.rpath, if any. + // See the cxx module for details on merging. + // + if (const value& v = config::optional (r, "config.bin.rpath")) + b.assign ("bin.rpath") += as (v); + + + // Configure "installability" of our target types. + // + install::path (b, dir_path ("bin")); // Install into install.bin. + + // Should shared libraries have executable bit? That depends on + // who you ask. In Debian, for example, it should not unless, it + // really is executable (i.e., has main()). On the other hand, on + // some systems, this may be required in order for the dynamic + // linker to be able to load the library. So, by default, we will + // keep it executable, especially seeing that this is also the + // behavior of autotools. At the same time, it is easy to override + // this, for example: + // + // config.install.lib.mode=644 + // + // And a library that wants to override any such overrides (e.g., + // because it does have main()) can do: + // + // libso{foo}: install.mode=755 + // + // Everyone is happy then? + // + install::path (b, dir_path ("lib")); // Install into install.lib. + + install::path (b, dir_path ("lib")); // Install into install.lib. + install::mode (b, "644"); + + return true; + } + } +} diff --git a/build2/bin/rule b/build2/bin/rule new file mode 100644 index 0000000..ad52396 --- /dev/null +++ b/build2/bin/rule @@ -0,0 +1,39 @@ +// file : build2/bin/rule -*- C++ -*- +// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BUILD2_BIN_RULE +#define BUILD2_BIN_RULE + +#include + +namespace build2 +{ + namespace bin + { + class obj_rule: public rule + { + public: + virtual match_result + match (action, target&, const std::string& hint) const; + + virtual recipe + apply (action, target&, const match_result&) const; + }; + + class lib_rule: public rule + { + public: + virtual match_result + match (action, target&, const std::string& hint) const; + + virtual recipe + apply (action, target&, const match_result&) const; + + static target_state + perform (action, target&); + }; + } +} + +#endif // BUILD2_BIN_RULE diff --git a/build2/bin/rule.cxx b/build2/bin/rule.cxx new file mode 100644 index 0000000..9d93b0a --- /dev/null +++ b/build2/bin/rule.cxx @@ -0,0 +1,145 @@ +// file : build2/bin/rule.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include + +#include +#include +#include +#include + +#include + +using namespace std; + +namespace build2 +{ + namespace bin + { + // obj + // + match_result 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"; + + return nullptr; + } + + recipe obj_rule:: + apply (action, target&, const match_result&) const {return empty_recipe;} + + // lib + // + // The whole logic is pretty much as if we had our two group + // members as our prerequisites. + // + match_result lib_rule:: + match (action a, target& xt, const std::string&) const + { + lib& t (static_cast (xt)); + + // @@ We have to re-query it on each match_only()! + + // Get the library type to build. If not set for a target, this + // should be configured at the project scope by init_lib(). + // + const string& type (as (*t["bin.lib"])); + + 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"; + + // Search and pre-match the members. The pre-match here is part + // of the "library meta-information protocol" that could be used + // by the module that actually builds the members. The idea is + // that pre-matching members may populate our prerequisite_targets + // with prerequisite libraries from which others can extract the + // meta-information about the library, such as the options to use + // when linking it, etc. + // + if (ar) + { + if (t.a == nullptr) + t.a = &search (t.dir, t.name, t.ext, nullptr); + + match_only (a, *t.a); + } + + if (so) + { + if (t.so == nullptr) + t.so = &search (t.dir, t.name, t.ext, nullptr); + + match_only (a, *t.so); + } + + match_result mr (t, &type); + + // If there is an outer operation, indicate that we match + // unconditionally so that we don't override ourselves. + // + if (a.outer_operation () != 0) + mr.recipe_action = action (a.meta_operation (), a.operation ()); + + return mr; + } + + recipe lib_rule:: + apply (action a, target& xt, const match_result& mr) const + { + lib& t (static_cast (xt)); + + const string& type (*static_cast (mr.cpvalue)); + + bool ar (type == "static" || type == "both"); + bool so (type == "shared" || type == "both"); + + // Now we do full match. + // + if (ar) + build2::match (a, *t.a); + + if (so) + build2::match (a, *t.so); + + return &perform; + } + + target_state lib_rule:: + perform (action a, target& xt) + { + lib& t (static_cast (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 (as (*t["bin.lib"])); + 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 r (target_state::unchanged); + + if (m1 != nullptr) + r |= execute (a, *m1); + + if (m2 != nullptr) + r |= execute (a, *m2); + + return r; + } + } +} diff --git a/build2/bin/target b/build2/bin/target new file mode 100644 index 0000000..e785ac0 --- /dev/null +++ b/build2/bin/target @@ -0,0 +1,99 @@ +// file : build2/bin/target -*- C++ -*- +// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BUILD2_BIN_TARGET +#define BUILD2_BIN_TARGET + +#include + +namespace build2 +{ + namespace bin + { + // The obj{} target group. + // + class obja: public file + { + public: + using file::file; + + public: + static const target_type static_type; + virtual const target_type& dynamic_type () const {return static_type;} + }; + + class objso: public file + { + public: + using file::file; + + public: + static const target_type static_type; + virtual const target_type& dynamic_type () const {return static_type;} + }; + + class obj: public target + { + public: + using target::target; + + obja* a {nullptr}; + objso* so {nullptr}; + + public: + static const target_type static_type; + virtual const target_type& dynamic_type () const {return static_type;} + }; + + class exe: public file + { + public: + using file::file; + + public: + static const target_type static_type; + virtual const target_type& dynamic_type () const {return static_type;} + }; + + // The lib{} target group. + // + class liba: public file + { + public: + using file::file; + + public: + static const target_type static_type; + virtual const target_type& dynamic_type () const {return static_type;} + }; + + class libso: public file + { + public: + using file::file; + + public: + static const target_type static_type; + virtual const target_type& dynamic_type () const {return static_type;} + }; + + class lib: public target + { + public: + using target::target; + + liba* a {nullptr}; + libso* so {nullptr}; + + virtual void + reset (action_type); + + public: + static const target_type static_type; + virtual const target_type& dynamic_type () const {return static_type;} + }; + } +} + +#endif // BUILD2_BIN_TARGET diff --git a/build2/bin/target.cxx b/build2/bin/target.cxx new file mode 100644 index 0000000..6241a7b --- /dev/null +++ b/build2/bin/target.cxx @@ -0,0 +1,190 @@ +// file : build2/bin/target.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include + +using namespace std; + +namespace build2 +{ + namespace bin + { + static target* + obja_factory (const target_type&, dir_path d, string n, const string* e) + { + obj* o (targets.find (d, n)); + obja* a (new obja (move (d), move (n), e)); + + if ((a->group = o)) + o->a = a; + + return a; + } + + const target_type obja::static_type + { + "obja", + &file::static_type, + &obja_factory, + nullptr, + &search_target, // Note: not _file(); don't look for an existing file. + false + }; + + static target* + objso_factory (const target_type&, dir_path d, string n, const string* e) + { + obj* o (targets.find (d, n)); + objso* so (new objso (move (d), move (n), e)); + + if ((so->group = o)) + o->so = so; + + return so; + } + + const target_type objso::static_type + { + "objso", + &file::static_type, + &objso_factory, + nullptr, + &search_target, // Note: not _file(); don't look for an existing file. + false + }; + + static target* + obj_factory (const target_type&, dir_path d, string n, const string* e) + { + obja* a (targets.find (d, n)); + objso* so (targets.find (d, n)); + obj* o (new obj (move (d), move (n), e)); + + if ((o->a = a)) + a->group = o; + + if ((o->so = so)) + so->group = o; + + return o; + } + + const target_type obj::static_type + { + "obj", + &target::static_type, + &obj_factory, + nullptr, + &search_target, + false + }; + + const target_type exe::static_type + { + "exe", + &file::static_type, + &target_factory, + nullptr, + &search_file, + false + }; + + static target* + liba_factory (const target_type& t, dir_path d, string n, const string* e) + { + // Only link-up to the group if the types match exactly. + // + lib* l (t == liba::static_type ? targets.find (d, n) : nullptr); + liba* a (new liba (move (d), move (n), e)); + + if ((a->group = l)) + l->a = a; + + return a; + } + + // @@ + // + // What extensions should we use? At the outset, this is platform- + // dependent. And if we consider cross-compilation, is it build or + // host-dependent? Feels like it should be host-dependent so that + // we can copy things between cross and native environments. So + // these will have to be determined based on what we are building. + // As if this is not complicated enough, the bin module doesn't + // know anything about building. So perhaps the extension should + // come from a variable that is set not by bin but by the module + // whose rule matched the target (e.g., cxx::link). + // + constexpr const char a_ext[] = "a"; + const target_type liba::static_type + { + "liba", + &file::static_type, + &liba_factory, + &target_extension_fix, + &search_file, + false + }; + + static target* + libso_factory (const target_type& t, dir_path d, string n, const string* e) + { + // Only link-up to the group if the types match exactly. + // + lib* l (t == libso::static_type ? targets.find (d, n) : nullptr); + libso* so (new libso (move (d), move (n), e)); + + if ((so->group = l)) + l->so = so; + + return so; + } + + constexpr const char so_ext[] = "so"; + const target_type libso::static_type + { + "libso", + &file::static_type, + &libso_factory, + &target_extension_fix, + &search_file, + false + }; + + // lib + // + void lib:: + reset (action_type) + { + // Don't clear prerequisite_targets since it is "given" to our + // members to implement "library meta-information protocol". + } + + static target* + lib_factory (const target_type&, dir_path d, string n, const string* e) + { + liba* a (targets.find (d, n)); + libso* so (targets.find (d, n)); + lib* l (new lib (move (d), move (n), e)); + + if ((l->a = a)) + a->group = l; + + if ((l->so = so)) + so->group = l; + + return l; + } + + const target_type lib::static_type + { + "lib", + &target::static_type, + &lib_factory, + nullptr, + &search_target, + false + }; + } +} -- cgit v1.1