From 3ab61fbc2ce25afa617ed6bb50c2f8d701beeaba Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 16 Dec 2016 17:23:54 +0200 Subject: Add support for passing target name to testscript via test variable Such a targets is automatically resolved and converted to path. --- build2/test/script/script.cxx | 87 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 70 insertions(+), 17 deletions(-) (limited to 'build2/test/script/script.cxx') diff --git a/build2/test/script/script.cxx b/build2/test/script/script.cxx index 7abc3b6..17eacaa 100644 --- a/build2/test/script/script.cxx +++ b/build2/test/script/script.cxx @@ -8,6 +8,7 @@ #include // find() #include +#include using namespace std; @@ -390,8 +391,9 @@ namespace build2 // script_base:: script_base () - : // Enter the test* variables with the same variable types as in - // buildfiles. + : // Enter the test.* variables with the same variable types as in + // buildfiles except for test: while in buildfiles it can be a + // target name, in testscripts it should be resolved to a path. // test_var (var_pool.insert ("test")), options_var (var_pool.insert ("test.options")), @@ -440,24 +442,75 @@ namespace build2 // const_cast (wd_path) = dir_path (rwd) /= id_path.string (); - // Unless we have the test variable set on the test or script target, - // set it at the script level to the test target's path. + // Set the test variable at the script level. We do it even if it's + // set in the buildfile since they use different types. // - // Note that test variable's visibility is target. - // - if (!find (test_var)) { value& v (assign (test_var)); - // If this is a path-based target, then we use the path. If this is - // an alias target (e.g., dir{}), then we use the directory path. - // Otherwise, we leave it NULL expecting the testscript to set it to - // something appropriate, if used. + // Note that the test variable's visibility is target. // - if (auto* p = tt.is_a ()) - v = p->path (); - else if (tt.is_a ()) - v = path (tt.dir.string ()); // Strip trailing slash. + lookup l (find_in_buildfile ("test", false)); + + target* t (nullptr); + if (l.defined ()) + { + const name* n (cast_null (l)); + + if (n == nullptr) + v = nullptr; + else if (n->empty ()) + v = path (); + else if (n->simple ()) + { + // Ignore the special 'true' value. + // + if (n->value != "true") + v = path (n->value); + else + t = &tt; + } + else if (n->directory ()) + v = path (n->dir); + else + { + // Must be a target name. + // + // @@ OUT: what if this is a @-qualified pair or names? + // + t = &search (*n, tt.base_scope ()); + } + } + else + // By default we set it to the test target's path. + // + t = &tt; + + // If this is a path-based target, then we use the path. If this + // is an alias target (e.g., dir{}), then we use the directory + // path. Otherwise, we leave it NULL expecting the testscript to + // set it to something appropriate, if used. + // + if (t != nullptr) + { + if (auto* p = t->is_a ()) + { + // Do some sanity checks: the target better be up-to-date with + // an assigned path. + // + if (p->path ().empty ()) + fail << "target " << *p << " specified in the test variable " + << "is out of date" << + info << "consider specifying it as a prerequisite of " << tt; + + v = p->path (); + } + else if (t->is_a ()) + v = path (t->dir); + else if (t != &tt) + fail << "target " << *t << " specified in the test variable " + << "is not path-based"; + } } // Set the special $*, $N variables. @@ -484,7 +537,7 @@ namespace build2 lookup scope:: - find_in_buildfile (const string& n) const + find_in_buildfile (const string& n, bool target_only) const { // Switch to the corresponding buildfile variable. Note that we don't // want to insert a new variable into the pool (we might be running @@ -506,7 +559,7 @@ namespace build2 // value. In this case, presumably the override also affects the // script target and we will pick it up there. A bit fuzzy. // - auto p (s.test_target.find_original (var, true)); + auto p (s.test_target.find_original (var, target_only)); if (p.first) { -- cgit v1.1