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/b.cxx | 14 +- build2/bin/init | 91 ++++++ build2/bin/init.cxx | 714 ++++++++++++++++++++++++++++++++++++++++++++++ build2/bin/module | 91 ------ build2/bin/module.cxx | 714 ---------------------------------------------- build2/buildfile | 15 +- build2/cli/init | 28 ++ build2/cli/init.cxx | 265 +++++++++++++++++ build2/cli/module | 28 -- build2/cli/module.cxx | 265 ----------------- build2/config/init | 31 ++ build2/config/init.cxx | 103 +++++++ build2/config/module | 14 +- build2/config/module.cxx | 102 ------- build2/cxx/init | 37 +++ build2/cxx/init.cxx | 247 ++++++++++++++++ build2/cxx/module | 37 --- build2/cxx/module.cxx | 247 ---------------- build2/dist/init | 31 ++ build2/dist/init.cxx | 146 ++++++++++ build2/dist/module | 31 -- build2/dist/module.cxx | 146 ---------- build2/install/init | 31 ++ build2/install/init.cxx | 219 ++++++++++++++ build2/install/module | 31 -- build2/install/module.cxx | 219 -------------- build2/test/init | 31 ++ build2/test/init.cxx | 103 +++++++ build2/test/module | 31 -- build2/test/module.cxx | 103 ------- 30 files changed, 2093 insertions(+), 2072 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 create mode 100644 build2/cli/init create mode 100644 build2/cli/init.cxx delete mode 100644 build2/cli/module delete mode 100644 build2/cli/module.cxx create mode 100644 build2/config/init create mode 100644 build2/config/init.cxx delete mode 100644 build2/config/module.cxx create mode 100644 build2/cxx/init create mode 100644 build2/cxx/init.cxx delete mode 100644 build2/cxx/module delete mode 100644 build2/cxx/module.cxx create mode 100644 build2/dist/init create mode 100644 build2/dist/init.cxx delete mode 100644 build2/dist/module delete mode 100644 build2/dist/module.cxx create mode 100644 build2/install/init create mode 100644 build2/install/init.cxx delete mode 100644 build2/install/module delete mode 100644 build2/install/module.cxx create mode 100644 build2/test/init create mode 100644 build2/test/init.cxx delete mode 100644 build2/test/module delete mode 100644 build2/test/module.cxx (limited to 'build2') diff --git a/build2/b.cxx b/build2/b.cxx index 5167cf6..d16d828 100644 --- a/build2/b.cxx +++ b/build2/b.cxx @@ -38,15 +38,15 @@ using namespace butl; using namespace std; -#include -#include -#include +#include +#include +#include #include #include -#include -#include -#include -#include +#include +#include +#include +#include using namespace build2; 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; - } - } -} diff --git a/build2/buildfile b/build2/buildfile index b0e9cf0..7e0a925 100644 --- a/build2/buildfile +++ b/build2/buildfile @@ -35,7 +35,7 @@ exe{b}: \ {hxx ixx txx cxx}{ variable } \ {hxx }{ version } \ bin/{hxx cxx}{ guess } \ - bin/{hxx cxx}{ module } \ + bin/{hxx cxx}{ init } \ bin/{hxx cxx}{ rule } \ bin/{hxx cxx}{ target } \ c/{hxx cxx}{ init } \ @@ -52,22 +52,23 @@ exe{b}: \ cc/{hxx ixx cxx}{ utility } \ cc/{ cxx}{ windows-manifest } \ cc/{ cxx}{ windows-rpath } \ - cli/{hxx cxx}{ module } \ + cli/{hxx cxx}{ init } \ cli/{hxx cxx}{ rule } \ cli/{hxx cxx}{ target } \ - config/{hxx cxx}{ module } \ + config/{hxx cxx}{ init } \ + config/{hxx }{ module } \ config/{hxx cxx}{ operation } \ config/{hxx txx cxx}{ utility } \ - cxx/{hxx cxx}{ module } \ + cxx/{hxx cxx}{ init } \ cxx/{hxx cxx}{ target } \ - dist/{hxx cxx}{ module } \ + dist/{hxx cxx}{ init } \ dist/{hxx cxx}{ operation } \ dist/{hxx cxx}{ rule } \ -install/{hxx cxx}{ module } \ +install/{hxx cxx}{ init } \ install/{hxx cxx}{ operation } \ install/{hxx cxx}{ rule } \ install/{hxx }{ utility } \ - test/{hxx cxx}{ module } \ + test/{hxx cxx}{ init } \ test/{hxx cxx}{ operation } \ test/{hxx cxx}{ rule } \ $libs diff --git a/build2/cli/init b/build2/cli/init new file mode 100644 index 0000000..917ab35 --- /dev/null +++ b/build2/cli/init @@ -0,0 +1,28 @@ +// file : build2/cli/init -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BUILD2_CLI_INIT +#define BUILD2_CLI_INIT + +#include +#include + +#include + +namespace build2 +{ + namespace cli + { + bool + init (scope&, + scope&, + const location&, + unique_ptr&, + bool, + bool, + const variable_map&); + } +} + +#endif // BUILD2_CLI_INIT diff --git a/build2/cli/init.cxx b/build2/cli/init.cxx new file mode 100644 index 0000000..467cf82 --- /dev/null +++ b/build2/cli/init.cxx @@ -0,0 +1,265 @@ +// file : build2/cli/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 + +using namespace std; +using namespace butl; + +namespace build2 +{ + namespace cli + { + static compile compile_; + + bool + init (scope& rs, + scope& bs, + const location& loc, + unique_ptr&, + bool first, + bool optional, + const variable_map& config_hints) + { + tracer trace ("cli::init"); + l5 ([&]{trace << "for " << bs.out_path ();}); + + assert (config_hints.empty ()); // We don't known any hints. + + // Make sure the cxx module has been loaded since we need its targets + // types (?xx{}). Note that we don't try to load it ourselves because of + // the non-trivial variable merging semantics. So it is better to let + // the user load cxx explicitly. + // + if (!cast_false (bs["cxx.loaded"])) + fail (loc) << "cxx module must be loaded before cli"; + + // Enter module variables. + // + if (first) + { + auto& v (var_pool); + + // Note: some overridable, some not. + // + v.insert ("config.cli", true); + v.insert ("config.cli.options", true); + + v.insert ("cli.options"); + } + + // Register target types. + // + { + auto& t (bs.target_types); + + t.insert (); + t.insert (); + } + + // Configure. + // + // The plan is as follows: try to configure the module. If this fails, + // we are using default values, and the module is optional, leave it + // unconfigured. + // + + // We will only honor optional if the user didn't specify any cli + // configuration explicitly. + // + optional = optional && !config::specified (rs, "config.cli"); + + // If the configuration says we are unconfigured, then we don't need to + // re-run tests, etc. But we may still need to print the config report. + // + bool unconf (optional && config::unconfigured (rs, "config.cli")); + + if (first) + { + // config.cli + // + + // Return version or empty string if unable to execute (e.g., the cli + // executable is not found). + // + auto test = [optional] (const path& cli) -> string + { + const char* args[] = {cli.string ().c_str (), "--version", nullptr}; + + if (verb >= 3) + print_process (args); + + try + { + process pr (args, 0, -1); // Open pipe to stdout. + + try + { + ifdstream is (pr.in_ofd, fdstream_mode::skip); + + // The version should be the last word on the first line. + // + string ver; + getline (is, ver); + auto p (ver.rfind (' ')); + if (p != string::npos) + ver = string (ver, p + 1); + + is.close (); // Don't block the other end. + + if (pr.wait ()) + { + if (ver.empty ()) + fail << "unexpected output from " << cli; + + return ver; + } + + // Presumably issued diagnostics. Fall through. + } + catch (const ifdstream::failure&) + { + pr.wait (); + + // Fall through. + } + + // Fall through. + } + catch (const process_error& e) + { + // In some cases this is not enough (e.g., the runtime linker + // will print scary errors if some shared libraries are not + // found). So it would be good to redirect child's STDERR. + // + if (!optional) + error << "unable to execute " << cli << ": " << e.what (); + + if (e.child ()) + exit (1); + + // Fall through. + } + + return string (); // Not found. + }; + + // Adjust module priority (code generator). + // + config::save_module (rs, "cli", 150); + + string ver; // Empty means unconfigured. + path cli ("cli"); // Default. + bool nv (false); // New value. + + if (optional) + { + // Test the default value before setting any config.cli.* values + // so that if we fail to configure, nothing will be written to + // config.build. + // + if (!unconf) + { + ver = test (cli); + + if (ver.empty ()) + { + // Note that we are unconfigured so that we don't keep + // re-testing this on each run. + // + config::unconfigured (rs, "config.cli", true); + unconf = true; + } + else + { + auto p (config::required (rs, "config.cli", cli)); + assert (p.second && cast (p.first) == cli); + } + + nv = true; + } + } + else + { + auto p (config::required (rs, "config.cli", cli)); + + cli = cast (p.first); + ver = test (cli); + + if (ver.empty ()) + throw failed (); // Diagnostics already issued. + + nv = p.second; + } + + // If this is a new value (e.g., we are configuring), then print the + // report at verbosity level 2 and up (-v). + // + if (verb >= (nv ? 2 : 3)) + { + diag_record dr (text); + dr << "cli " << project (rs) << '@' << rs.out_path () << '\n'; + + if (unconf) + dr << " cli " << "not found, leaving unconfigured"; + else + dr << " cli " << cli << '\n' + << " version " << ver; + } + } + + // Nothing else to do if we are unconfigured. + // + if (unconf) + return false; + + // config.cli.options + // + // This one is optional. We also merge it into the corresponding + // cli.* variables. See the cxx module for more information on + // this merging semantics and some of its tricky aspects. + // + bs.assign ("cli.options") += cast_null ( + config::optional (rs, "config.cli.options")); + + // Register our rules. + // + { + auto& r (bs.rules); + + r.insert (perform_update_id, "cli.compile", compile_); + r.insert (perform_clean_id, "cli.compile", compile_); + + r.insert (perform_update_id, "cli.compile", compile_); + r.insert (perform_clean_id, "cli.compile", compile_); + + r.insert (perform_update_id, "cli.compile", compile_); + r.insert (perform_clean_id, "cli.compile", compile_); + + r.insert (perform_update_id, "cli.compile", compile_); + r.insert (perform_clean_id, "cli.compile", compile_); + + // Other rules (e.g., cxx::compile) may need to have the group + // members resolved. Looks like a general pattern: groups should + // resolve on configure(update). + // + r.insert (configure_update_id, "cli.compile", compile_); + } + + return true; + } + } +} diff --git a/build2/cli/module b/build2/cli/module deleted file mode 100644 index 50d07ef..0000000 --- a/build2/cli/module +++ /dev/null @@ -1,28 +0,0 @@ -// file : build2/cli/module -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BUILD2_CLI_MODULE -#define BUILD2_CLI_MODULE - -#include -#include - -#include - -namespace build2 -{ - namespace cli - { - bool - init (scope&, - scope&, - const location&, - unique_ptr&, - bool, - bool, - const variable_map&); - } -} - -#endif // BUILD2_CLI_MODULE diff --git a/build2/cli/module.cxx b/build2/cli/module.cxx deleted file mode 100644 index ef9c2f8..0000000 --- a/build2/cli/module.cxx +++ /dev/null @@ -1,265 +0,0 @@ -// file : build2/cli/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 - -using namespace std; -using namespace butl; - -namespace build2 -{ - namespace cli - { - static compile compile_; - - bool - init (scope& rs, - scope& bs, - const location& loc, - unique_ptr&, - bool first, - bool optional, - const variable_map& config_hints) - { - tracer trace ("cli::init"); - l5 ([&]{trace << "for " << bs.out_path ();}); - - assert (config_hints.empty ()); // We don't known any hints. - - // Make sure the cxx module has been loaded since we need its targets - // types (?xx{}). Note that we don't try to load it ourselves because of - // the non-trivial variable merging semantics. So it is better to let - // the user load cxx explicitly. - // - if (!cast_false (bs["cxx.loaded"])) - fail (loc) << "cxx module must be loaded before cli"; - - // Enter module variables. - // - if (first) - { - auto& v (var_pool); - - // Note: some overridable, some not. - // - v.insert ("config.cli", true); - v.insert ("config.cli.options", true); - - v.insert ("cli.options"); - } - - // Register target types. - // - { - auto& t (bs.target_types); - - t.insert (); - t.insert (); - } - - // Configure. - // - // The plan is as follows: try to configure the module. If this fails, - // we are using default values, and the module is optional, leave it - // unconfigured. - // - - // We will only honor optional if the user didn't specify any cli - // configuration explicitly. - // - optional = optional && !config::specified (rs, "config.cli"); - - // If the configuration says we are unconfigured, then we don't need to - // re-run tests, etc. But we may still need to print the config report. - // - bool unconf (optional && config::unconfigured (rs, "config.cli")); - - if (first) - { - // config.cli - // - - // Return version or empty string if unable to execute (e.g., the cli - // executable is not found). - // - auto test = [optional] (const path& cli) -> string - { - const char* args[] = {cli.string ().c_str (), "--version", nullptr}; - - if (verb >= 3) - print_process (args); - - try - { - process pr (args, 0, -1); // Open pipe to stdout. - - try - { - ifdstream is (pr.in_ofd, fdstream_mode::skip); - - // The version should be the last word on the first line. - // - string ver; - getline (is, ver); - auto p (ver.rfind (' ')); - if (p != string::npos) - ver = string (ver, p + 1); - - is.close (); // Don't block the other end. - - if (pr.wait ()) - { - if (ver.empty ()) - fail << "unexpected output from " << cli; - - return ver; - } - - // Presumably issued diagnostics. Fall through. - } - catch (const ifdstream::failure&) - { - pr.wait (); - - // Fall through. - } - - // Fall through. - } - catch (const process_error& e) - { - // In some cases this is not enough (e.g., the runtime linker - // will print scary errors if some shared libraries are not - // found). So it would be good to redirect child's STDERR. - // - if (!optional) - error << "unable to execute " << cli << ": " << e.what (); - - if (e.child ()) - exit (1); - - // Fall through. - } - - return string (); // Not found. - }; - - // Adjust module priority (code generator). - // - config::save_module (rs, "cli", 150); - - string ver; // Empty means unconfigured. - path cli ("cli"); // Default. - bool nv (false); // New value. - - if (optional) - { - // Test the default value before setting any config.cli.* values - // so that if we fail to configure, nothing will be written to - // config.build. - // - if (!unconf) - { - ver = test (cli); - - if (ver.empty ()) - { - // Note that we are unconfigured so that we don't keep - // re-testing this on each run. - // - config::unconfigured (rs, "config.cli", true); - unconf = true; - } - else - { - auto p (config::required (rs, "config.cli", cli)); - assert (p.second && cast (p.first) == cli); - } - - nv = true; - } - } - else - { - auto p (config::required (rs, "config.cli", cli)); - - cli = cast (p.first); - ver = test (cli); - - if (ver.empty ()) - throw failed (); // Diagnostics already issued. - - nv = p.second; - } - - // If this is a new value (e.g., we are configuring), then print the - // report at verbosity level 2 and up (-v). - // - if (verb >= (nv ? 2 : 3)) - { - diag_record dr (text); - dr << "cli " << project (rs) << '@' << rs.out_path () << '\n'; - - if (unconf) - dr << " cli " << "not found, leaving unconfigured"; - else - dr << " cli " << cli << '\n' - << " version " << ver; - } - } - - // Nothing else to do if we are unconfigured. - // - if (unconf) - return false; - - // config.cli.options - // - // This one is optional. We also merge it into the corresponding - // cli.* variables. See the cxx module for more information on - // this merging semantics and some of its tricky aspects. - // - bs.assign ("cli.options") += cast_null ( - config::optional (rs, "config.cli.options")); - - // Register our rules. - // - { - auto& r (bs.rules); - - r.insert (perform_update_id, "cli.compile", compile_); - r.insert (perform_clean_id, "cli.compile", compile_); - - r.insert (perform_update_id, "cli.compile", compile_); - r.insert (perform_clean_id, "cli.compile", compile_); - - r.insert (perform_update_id, "cli.compile", compile_); - r.insert (perform_clean_id, "cli.compile", compile_); - - r.insert (perform_update_id, "cli.compile", compile_); - r.insert (perform_clean_id, "cli.compile", compile_); - - // Other rules (e.g., cxx::compile) may need to have the group - // members resolved. Looks like a general pattern: groups should - // resolve on configure(update). - // - r.insert (configure_update_id, "cli.compile", compile_); - } - - return true; - } - } -} diff --git a/build2/config/init b/build2/config/init new file mode 100644 index 0000000..7efae99 --- /dev/null +++ b/build2/config/init @@ -0,0 +1,31 @@ +// file : build2/config/init -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BUILD2_CONFIG_INIT +#define BUILD2_CONFIG_INIT + +#include +#include + +#include + +namespace build2 +{ + namespace config + { + void + boot (scope&, const location&, unique_ptr&); + + bool + init (scope&, + scope&, + const location&, + unique_ptr&, + bool, + bool, + const variable_map&); + } +} + +#endif // BUILD2_CONFIG_INIT diff --git a/build2/config/init.cxx b/build2/config/init.cxx new file mode 100644 index 0000000..6c713df --- /dev/null +++ b/build2/config/init.cxx @@ -0,0 +1,103 @@ +// file : build2/config/init.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include + +#include +#include +#include +#include +#include // file_exists() +#include + +#include +#include +#include + +using namespace std; +using namespace butl; + +namespace build2 +{ + namespace config + { + const string module::name ("config"); + + void + boot (scope& rs, const location&, unique_ptr&) + { + tracer trace ("config::boot"); + + const dir_path& out_root (rs.out_path ()); + l5 ([&]{trace << "for " << out_root;}); + + // Register meta-operations. + // + rs.meta_operations.insert (configure_id, configure); + rs.meta_operations.insert (disfigure_id, disfigure); + + // Load config.build if one exists. + // + // Note that we have to do this during bootstrap since the order in + // which the modules will be initialized is unspecified. So it is + // possible that some module which needs the configuration will get + // called first. + // + path f (out_root / config_file); + + if (file_exists (f)) + source (f, rs, rs); + } + + bool + init (scope& rs, + scope&, + const location& l, + unique_ptr& mod, + bool first, + bool, + const variable_map& config_hints) + { + tracer trace ("config::init"); + + if (!first) + { + warn (l) << "multiple config module initializations"; + return true; + } + + l5 ([&]{trace << "for " << rs.out_path ();}); + + assert (config_hints.empty ()); // We don't known any hints. + + // Only create the module if we are configuring. + // + if (current_mif->id == configure_id) + mod.reset (new module); + + // Adjust priority for the import pseudo-module so that config.import.* + // values come first in config.build. + // + config::save_module (rs, "import", INT32_MIN); + + // Register alias and fallback rule for the configure meta-operation. + // + { + // We need this rule for out-of-any-project dependencies (e.g., + // libraries imported from /usr/lib). + // + global_scope->rules.insert ( + configure_id, 0, "config.file", file_rule::instance); + + auto& r (rs.rules); + + r.insert (configure_id, 0, "config", fallback_rule::instance); + r.insert (configure_id, 0, "config.file", fallback_rule::instance); + r.insert (configure_id, 0, "config.alias", alias_rule::instance); + } + + return true; + } + } +} diff --git a/build2/config/module b/build2/config/module index 21a7e28..e6fb197 100644 --- a/build2/config/module +++ b/build2/config/module @@ -78,20 +78,8 @@ namespace build2 struct module: module_base { config::saved_modules saved_modules; - static const string name; + static const string name; // init.cxx }; - - void - boot (scope&, const location&, unique_ptr&); - - bool - init (scope&, - scope&, - const location&, - unique_ptr&, - bool, - bool, - const variable_map&); } } diff --git a/build2/config/module.cxx b/build2/config/module.cxx deleted file mode 100644 index de106b7..0000000 --- a/build2/config/module.cxx +++ /dev/null @@ -1,102 +0,0 @@ -// file : build2/config/module.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include - -#include -#include -#include -#include -#include // file_exists() -#include - -#include -#include - -using namespace std; -using namespace butl; - -namespace build2 -{ - namespace config - { - const string module::name ("config"); - - void - boot (scope& rs, const location&, unique_ptr&) - { - tracer trace ("config::boot"); - - const dir_path& out_root (rs.out_path ()); - l5 ([&]{trace << "for " << out_root;}); - - // Register meta-operations. - // - rs.meta_operations.insert (configure_id, configure); - rs.meta_operations.insert (disfigure_id, disfigure); - - // Load config.build if one exists. - // - // Note that we have to do this during bootstrap since the order in - // which the modules will be initialized is unspecified. So it is - // possible that some module which needs the configuration will get - // called first. - // - path f (out_root / config_file); - - if (file_exists (f)) - source (f, rs, rs); - } - - bool - init (scope& rs, - scope&, - const location& l, - unique_ptr& mod, - bool first, - bool, - const variable_map& config_hints) - { - tracer trace ("config::init"); - - if (!first) - { - warn (l) << "multiple config module initializations"; - return true; - } - - l5 ([&]{trace << "for " << rs.out_path ();}); - - assert (config_hints.empty ()); // We don't known any hints. - - // Only create the module if we are configuring. - // - if (current_mif->id == configure_id) - mod.reset (new module); - - // Adjust priority for the import pseudo-module so that config.import.* - // values come first in config.build. - // - config::save_module (rs, "import", INT32_MIN); - - // Register alias and fallback rule for the configure meta-operation. - // - { - // We need this rule for out-of-any-project dependencies (e.g., - // libraries imported from /usr/lib). - // - global_scope->rules.insert ( - configure_id, 0, "config.file", file_rule::instance); - - auto& r (rs.rules); - - r.insert (configure_id, 0, "config", fallback_rule::instance); - r.insert (configure_id, 0, "config.file", fallback_rule::instance); - r.insert (configure_id, 0, "config.alias", alias_rule::instance); - } - - return true; - } - } -} diff --git a/build2/cxx/init b/build2/cxx/init new file mode 100644 index 0000000..a06f193 --- /dev/null +++ b/build2/cxx/init @@ -0,0 +1,37 @@ +// file : build2/cxx/init -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BUILD2_CXX_INIT +#define BUILD2_CXX_INIT + +#include +#include + +#include + +namespace build2 +{ + namespace cxx + { + 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&); + } +} + +#endif // BUILD2_CXX_INIT diff --git a/build2/cxx/init.cxx b/build2/cxx/init.cxx new file mode 100644 index 0000000..7170282 --- /dev/null +++ b/build2/cxx/init.cxx @@ -0,0 +1,247 @@ +// file : build2/cxx/init.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include + +#include +#include +#include + +#include + +#include + +using namespace std; +using namespace butl; + +namespace build2 +{ + namespace cxx + { + using cc::config_module; + + class module: public cc::module + { + public: + explicit + module (data&& d): common (move (d)), cc::module (move (d)) {} + + bool + translate_std (string&, scope&, const value&) const override; + }; + + bool module:: + translate_std (string& s, scope& r, const value& val) const + { + const string& v (cast (val)); + + if (cid == "msvc") + { + // C++ standard-wise, with VC you get what you get. The question is + // whether we should verify that the requested standard is provided by + // this VC version. And if so, from which version should we say VC + // supports 11, 14, and 17? We should probably be as loose as possible + // here since the author will always be able to tighten (but not + // loosen) this in the buildfile (i.e., detect unsupported versions). + // + // For now we are not going to bother doing this for C++03. + // + if (v != "98" && v != "03") + { + uint64_t cver (cast (r[x_version_major])); + + // @@ Is mapping for 14 and 17 correct? Maybe Update 2 for 14? + // + if ((v == "11" && cver < 16) || // C++11 since VS2010/10.0. + (v == "14" && cver < 19) || // C++14 since VS2015/14.0. + (v == "17" && cver < 20)) // C++17 since VS20??/15.0. + { + fail << "C++" << v << " is not supported by " + << cast (r[x_signature]) << + info << "required by " << project (r) << '@' << r.out_path (); + } + } + + return false; + } + else + { + // Translate 11 to 0x, 14 to 1y, and 17 to 1z for compatibility with + // older versions of the compilers. + // + s = "-std="; + + if (v == "98") + s += "c++98"; + else if (v == "03") + s += "c++03"; + else if (v == "11") + s += "c++0x"; + else if (v == "14") + s += "c++1y"; + else if (v == "17") + s += "c++1z"; + else + s += v; // In case the user specifies something like 'gnu++17'. + + return true; + } + } + + bool + config_init (scope& r, + scope& b, + const location& loc, + unique_ptr& m, + bool first, + bool, + const variable_map& hints) + { + tracer trace ("cxx::config_init"); + l5 ([&]{trace << "for " << b.out_path ();}); + + if (first) + { + // Load cc.vars so that we can cache all the cc.* variables. + // + if (!cast_false (b["cc.vars.loaded"])) + load_module ("cc.vars", r, b, loc); + + // Enter all the variables and initialize the module data. + // + auto& v (var_pool); + + cc::config_data d { + cc::lang::cxx, + + "cxx", + "c++", + "g++", + + // Note: some overridable, some not. + // + v.insert ("config.cxx", true), + v.insert ("config.cxx.poptions", true), + v.insert ("config.cxx.coptions", true), + v.insert ("config.cxx.loptions", true), + v.insert ("config.cxx.libs", true), + + v.insert ("cxx.poptions"), + v.insert ("cxx.coptions"), + v.insert ("cxx.loptions"), + v.insert ("cxx.libs"), + + v["cc.poptions"], + v["cc.coptions"], + v["cc.loptions"], + v["cc.libs"], + + v.insert ("cxx.export.poptions"), + v.insert ("cxx.export.coptions"), + v.insert ("cxx.export.loptions"), + v.insert ("cxx.export.libs"), + + v["cc.export.poptions"], + v["cc.export.coptions"], + v["cc.export.loptions"], + v["cc.export.libs"], + + v.insert ("cxx.std", true), + + v.insert ("cxx.id"), + v.insert ("cxx.id.type"), + v.insert ("cxx.id.variant"), + + v.insert ("cxx.version"), + v.insert ("cxx.version.major"), + v.insert ("cxx.version.minor"), + v.insert ("cxx.version.patch"), + v.insert ("cxx.version.build"), + + v.insert ("cxx.signature"), + v.insert ("cxx.checksum"), + + v.insert ("cxx.target"), + v.insert ("cxx.target.cpu"), + v.insert ("cxx.target.vendor"), + v.insert ("cxx.target.system"), + v.insert ("cxx.target.version"), + v.insert ("cxx.target.class") + }; + + assert (m == nullptr); + m.reset (new config_module (move (d))); + } + + static_cast (*m).init (r, b, loc, first, hints); + return true; + } + + static const target_type* hdr[] = + { + &hxx::static_type, + &ixx::static_type, + &txx::static_type, + &h::static_type, + nullptr + }; + + static const target_type* inc[] = + { + &hxx::static_type, + &ixx::static_type, + &txx::static_type, + &cxx::static_type, + &h::static_type, + &c::static_type, + nullptr + }; + + bool + init (scope& r, + scope& b, + const location& loc, + unique_ptr& m, + bool first, + bool, + const variable_map& hints) + { + tracer trace ("cxx::init"); + l5 ([&]{trace << "for " << b.out_path ();}); + + // Load cxx.config. + // + if (!cast_false (b["cxx.config.loaded"])) + load_module ("cxx.config", r, b, loc, false, hints); + + if (first) + { + config_module& cm (*r.modules.lookup ("cxx.config")); + + cc::data d { + cm, + + "cxx.compile", + "cxx.link", + "cxx.install", + + cast (r[cm.x_id]), + cast (r[cm.x_target]), + cast (r[cm.x_target_system]), + cast (r[cm.x_target_class]), + + cxx::static_type, + hdr, + inc + }; + + assert (m == nullptr); + m.reset (new module (move (d))); + } + + static_cast (*m).init (r, b, loc, first, hints); + return true; + } + } +} diff --git a/build2/cxx/module b/build2/cxx/module deleted file mode 100644 index 8c1a01f..0000000 --- a/build2/cxx/module +++ /dev/null @@ -1,37 +0,0 @@ -// file : build2/cxx/module -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BUILD2_CXX_MODULE -#define BUILD2_CXX_MODULE - -#include -#include - -#include - -namespace build2 -{ - namespace cxx - { - 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&); - } -} - -#endif // BUILD2_CXX_MODULE diff --git a/build2/cxx/module.cxx b/build2/cxx/module.cxx deleted file mode 100644 index fd98114..0000000 --- a/build2/cxx/module.cxx +++ /dev/null @@ -1,247 +0,0 @@ -// file : build2/cxx/module.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include - -#include -#include -#include - -#include - -#include - -using namespace std; -using namespace butl; - -namespace build2 -{ - namespace cxx - { - using cc::config_module; - - class module: public cc::module - { - public: - explicit - module (data&& d): common (move (d)), cc::module (move (d)) {} - - bool - translate_std (string&, scope&, const value&) const override; - }; - - bool module:: - translate_std (string& s, scope& r, const value& val) const - { - const string& v (cast (val)); - - if (cid == "msvc") - { - // C++ standard-wise, with VC you get what you get. The question is - // whether we should verify that the requested standard is provided by - // this VC version. And if so, from which version should we say VC - // supports 11, 14, and 17? We should probably be as loose as possible - // here since the author will always be able to tighten (but not - // loosen) this in the buildfile (i.e., detect unsupported versions). - // - // For now we are not going to bother doing this for C++03. - // - if (v != "98" && v != "03") - { - uint64_t cver (cast (r[x_version_major])); - - // @@ Is mapping for 14 and 17 correct? Maybe Update 2 for 14? - // - if ((v == "11" && cver < 16) || // C++11 since VS2010/10.0. - (v == "14" && cver < 19) || // C++14 since VS2015/14.0. - (v == "17" && cver < 20)) // C++17 since VS20??/15.0. - { - fail << "C++" << v << " is not supported by " - << cast (r[x_signature]) << - info << "required by " << project (r) << '@' << r.out_path (); - } - } - - return false; - } - else - { - // Translate 11 to 0x, 14 to 1y, and 17 to 1z for compatibility with - // older versions of the compilers. - // - s = "-std="; - - if (v == "98") - s += "c++98"; - else if (v == "03") - s += "c++03"; - else if (v == "11") - s += "c++0x"; - else if (v == "14") - s += "c++1y"; - else if (v == "17") - s += "c++1z"; - else - s += v; // In case the user specifies something like 'gnu++17'. - - return true; - } - } - - bool - config_init (scope& r, - scope& b, - const location& loc, - unique_ptr& m, - bool first, - bool, - const variable_map& hints) - { - tracer trace ("cxx::config_init"); - l5 ([&]{trace << "for " << b.out_path ();}); - - if (first) - { - // Load cc.vars so that we can cache all the cc.* variables. - // - if (!cast_false (b["cc.vars.loaded"])) - load_module ("cc.vars", r, b, loc); - - // Enter all the variables and initialize the module data. - // - auto& v (var_pool); - - cc::config_data d { - cc::lang::cxx, - - "cxx", - "c++", - "g++", - - // Note: some overridable, some not. - // - v.insert ("config.cxx", true), - v.insert ("config.cxx.poptions", true), - v.insert ("config.cxx.coptions", true), - v.insert ("config.cxx.loptions", true), - v.insert ("config.cxx.libs", true), - - v.insert ("cxx.poptions"), - v.insert ("cxx.coptions"), - v.insert ("cxx.loptions"), - v.insert ("cxx.libs"), - - v["cc.poptions"], - v["cc.coptions"], - v["cc.loptions"], - v["cc.libs"], - - v.insert ("cxx.export.poptions"), - v.insert ("cxx.export.coptions"), - v.insert ("cxx.export.loptions"), - v.insert ("cxx.export.libs"), - - v["cc.export.poptions"], - v["cc.export.coptions"], - v["cc.export.loptions"], - v["cc.export.libs"], - - v.insert ("cxx.std", true), - - v.insert ("cxx.id"), - v.insert ("cxx.id.type"), - v.insert ("cxx.id.variant"), - - v.insert ("cxx.version"), - v.insert ("cxx.version.major"), - v.insert ("cxx.version.minor"), - v.insert ("cxx.version.patch"), - v.insert ("cxx.version.build"), - - v.insert ("cxx.signature"), - v.insert ("cxx.checksum"), - - v.insert ("cxx.target"), - v.insert ("cxx.target.cpu"), - v.insert ("cxx.target.vendor"), - v.insert ("cxx.target.system"), - v.insert ("cxx.target.version"), - v.insert ("cxx.target.class") - }; - - assert (m == nullptr); - m.reset (new config_module (move (d))); - } - - static_cast (*m).init (r, b, loc, first, hints); - return true; - } - - static const target_type* hdr[] = - { - &hxx::static_type, - &ixx::static_type, - &txx::static_type, - &h::static_type, - nullptr - }; - - static const target_type* inc[] = - { - &hxx::static_type, - &ixx::static_type, - &txx::static_type, - &cxx::static_type, - &h::static_type, - &c::static_type, - nullptr - }; - - bool - init (scope& r, - scope& b, - const location& loc, - unique_ptr& m, - bool first, - bool, - const variable_map& hints) - { - tracer trace ("cxx::init"); - l5 ([&]{trace << "for " << b.out_path ();}); - - // Load cxx.config. - // - if (!cast_false (b["cxx.config.loaded"])) - load_module ("cxx.config", r, b, loc, false, hints); - - if (first) - { - config_module& cm (*r.modules.lookup ("cxx.config")); - - cc::data d { - cm, - - "cxx.compile", - "cxx.link", - "cxx.install", - - cast (r[cm.x_id]), - cast (r[cm.x_target]), - cast (r[cm.x_target_system]), - cast (r[cm.x_target_class]), - - cxx::static_type, - hdr, - inc - }; - - assert (m == nullptr); - m.reset (new module (move (d))); - } - - static_cast (*m).init (r, b, loc, first, hints); - return true; - } - } -} diff --git a/build2/dist/init b/build2/dist/init new file mode 100644 index 0000000..9a439ea --- /dev/null +++ b/build2/dist/init @@ -0,0 +1,31 @@ +// file : build2/dist/init -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BUILD2_DIST_INIT +#define BUILD2_DIST_INIT + +#include +#include + +#include + +namespace build2 +{ + namespace dist + { + void + boot (scope&, const location&, unique_ptr&); + + bool + init (scope&, + scope&, + const location&, + unique_ptr&, + bool, + bool, + const variable_map&); + } +} + +#endif // BUILD2_DIST_INIT diff --git a/build2/dist/init.cxx b/build2/dist/init.cxx new file mode 100644 index 0000000..637a232 --- /dev/null +++ b/build2/dist/init.cxx @@ -0,0 +1,146 @@ +// file : build2/dist/init.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include + +#include +#include +#include + +#include + +#include +#include + +using namespace std; +using namespace butl; + +namespace build2 +{ + namespace dist + { + static rule rule_; + + void + boot (scope& r, const location&, unique_ptr&) + { + tracer trace ("dist::boot"); + + l5 ([&]{trace << "for " << r.out_path ();}); + + // Register meta-operation. + // + r.meta_operations.insert (dist_id, dist); + + // Enter module variables. Do it during boot in case they get assigned + // in bootstrap.build (which is customary for, e.g., dist.package). + // + { + auto& v (var_pool); + + // Note: some overridable, some not. + // + v.insert ("config.dist.root", true); + v.insert ("config.dist.archives", true); + v.insert ("config.dist.cmd", true); + + v.insert ("dist.root"); + v.insert ("dist.cmd"); + v.insert ("dist.archives"); + + v.insert ("dist"); // Flag. + v.insert ("dist.package"); // Project's package name. + } + } + + bool + init (scope& r, + scope&, + const location& l, + unique_ptr&, + bool first, + bool, + const variable_map& config_hints) + { + tracer trace ("dist::init"); + + if (!first) + { + warn (l) << "multiple dist module initializations"; + return true; + } + + const dir_path& out_root (r.out_path ()); + l5 ([&]{trace << "for " << out_root;}); + + assert (config_hints.empty ()); // We don't known any hints. + + // Register our wildcard rule. Do it explicitly for the alias + // to prevent something like insert(dist_id, test_id) + // taking precedence. + // + r.rules.insert (dist_id, 0, "dist", rule_); + r.rules.insert (dist_id, 0, "dist.alias", rule_); + + // Configuration. + // + // Note that we don't use any defaults for root -- the location + // must be explicitly specified or we will complain if and when + // we try to dist. + // + bool s (config::specified (r, "config.dist")); + + // Adjust module priority so that the config.dist.* values are saved at + // the end of config.build. + // + if (s) + config::save_module (r, "dist", INT32_MAX); + + // dist.root + // + { + value& v (r.assign ("dist.root")); + + if (s) + { + const value& cv (config::optional (r, "config.dist.root")); + + if (cv && !cv.empty ()) // @@ BC LT [null] + v = cast (cv); // Strip abs_dir_path. + } + } + + // dist.cmd + // + { + value& v (r.assign ("dist.cmd")); + + if (s) + { + const value& cv ( + config::required (r, "config.dist.cmd", path ("install")).first); + + if (cv && !cv.empty ()) // @@ BC LT [null] + v = cv; + } + } + + // dist.archives + // + { + value& v (r.assign ("dist.archives")); + + if (s) + { + const value& cv (config::optional (r, "config.dist.archives")); + + if (cv && !cv.empty ()) // @@ BC LT [null] + v = cv; + } + } + + return true; + } + } +} diff --git a/build2/dist/module b/build2/dist/module deleted file mode 100644 index 3c43c1f..0000000 --- a/build2/dist/module +++ /dev/null @@ -1,31 +0,0 @@ -// file : build2/dist/module -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BUILD2_DIST_MODULE -#define BUILD2_DIST_MODULE - -#include -#include - -#include - -namespace build2 -{ - namespace dist - { - void - boot (scope&, const location&, unique_ptr&); - - bool - init (scope&, - scope&, - const location&, - unique_ptr&, - bool, - bool, - const variable_map&); - } -} - -#endif // BUILD2_DIST_MODULE diff --git a/build2/dist/module.cxx b/build2/dist/module.cxx deleted file mode 100644 index 2da75c4..0000000 --- a/build2/dist/module.cxx +++ /dev/null @@ -1,146 +0,0 @@ -// file : build2/dist/module.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include - -#include -#include -#include - -#include - -#include -#include - -using namespace std; -using namespace butl; - -namespace build2 -{ - namespace dist - { - static rule rule_; - - void - boot (scope& r, const location&, unique_ptr&) - { - tracer trace ("dist::boot"); - - l5 ([&]{trace << "for " << r.out_path ();}); - - // Register meta-operation. - // - r.meta_operations.insert (dist_id, dist); - - // Enter module variables. Do it during boot in case they get assigned - // in bootstrap.build (which is customary for, e.g., dist.package). - // - { - auto& v (var_pool); - - // Note: some overridable, some not. - // - v.insert ("config.dist.root", true); - v.insert ("config.dist.archives", true); - v.insert ("config.dist.cmd", true); - - v.insert ("dist.root"); - v.insert ("dist.cmd"); - v.insert ("dist.archives"); - - v.insert ("dist"); // Flag. - v.insert ("dist.package"); // Project's package name. - } - } - - bool - init (scope& r, - scope&, - const location& l, - unique_ptr&, - bool first, - bool, - const variable_map& config_hints) - { - tracer trace ("dist::init"); - - if (!first) - { - warn (l) << "multiple dist module initializations"; - return true; - } - - const dir_path& out_root (r.out_path ()); - l5 ([&]{trace << "for " << out_root;}); - - assert (config_hints.empty ()); // We don't known any hints. - - // Register our wildcard rule. Do it explicitly for the alias - // to prevent something like insert(dist_id, test_id) - // taking precedence. - // - r.rules.insert (dist_id, 0, "dist", rule_); - r.rules.insert (dist_id, 0, "dist.alias", rule_); - - // Configuration. - // - // Note that we don't use any defaults for root -- the location - // must be explicitly specified or we will complain if and when - // we try to dist. - // - bool s (config::specified (r, "config.dist")); - - // Adjust module priority so that the config.dist.* values are saved at - // the end of config.build. - // - if (s) - config::save_module (r, "dist", INT32_MAX); - - // dist.root - // - { - value& v (r.assign ("dist.root")); - - if (s) - { - const value& cv (config::optional (r, "config.dist.root")); - - if (cv && !cv.empty ()) // @@ BC LT [null] - v = cast (cv); // Strip abs_dir_path. - } - } - - // dist.cmd - // - { - value& v (r.assign ("dist.cmd")); - - if (s) - { - const value& cv ( - config::required (r, "config.dist.cmd", path ("install")).first); - - if (cv && !cv.empty ()) // @@ BC LT [null] - v = cv; - } - } - - // dist.archives - // - { - value& v (r.assign ("dist.archives")); - - if (s) - { - const value& cv (config::optional (r, "config.dist.archives")); - - if (cv && !cv.empty ()) // @@ BC LT [null] - v = cv; - } - } - - return true; - } - } -} diff --git a/build2/install/init b/build2/install/init new file mode 100644 index 0000000..926d1c3 --- /dev/null +++ b/build2/install/init @@ -0,0 +1,31 @@ +// file : build2/install/init -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BUILD2_INSTALL_INIT +#define BUILD2_INSTALL_INIT + +#include +#include + +#include + +namespace build2 +{ + namespace install + { + void + boot (scope&, const location&, unique_ptr&); + + bool + init (scope&, + scope&, + const location&, + unique_ptr&, + bool, + bool, + const variable_map&); + } +} + +#endif // BUILD2_INSTALL_INIT diff --git a/build2/install/init.cxx b/build2/install/init.cxx new file mode 100644 index 0000000..1e092e8 --- /dev/null +++ b/build2/install/init.cxx @@ -0,0 +1,219 @@ +// file : build2/install/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 install + { + // Set install..* values based on config.install..* ones + // or the defaults. If none of config.install.* values were specified, + // then we do omitted/delayed configuration. Note that we still need + // to set all the install.* values to defaults, as if we had the + // default configuration. + // + // If override is true, then override values that came from outer + // configurations. We have to do this for paths that contain the + // package name. + // + template + static void + set_var (bool spec, + scope& r, + const char* name, + const char* var, + const CT* dv, + bool override = false) + { + string vn; + const value* cv (nullptr); + + if (spec) + { + vn = "config.install."; + vn += name; + vn += var; + const variable& vr (var_pool.insert (move (vn), true)); + + cv = dv != nullptr + ? &config::required (r, vr, *dv, override).first.get () + : &config::optional (r, vr); + } + + vn = "install."; + vn += name; + vn += var; + const variable& vr (var_pool.insert (move (vn))); // Not overridable. + + value& v (r.assign (vr)); + + if (spec) + { + if (*cv && !cv->empty ()) // @@ BC LT [null] + v = cast (*cv); // Strip CT to T. + } + else + { + if (dv != nullptr) + v = *dv; + } + } + + template + static void + set_dir (bool s, // specified + scope& r, // root scope + const char* n, // var name + const T& p, // path + bool o = false, // override + const string& fm = string (), // file mode + const string& dm = string (), // dir mode + const build2::path& c = build2::path ()) // command + { + using build2::path; + + set_var (s, r, n, "", p.empty () ? nullptr : &p, o); + set_var (s, r, n, ".mode", fm.empty () ? nullptr : &fm); + set_var (s, r, n, ".dir_mode", dm.empty () ? nullptr : &dm); + set_var (s, r, n, ".sudo", (string*) (nullptr)); + set_var (s, r, n, ".cmd", c.empty () ? nullptr : &c); + set_var (s, r, n, ".options", (strings*) (nullptr)); + + // This one doesn't have config.* value (only set in a buildfile). + // + var_pool.insert (string ("install.") + n + ".subdirs"); + } + + static alias_rule alias_; + static file_rule file_; + + void + boot (scope& r, const location&, unique_ptr&) + { + tracer trace ("install::boot"); + + l5 ([&]{trace << "for " << r.out_path ();}); + + // Register the install operation. + // + r.operations.insert (install_id, install); + } + + static const dir_path dir_root ("root"); + + static const dir_path dir_sbin (dir_path ("exec_root") /= "sbin"); + static const dir_path dir_bin (dir_path ("exec_root") /= "bin"); + static const dir_path dir_lib (dir_path ("exec_root") /= "lib"); + static const dir_path dir_libexec (dir_path ("exec_root") /= "libexec"); + + static const dir_path dir_data (dir_path ("data_root") /= "share"); + static const dir_path dir_include (dir_path ("data_root") /= "include"); + + static const dir_path dir_doc (dir_path (dir_data) /= "doc"); + static const dir_path dir_man (dir_path (dir_data) /= "man"); + static const dir_path dir_man1 (dir_path ("man") /= "man1"); + + bool + init (scope& r, + scope& b, + const location& l, + unique_ptr&, + bool first, + bool, + const variable_map& config_hints) + { + tracer trace ("install::init"); + + if (!first) + { + warn (l) << "multiple install module initializations"; + return true; + } + + const dir_path& out_root (r.out_path ()); + l5 ([&]{trace << "for " << out_root;}); + + assert (config_hints.empty ()); // We don't known any hints. + + // Enter module variables. + // + // Note that the set_dir() calls below enter some more. + // + { + auto& v (var_pool); + + // Note: not overridable. + // + v.insert ("install"); + v.insert ("install.mode"); + } + + // Register our alias and file installer rule. + // + b.rules.insert (perform_install_id, "install.alias", alias_); + b.rules.insert (perform_install_id, "install.file", file_); + + // Configuration. + // + // Note that we don't use any defaults for root -- the location + // must be explicitly specified or the installer will complain + // if and when we try to install. + // + { + using build2::path; + + bool s (config::specified (r, "config.install")); + + // Adjust module priority so that the (numerous) config.install.* + // values are saved at the end of config.build. + // + if (s) + config::save_module (r, "install", INT32_MAX); + + const string& n (cast (r["project"])); + + set_dir (s, r, "root", abs_dir_path (), false, "", "755", path ("install")); + + set_dir (s, r, "data_root", dir_root, false, "644"); + set_dir (s, r, "exec_root", dir_root, false, "755"); + + set_dir (s, r, "sbin", dir_sbin); + set_dir (s, r, "bin", dir_bin); + set_dir (s, r, "lib", dir_lib); + set_dir (s, r, "libexec", dir_path (dir_libexec) /= n, true); + + set_dir (s, r, "data", dir_path (dir_data) /= n, true); + set_dir (s, r, "include", dir_include); + + set_dir (s, r, "doc", dir_path (dir_doc) /= n, true); + set_dir (s, r, "man", dir_man); + set_dir (s, r, "man1", dir_man1); + } + + // Configure "installability" for built-in target types. + // + install_path (b, dir_path ("doc")); // Install into install.doc. + install_path (b, dir_path ("man")); // Install into install.man. + install_path (b, dir_path ("man1")); // Install into install.man1. + + return true; + } + } +} diff --git a/build2/install/module b/build2/install/module deleted file mode 100644 index 3f59fee..0000000 --- a/build2/install/module +++ /dev/null @@ -1,31 +0,0 @@ -// file : build2/install/module -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BUILD2_INSTALL_MODULE -#define BUILD2_INSTALL_MODULE - -#include -#include - -#include - -namespace build2 -{ - namespace install - { - void - boot (scope&, const location&, unique_ptr&); - - bool - init (scope&, - scope&, - const location&, - unique_ptr&, - bool, - bool, - const variable_map&); - } -} - -#endif // BUILD2_INSTALL_MODULE diff --git a/build2/install/module.cxx b/build2/install/module.cxx deleted file mode 100644 index 18ce2ad..0000000 --- a/build2/install/module.cxx +++ /dev/null @@ -1,219 +0,0 @@ -// file : build2/install/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 install - { - // Set install..* values based on config.install..* ones - // or the defaults. If none of config.install.* values were specified, - // then we do omitted/delayed configuration. Note that we still need - // to set all the install.* values to defaults, as if we had the - // default configuration. - // - // If override is true, then override values that came from outer - // configurations. We have to do this for paths that contain the - // package name. - // - template - static void - set_var (bool spec, - scope& r, - const char* name, - const char* var, - const CT* dv, - bool override = false) - { - string vn; - const value* cv (nullptr); - - if (spec) - { - vn = "config.install."; - vn += name; - vn += var; - const variable& vr (var_pool.insert (move (vn), true)); - - cv = dv != nullptr - ? &config::required (r, vr, *dv, override).first.get () - : &config::optional (r, vr); - } - - vn = "install."; - vn += name; - vn += var; - const variable& vr (var_pool.insert (move (vn))); // Not overridable. - - value& v (r.assign (vr)); - - if (spec) - { - if (*cv && !cv->empty ()) // @@ BC LT [null] - v = cast (*cv); // Strip CT to T. - } - else - { - if (dv != nullptr) - v = *dv; - } - } - - template - static void - set_dir (bool s, // specified - scope& r, // root scope - const char* n, // var name - const T& p, // path - bool o = false, // override - const string& fm = string (), // file mode - const string& dm = string (), // dir mode - const build2::path& c = build2::path ()) // command - { - using build2::path; - - set_var (s, r, n, "", p.empty () ? nullptr : &p, o); - set_var (s, r, n, ".mode", fm.empty () ? nullptr : &fm); - set_var (s, r, n, ".dir_mode", dm.empty () ? nullptr : &dm); - set_var (s, r, n, ".sudo", (string*) (nullptr)); - set_var (s, r, n, ".cmd", c.empty () ? nullptr : &c); - set_var (s, r, n, ".options", (strings*) (nullptr)); - - // This one doesn't have config.* value (only set in a buildfile). - // - var_pool.insert (string ("install.") + n + ".subdirs"); - } - - static alias_rule alias_; - static file_rule file_; - - void - boot (scope& r, const location&, unique_ptr&) - { - tracer trace ("install::boot"); - - l5 ([&]{trace << "for " << r.out_path ();}); - - // Register the install operation. - // - r.operations.insert (install_id, install); - } - - static const dir_path dir_root ("root"); - - static const dir_path dir_sbin (dir_path ("exec_root") /= "sbin"); - static const dir_path dir_bin (dir_path ("exec_root") /= "bin"); - static const dir_path dir_lib (dir_path ("exec_root") /= "lib"); - static const dir_path dir_libexec (dir_path ("exec_root") /= "libexec"); - - static const dir_path dir_data (dir_path ("data_root") /= "share"); - static const dir_path dir_include (dir_path ("data_root") /= "include"); - - static const dir_path dir_doc (dir_path (dir_data) /= "doc"); - static const dir_path dir_man (dir_path (dir_data) /= "man"); - static const dir_path dir_man1 (dir_path ("man") /= "man1"); - - bool - init (scope& r, - scope& b, - const location& l, - unique_ptr&, - bool first, - bool, - const variable_map& config_hints) - { - tracer trace ("install::init"); - - if (!first) - { - warn (l) << "multiple install module initializations"; - return true; - } - - const dir_path& out_root (r.out_path ()); - l5 ([&]{trace << "for " << out_root;}); - - assert (config_hints.empty ()); // We don't known any hints. - - // Enter module variables. - // - // Note that the set_dir() calls below enter some more. - // - { - auto& v (var_pool); - - // Note: not overridable. - // - v.insert ("install"); - v.insert ("install.mode"); - } - - // Register our alias and file installer rule. - // - b.rules.insert (perform_install_id, "install.alias", alias_); - b.rules.insert (perform_install_id, "install.file", file_); - - // Configuration. - // - // Note that we don't use any defaults for root -- the location - // must be explicitly specified or the installer will complain - // if and when we try to install. - // - { - using build2::path; - - bool s (config::specified (r, "config.install")); - - // Adjust module priority so that the (numerous) config.install.* - // values are saved at the end of config.build. - // - if (s) - config::save_module (r, "install", INT32_MAX); - - const string& n (cast (r["project"])); - - set_dir (s, r, "root", abs_dir_path (), false, "", "755", path ("install")); - - set_dir (s, r, "data_root", dir_root, false, "644"); - set_dir (s, r, "exec_root", dir_root, false, "755"); - - set_dir (s, r, "sbin", dir_sbin); - set_dir (s, r, "bin", dir_bin); - set_dir (s, r, "lib", dir_lib); - set_dir (s, r, "libexec", dir_path (dir_libexec) /= n, true); - - set_dir (s, r, "data", dir_path (dir_data) /= n, true); - set_dir (s, r, "include", dir_include); - - set_dir (s, r, "doc", dir_path (dir_doc) /= n, true); - set_dir (s, r, "man", dir_man); - set_dir (s, r, "man1", dir_man1); - } - - // Configure "installability" for built-in target types. - // - install_path (b, dir_path ("doc")); // Install into install.doc. - install_path (b, dir_path ("man")); // Install into install.man. - install_path (b, dir_path ("man1")); // Install into install.man1. - - return true; - } - } -} diff --git a/build2/test/init b/build2/test/init new file mode 100644 index 0000000..ec0c4b4 --- /dev/null +++ b/build2/test/init @@ -0,0 +1,31 @@ +// file : build2/test/init -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BUILD2_TEST_INIT +#define BUILD2_TEST_INIT + +#include +#include + +#include + +namespace build2 +{ + namespace test + { + void + boot (scope&, const location&, unique_ptr&); + + bool + init (scope&, + scope&, + const location&, + unique_ptr&, + bool, + bool, + const variable_map&); + } +} + +#endif // BUILD2_TEST_INIT diff --git a/build2/test/init.cxx b/build2/test/init.cxx new file mode 100644 index 0000000..bd03f00 --- /dev/null +++ b/build2/test/init.cxx @@ -0,0 +1,103 @@ +// file : build2/test/init.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include + +#include +#include +#include +#include + +#include +#include + +using namespace std; +using namespace butl; + +namespace build2 +{ + namespace test + { + static rule rule_; + + void + boot (scope& root, const location&, unique_ptr&) + { + tracer trace ("test::boot"); + + l5 ([&]{trace << "for " << root.out_path ();}); + + // Register the test operation. + // + root.operations.insert (test_id, test); + + // Enter module variables. Do it during boot in case they get assigned + // in bootstrap.build. + // + { + auto& v (var_pool); + + // Note: none are overridable. + // + v.insert ("test"); + v.insert ("test.input"); + v.insert ("test.output"); + v.insert ("test.roundtrip"); + v.insert ("test.options"); + v.insert ("test.arguments"); + } + } + + bool + init (scope& root, + scope&, + const location& l, + unique_ptr&, + bool first, + bool, + const variable_map& config_hints) + { + tracer trace ("test::init"); + + if (!first) + { + warn (l) << "multiple test module initializations"; + return true; + } + + const dir_path& out_root (root.out_path ()); + l5 ([&]{trace << "for " << out_root;}); + + assert (config_hints.empty ()); // We don't known any hints. + + //@@ TODO: Need ability to specify extra diff options (e.g., + // --strip-trailing-cr, now hardcoded). + + // Adjust module priority so that the config.test.* values are saved at + // the end of config.build. + // + // if (s) + // config::save_module (r, "test", INT32_MAX); + + // Register rules. + // + { + auto& r (root.rules); + + // Register our test running rule. + // + r.insert (perform_test_id, "test", rule_); + + // Register our rule for the dist meta-operation. We need + // to do this because we have "ad-hoc prerequisites" (test + // input/output files) that need to be entered into the + // target list. + // + r.insert (dist_id, test_id, "test", rule_); + } + + return true; + } + } +} diff --git a/build2/test/module b/build2/test/module deleted file mode 100644 index dacb364..0000000 --- a/build2/test/module +++ /dev/null @@ -1,31 +0,0 @@ -// file : build2/test/module -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BUILD2_TEST_MODULE -#define BUILD2_TEST_MODULE - -#include -#include - -#include - -namespace build2 -{ - namespace test - { - void - boot (scope&, const location&, unique_ptr&); - - bool - init (scope&, - scope&, - const location&, - unique_ptr&, - bool, - bool, - const variable_map&); - } -} - -#endif // BUILD2_TEST_MODULE diff --git a/build2/test/module.cxx b/build2/test/module.cxx deleted file mode 100644 index 83ccf3c..0000000 --- a/build2/test/module.cxx +++ /dev/null @@ -1,103 +0,0 @@ -// file : build2/test/module.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include - -#include -#include -#include -#include - -#include -#include - -using namespace std; -using namespace butl; - -namespace build2 -{ - namespace test - { - static rule rule_; - - void - boot (scope& root, const location&, unique_ptr&) - { - tracer trace ("test::boot"); - - l5 ([&]{trace << "for " << root.out_path ();}); - - // Register the test operation. - // - root.operations.insert (test_id, test); - - // Enter module variables. Do it during boot in case they get assigned - // in bootstrap.build. - // - { - auto& v (var_pool); - - // Note: none are overridable. - // - v.insert ("test"); - v.insert ("test.input"); - v.insert ("test.output"); - v.insert ("test.roundtrip"); - v.insert ("test.options"); - v.insert ("test.arguments"); - } - } - - bool - init (scope& root, - scope&, - const location& l, - unique_ptr&, - bool first, - bool, - const variable_map& config_hints) - { - tracer trace ("test::init"); - - if (!first) - { - warn (l) << "multiple test module initializations"; - return true; - } - - const dir_path& out_root (root.out_path ()); - l5 ([&]{trace << "for " << out_root;}); - - assert (config_hints.empty ()); // We don't known any hints. - - //@@ TODO: Need ability to specify extra diff options (e.g., - // --strip-trailing-cr, now hardcoded). - - // Adjust module priority so that the config.test.* values are saved at - // the end of config.build. - // - // if (s) - // config::save_module (r, "test", INT32_MAX); - - // Register rules. - // - { - auto& r (root.rules); - - // Register our test running rule. - // - r.insert (perform_test_id, "test", rule_); - - // Register our rule for the dist meta-operation. We need - // to do this because we have "ad-hoc prerequisites" (test - // input/output files) that need to be entered into the - // target list. - // - r.insert (dist_id, test_id, "test", rule_); - } - - return true; - } - } -} -- cgit v1.1