diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2017-06-16 16:22:48 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2017-06-16 16:22:48 +0200 |
commit | 5c8de4f515c99d894bec764a6793352c9cad0825 (patch) | |
tree | 6a590192c8010e19d9fa152058ba382ec160d603 | |
parent | f3e193b2651b2589daecaf181b96c5622acc51e9 (diff) |
Add support for explicitly specifying module name on mxx{} target
-rw-r--r-- | build2/algorithm.hxx | 10 | ||||
-rw-r--r-- | build2/algorithm.ixx | 32 | ||||
-rw-r--r-- | build2/cc/compile.cxx | 51 | ||||
-rw-r--r-- | build2/target.hxx | 14 | ||||
-rw-r--r-- | tests/cc/modules/testscript | 15 |
5 files changed, 95 insertions, 27 deletions
diff --git a/build2/algorithm.hxx b/build2/algorithm.hxx index 49ca7a7..fc5e02a 100644 --- a/build2/algorithm.hxx +++ b/build2/algorithm.hxx @@ -24,6 +24,11 @@ namespace build2 const target& search (const target&, const prerequisite&); + // As above but only search for an already existing target. + // + const target* + search_existing (const target&, const prerequisite&); + // As above but specify the prerequisite to search as a key. // const target& @@ -72,9 +77,8 @@ namespace build2 const target& search (const target&, name, const scope&); - // As above but only search for an already existing target. Unlike the above - // version, this one can be called during the execute phase. Return NULL for - // unknown target types. + // Unlike the above version, this one can be called during the execute + // phase. Return NULL for unknown target types. // const target* search_existing (const name&, diff --git a/build2/algorithm.ixx b/build2/algorithm.ixx index 27759c9..4885ecf 100644 --- a/build2/algorithm.ixx +++ b/build2/algorithm.ixx @@ -29,6 +29,38 @@ namespace build2 return *r; } + const target* + search_existing_target (const prerequisite_key&); // <build2/search.hxx> + + const target* + import_existing (const prerequisite_key&); // <build2/file.hxx> + + inline const target* + search_existing (const prerequisite& p) + { + assert (phase == run_phase::match); // Could be relaxed. + + const target* r (p.target.load (memory_order_consume)); + + if (r == nullptr) + { + const prerequisite_key& pk (p.key ()); + r = pk.proj ? import_existing (pk) : search_existing_target (pk); + + if (r != nullptr) + { + const target* e (nullptr); + if (!p.target.compare_exchange_strong ( + e, r, + memory_order_release, + memory_order_consume)) + assert (e == r); + } + } + + return r; + } + inline const target& search (const target& t, const target_type& tt, const prerequisite_key& k) { diff --git a/build2/cc/compile.cxx b/build2/cc/compile.cxx index 265b1a9..c23eff2 100644 --- a/build2/cc/compile.cxx +++ b/build2/cc/compile.cxx @@ -2780,37 +2780,48 @@ namespace build2 continue; // Find the mxx{} prerequisite and extract its "file name" for the - // fuzzy match. + // fuzzy match unless the user specified the module name explicitly. // - string f; for (prerequisite_member p: group_prerequisite_members (act, *pt)) { if (p.is_a (*x_mod)) { - //@@ MOD: TODO check if module name set? Won't we have to search - // it for that? Search to existing only? - - // Add the directory part if it is relative. The idea is to - // include it into the module match, say hello.core vs - // hello/mxx{core}. Why not for absolute? Good question. What - // if it contains special components, say, ../mxx{core}? + // Check for an explicit module name. Only look for an existing + // target (which means the name can only be specified on the + // target itself, no target type/pattern-spec). // - const dir_path& d (p.dir ()); + const target* t (p.search_existing ()); + const string* n (t != nullptr + ? cast_null<string> (t->vars[c_module_name]) + : nullptr); + if (n != nullptr) + done = check (pt, *n, false); + else + { + // Fuzzy match. + // + string f; - if (!d.empty () && d.relative ()) - f = d.representation (); // Includes trailing slash. + // Add the directory part if it is relative. The idea is to + // include it into the module match, say hello.core vs + // hello/mxx{core}. + // + // @@ MOD: Why not for absolute? Good question. What if it + // contains special components, say, ../mxx{core}? + // + const dir_path& d (p.dir ()); - f += p.name (); + if (!d.empty () && d.relative ()) + f = d.representation (); // Includes trailing slash. + + f += p.name (); + done = check (pt, f, true); + } break; } } - if (f.empty ()) // bmi{} without mxx{}? Good luck with that. - continue; - - // Check if it resolves any of our imports. - // - if ((done = check (pt, f, true))) + if (done) break; } @@ -2880,7 +2891,7 @@ namespace build2 info << "guessed: " << in << info << "actual: " << mn << info << "consider adjusting module interface file names or" << - info << "consider explicitly specifying module name with @@ MOD"; + info << "consider specifying module name with cc.module_name"; } } } diff --git a/build2/target.hxx b/build2/target.hxx index 418a8ea..906d92d 100644 --- a/build2/target.hxx +++ b/build2/target.hxx @@ -29,8 +29,10 @@ namespace build2 extern size_t current_on; // From <build/context>. - const target& - search (const target&, const prerequisite&); // From <build2/algorithm.hxx>. + // From <build2/algorithm.hxx>. + // + const target& search (const target&, const prerequisite&); + const target* search_existing (const prerequisite&); // Target state. // @@ -906,6 +908,14 @@ namespace build2 return target != nullptr ? target : prerequisite.target.load (mo); } + const target_type* + search_existing () const + { + return target != nullptr + ? target + : build2::search_existing (prerequisite); + } + // Return as a new prerequisite instance. // prerequisite_type diff --git a/tests/cc/modules/testscript b/tests/cc/modules/testscript index 50dc9b2..ce2f1e9 100644 --- a/tests/cc/modules/testscript +++ b/tests/cc/modules/testscript @@ -118,7 +118,7 @@ $* test clean <<EOI : name-match : -: Test fuzzy match between module name and file name +: Test fuzzy/explicit match between module name and file name. : { # "Bad" match which we should better. @@ -154,6 +154,17 @@ $* test clean <<EOI ln -s ../../core.mxx foo/core.mxx; ln -s ../core.mxx ../../core.cxx ../../driver.cxx ./; $* test clean <'exe{test}: cxx{driver core} mxx{core} foo/mxx{core}' + + : explicit + : + : Explicit module name. + : + ln -s ../../core.mxx baz.mxx; + ln -s ../core.mxx ../../core.cxx ../../driver.cxx ./; + $* test clean <<EOO + exe{test}: cxx{driver core} mxx{core baz} + mxx{baz}@./: cc.module_name = foo.core + EOO } : unresolved @@ -172,7 +183,7 @@ $* test &*.d <'exe{test}: cxx{driver} mxx{core}' 2>>EOE != 0 info: guessed: bar.core info: actual: foo.core info: consider adjusting module interface file names or - info: consider explicitly specifying module name with @@ MOD + info: consider specifying module name with cc.module_name EOE : library |