From 9d5a9628d22bae7c6a4f9688e8efdfc2cbb5c4fb Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sun, 7 Jan 2024 12:12:19 +0200 Subject: Add {bin,c,cxx}.types submodules that only register target types --- libbuild2/bin/init.cxx | 120 ++++++++++++++++++++++------------- libbuild2/bin/init.hxx | 6 +- libbuild2/c/init.cxx | 162 +++++++++++++++++++++++++++++++++++++++--------- libbuild2/c/init.hxx | 25 +++++--- libbuild2/cc/module.cxx | 43 +------------ libbuild2/cxx/init.cxx | 161 ++++++++++++++++++++++++++++++++++++----------- libbuild2/cxx/init.hxx | 20 +++--- 7 files changed, 371 insertions(+), 166 deletions(-) diff --git a/libbuild2/bin/init.cxx b/libbuild2/bin/init.cxx index 1b3039f..610082e 100644 --- a/libbuild2/bin/init.cxx +++ b/libbuild2/bin/init.cxx @@ -41,16 +41,19 @@ namespace build2 bool vars_init (scope& rs, - scope&, - const location&, - bool first, + scope& bs, + const location& loc, + bool, bool, module_init_extra&) { tracer trace ("bin::vars_init"); l5 ([&]{trace << "for " << rs;}); - assert (first); + // We only support root loading (which means there can only be one). + // + if (rs != bs) + fail (loc) << "bin.vars module must be loaded in project root"; // Enter variables. // @@ -156,6 +159,68 @@ namespace build2 return true; } + bool + types_init (scope& rs, + scope& bs, + const location& loc, + bool, + bool, + module_init_extra&) + { + tracer trace ("bin::types_init"); + l5 ([&]{trace << "for " << rs;}); + + // We only support root loading (which means there can only be one). + // + if (rs != bs) + fail (loc) << "bin.types module must be loaded in project root"; + + // Register target types. + // + // Note that certain platform-specific and toolchain-specific types are + // registered in bin and bin.ld. + // + // Note also that it would make sense to configure their default + // "installability" here but that requires the knowledge of the platform + // in some cases. So we do it all in bin for now. One way to support + // both use-cases would be to detect if we are loaded after bin.guess + // and then decide whether to do it here or delay to bin. + // + // NOTE: remember to update the documentation if changing anything here! + // + rs.insert_target_type (); + rs.insert_target_type (); + rs.insert_target_type (); + rs.insert_target_type (); + + rs.insert_target_type (); + rs.insert_target_type (); + rs.insert_target_type (); + rs.insert_target_type (); + + rs.insert_target_type (); + rs.insert_target_type (); + rs.insert_target_type (); + rs.insert_target_type (); + + rs.insert_target_type (); + rs.insert_target_type (); + rs.insert_target_type (); + rs.insert_target_type (); + + rs.insert_target_type (); + rs.insert_target_type (); + rs.insert_target_type (); + + // Register the def{} target type. Note that we do it here since it is + // input and can be specified unconditionally (i.e., not only when + // building for Windows). + // + rs.insert_target_type (); + + return true; + } + void functions (function_map&); // functions.cxx @@ -450,56 +515,22 @@ namespace build2 tracer trace ("bin::init"); l5 ([&]{trace << "for " << bs;}); - // Load bin.config. + // Load bin.{config,types}. // load_module (rs, rs, "bin.config", loc, extra.hints); + load_module (rs, rs, "bin.types", loc); // Cache some config values we will be needing below. // const target_triplet& tgt (cast (rs["bin.target"])); - // Register target types and configure their default "installability". + // Configure target type default "installability". Also register + // additional platform-specific types. // bool install_loaded (cast_false (rs["install.loaded"])); { using namespace install; - if (first) - { - // NOTE: remember to update the documentation if changing anything - // here! - // - rs.insert_target_type (); - rs.insert_target_type (); - rs.insert_target_type (); - rs.insert_target_type (); - - rs.insert_target_type (); - rs.insert_target_type (); - rs.insert_target_type (); - rs.insert_target_type (); - - rs.insert_target_type (); - rs.insert_target_type (); - rs.insert_target_type (); - rs.insert_target_type (); - - rs.insert_target_type (); - rs.insert_target_type (); - rs.insert_target_type (); - rs.insert_target_type (); - - rs.insert_target_type (); - rs.insert_target_type (); - rs.insert_target_type (); - - // Register the def{} target type. Note that we do it here since it - // is input and can be specified unconditionally (i.e., not only - // when building for Windows). - // - rs.insert_target_type (); - } - // Note: libu*{} members are not installable. // if (install_loaded) @@ -549,6 +580,8 @@ namespace build2 if (tgt.cpu == "wasm32" || tgt.cpu == "wasm64") { + // @@ TODO: shouldn't this be wrapped in if(first) somehow? + const target_type& wasm ( rs.derive_target_type( target_type { @@ -945,6 +978,8 @@ namespace build2 if (lid == "msvc") { + // @@ TODO: shouldn't this be wrapped in if(first) somehow? + const target_type& pdb ( rs.derive_target_type( target_type { @@ -1219,6 +1254,7 @@ namespace build2 // changing anything here. {"bin.vars", nullptr, vars_init}, + {"bin.types", nullptr, types_init}, {"bin.config", nullptr, config_init}, {"bin.ar.config", nullptr, ar_config_init}, {"bin.ar", nullptr, ar_init}, diff --git a/libbuild2/bin/init.hxx b/libbuild2/bin/init.hxx index 4eb0f10..b163bf5 100644 --- a/libbuild2/bin/init.hxx +++ b/libbuild2/bin/init.hxx @@ -20,9 +20,11 @@ namespace build2 // Submodules: // // `bin.vars` -- registers some variables. + // `bin.types` -- registers target types. // `bin.config` -- loads bin.vars and sets some variables. - // `bin` -- loads bin.config and registers target types and - // rules. + // `bin` -- loads bin.{types,config} and registers rules and + // functions. + // // `bin.ar.config` -- loads bin.config and registers/sets more variables. // `bin.ar` -- loads bin and bin.ar.config. // diff --git a/libbuild2/c/init.cxx b/libbuild2/c/init.cxx index d8d7488..3c03c9c 100644 --- a/libbuild2/c/init.cxx +++ b/libbuild2/c/init.cxx @@ -6,9 +6,12 @@ #include #include +#include + #include #include +#include // pc* #include #ifndef BUILD2_DEFAULT_C @@ -154,6 +157,79 @@ namespace build2 } } + // See cc::data::x_{hdr,inc} for background. + // + static const target_type* const hdr[] = + { + &h::static_type, + nullptr + }; + + // Note that we include S{} here because .S files can include each other. + // (And maybe from inline assembler instructions?) + // + static const target_type* const inc[] = + { + &h::static_type, + &c::static_type, + &m::static_type, + &S::static_type, + &c_inc::static_type, + nullptr + }; + + bool + types_init (scope& rs, + scope& bs, + const location& loc, + bool, + bool, + module_init_extra&) + { + tracer trace ("c::types_init"); + l5 ([&]{trace << "for " << bs;}); + + // We only support root loading (which means there can only be one). + // + if (rs != bs) + fail (loc) << "c.types module must be loaded in project root"; + + // Register target types and configure their "installability". + // + using namespace install; + + bool install_loaded (cast_false (rs["install.loaded"])); + + // Note: not registering m{} or S{} (they are registered seperately + // by the respective optional .types submodules). + // + rs.insert_target_type (); + + auto insert_hdr = [&rs, install_loaded] (const target_type& tt) + { + rs.insert_target_type (tt); + + // Install headers into install.include. + // + if (install_loaded) + install_path (rs, tt, dir_path ("include")); + }; + + for (const target_type* const* ht (hdr); *ht != nullptr; ++ht) + insert_hdr (**ht); + + // @@ PERF: maybe factor this to cc.types? + // + rs.insert_target_type (); + rs.insert_target_type (); + rs.insert_target_type (); + + if (install_loaded) + install_path (rs, dir_path ("pkgconfig")); + + return true; + } + static const char* const hinters[] = {"cxx", nullptr}; // See cc::module for details on guess_init vs config_init. @@ -343,25 +419,6 @@ namespace build2 return true; } - static const target_type* const hdr[] = - { - &h::static_type, - nullptr - }; - - // Note that we include S{} here because .S files can include each other. - // (And maybe from inline assembler instructions?) - // - static const target_type* const inc[] = - { - &h::static_type, - &c::static_type, - &m::static_type, - &S::static_type, - &c_inc::static_type, - nullptr - }; - bool init (scope& rs, scope& bs, @@ -435,6 +492,29 @@ namespace build2 } bool + objc_types_init (scope& rs, + scope& bs, + const location& loc, + bool, + bool, + module_init_extra&) + { + tracer trace ("c::objc_types_init"); + l5 ([&]{trace << "for " << bs;}); + + // We only support root loading (which means there can only be one). + // + if (rs != bs) + fail (loc) << "c.objc.types module must be loaded in project root"; + + // Register the m{} target type. + // + rs.insert_target_type (); + + return true; + } + + bool objc_init (scope& rs, scope& bs, const location& loc, @@ -463,7 +543,7 @@ namespace build2 // // Note: see similar code in the cxx module. // - rs.insert_target_type (); + load_module (rs, rs, "c.objc.types", loc); // Note that while Objective-C is supported by MinGW GCC, it's unlikely // Clang supports it when targeting MSVC or Emscripten. But let's keep @@ -477,6 +557,29 @@ namespace build2 } bool + as_cpp_types_init (scope& rs, + scope& bs, + const location& loc, + bool, + bool, + module_init_extra&) + { + tracer trace ("c::as_cpp_types_init"); + l5 ([&]{trace << "for " << bs;}); + + // We only support root loading (which means there can only be one). + // + if (rs != bs) + fail (loc) << "c.as-cpp.types module must be loaded in project root"; + + // Register the S{} target type. + // + rs.insert_target_type (); + + return true; + } + + bool as_cpp_init (scope& rs, scope& bs, const location& loc, @@ -503,7 +606,7 @@ namespace build2 // C compiler is capable of compiling Assember with C preprocessor. But // we enable only if it is. // - rs.insert_target_type (); + load_module (rs, rs, "c.as-cpp.types", loc); if (mod->ctype == compiler_type::gcc || mod->ctype == compiler_type::clang) @@ -553,13 +656,16 @@ namespace build2 // NOTE: don't forget to also update the documentation in init.hxx if // changing anything here. - {"c.guess", nullptr, guess_init}, - {"c.config", nullptr, config_init}, - {"c.objc", nullptr, objc_init}, - {"c.as-cpp", nullptr, as_cpp_init}, - {"c.predefs", nullptr, predefs_init}, - {"c", nullptr, init}, - {nullptr, nullptr, nullptr} + {"c.types", nullptr, types_init}, + {"c.guess", nullptr, guess_init}, + {"c.config", nullptr, config_init}, + {"c.objc.types", nullptr, objc_types_init}, + {"c.objc", nullptr, objc_init}, + {"c.as-cpp.types", nullptr, as_cpp_types_init}, + {"c.as-cpp", nullptr, as_cpp_init}, + {"c.predefs", nullptr, predefs_init}, + {"c", nullptr, init}, + {nullptr, nullptr, nullptr} }; const module_functions* diff --git a/libbuild2/c/init.hxx b/libbuild2/c/init.hxx index 713a78a..38515c1 100644 --- a/libbuild2/c/init.hxx +++ b/libbuild2/c/init.hxx @@ -19,15 +19,22 @@ namespace build2 // // Submodules: // - // `c.guess` -- registers and sets some variables. - // `c.config` -- loads c.guess and sets more variables. - // `c` -- loads c.config and registers target types and rules. - // `c.objc` -- registers m{} target type and enables Objective-C - // compilation. Must be loaded after c. - // `c.as-cpp` -- registers S{} target type and enables Assembler with - // C preprocessor compilation. Must be loaded after c. - // `c.predefs` -- registers rule for generating a C header with - // predefined compiler macros. Must be loaded after c. + // `c.types` -- registers target types. + // `c.guess` -- registers and sets some variables. + // `c.config` -- loads c.guess and sets more variables. + // `c` -- loads c.{types,config} and registers rules and + // functions. + // + // `c.objc.types` -- registers m{} target type. + // `c.objc` -- loads c.objc.types and enables Objective-C + // compilation. Must be loaded after c. + // + // `c.as-cpp.types` -- registers S{} target type. + // `c.as-cpp` -- loads c.as-cpp.types and enables Assembler with C + // preprocessor compilation. Must be loaded after c. + // + // `c.predefs` -- registers rule for generating a C header with + // predefined compiler macros. Must be loaded after c. // extern "C" LIBBUILD2_C_SYMEXPORT const module_functions* build2_c_load (); diff --git a/libbuild2/cc/module.cxx b/libbuild2/cc/module.cxx index eed7db1..70624a2 100644 --- a/libbuild2/cc/module.cxx +++ b/libbuild2/cc/module.cxx @@ -11,10 +11,7 @@ #include -#include // pc* - #include -#include #include @@ -989,43 +986,7 @@ namespace build2 // Register target types and configure their "installability". // - bool install_loaded (cast_false (rs["install.loaded"])); - - { - using namespace install; - - // Note: not registering x_obj or x_asp (they are registered - // seperately by the respective optional submodules). - // - rs.insert_target_type (x_src); - - auto insert_hdr = [&rs, install_loaded] (const target_type& tt) - { - rs.insert_target_type (tt); - - // Install headers into install.include. - // - if (install_loaded) - install_path (rs, tt, dir_path ("include")); - }; - - // Note: module (x_mod) is in x_hdrs. - // - for (const target_type* const* ht (x_hdrs); *ht != nullptr; ++ht) - insert_hdr (**ht); - - // Also register the C header for C-derived languages. - // - if (*x_hdrs != &h::static_type) - insert_hdr (h::static_type); - - rs.insert_target_type (); - rs.insert_target_type (); - rs.insert_target_type (); - - if (install_loaded) - install_path (rs, dir_path ("pkgconfig")); - } + load_module (rs, rs, (string (x) += ".types"), loc); // Register rules. // @@ -1123,7 +1084,7 @@ namespace build2 // them in case they depend on stuff that we need to install (see the // install rule implementations for details). // - if (install_loaded) + if (cast_false (rs["install.loaded"])) { // Note: we rely quite heavily in these rule implementations that // these are the only target types they are registered for. diff --git a/libbuild2/cxx/init.cxx b/libbuild2/cxx/init.cxx index 7dadce8..941593e 100644 --- a/libbuild2/cxx/init.cxx +++ b/libbuild2/cxx/init.cxx @@ -7,10 +7,12 @@ #include #include +#include #include #include +#include // pc* #include #ifndef BUILD2_DEFAULT_CXX @@ -617,6 +619,95 @@ namespace build2 //set_feature (concepts); } + // See cc::data::x_{hdr,inc} for background. + // + static const target_type* const hdr[] = + { + &hxx::static_type, + &ixx::static_type, + &txx::static_type, + &mxx::static_type, + nullptr + }; + + // Note that we don't include S{} here because none of the files we + // compile can plausibly want to include .S. (Maybe in inline assembler + // instructions?) + // + static const target_type* const inc[] = + { + &hxx::static_type, + &h::static_type, + &ixx::static_type, + &txx::static_type, + &mxx::static_type, + &cxx::static_type, + &c::static_type, + &mm::static_type, + &m::static_type, + &cxx_inc::static_type, + &cc::c_inc::static_type, + nullptr + }; + + bool + types_init (scope& rs, + scope& bs, + const location& loc, + bool, + bool, + module_init_extra&) + { + tracer trace ("cxx::types_init"); + l5 ([&]{trace << "for " << bs;}); + + // We only support root loading (which means there can only be one). + // + if (rs != bs) + fail (loc) << "cxx.types module must be loaded in project root"; + + // Register target types and configure their "installability". + // + using namespace install; + + bool install_loaded (cast_false (rs["install.loaded"])); + + // Note: not registering mm{} (it is registered seperately by the + // respective optional .types submodule). + // + // Note: mxx{} is in hdr. @@ But maybe it shouldn't be... + // + rs.insert_target_type (); + + auto insert_hdr = [&rs, install_loaded] (const target_type& tt) + { + rs.insert_target_type (tt); + + // Install headers into install.include. + // + if (install_loaded) + install_path (rs, tt, dir_path ("include")); + }; + + for (const target_type* const* ht (hdr); *ht != nullptr; ++ht) + insert_hdr (**ht); + + // Also register the C header for C-derived languages. + // + insert_hdr (h::static_type); + + // @@ PERF: maybe factor this to cc.types? + // + rs.insert_target_type (); + rs.insert_target_type (); + rs.insert_target_type (); + + if (install_loaded) + install_path (rs, dir_path ("pkgconfig")); + + return true; + } + static const char* const hinters[] = {"c", nullptr}; // See cc::module for details on guess_init vs config_init. @@ -948,35 +1039,6 @@ namespace build2 return true; } - static const target_type* const hdr[] = - { - &hxx::static_type, - &ixx::static_type, - &txx::static_type, - &mxx::static_type, - nullptr - }; - - // Note that we don't include S{} here because none of the files we - // compile can plausibly want to include .S. (Maybe in inline assembler - // instructions?) - // - static const target_type* const inc[] = - { - &hxx::static_type, - &h::static_type, - &ixx::static_type, - &txx::static_type, - &mxx::static_type, - &cxx::static_type, - &c::static_type, - &mm::static_type, - &m::static_type, - &cxx_inc::static_type, - &cc::c_inc::static_type, - nullptr - }; - bool init (scope& rs, scope& bs, @@ -1062,12 +1124,35 @@ namespace build2 } bool + objcxx_types_init (scope& rs, + scope& bs, + const location& loc, + bool, + bool, + module_init_extra&) + { + tracer trace ("cxx::objcxx_types_init"); + l5 ([&]{trace << "for " << bs;}); + + // We only support root loading (which means there can only be one). + // + if (rs != bs) + fail (loc) << "cxx.objcxx.types module must be loaded in project root"; + + // Register the mm{} target type. + // + rs.insert_target_type (); + + return true; + } + + bool objcxx_init (scope& rs, scope& bs, const location& loc, bool, bool, - module_init_extra&) + module_init_extra&) { tracer trace ("cxx::objcxx_init"); l5 ([&]{trace << "for " << bs;}); @@ -1090,7 +1175,7 @@ namespace build2 // // Note: see similar code in the c module. // - rs.insert_target_type (); + load_module (rs, rs, "cxx.objcxx.types", loc); // Note that while Objective-C++ is supported by MinGW GCC, it's // unlikely Clang supports it when targeting MSVC or Emscripten. But @@ -1144,12 +1229,14 @@ namespace build2 // NOTE: don't forget to also update the documentation in init.hxx if // changing anything here. - {"cxx.guess", nullptr, guess_init}, - {"cxx.config", nullptr, config_init}, - {"cxx.objcxx", nullptr, objcxx_init}, - {"cxx.predefs", nullptr, predefs_init}, - {"cxx", nullptr, init}, - {nullptr, nullptr, nullptr} + {"cxx.types", nullptr, types_init}, + {"cxx.guess", nullptr, guess_init}, + {"cxx.config", nullptr, config_init}, + {"cxx.objcxx.types", nullptr, objcxx_types_init}, + {"cxx.objcxx", nullptr, objcxx_init}, + {"cxx.predefs", nullptr, predefs_init}, + {"cxx", nullptr, init}, + {nullptr, nullptr, nullptr} }; const module_functions* diff --git a/libbuild2/cxx/init.hxx b/libbuild2/cxx/init.hxx index 5b80fdc..a193e74 100644 --- a/libbuild2/cxx/init.hxx +++ b/libbuild2/cxx/init.hxx @@ -19,13 +19,19 @@ namespace build2 // // Submodules: // - // `cxx.guess` -- registers and sets some variables. - // `cxx.config` -- loads cxx.guess and sets more variables. - // `cxx` -- loads cxx.config and registers target types and rules. - // `cxx.objcxx` -- registers mm{} target type and enables Objective-C++ - // compilation. - // `cxx.predefs` -- registers rule for generating a C++ header with - // predefined compiler macros. Must be loaded after cxx. + // `cxx.types` -- registers target types. + // `cxx.guess` -- registers and sets some variables. + // `cxx.config` -- loads cxx.guess and sets more variables. + // `cxx` -- loads cxx.{types,config} and registers rules + // and functions. + // + // `cxx.objcxx.types` -- registers mm{} target type. + // `cxx.objcxx` -- loads cxx.objcxx and enables Objective-C++ + // compilation. + // + // `cxx.predefs` -- registers rule for generating a C++ header with + // predefined compiler macros. Must be loaded after + // cxx. // extern "C" LIBBUILD2_CXX_SYMEXPORT const module_functions* build2_cxx_load (); -- cgit v1.1