aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-06-16 16:22:48 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-06-16 16:22:48 +0200
commit5c8de4f515c99d894bec764a6793352c9cad0825 (patch)
tree6a590192c8010e19d9fa152058ba382ec160d603
parentf3e193b2651b2589daecaf181b96c5622acc51e9 (diff)
Add support for explicitly specifying module name on mxx{} target
-rw-r--r--build2/algorithm.hxx10
-rw-r--r--build2/algorithm.ixx32
-rw-r--r--build2/cc/compile.cxx51
-rw-r--r--build2/target.hxx14
-rw-r--r--tests/cc/modules/testscript15
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