From acdcc228c252e2a0a90a8586c5b5c6984332635b Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 26 Jul 2018 09:30:11 +0200 Subject: Pass extension supplied by rule to target type default extension function Also revert the precedence back to target type over rule. But now the target type is able to customize this logic (see exe{} for a use case). --- build2/cc/compile-rule.cxx | 2 +- build2/search.cxx | 2 +- build2/target-type.hxx | 9 ++++++--- build2/target.cxx | 39 +++++++++++++++++++++++---------------- build2/target.hxx | 6 +++--- build2/target.txx | 5 ++++- 6 files changed, 38 insertions(+), 25 deletions(-) diff --git a/build2/cc/compile-rule.cxx b/build2/cc/compile-rule.cxx index 12bf2fa..ebd12fd 100644 --- a/build2/cc/compile-rule.cxx +++ b/build2/cc/compile-rule.cxx @@ -1068,7 +1068,7 @@ namespace build2 // This is like prerequisite search. // - if (optional de = tt.default_extension (tk, s, true)) + if (optional de = tt.default_extension (tk, s, nullptr, true)) if (*de == e) return true; diff --git a/build2/search.cxx b/build2/search.cxx index 69e9986..960229b 100644 --- a/build2/search.cxx +++ b/build2/search.cxx @@ -117,7 +117,7 @@ namespace build2 if (auto f = ctk.type->fixed_extension) ext = f (ctk); else if (auto f = ctk.type->default_extension) - ext = f (ctk, *s, true); + ext = f (ctk, *s, nullptr, true); if (!ext) { diff --git a/build2/target-type.hxx b/build2/target-type.hxx index ebe60db..408a520 100644 --- a/build2/target-type.hxx +++ b/build2/target-type.hxx @@ -34,12 +34,14 @@ namespace build2 // returns NULL, then it means the default extension for this target could // not be derived. // - // The default extension is used in two (key; there are others) places: + // The default extension is used in two key (there are others) places: // search_existing_file() (called for a prerequisite with the last argument // true) and in target::derive_extension() (called for a target with the // last argument false); see their respective implementations for details. - // Note that the default extension supplied to derive_extension() (e.g., by - // a rule) takes precedence over the one returned by default_extension. + // The third argument is the default extension that is supplied (e.g., by a + // rule) to derive_extension(), if any. The implementation can decide which + // takes precedence, etc (see the exe{} target type for some interesting + // logic). // // If the pattern function is not NULL, then it is used to amend a pattern // or match (reverse is false) and then, if the amendment call returned @@ -55,6 +57,7 @@ namespace build2 const char* (*fixed_extension) (const target_key&); optional (*default_extension) (const target_key&, const scope&, + const char*, bool search); bool (*pattern) (const target_type&, const scope&, string&, bool reverse); diff --git a/build2/target.cxx b/build2/target.cxx index 200f562..e6188cd 100644 --- a/build2/target.cxx +++ b/build2/target.cxx @@ -488,19 +488,21 @@ namespace build2 { optional e; - // Prefer the default extension specified (presumably) by the rule over - // the one returned by the default extension function. Here we assume - // the rule knows what it is doing (see the exe{} target type for a use - // case). + // If the target type has the default extension function then try that + // first. The reason for preferring it over what's been provided by the + // caller is that this function will often use the 'extension' variable + // which the user can use to override extensions. But since we pass the + // provided default extension, the target type can override this logic + // (see the exe{} target type for a use case). // - if (de != nullptr) - e = de; - else - { - if (auto f = type ().default_extension) - e = f (key (), base_scope (), search); + if (auto f = type ().default_extension) + e = f (key (), base_scope (), de, search); - if (!e) + if (!e) + { + if (de != nullptr) + e = de; + else { if (search) return nullptr; @@ -577,13 +579,13 @@ namespace build2 } optional - target_extension_null (const target_key&, const scope&, bool) + target_extension_null (const target_key&, const scope&, const char*, bool) { return nullopt; } optional - target_extension_assert (const target_key&, const scope&, bool) + target_extension_assert (const target_key&, const scope&, const char*, bool) { assert (false); // Attempt to obtain the default extension. throw failed (); @@ -847,14 +849,19 @@ namespace build2 }; static optional - exe_target_extension (const target_key&, const scope&, bool search) + exe_target_extension (const target_key&, + const scope&, + const char* e, + bool search) { // If we are searching for an executable that is not a target, then use // the build machine executable extension. Otherwise, if this is a target, // then we expect the rule to supply the target machine extension. But if - // it doesn't, then assume no extension (e.g., a script). + // it doesn't, then fallback to no extension (e.g., a script). // - return string (!search ? "" : + return string (!search + ? (e != nullptr ? e : "") + : #ifdef _WIN32 "exe" #else diff --git a/build2/target.hxx b/build2/target.hxx index aad5331..0f8c8ea 100644 --- a/build2/target.hxx +++ b/build2/target.hxx @@ -1713,7 +1713,7 @@ namespace build2 // template optional - target_extension_var (const target_key&, const scope&, bool); + target_extension_var (const target_key&, const scope&, const char*, bool); template bool @@ -1722,12 +1722,12 @@ namespace build2 // Always return NULL extension. // optional - target_extension_null (const target_key&, const scope&, bool); + target_extension_null (const target_key&, const scope&, const char*, bool); // Assert if called. // optional - target_extension_assert (const target_key&, const scope&, bool); + target_extension_assert (const target_key&, const scope&, const char*, bool); // Target print functions. // diff --git a/build2/target.txx b/build2/target.txx index 4feea2f..d832d6b 100644 --- a/build2/target.txx +++ b/build2/target.txx @@ -105,7 +105,10 @@ namespace build2 template optional - target_extension_var (const target_key& tk, const scope& s, bool) + target_extension_var (const target_key& tk, + const scope& s, + const char*, + bool) { return target_extension_var_impl (*tk.type, *tk.name, s, var, def); } -- cgit v1.1