From b4c8dc71b6f2c9d8bd63591b3e9a1c6bc329c240 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 30 May 2023 07:12:30 +0200 Subject: Add depdb-dyndep --target-extension-type option This allows specifying custom extension to target type mapping. --- libbuild2/build/script/builtin-options.cxx | 5 +++ libbuild2/build/script/builtin-options.hxx | 17 +++++++++ libbuild2/build/script/builtin-options.ixx | 30 +++++++++++++++ libbuild2/build/script/builtin.cli | 18 +++++---- libbuild2/build/script/parser.cxx | 61 +++++++++++++++++++++++++++++- 5 files changed, 122 insertions(+), 9 deletions(-) (limited to 'libbuild2') diff --git a/libbuild2/build/script/builtin-options.cxx b/libbuild2/build/script/builtin-options.cxx index 3b64de1..dba3c59 100644 --- a/libbuild2/build/script/builtin-options.cxx +++ b/libbuild2/build/script/builtin-options.cxx @@ -294,6 +294,8 @@ namespace build2 target_what_specified_ (false), target_default_type_ (), target_default_type_specified_ (false), + target_extension_type_ (), + target_extension_type_specified_ (false), target_cwd_ (), target_cwd_specified_ (false) { @@ -403,6 +405,9 @@ namespace build2 _cli_depdb_dyndep_options_map_["--target-default-type"] = &::build2::build::cli::thunk< depdb_dyndep_options, string, &depdb_dyndep_options::target_default_type_, &depdb_dyndep_options::target_default_type_specified_ >; + _cli_depdb_dyndep_options_map_["--target-extension-type"] = + &::build2::build::cli::thunk< depdb_dyndep_options, map, &depdb_dyndep_options::target_extension_type_, + &depdb_dyndep_options::target_extension_type_specified_ >; _cli_depdb_dyndep_options_map_["--target-cwd"] = &::build2::build::cli::thunk< depdb_dyndep_options, dir_path, &depdb_dyndep_options::target_cwd_, &depdb_dyndep_options::target_cwd_specified_ >; diff --git a/libbuild2/build/script/builtin-options.hxx b/libbuild2/build/script/builtin-options.hxx index 2a00072..a8c3440 100644 --- a/libbuild2/build/script/builtin-options.hxx +++ b/libbuild2/build/script/builtin-options.hxx @@ -204,6 +204,21 @@ namespace build2 void target_default_type_specified (bool); + const map& + target_extension_type () const; + + map& + target_extension_type (); + + void + target_extension_type (const map&); + + bool + target_extension_type_specified () const; + + void + target_extension_type_specified (bool); + const dir_path& target_cwd () const; @@ -250,6 +265,8 @@ namespace build2 bool target_what_specified_; string target_default_type_; bool target_default_type_specified_; + map target_extension_type_; + bool target_extension_type_specified_; dir_path target_cwd_; bool target_cwd_specified_; }; diff --git a/libbuild2/build/script/builtin-options.ixx b/libbuild2/build/script/builtin-options.ixx index 3e3787f..20847c2 100644 --- a/libbuild2/build/script/builtin-options.ixx +++ b/libbuild2/build/script/builtin-options.ixx @@ -294,6 +294,36 @@ namespace build2 this->target_default_type_specified_ = x; } + inline const map& depdb_dyndep_options:: + target_extension_type () const + { + return this->target_extension_type_; + } + + inline map& depdb_dyndep_options:: + target_extension_type () + { + return this->target_extension_type_; + } + + inline void depdb_dyndep_options:: + target_extension_type (const map& x) + { + this->target_extension_type_ = x; + } + + inline bool depdb_dyndep_options:: + target_extension_type_specified () const + { + return this->target_extension_type_specified_; + } + + inline void depdb_dyndep_options:: + target_extension_type_specified (bool x) + { + this->target_extension_type_specified_ = x; + } + inline const dir_path& depdb_dyndep_options:: target_cwd () const { diff --git a/libbuild2/build/script/builtin.cli b/libbuild2/build/script/builtin.cli index cf1540d..6d6369b 100644 --- a/libbuild2/build/script/builtin.cli +++ b/libbuild2/build/script/builtin.cli @@ -76,8 +76,8 @@ namespace build2 dir_paths --include-path|-I; // Search paths for generated // prerequisites. - string --default-type; // Default prerequisite type to use - // if none could be derived from ext. + string --default-type; // Default prerequisite type to use if + // none could be derived from extension. bool --adhoc; // Treat dynamically discovered // prerequisites as ad hoc (so they @@ -103,15 +103,17 @@ namespace build2 // ad hoc group members (unless already specified as static members). // This functionality is not available in the byproduct mode. // - // @@ BTW, here what would likely be more useful than default target - // is the ability to specify custom extension-to-type mapping in - // order to resolve ambiguities. See also the issue with getting - // these options during clean. - // string --target-what; // Target kind, e.g., "source". string --target-default-type; // Default target type to use if none - // could be derived from ext. + // could be derived from extension. + + map // Extension to target type mapping in + --target-extension-type; // the = form, for example, + // h=hxx. This mapping is considered + // before attempting to automatically + // map the extension and so can be used + // to resolve ambiguities. dir_path --target-cwd; // Builtin's working directory used to // complete relative paths of targets. diff --git a/libbuild2/build/script/parser.cxx b/libbuild2/build/script/parser.cxx index 3814305..9965799 100644 --- a/libbuild2/build/script/parser.cxx +++ b/libbuild2/build/script/parser.cxx @@ -2087,6 +2087,23 @@ namespace build2 << "' specified with --target-default-type"; } + map map_tt; + if (ops.target_extension_type_specified ()) + { + if (!dyn_tgt) + fail (ll) << "depdb dyndep: --target-extension-type specified " + << "without --dyn-target"; + + for (pair& p: ops.target_extension_type ()) + { + const target_type* tt (bs.find_target_type (p.second)); + if (tt == nullptr) + fail (ll) << "depdb dyndep: unknown target type '" << p.second + << "' specified with --target-extension-type"; + + map_tt[p.first] = tt; + } + } // --file (last since need --*cwd) // @@ -2256,7 +2273,6 @@ namespace build2 [] (const scope& bs, const string& n, const string& e) { // NOTE: another version in adhoc_buildscript_rule::apply(). - // NOTE: now also used for dynamic targets below! // @@ TODO: allow specifying base target types. // @@ -3106,6 +3122,47 @@ namespace build2 } } + struct map_ext_data + { + const char* what_tgt; + const map& map_tt; + const path* f; // Updated on each iteration. + } d {what_tgt, map_tt, nullptr}; + + function map_ext ( + [this, &d] (const scope& bs, const string& n, const string& e) + { + small_vector tts; + + // Check the custom mapping first. + // + auto i (d.map_tt.find (e)); + if (i != d.map_tt.end ()) + tts.push_back (i->second); + else + { + tts = dyndep::map_extension (bs, n, e, nullptr); + + // Issue custom diagnostics suggesting --target-extension-type. + // + if (tts.size () > 1) + { + diag_record dr (fail); + + dr << "mapping of " << d.what_tgt << " target path " << *d.f + << " to target type is ambiguous"; + + for (const target_type* tt: tts) + dr << info << "can be " << tt->name << "{}"; + + dr << info << "use --target-extension-type to provide custom " + << "mapping"; + } + } + + return tts; + }); + function filter; if (g != nullptr) { @@ -3131,6 +3188,8 @@ namespace build2 { const path& f (dt.path); + d.f = &f; // Current file being mapped. + // Note that this logic should be consistent with what we have in // adhoc_buildscript_rule::apply() for perform_clean. // -- cgit v1.1