From 20e49b4e63779abc0e25bec4c74399a83ec8a83c Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 12 Feb 2024 09:34:50 +0200 Subject: Add ability to specify recipes in separate files This can now be achieved with the new `recipe` directive: recipe Note that similar to the use of if-else and switch directives with recipes, this directive requires explicit % recipe header. For example, instead of: file{foo.output}: {{ echo 'hello' >$path($>) }} We can now write: file{foo.output}: % recipe buildscript hello.buildscript With hello.buildscript containing: echo 'hello' >$path($>) Similarly, for C++ recipes (this time for a pattern), instead of: [rule_name=hello] file{~'/(.+)\.output/'}: % update clean {{ c++ 1 -- -- ... }} We can now write: [rule_name=hello] file{~'/(.+)\.output/'}: % update clean recipe c++ hello.cxx With hello.cxx containing: // c++ 1 -- -- ... Relative paths are resolved using the buildfile directory that contains the `recipe` directive as a base. Note also that this mechanism can be used in exported buildfiles with recipe files placed into build/export/ together with buildfiles. --- libbuild2/target.cxx | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'libbuild2/target.cxx') diff --git a/libbuild2/target.cxx b/libbuild2/target.cxx index a70830e..2a134a4 100644 --- a/libbuild2/target.cxx +++ b/libbuild2/target.cxx @@ -1775,6 +1775,55 @@ namespace build2 target_type::flag::none }; + static const char* + buildscript_target_extension (const target_key& tk, const scope*) + { + // If the name is special 'buildscript', then there is no extension, + // otherwise it is .buildscript. + // + return *tk.name == "buildscript" ? "" : "buildscript"; + } + + static bool + buildscript_target_pattern (const target_type&, + const scope&, + string& v, + optional& e, + const location& l, + bool r) + { + if (r) + { + assert (e); + e = nullopt; + } + else + { + e = target::split_name (v, l); + + if (!e && v != "buildscript") + { + e = "buildscript"; + return true; + } + } + + return false; + } + + const target_type buildscript::static_type + { + "buildscript", + &file::static_type, + &target_factory, + &buildscript_target_extension, + nullptr, /* default_extension */ + &buildscript_target_pattern, + nullptr, + &file_search, + target_type::flag::none + }; + const target_type doc::static_type { "doc", -- cgit v1.1