From 75152526696fc024628796f0633ed695d5ebc49c Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 16 Dec 2016 17:22:28 +0200 Subject: Move exe{} to build2 core, add fallback extensions (existing files) --- build2/bin/init.cxx | 3 --- build2/bin/target | 10 ---------- build2/bin/target.cxx | 22 ---------------------- build2/cc/compile.cxx | 4 +++- build2/cc/utility.ixx | 2 +- build2/context.cxx | 1 + build2/install/init.cxx | 1 + build2/rule.cxx | 5 +++++ build2/search.cxx | 4 +--- build2/target | 27 ++++++++++++++++++++------- build2/target-type | 9 +++++---- build2/target.cxx | 39 ++++++++++++++++++++++++++++++++++----- build2/target.txx | 4 ++-- build2/test/target.cxx | 2 +- 14 files changed, 74 insertions(+), 59 deletions(-) diff --git a/build2/bin/init.cxx b/build2/bin/init.cxx index 498118f..ff30c4f 100644 --- a/build2/bin/init.cxx +++ b/build2/bin/init.cxx @@ -342,9 +342,6 @@ namespace build2 t.insert (); t.insert (); - t.insert (); - install_path (b, dir_path ("bin")); // Install into install.bin. - t.insert (); t.insert (); t.insert (); diff --git a/build2/bin/target b/build2/bin/target index caf96f4..f3fe4fe 100644 --- a/build2/bin/target +++ b/build2/bin/target @@ -60,16 +60,6 @@ namespace build2 virtual const target_type& dynamic_type () const {return static_type;} }; - class exe: public file - { - public: - using file::file; - - public: - static const target_type static_type; - virtual const target_type& dynamic_type () const {return static_type;} - }; - // The lib{} target group. // class liba: public file diff --git a/build2/bin/target.cxx b/build2/bin/target.cxx index 770afbb..3277eb1 100644 --- a/build2/bin/target.cxx +++ b/build2/bin/target.cxx @@ -129,28 +129,6 @@ namespace build2 false }; - // @@ What extension should we be using when searching for an existing - // exe{}? Say we have a dependency on some pre-existing tool, maybe - // some source code generator. Should we use 'build' extension? But - // what if we find such an executable for something that we need to - // build for 'host'? - // - // What if we use extension variables and scoping. We could set the - // root scope exe{*} extension to 'build' and then, say, cxx module - // (or any module that knows how to build exe{}) changes it to the - // 'host'. Maybe that's not a bad idea? - // - const target_type exe::static_type - { - "exe", - &file::static_type, - &target_factory, - &target_extension_var, - nullptr, - &search_file, - false - }; - static target* liba_factory (const target_type& t, dir_path d, diff --git a/build2/cc/compile.cxx b/build2/cc/compile.cxx index 37cd7d7..74a9422 100644 --- a/build2/cc/compile.cxx +++ b/build2/cc/compile.cxx @@ -418,7 +418,9 @@ namespace build2 const string* dummy (nullptr); target_key tk {&tt, nullptr, nullptr, &n, dummy}; - if (const string* de = tt.extension (tk, s)) + // This is like prerequisite search. + // + if (const string* de = tt.extension (tk, s, true)) if (*de == e) return true; diff --git a/build2/cc/utility.ixx b/build2/cc/utility.ixx index dda74eb..ee54b6d 100644 --- a/build2/cc/utility.ixx +++ b/build2/cc/utility.ixx @@ -19,7 +19,7 @@ namespace build2 link_type (target& t) { return - t.is_a () ? otype::e : + t.is_a () ? otype::e : t.is_a () ? otype::a : otype::s; } diff --git a/build2/context.cxx b/build2/context.cxx index 0966c3a..2b1f24d 100644 --- a/build2/context.cxx +++ b/build2/context.cxx @@ -314,6 +314,7 @@ namespace build2 t.insert (); t.insert (); t.insert (); + t.insert (); t.insert (); t.insert (); t.insert (); diff --git a/build2/install/init.cxx b/build2/install/init.cxx index 73e4c1e..842eb0c 100644 --- a/build2/install/init.cxx +++ b/build2/install/init.cxx @@ -245,6 +245,7 @@ namespace build2 // Configure "installability" for built-in target types. // + install_path (b, dir_path ("bin")); // Install into install.bin. 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. diff --git a/build2/rule.cxx b/build2/rule.cxx index f9805db..49172a7 100644 --- a/build2/rule.cxx +++ b/build2/rule.cxx @@ -57,6 +57,11 @@ namespace build2 // if (pt.path ().empty ()) { + // Since we cannot come up with an extension, ask the target's + // derivation function to treat this as prerequisite (just like + // in search_existing_file()). + // + pt.derive_extension (nullptr, true); pt.derive_path (); ts = pt.mtime (); } diff --git a/build2/search.cxx b/build2/search.cxx index 68191f5..6889a36 100644 --- a/build2/search.cxx +++ b/build2/search.cxx @@ -81,9 +81,7 @@ namespace build2 if (ext == nullptr) { if (auto f = ctk.type->extension) - { - ext = f (ctk, *cpk.scope); // Already from the pool. - } + ext = f (ctk, *cpk.scope, true); // Already from the pool. if (ext == nullptr) { diff --git a/build2/target b/build2/target index f824689..5c897f1 100644 --- a/build2/target +++ b/build2/target @@ -425,7 +425,7 @@ namespace build2 // By default we go an extra step and short-circuit to the target state // even if the raw state is not group provided the recipe is group_recipe. // This is normally what you want or need, as in inject_prerequisites() - // in the cxx module. But sometimes not, as in execute(). + // in the cc module. But sometimes not, as in execute(). // target_state state (bool shortcircuit = true) const @@ -1140,10 +1140,11 @@ namespace build2 derive_path (path_type base, const char* default_ext = nullptr); // As above but only derives (and returns) the extension (empty means no - // extension used). + // extension used). If search is true then look for the extension as if + // it was a prerequisite, not a target. // const string& - derive_extension (const char* default_ext = nullptr); + derive_extension (const char* default_ext = nullptr, bool search = false); public: static const target_type static_type; @@ -1215,6 +1216,18 @@ namespace build2 virtual const target_type& dynamic_type () const {return static_type;} }; + // Executable file. + // + class exe: public file + { + public: + using file::file; + + public: + static const target_type static_type; + virtual const target_type& dynamic_type () const {return static_type;} + }; + class buildfile: public file { public: @@ -1311,24 +1324,24 @@ namespace build2 // template const string* - target_extension_fix (const target_key&, scope&); + target_extension_fix (const target_key&, scope&, bool); // Get the extension from the variable or use the default if none set. If // the default is NULL, then return NULL. // template const string* - target_extension_var (const target_key&, scope&); + target_extension_var (const target_key&, scope&, bool); // Always return NULL extension. // const string* - target_extension_null (const target_key&, scope&); + target_extension_null (const target_key&, scope&, bool); // Assert if called. // const string* - target_extension_assert (const target_key&, scope&); + target_extension_assert (const target_key&, scope&, bool); // Target print functions. // diff --git a/build2/target-type b/build2/target-type index 378fd7c..5e7f59b 100644 --- a/build2/target-type +++ b/build2/target-type @@ -31,9 +31,10 @@ namespace build2 // respectively. If the extension function returns NULL, then that means the // default extension for this target could not be derived. // - // The extension is primarily used in two places: search_existing_file() - // (called for a prerequisite) and in target::derive_path() (called for a - // target); see their implementations for details. + // The extension is used in two places: search_existing_file() (called for a + // prerequisite with the last argument true) and in target::derive_path() + // (called for a target with the last argument false); see their + // implementations for details. // struct target_type { @@ -41,7 +42,7 @@ namespace build2 const target_type* base; target* (*factory) ( const target_type&, dir_path, dir_path, string, const string*); - const string* (*extension) (const target_key&, scope&); + const string* (*extension) (const target_key&, scope&, bool search); void (*print) (ostream&, const target_key&); target* (*search) (const prerequisite_key&); bool see_through; // A group with the default "see through" semantics. diff --git a/build2/target.cxx b/build2/target.cxx index 126159c..385cebd 100644 --- a/build2/target.cxx +++ b/build2/target.cxx @@ -332,7 +332,7 @@ namespace build2 // path_target // const string& path_target:: - derive_extension (const char* de) + derive_extension (const char* de, bool search) { // See also search_existing_file() if updating anything here. // @@ -346,7 +346,7 @@ namespace build2 // the user can use to override extensions. // if (auto f = type ().extension) - ext = f (key (), base_scope ()); // Already from the pool. + ext = f (key (), base_scope (), search); // Already from the pool. if (ext == nullptr) { @@ -453,13 +453,13 @@ namespace build2 } const string* - target_extension_null (const target_key&, scope&) + target_extension_null (const target_key&, scope&, bool) { return nullptr; } const string* - target_extension_assert (const target_key&, scope&) + target_extension_assert (const target_key&, scope&, bool) { assert (false); // Attempt to obtain the default extension. throw failed (); @@ -585,6 +585,35 @@ namespace build2 false }; + static const string* + exe_extension (const target_key&, scope&, 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 use target machine extension. + // + return search + ? &extension_pool.find ( +#ifdef _WIN32 + "exe" +#else + "" +#endif + ) + : nullptr; + } + + const target_type exe::static_type + { + "exe", + &file::static_type, + &target_factory, + &exe_extension, + nullptr, + &search_file, + false + }; + static target* buildfile_factory (const target_type&, dir_path d, @@ -599,7 +628,7 @@ namespace build2 } static const string* - buildfile_target_extension (const target_key& tk, scope&) + buildfile_target_extension (const target_key& tk, scope&, bool) { // If the name is special 'buildfile', then there is no extension, // otherwise it is .build. diff --git a/build2/target.txx b/build2/target.txx index bdd1224..f342728 100644 --- a/build2/target.txx +++ b/build2/target.txx @@ -35,14 +35,14 @@ namespace build2 // template const string* - target_extension_fix (const target_key&, scope&) + target_extension_fix (const target_key&, scope&, bool) { return &extension_pool.find (ext); } template const string* - target_extension_var (const target_key& tk, scope& s) + target_extension_var (const target_key& tk, scope& s, bool) { // Include target type/pattern-specific variables. // diff --git a/build2/test/target.cxx b/build2/test/target.cxx index 1a215ca..727ae48 100644 --- a/build2/test/target.cxx +++ b/build2/test/target.cxx @@ -25,7 +25,7 @@ namespace build2 } static const string* - testscript_target_extension (const target_key& tk, scope&) + testscript_target_extension (const target_key& tk, scope&, bool) { // If the name is special 'testscript', then there is no extension, // otherwise it is .test. -- cgit v1.1