From 53eb43126e562a43f4e8f2247af10da5c4c3c87f Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 12 Aug 2016 16:39:13 +0200 Subject: Rename module to init --- build2/bin/init | 91 +++++++ build2/bin/init.cxx | 714 ++++++++++++++++++++++++++++++++++++++++++++++++++ build2/bin/module | 91 ------- build2/bin/module.cxx | 714 -------------------------------------------------- 4 files changed, 805 insertions(+), 805 deletions(-) create mode 100644 build2/bin/init create mode 100644 build2/bin/init.cxx delete mode 100644 build2/bin/module delete mode 100644 build2/bin/module.cxx (limited to 'build2/bin') diff --git a/build2/bin/init b/build2/bin/init new file mode 100644 index 0000000..139362d --- /dev/null +++ b/build2/bin/init @@ -0,0 +1,91 @@ +// file : build2/bin/init -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BUILD2_BIN_INIT +#define BUILD2_BIN_INIT + +#include +#include + +#include + +namespace build2 +{ + namespace bin + { + bool + config_init (scope&, + scope&, + const location&, + unique_ptr&, + bool, + bool, + const variable_map&); + + bool + init (scope&, + scope&, + const location&, + unique_ptr&, + bool, + bool, + const variable_map&); + + bool + ar_config_init (scope&, + scope&, + const location&, + unique_ptr&, + bool, + bool, + const variable_map&); + + bool + ar_init (scope&, + scope&, + const location&, + unique_ptr&, + bool, + bool, + const variable_map&); + + bool + ld_config_init (scope&, + scope&, + const location&, + unique_ptr&, + bool, + bool, + const variable_map&); + + bool + ld_init (scope&, + scope&, + const location&, + unique_ptr&, + bool, + bool, + const variable_map&); + + bool + rc_config_init (scope&, + scope&, + const location&, + unique_ptr&, + bool, + bool, + const variable_map&); + + bool + rc_init (scope&, + scope&, + const location&, + unique_ptr&, + bool, + bool, + const variable_map&); + } +} + +#endif // BUILD2_BIN_INIT diff --git a/build2/bin/init.cxx b/build2/bin/init.cxx new file mode 100644 index 0000000..102c060 --- /dev/null +++ b/build2/bin/init.cxx @@ -0,0 +1,714 @@ +// file : build2/bin/init.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include + +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +using namespace std; +using namespace butl; + +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 libs_lib {"shared"}; + + bool + config_init (scope& r, + scope& b, + const location& loc, + unique_ptr&, + bool first, + bool, + const variable_map& hints) + { + tracer trace ("bin::config_init"); + l5 ([&]{trace << "for " << b.out_path ();}); + + // Enter configuration variables. + // + if (first) + { + auto& v (var_pool); + + // Note: some overridable, some not. + // + v.insert ("config.bin.target", true); + v.insert ("config.bin.pattern", true); + + v.insert ("config.bin.lib", true); + v.insert ("config.bin.exe.lib", true); + v.insert ("config.bin.liba.lib", true); + v.insert ("config.bin.libs.lib", true); + v.insert ("config.bin.rpath", true); + + v.insert ("bin.lib"); + v.insert ("bin.exe.lib"); + v.insert ("bin.liba.lib"); + v.insert ("bin.libs.lib"); + v.insert ("bin.rpath"); + } + + // Configure. + // + using config::required; + using config::optional; + + // Adjust module priority (binutils). + // + config::save_module (r, "bin", 350); + + // 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.libs.lib + // + { + value& v (b.assign ("bin.libs.lib")); + if (!v) + v = required (r, "config.bin.libs.lib", libs_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. + // + b.assign ("bin.rpath") += cast_null ( + optional (r, "config.bin.rpath")); + + if (first) + { + bool new_val (false); // Set any new values? + + // config.bin.target + // + { + const variable& var (var_pool.find ("config.bin.target")); + + // We first see if the value was specified via the configuration + // mechanism. + // + auto p (required (r, var)); + const value* v (p.first); + + // Then see if there is a config hint (e.g., from the C++ module). + // + bool hint (false); + if (v == nullptr) + { + if (auto l = hints[var]) + { + v = l.value; + hint = true; + } + } + + if (v == nullptr) + fail (loc) << "unable to determine binutils target" << + info << "consider specifying it with " << var.name << + info << "or first load a module that can provide it as a hint, " + << "such as c or cxx"; + + // Split/canonicalize the target. + // + string s (cast (*v)); + + // Did the user ask us to use config.sub? If this is a hinted value, + // then we assume it has already been passed through config.sub. + // + if (!hint && ops.config_sub_specified ()) + { + s = run (ops.config_sub (), + s.c_str (), + [] (string& l) {return move (l);}); + l5 ([&]{trace << "config.sub target: '" << s << "'";}); + } + + try + { + string canon; + triplet t (s, canon); + + l5 ([&]{trace << "canonical target: '" << canon << "'; " + << "class: " << t.class_;}); + + assert (!hint || s == canon); + + // Enter as bin.target.{cpu,vendor,system,version,class}. + // + r.assign ("bin.target") = move (canon); + r.assign ("bin.target.cpu") = move (t.cpu); + r.assign ("bin.target.vendor") = move (t.vendor); + r.assign ("bin.target.system") = move (t.system); + r.assign ("bin.target.version") = move (t.version); + r.assign ("bin.target.class") = move (t.class_); + } + catch (const invalid_argument& e) + { + // This is where we suggest that the user specifies --config-sub + // to help us out. + // + fail << "unable to parse binutils target '" << s << "': " + << e.what () << + info << "consider using the --config-sub option"; + } + + new_val = new_val || p.second; // False for a hinted value. + } + + // config.bin.pattern + // + { + const variable& var (var_pool.find ("config.bin.pattern")); + + // We first see if the value was specified via the configuration + // mechanism. + // + auto p (required (r, var)); + const value* v (p.first); + + // Then see if there is a config hint (e.g., from the C++ module). + // + if (v == nullptr) + { + if (auto l = hints[var]) + v = l.value; + } + + // For ease of use enter it as bin.pattern (since it can come from + // different places). + // + if (v != nullptr) + { + const string& s (cast (*v)); + + if (s.find ('*') == string::npos) + fail << "missing '*' in binutils pattern '" << s << "'"; + + r.assign ("bin.pattern") = s; + new_val = new_val || p.second; // False for a hinted value. + } + } + + // If we set any new values (e.g., we are configuring), then print the + // report at verbosity level 2 and up (-v). + // + if (verb >= (new_val ? 2 : 3)) + { + diag_record dr (text); + + dr << "bin " << project (r) << '@' << r.out_path () << '\n' + << " target " << cast (r["bin.target"]); + + if (auto l = r["bin.pattern"]) + dr << '\n' + << " pattern " << cast (l); + } + } + + return true; + } + + bool + init (scope& r, + scope& b, + const location& loc, + unique_ptr&, + bool first, + bool, + const variable_map& hints) + { + tracer trace ("bin::init"); + l5 ([&]{trace << "for " << b.out_path ();}); + + // Enter the rest of the variables. + // + if (first) + { + auto& v (var_pool); + + v.insert ("bin.libprefix", true); + } + + // Load bin.config. + // + if (!cast_false (b["bin.config.loaded"])) + load_module ("bin.config", r, b, loc, false, hints); + + // Cache some config values we will be needing below. + // + const string& tclass (cast (r["bin.target.class"])); + + // Register target types and configure their default "installability". + // + using namespace install; + + { + auto& t (b.target_types); + + t.insert (); + t.insert (); + t.insert (); + t.insert (); + + t.insert (); + install_path (b, dir_path ("bin")); // Install into install.bin. + + t.insert (); + t.insert (); + t.insert (); + + install_path (b, dir_path ("lib")); // Install into install.lib. + install_mode (b, "644"); + + // Should shared libraries have the 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: + // + // libs{foo}: install.mode=755 + // + // Everyone is happy then? On Windows libs{} is the DLL and goes to + // bin/, not lib/. + // + install_path (b, dir_path (tclass == "windows" ? "bin" : "lib")); + + // Create additional target types for certain targets. + // + if (tclass == "windows") + { + // Import library. + // + t.insert (); + install_path (b, dir_path ("lib")); + install_mode (b, "644"); + } + } + + // 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_); + } + + return true; + } + + bool + ar_config_init (scope& r, + scope& b, + const location& loc, + unique_ptr&, + bool first, + bool, + const variable_map& hints) + { + tracer trace ("bin::ar_config_init"); + l5 ([&]{trace << "for " << b.out_path ();}); + + // Make sure bin.config is loaded. + // + if (!cast_false (b["bin.config.loaded"])) + load_module ("bin.config", r, b, loc, false, hints); + + // Enter configuration variables. + // + if (first) + { + auto& v (var_pool); + + v.insert ("config.bin.ar", true); + v.insert ("config.bin.ranlib", true); + } + + // Configure. + // + if (first) + { + // config.bin.ar + // config.bin.ranlib + // + // For config.bin.ar we have the default (plus the pattern) while + // ranlib should be explicitly specified by the user in order for us + // to use it (all targets that we currently care to support have the + // ar -s option but if that changes we can always force the use of + // ranlib for certain targets). + // + // Another idea is to refuse to use default 'ar' (without the pattern) + // if the host/build targets don't match. On the other hand, a cross- + // toolchain can be target-unprefixed. Also, without canonicalization, + // comparing targets will be unreliable. + // + + // Use the target to decide on the default binutils program names. + // + const string& tsys (cast (r["bin.target.system"])); + const char* ar_d (tsys == "win32-msvc" ? "lib" : "ar"); + + // Don't save the default value to config.build so that if the user + // changes, say, the C++ compiler (which hinted the pattern), then + // ar will automatically change as well. + // + auto ap ( + config::required ( + r, + "config.bin.ar", + path (apply_pattern (ar_d, cast_null (r["bin.pattern"]))), + false, + config::save_commented)); + + auto rp ( + config::required ( + r, + "config.bin.ranlib", + nullptr, + false, + config::save_commented)); + + const path& ar (cast (ap.first)); + const path* ranlib (cast_null (rp.first)); + + if (ranlib != nullptr && ranlib->empty ()) // @@ BC LT [null]. + ranlib = nullptr; + + ar_info ari (guess_ar (ar, ranlib)); + + // If this is a new value (e.g., we are configuring), then print the + // report at verbosity level 2 and up (-v). + // + if (verb >= (ap.second || rp.second ? 2 : 3)) + { + diag_record dr (text); + + dr << "bin.ar " << project (r) << '@' << r.out_path () << '\n' + << " ar " << ar << '\n' + << " id " << ari.ar_id << '\n' + << " signature " << ari.ar_signature << '\n' + << " checksum " << ari.ar_checksum; + + if (ranlib != nullptr) + { + dr << '\n' + << " ranlib " << *ranlib << '\n' + << " id " << ari.ranlib_id << '\n' + << " signature " << ari.ranlib_signature << '\n' + << " checksum " << ari.ranlib_checksum; + } + } + + r.assign ("bin.ar.id") = move (ari.ar_id); + r.assign ("bin.ar.signature") = move (ari.ar_signature); + r.assign ("bin.ar.checksum") = move (ari.ar_checksum); + + if (ranlib != nullptr) + { + r.assign ("bin.ranlib.id") = move (ari.ranlib_id); + r.assign ("bin.ranlib.signature") = + move (ari.ranlib_signature); + r.assign ("bin.ranlib.checksum") = + move (ari.ranlib_checksum); + } + } + + return true; + } + + bool + ar_init (scope& r, + scope& b, + const location& loc, + unique_ptr&, + bool, + bool, + const variable_map& hints) + { + tracer trace ("bin::ar_init"); + l5 ([&]{trace << "for " << b.out_path ();}); + + // Make sure the bin core and ar.config are loaded. + // + if (!cast_false (b["bin.loaded"])) + load_module ("bin", r, b, loc, false, hints); + + if (!cast_false (b["bin.ar.config.loaded"])) + load_module ("bin.ar.config", r, b, loc, false, hints); + + return true; + } + + bool + ld_config_init (scope& r, + scope& b, + const location& loc, + unique_ptr&, + bool first, + bool, + const variable_map& hints) + { + tracer trace ("bin::ld_config_init"); + l5 ([&]{trace << "for " << b.out_path ();}); + + // Make sure bin.config is loaded. + // + if (!cast_false (b["bin.config.loaded"])) + load_module ("bin.config", r, b, loc, false, hints); + + // Enter configuration variables. + // + if (first) + { + auto& v (var_pool); + + v.insert ("config.bin.ld", true); + } + + // Configure. + // + if (first) + { + // config.bin.ld + // + // Use the target to decide on the default ld name. + // + const string& tsys (cast (r["bin.target.system"])); + const char* ld_d (tsys == "win32-msvc" ? "link" : "ld"); + + auto p ( + config::required ( + r, + "config.bin.ld", + path (apply_pattern (ld_d, cast_null (r["bin.pattern"]))), + false, + config::save_commented)); + + const path& ld (cast (p.first)); + ld_info ldi (guess_ld (ld)); + + // If this is a new value (e.g., we are configuring), then print the + // report at verbosity level 2 and up (-v). + // + if (verb >= (p.second ? 2 : 3)) + { + text << "bin.ld " << project (r) << '@' << r.out_path () << '\n' + << " ld " << ld << '\n' + << " id " << ldi.id << '\n' + << " signature " << ldi.signature << '\n' + << " checksum " << ldi.checksum; + } + + r.assign ("bin.ld.id") = move (ldi.id); + r.assign ("bin.ld.signature") = move (ldi.signature); + r.assign ("bin.ld.checksum") = move (ldi.checksum); + } + + return true; + } + + bool + ld_init (scope& r, + scope& b, + const location& loc, + unique_ptr&, + bool, + bool, + const variable_map& hints) + { + tracer trace ("bin::ld_init"); + l5 ([&]{trace << "for " << b.out_path ();}); + + // Make sure the bin core and ld.config are loaded. + // + if (!cast_false (b["bin.loaded"])) + load_module ("bin", r, b, loc, false, hints); + + if (!cast_false (b["bin.ld.config.loaded"])) + load_module ("bin.ld.config", r, b, loc, false, hints); + + const string& lid (cast (r["bin.ld.id"])); + + // Register the pdb{} target if using the VC toolchain. + // + using namespace install; + + if (lid == "msvc") + { + const target_type& pdb (b.derive_target_type ("pdb").first); + install_path (pdb, b, dir_path ("bin")); // Goes to install.bin + install_mode (pdb, b, "644"); // But not executable. + } + + return true; + } + + bool + rc_config_init (scope& r, + scope& b, + const location& loc, + unique_ptr&, + bool first, + bool, + const variable_map& hints) + { + tracer trace ("bin::rc_config_init"); + l5 ([&]{trace << "for " << b.out_path ();}); + + // Make sure bin.config is loaded. + // + if (!cast_false (b["bin.config.loaded"])) + load_module ("bin.config", r, b, loc, false, hints); + + // Enter configuration variables. + // + if (first) + { + auto& v (var_pool); + + v.insert ("config.bin.rc", true); + } + + // Configure. + // + if (first) + { + // config.bin.rc + // + // Use the target to decide on the default rc name. + // + const string& tsys (cast (r["bin.target.system"])); + const char* rc_d (tsys == "win32-msvc" ? "rc" : "windres"); + + auto p ( + config::required ( + r, + "config.bin.rc", + path (apply_pattern (rc_d, cast_null (r["bin.pattern"]))), + false, + config::save_commented)); + + const path& rc (cast (p.first)); + rc_info rci (guess_rc (rc)); + + // If this is a new value (e.g., we are configuring), then print the + // report at verbosity level 2 and up (-v). + // + if (verb >= (p.second ? 2 : 3)) + { + text << "bin.rc " << project (r) << '@' << r.out_path () << '\n' + << " rc " << rc << '\n' + << " id " << rci.id << '\n' + << " signature " << rci.signature << '\n' + << " checksum " << rci.checksum; + } + + r.assign ("bin.rc.id") = move (rci.id); + r.assign ("bin.rc.signature") = move (rci.signature); + r.assign ("bin.rc.checksum") = move (rci.checksum); + } + + return true; + } + + bool + rc_init (scope& r, + scope& b, + const location& loc, + unique_ptr&, + bool, + bool, + const variable_map& hints) + { + tracer trace ("bin::rc_init"); + l5 ([&]{trace << "for " << b.out_path ();}); + + // Make sure the bin core and rc.config are loaded. + // + if (!cast_false (b["bin.loaded"])) + load_module ("bin", r, b, loc, false, hints); + + if (!cast_false (b["bin.rc.config.loaded"])) + load_module ("bin.rc.config", r, b, loc, false, hints); + + return true; + } + } +} diff --git a/build2/bin/module b/build2/bin/module deleted file mode 100644 index 8cf0255..0000000 --- a/build2/bin/module +++ /dev/null @@ -1,91 +0,0 @@ -// file : build2/bin/module -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BUILD2_BIN_MODULE -#define BUILD2_BIN_MODULE - -#include -#include - -#include - -namespace build2 -{ - namespace bin - { - bool - config_init (scope&, - scope&, - const location&, - unique_ptr&, - bool, - bool, - const variable_map&); - - bool - init (scope&, - scope&, - const location&, - unique_ptr&, - bool, - bool, - const variable_map&); - - bool - ar_config_init (scope&, - scope&, - const location&, - unique_ptr&, - bool, - bool, - const variable_map&); - - bool - ar_init (scope&, - scope&, - const location&, - unique_ptr&, - bool, - bool, - const variable_map&); - - bool - ld_config_init (scope&, - scope&, - const location&, - unique_ptr&, - bool, - bool, - const variable_map&); - - bool - ld_init (scope&, - scope&, - const location&, - unique_ptr&, - bool, - bool, - const variable_map&); - - bool - rc_config_init (scope&, - scope&, - const location&, - unique_ptr&, - bool, - bool, - const variable_map&); - - bool - rc_init (scope&, - scope&, - const location&, - unique_ptr&, - bool, - bool, - const variable_map&); - } -} - -#endif // BUILD2_BIN_MODULE diff --git a/build2/bin/module.cxx b/build2/bin/module.cxx deleted file mode 100644 index 89f20af..0000000 --- a/build2/bin/module.cxx +++ /dev/null @@ -1,714 +0,0 @@ -// file : build2/bin/module.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include - -#include - -#include -#include -#include - -#include -#include - -#include -#include -#include - -using namespace std; -using namespace butl; - -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 libs_lib {"shared"}; - - bool - config_init (scope& r, - scope& b, - const location& loc, - unique_ptr&, - bool first, - bool, - const variable_map& hints) - { - tracer trace ("bin::config_init"); - l5 ([&]{trace << "for " << b.out_path ();}); - - // Enter configuration variables. - // - if (first) - { - auto& v (var_pool); - - // Note: some overridable, some not. - // - v.insert ("config.bin.target", true); - v.insert ("config.bin.pattern", true); - - v.insert ("config.bin.lib", true); - v.insert ("config.bin.exe.lib", true); - v.insert ("config.bin.liba.lib", true); - v.insert ("config.bin.libs.lib", true); - v.insert ("config.bin.rpath", true); - - v.insert ("bin.lib"); - v.insert ("bin.exe.lib"); - v.insert ("bin.liba.lib"); - v.insert ("bin.libs.lib"); - v.insert ("bin.rpath"); - } - - // Configure. - // - using config::required; - using config::optional; - - // Adjust module priority (binutils). - // - config::save_module (r, "bin", 350); - - // 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.libs.lib - // - { - value& v (b.assign ("bin.libs.lib")); - if (!v) - v = required (r, "config.bin.libs.lib", libs_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. - // - b.assign ("bin.rpath") += cast_null ( - optional (r, "config.bin.rpath")); - - if (first) - { - bool new_val (false); // Set any new values? - - // config.bin.target - // - { - const variable& var (var_pool.find ("config.bin.target")); - - // We first see if the value was specified via the configuration - // mechanism. - // - auto p (required (r, var)); - const value* v (p.first); - - // Then see if there is a config hint (e.g., from the C++ module). - // - bool hint (false); - if (v == nullptr) - { - if (auto l = hints[var]) - { - v = l.value; - hint = true; - } - } - - if (v == nullptr) - fail (loc) << "unable to determine binutils target" << - info << "consider specifying it with " << var.name << - info << "or first load a module that can provide it as a hint, " - << "such as c or cxx"; - - // Split/canonicalize the target. - // - string s (cast (*v)); - - // Did the user ask us to use config.sub? If this is a hinted value, - // then we assume it has already been passed through config.sub. - // - if (!hint && ops.config_sub_specified ()) - { - s = run (ops.config_sub (), - s.c_str (), - [] (string& l) {return move (l);}); - l5 ([&]{trace << "config.sub target: '" << s << "'";}); - } - - try - { - string canon; - triplet t (s, canon); - - l5 ([&]{trace << "canonical target: '" << canon << "'; " - << "class: " << t.class_;}); - - assert (!hint || s == canon); - - // Enter as bin.target.{cpu,vendor,system,version,class}. - // - r.assign ("bin.target") = move (canon); - r.assign ("bin.target.cpu") = move (t.cpu); - r.assign ("bin.target.vendor") = move (t.vendor); - r.assign ("bin.target.system") = move (t.system); - r.assign ("bin.target.version") = move (t.version); - r.assign ("bin.target.class") = move (t.class_); - } - catch (const invalid_argument& e) - { - // This is where we suggest that the user specifies --config-sub - // to help us out. - // - fail << "unable to parse binutils target '" << s << "': " - << e.what () << - info << "consider using the --config-sub option"; - } - - new_val = new_val || p.second; // False for a hinted value. - } - - // config.bin.pattern - // - { - const variable& var (var_pool.find ("config.bin.pattern")); - - // We first see if the value was specified via the configuration - // mechanism. - // - auto p (required (r, var)); - const value* v (p.first); - - // Then see if there is a config hint (e.g., from the C++ module). - // - if (v == nullptr) - { - if (auto l = hints[var]) - v = l.value; - } - - // For ease of use enter it as bin.pattern (since it can come from - // different places). - // - if (v != nullptr) - { - const string& s (cast (*v)); - - if (s.find ('*') == string::npos) - fail << "missing '*' in binutils pattern '" << s << "'"; - - r.assign ("bin.pattern") = s; - new_val = new_val || p.second; // False for a hinted value. - } - } - - // If we set any new values (e.g., we are configuring), then print the - // report at verbosity level 2 and up (-v). - // - if (verb >= (new_val ? 2 : 3)) - { - diag_record dr (text); - - dr << "bin " << project (r) << '@' << r.out_path () << '\n' - << " target " << cast (r["bin.target"]); - - if (auto l = r["bin.pattern"]) - dr << '\n' - << " pattern " << cast (l); - } - } - - return true; - } - - bool - init (scope& r, - scope& b, - const location& loc, - unique_ptr&, - bool first, - bool, - const variable_map& hints) - { - tracer trace ("bin::init"); - l5 ([&]{trace << "for " << b.out_path ();}); - - // Enter the rest of the variables. - // - if (first) - { - auto& v (var_pool); - - v.insert ("bin.libprefix", true); - } - - // Load bin.config. - // - if (!cast_false (b["bin.config.loaded"])) - load_module ("bin.config", r, b, loc, false, hints); - - // Cache some config values we will be needing below. - // - const string& tclass (cast (r["bin.target.class"])); - - // Register target types and configure their default "installability". - // - using namespace install; - - { - auto& t (b.target_types); - - t.insert (); - t.insert (); - t.insert (); - t.insert (); - - t.insert (); - install_path (b, dir_path ("bin")); // Install into install.bin. - - t.insert (); - t.insert (); - t.insert (); - - install_path (b, dir_path ("lib")); // Install into install.lib. - install_mode (b, "644"); - - // Should shared libraries have the 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: - // - // libs{foo}: install.mode=755 - // - // Everyone is happy then? On Windows libs{} is the DLL and goes to - // bin/, not lib/. - // - install_path (b, dir_path (tclass == "windows" ? "bin" : "lib")); - - // Create additional target types for certain targets. - // - if (tclass == "windows") - { - // Import library. - // - t.insert (); - install_path (b, dir_path ("lib")); - install_mode (b, "644"); - } - } - - // 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_); - } - - return true; - } - - bool - ar_config_init (scope& r, - scope& b, - const location& loc, - unique_ptr&, - bool first, - bool, - const variable_map& hints) - { - tracer trace ("bin::ar_config_init"); - l5 ([&]{trace << "for " << b.out_path ();}); - - // Make sure bin.config is loaded. - // - if (!cast_false (b["bin.config.loaded"])) - load_module ("bin.config", r, b, loc, false, hints); - - // Enter configuration variables. - // - if (first) - { - auto& v (var_pool); - - v.insert ("config.bin.ar", true); - v.insert ("config.bin.ranlib", true); - } - - // Configure. - // - if (first) - { - // config.bin.ar - // config.bin.ranlib - // - // For config.bin.ar we have the default (plus the pattern) while - // ranlib should be explicitly specified by the user in order for us - // to use it (all targets that we currently care to support have the - // ar -s option but if that changes we can always force the use of - // ranlib for certain targets). - // - // Another idea is to refuse to use default 'ar' (without the pattern) - // if the host/build targets don't match. On the other hand, a cross- - // toolchain can be target-unprefixed. Also, without canonicalization, - // comparing targets will be unreliable. - // - - // Use the target to decide on the default binutils program names. - // - const string& tsys (cast (r["bin.target.system"])); - const char* ar_d (tsys == "win32-msvc" ? "lib" : "ar"); - - // Don't save the default value to config.build so that if the user - // changes, say, the C++ compiler (which hinted the pattern), then - // ar will automatically change as well. - // - auto ap ( - config::required ( - r, - "config.bin.ar", - path (apply_pattern (ar_d, cast_null (r["bin.pattern"]))), - false, - config::save_commented)); - - auto rp ( - config::required ( - r, - "config.bin.ranlib", - nullptr, - false, - config::save_commented)); - - const path& ar (cast (ap.first)); - const path* ranlib (cast_null (rp.first)); - - if (ranlib != nullptr && ranlib->empty ()) // @@ BC LT [null]. - ranlib = nullptr; - - ar_info ari (guess_ar (ar, ranlib)); - - // If this is a new value (e.g., we are configuring), then print the - // report at verbosity level 2 and up (-v). - // - if (verb >= (ap.second || rp.second ? 2 : 3)) - { - diag_record dr (text); - - dr << "bin.ar " << project (r) << '@' << r.out_path () << '\n' - << " ar " << ar << '\n' - << " id " << ari.ar_id << '\n' - << " signature " << ari.ar_signature << '\n' - << " checksum " << ari.ar_checksum; - - if (ranlib != nullptr) - { - dr << '\n' - << " ranlib " << *ranlib << '\n' - << " id " << ari.ranlib_id << '\n' - << " signature " << ari.ranlib_signature << '\n' - << " checksum " << ari.ranlib_checksum; - } - } - - r.assign ("bin.ar.id") = move (ari.ar_id); - r.assign ("bin.ar.signature") = move (ari.ar_signature); - r.assign ("bin.ar.checksum") = move (ari.ar_checksum); - - if (ranlib != nullptr) - { - r.assign ("bin.ranlib.id") = move (ari.ranlib_id); - r.assign ("bin.ranlib.signature") = - move (ari.ranlib_signature); - r.assign ("bin.ranlib.checksum") = - move (ari.ranlib_checksum); - } - } - - return true; - } - - bool - ar_init (scope& r, - scope& b, - const location& loc, - unique_ptr&, - bool, - bool, - const variable_map& hints) - { - tracer trace ("bin::ar_init"); - l5 ([&]{trace << "for " << b.out_path ();}); - - // Make sure the bin core and ar.config are loaded. - // - if (!cast_false (b["bin.loaded"])) - load_module ("bin", r, b, loc, false, hints); - - if (!cast_false (b["bin.ar.config.loaded"])) - load_module ("bin.ar.config", r, b, loc, false, hints); - - return true; - } - - bool - ld_config_init (scope& r, - scope& b, - const location& loc, - unique_ptr&, - bool first, - bool, - const variable_map& hints) - { - tracer trace ("bin::ld_config_init"); - l5 ([&]{trace << "for " << b.out_path ();}); - - // Make sure bin.config is loaded. - // - if (!cast_false (b["bin.config.loaded"])) - load_module ("bin.config", r, b, loc, false, hints); - - // Enter configuration variables. - // - if (first) - { - auto& v (var_pool); - - v.insert ("config.bin.ld", true); - } - - // Configure. - // - if (first) - { - // config.bin.ld - // - // Use the target to decide on the default ld name. - // - const string& tsys (cast (r["bin.target.system"])); - const char* ld_d (tsys == "win32-msvc" ? "link" : "ld"); - - auto p ( - config::required ( - r, - "config.bin.ld", - path (apply_pattern (ld_d, cast_null (r["bin.pattern"]))), - false, - config::save_commented)); - - const path& ld (cast (p.first)); - ld_info ldi (guess_ld (ld)); - - // If this is a new value (e.g., we are configuring), then print the - // report at verbosity level 2 and up (-v). - // - if (verb >= (p.second ? 2 : 3)) - { - text << "bin.ld " << project (r) << '@' << r.out_path () << '\n' - << " ld " << ld << '\n' - << " id " << ldi.id << '\n' - << " signature " << ldi.signature << '\n' - << " checksum " << ldi.checksum; - } - - r.assign ("bin.ld.id") = move (ldi.id); - r.assign ("bin.ld.signature") = move (ldi.signature); - r.assign ("bin.ld.checksum") = move (ldi.checksum); - } - - return true; - } - - bool - ld_init (scope& r, - scope& b, - const location& loc, - unique_ptr&, - bool, - bool, - const variable_map& hints) - { - tracer trace ("bin::ld_init"); - l5 ([&]{trace << "for " << b.out_path ();}); - - // Make sure the bin core and ld.config are loaded. - // - if (!cast_false (b["bin.loaded"])) - load_module ("bin", r, b, loc, false, hints); - - if (!cast_false (b["bin.ld.config.loaded"])) - load_module ("bin.ld.config", r, b, loc, false, hints); - - const string& lid (cast (r["bin.ld.id"])); - - // Register the pdb{} target if using the VC toolchain. - // - using namespace install; - - if (lid == "msvc") - { - const target_type& pdb (b.derive_target_type ("pdb").first); - install_path (pdb, b, dir_path ("bin")); // Goes to install.bin - install_mode (pdb, b, "644"); // But not executable. - } - - return true; - } - - bool - rc_config_init (scope& r, - scope& b, - const location& loc, - unique_ptr&, - bool first, - bool, - const variable_map& hints) - { - tracer trace ("bin::rc_config_init"); - l5 ([&]{trace << "for " << b.out_path ();}); - - // Make sure bin.config is loaded. - // - if (!cast_false (b["bin.config.loaded"])) - load_module ("bin.config", r, b, loc, false, hints); - - // Enter configuration variables. - // - if (first) - { - auto& v (var_pool); - - v.insert ("config.bin.rc", true); - } - - // Configure. - // - if (first) - { - // config.bin.rc - // - // Use the target to decide on the default rc name. - // - const string& tsys (cast (r["bin.target.system"])); - const char* rc_d (tsys == "win32-msvc" ? "rc" : "windres"); - - auto p ( - config::required ( - r, - "config.bin.rc", - path (apply_pattern (rc_d, cast_null (r["bin.pattern"]))), - false, - config::save_commented)); - - const path& rc (cast (p.first)); - rc_info rci (guess_rc (rc)); - - // If this is a new value (e.g., we are configuring), then print the - // report at verbosity level 2 and up (-v). - // - if (verb >= (p.second ? 2 : 3)) - { - text << "bin.rc " << project (r) << '@' << r.out_path () << '\n' - << " rc " << rc << '\n' - << " id " << rci.id << '\n' - << " signature " << rci.signature << '\n' - << " checksum " << rci.checksum; - } - - r.assign ("bin.rc.id") = move (rci.id); - r.assign ("bin.rc.signature") = move (rci.signature); - r.assign ("bin.rc.checksum") = move (rci.checksum); - } - - return true; - } - - bool - rc_init (scope& r, - scope& b, - const location& loc, - unique_ptr&, - bool, - bool, - const variable_map& hints) - { - tracer trace ("bin::rc_init"); - l5 ([&]{trace << "for " << b.out_path ();}); - - // Make sure the bin core and rc.config are loaded. - // - if (!cast_false (b["bin.loaded"])) - load_module ("bin", r, b, loc, false, hints); - - if (!cast_false (b["bin.rc.config.loaded"])) - load_module ("bin.rc.config", r, b, loc, false, hints); - - return true; - } - } -} -- cgit v1.1