aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build2/algorithm4
-rw-r--r--build2/algorithm.cxx8
-rw-r--r--build2/algorithm.ixx4
-rw-r--r--build2/b.cxx4
-rw-r--r--build2/bin/rule.cxx4
-rw-r--r--build2/bin/target.cxx28
-rw-r--r--build2/cc/common.cxx26
-rw-r--r--build2/cc/compile.cxx9
-rw-r--r--build2/cc/link.cxx4
-rw-r--r--build2/cc/msvc.cxx13
-rw-r--r--build2/cc/pkgconfig.cxx5
-rw-r--r--build2/cli/rule.cxx8
-rw-r--r--build2/cli/target4
-rw-r--r--build2/cli/target.cxx4
-rw-r--r--build2/config/operation.cxx2
-rw-r--r--build2/context2
-rw-r--r--build2/context.cxx4
-rw-r--r--build2/dist/operation.cxx2
-rw-r--r--build2/file.cxx9
-rw-r--r--build2/parser.cxx14
-rw-r--r--build2/prerequisite22
-rw-r--r--build2/prerequisite.cxx17
-rw-r--r--build2/scope2
-rw-r--r--build2/scope.cxx10
-rw-r--r--build2/search.cxx9
-rw-r--r--build2/target38
-rw-r--r--build2/target-key9
-rw-r--r--build2/target-type4
-rw-r--r--build2/target.cxx66
-rw-r--r--build2/target.txx12
-rw-r--r--build2/test/target.cxx12
-rw-r--r--build2/utility11
-rw-r--r--unit-tests/test/script/parser/driver.cxx15
33 files changed, 187 insertions, 198 deletions
diff --git a/build2/algorithm b/build2/algorithm
index 9a91781..ad52fe1 100644
--- a/build2/algorithm
+++ b/build2/algorithm
@@ -44,7 +44,7 @@ namespace build2
const dir_path& dir,
const dir_path& out,
const string& name,
- const string* ext,
+ const optional<string>& ext,
scope*,
const optional<string>& proj = nullopt);
@@ -55,7 +55,7 @@ namespace build2
search (const dir_path& dir,
const dir_path& out,
const string& name,
- const string* ext,
+ const optional<string>& ext,
scope*);
// Search for a target identified by the name. The semantics is "as if" we
diff --git a/build2/algorithm.cxx b/build2/algorithm.cxx
index 78af195..22633bb 100644
--- a/build2/algorithm.cxx
+++ b/build2/algorithm.cxx
@@ -37,8 +37,8 @@ namespace build2
target&
search (name n, scope& s)
{
- const string* e;
- const target_type* tt (s.find_target_type (n, e));
+ optional<string> ext;
+ const target_type* tt (s.find_target_type (n, ext));
if (tt == nullptr)
fail << "unknown target type " << n.type << " in name " << n;
@@ -49,7 +49,7 @@ namespace build2
// @@ OUT: for now we assume the prerequisite's out is undetermined.
// Would need to pass a pair of names.
//
- return search (*tt, n.dir, dir_path (), n.value, e, &s, n.proj);
+ return search (*tt, n.dir, dir_path (), n.value, ext, &s, n.proj);
}
pair<const rule*, match_result>
@@ -333,7 +333,7 @@ namespace build2
// Target is in the out tree, so out directory is empty.
//
- fsdir* r (&search<fsdir> (d, dir_path (), string (), nullptr, nullptr));
+ fsdir* r (&search<fsdir> (d, dir_path (), string (), nullopt, nullptr));
match (a, *r);
t.prerequisite_targets.emplace_back (r);
return r;
diff --git a/build2/algorithm.ixx b/build2/algorithm.ixx
index 84b0ee7..90a0789 100644
--- a/build2/algorithm.ixx
+++ b/build2/algorithm.ixx
@@ -30,7 +30,7 @@ namespace build2
const dir_path& dir,
const dir_path& out,
const string& name,
- const string* ext,
+ const optional<string>& ext,
scope* scope,
const optional<string>& proj)
{
@@ -43,7 +43,7 @@ namespace build2
search (const dir_path& dir,
const dir_path& out,
const string& name,
- const string* ext,
+ const optional<string>& ext,
scope* scope)
{
return static_cast<T&> (
diff --git a/build2/b.cxx b/build2/b.cxx
index bd77a02..ca8c15b 100644
--- a/build2/b.cxx
+++ b/build2/b.cxx
@@ -967,7 +967,9 @@ main (int argc, char* argv[])
//
scope& bs (scopes.find (ts.out_base));
- const string* e;
+ // Find the target type and extract the extension.
+ //
+ optional<string> e;
const target_type* ti (bs.find_target_type (tn, e));
if (ti == nullptr)
diff --git a/build2/bin/rule.cxx b/build2/bin/rule.cxx
index 70ad7df..ede2c85 100644
--- a/build2/bin/rule.cxx
+++ b/build2/bin/rule.cxx
@@ -75,7 +75,7 @@ namespace build2
if (a)
{
if (t.a == nullptr)
- t.a = &search<liba> (t.dir, t.out, t.name, nullptr, nullptr);
+ t.a = &search<liba> (t.dir, t.out, t.name, nullopt, nullptr);
match_only (act, *t.a);
}
@@ -83,7 +83,7 @@ namespace build2
if (s)
{
if (t.s == nullptr)
- t.s = &search<libs> (t.dir, t.out, t.name, nullptr, nullptr);
+ t.s = &search<libs> (t.dir, t.out, t.name, nullopt, nullptr);
match_only (act, *t.s);
}
diff --git a/build2/bin/target.cxx b/build2/bin/target.cxx
index 9086369..e9ef81e 100644
--- a/build2/bin/target.cxx
+++ b/build2/bin/target.cxx
@@ -17,10 +17,10 @@ namespace build2
dir_path dir,
dir_path out,
string n,
- const string* ext)
+ optional<string> ext)
{
obj* o (targets.find<obj> (dir, out, n));
- obje* e (new obje (move (dir), move (out), move (n), ext));
+ obje* e (new obje (move (dir), move (out), move (n), move (ext)));
if ((e->group = o))
o->e = e;
@@ -44,10 +44,10 @@ namespace build2
dir_path dir,
dir_path out,
string n,
- const string* ext)
+ optional<string> ext)
{
obj* o (targets.find<obj> (dir, out, n));
- obja* a (new obja (move (dir), move (out), move (n), ext));
+ obja* a (new obja (move (dir), move (out), move (n), move (ext)));
if ((a->group = o))
o->a = a;
@@ -71,10 +71,10 @@ namespace build2
dir_path dir,
dir_path out,
string n,
- const string* ext)
+ optional<string> ext)
{
obj* o (targets.find<obj> (dir, out, n));
- objs* s (new objs (move (dir), move (out), move (n), ext));
+ objs* s (new objs (move (dir), move (out), move (n), move (ext)));
if ((s->group = o))
o->s = s;
@@ -98,13 +98,13 @@ namespace build2
dir_path dir,
dir_path out,
string n,
- const string* ext)
+ optional<string> ext)
{
obje* e (targets.find<obje> (dir, out, n));
obja* a (targets.find<obja> (dir, out, n));
objs* s (targets.find<objs> (dir, out, n));
- obj* o (new obj (move (dir), move (out), move (n), ext));
+ obj* o (new obj (move (dir), move (out), move (n), move (ext)));
if ((o->e = e))
e->group = o;
@@ -134,12 +134,12 @@ namespace build2
dir_path d,
dir_path o,
string n,
- const string* ext)
+ optional<string> ext)
{
// Only link-up to the group if the types match exactly.
//
lib* l (t == liba::static_type ? targets.find<lib> (d, o, n) : nullptr);
- liba* a (new liba (move (d), move (o), move (n), ext));
+ liba* a (new liba (move (d), move (o), move (n), move (ext)));
if ((a->group = l))
l->a = a;
@@ -175,12 +175,12 @@ namespace build2
dir_path d,
dir_path o,
string n,
- const string* ext)
+ optional<string> ext)
{
// Only link-up to the group if the types match exactly.
//
lib* l (t == libs::static_type ? targets.find<lib> (d, o, n) : nullptr);
- libs* s (new libs (move (d), move (o), move (n), ext));
+ libs* s (new libs (move (d), move (o), move (n), move (ext)));
if ((s->group = l))
l->s = s;
@@ -215,12 +215,12 @@ namespace build2
dir_path d,
dir_path o,
string n,
- const string* ext)
+ optional<string> ext)
{
liba* a (targets.find<liba> (d, o, n));
libs* s (targets.find<libs> (d, o, n));
- lib* l (new lib (move (d), move (o), move (n), ext));
+ lib* l (new lib (move (d), move (o), move (n), move (ext)));
if ((l->a = a))
a->group = l;
diff --git a/build2/cc/common.cxx b/build2/cc/common.cxx
index 86d998e..6429a38 100644
--- a/build2/cc/common.cxx
+++ b/build2/cc/common.cxx
@@ -408,7 +408,7 @@ namespace build2
{
// This is import.
//
- const string* ext;
+ optional<string> ext;
const target_type* tt (s.find_target_type (n, ext)); // Changes name.
if (tt == nullptr)
@@ -455,7 +455,7 @@ namespace build2
// Windows.
//
bool l (p.is_a<lib> ());
- const string* ext (l ? nullptr : p.tk.ext); // Only for liba/libs.
+ const optional<string>& ext (l ? nullopt : p.tk.ext); // Only liba/libs.
// Then figure out what we need to search for.
//
@@ -464,7 +464,7 @@ namespace build2
// liba
//
path an;
- const string* ae (nullptr);
+ optional<string> ae;
if (l || p.is_a<liba> ())
{
@@ -494,10 +494,7 @@ namespace build2
e = "a";
}
- ae = ext == nullptr
- ? &extension_pool.find (e)
- : ext;
-
+ ae = ext ? ext : string (e);
if (!ae->empty ())
{
an += '.';
@@ -508,7 +505,7 @@ namespace build2
// libs
//
path sn;
- const string* se (nullptr);
+ optional<string> se;
if (l || p.is_a<libs> ())
{
@@ -528,10 +525,7 @@ namespace build2
else e = "so";
}
- se = ext == nullptr
- ? &extension_pool.find (e)
- : ext;
-
+ se = ext ? ext : string (e);
if (!se->empty ())
{
sn += '.';
@@ -574,7 +568,7 @@ namespace build2
//
if (tclass == "windows")
{
- s = &targets.insert<libs> (d, dir_path (), name, nullptr, trace);
+ s = &targets.insert<libs> (d, dir_path (), name, nullopt, trace);
if (s->member == nullptr)
{
@@ -606,7 +600,7 @@ namespace build2
s->mtime (mt);
}
}
- else if (ext == nullptr && tsys == "mingw32")
+ else if (!ext && tsys == "mingw32")
{
// Above we searched for the import library (.dll.a) but if it's
// not found, then we also search for the .dll (unless the
@@ -614,7 +608,7 @@ namespace build2
// directly. Note also that the resulting libs{} would end up
// being the .dll.
//
- se = &extension_pool.find ("dll");
+ se = string ("dll");
f = f.base (); // Remove .a from .dll.a.
mt = file_mtime (f);
@@ -762,7 +756,7 @@ namespace build2
//
lib& lt (
targets.insert<lib> (
- *pd, dir_path (), name, l ? p.tk.ext : nullptr, trace));
+ *pd, dir_path (), name, l ? p.tk.ext : nullopt, trace));
// It should automatically link-up to the members we have found.
//
diff --git a/build2/cc/compile.cxx b/build2/cc/compile.cxx
index 23499ad..f837765 100644
--- a/build2/cc/compile.cxx
+++ b/build2/cc/compile.cxx
@@ -415,12 +415,11 @@ namespace build2
// only use the target type and name from the target key so we can
// pass bogus values for the rest.
//
- const string* dummy (nullptr);
- target_key tk {&tt, nullptr, nullptr, &n, dummy};
+ target_key tk {&tt, nullptr, nullptr, &n, target_key::nullext};
// This is like prerequisite search.
//
- if (const string* de = tt.extension (tk, s, true))
+ if (optional<string> de = tt.extension (tk, s, true))
if (*de == e)
return true;
@@ -913,7 +912,7 @@ namespace build2
//
dir_path d (f.directory ());
string n (f.leaf ().base ().string ());
- const string* e (&extension_pool.find (f.extension ()));
+ string e (f.extension ());
// Determine the target type.
//
@@ -935,7 +934,7 @@ namespace build2
scope& bs (scopes.find (d));
if (scope* rs = bs.root_scope ())
{
- tt = map_extension (bs, n, *e);
+ tt = map_extension (bs, n, e);
if (bs.out_path () != bs.src_path () && d.sub (bs.src_path ()))
out = out_src (d, *rs);
diff --git a/build2/cc/link.cxx b/build2/cc/link.cxx
index 8010598..e1dac16 100644
--- a/build2/cc/link.cxx
+++ b/build2/cc/link.cxx
@@ -337,7 +337,7 @@ namespace build2
if (t.member != nullptr) // Might already be there.
assert (t.member->type () == tt);
else
- t.member = &search (tt, t.dir, t.out, t.name, nullptr, nullptr);
+ t.member = &search (tt, t.dir, t.out, t.name, nullopt, nullptr);
file& r (static_cast<file&> (*t.member));
r.recipe (a, group_recipe);
@@ -519,7 +519,7 @@ namespace build2
// obj*{} is always in the out tree.
//
target& ot (
- search (tt, d, dir_path (), *cp.tk.name, nullptr, cp.scope));
+ search (tt, d, dir_path (), *cp.tk.name, nullopt, cp.scope));
// If we are cleaning, check that this target is in the same or
// a subdirectory of our project root.
diff --git a/build2/cc/msvc.cxx b/build2/cc/msvc.cxx
index 5ce2f2a..4ac82a0 100644
--- a/build2/cc/msvc.cxx
+++ b/build2/cc/msvc.cxx
@@ -231,7 +231,7 @@ namespace build2
//
tracer trace (mod, "msvc_search_library");
- const string* ext (p.tk.ext);
+ const optional<string>& ext (p.tk.ext);
const string& name (*p.tk.name);
// Assemble the file path.
@@ -249,10 +249,9 @@ namespace build2
if (*sfx != '\0')
f += sfx;
- const string& e (
- ext == nullptr || p.is_a<lib> () // Only for liba/libs.
- ? extension_pool.find ("lib")
- : *ext);
+ const string& e (!ext || p.is_a<lib> () // Only for liba/libs.
+ ? string ("lib")
+ : *ext);
if (!e.empty ())
{
@@ -268,7 +267,7 @@ namespace build2
{
// Enter the target.
//
- T& t (targets.insert<T> (d, dir_path (), name, &e, trace));
+ T& t (targets.insert<T> (d, dir_path (), name, e, trace));
if (t.path ().empty ())
t.path (move (f));
@@ -323,7 +322,7 @@ namespace build2
msvc_search_library<libi> (x, ld, d, p, otype::s, pf, sf))
{
r = &targets.insert<libs> (
- d, dir_path (), *p.tk.name, nullptr, trace);
+ d, dir_path (), *p.tk.name, nullopt, trace);
if (r->member == nullptr)
{
diff --git a/build2/cc/pkgconfig.cxx b/build2/cc/pkgconfig.cxx
index f8d35af..6c8159f 100644
--- a/build2/cc/pkgconfig.cxx
+++ b/build2/cc/pkgconfig.cxx
@@ -417,10 +417,11 @@ namespace build2
//
dir_path out;
string name (l, 2); // Sans -l.
- const string* ext (nullptr);
prerequisite_key pk {
- nullopt, {&lib::static_type, &out, &out, &name, ext}, &s};
+ nullopt,
+ {&lib::static_type, &out, &out, &name, target_key::nullext},
+ &s};
if (lib* lt = static_cast<lib*> (search_library (sysd, usrd, pk)))
{
diff --git a/build2/cli/rule.cxx b/build2/cli/rule.cxx
index b97bea2..d457e6d 100644
--- a/build2/cli/rule.cxx
+++ b/build2/cli/rule.cxx
@@ -88,15 +88,15 @@ namespace build2
//
if (t.h == nullptr)
{
- t.h = &search<cxx::hxx> (t.dir, t.out, t.name, nullptr, nullptr);
+ t.h = &search<cxx::hxx> (t.dir, t.out, t.name, nullopt, nullptr);
t.h->group = &t;
- t.c = &search<cxx::cxx> (t.dir, t.out, t.name, nullptr, nullptr);
+ t.c = &search<cxx::cxx> (t.dir, t.out, t.name, nullopt, nullptr);
t.c->group = &t;
if (!find_option ("--suppress-inline", t, "cli.options"))
{
- t.i = &search<cxx::ixx> (t.dir, t.out, t.name, nullptr, nullptr);
+ t.i = &search<cxx::ixx> (t.dir, t.out, t.name, nullopt, nullptr);
t.i->group = &t;
}
}
@@ -211,7 +211,7 @@ namespace build2
const char* option,
const char* default_extension)
{
- assert (t.ext != nullptr); // Should have been figured out in apply().
+ assert (t.ext); // Should have been figured out in apply().
if (*t.ext != default_extension)
{
diff --git a/build2/cli/target b/build2/cli/target
index 0160ef3..0cc448d 100644
--- a/build2/cli/target
+++ b/build2/cli/target
@@ -49,8 +49,8 @@ namespace build2
//using mtime_target::mtime_target; // @@ GCC 4.8
- cli_cxx (dir_path d, dir_path o, string n, const string* e)
- : mtime_target (move (d), move (o), move (n), e)
+ cli_cxx (dir_path d, dir_path o, string n, optional<string> e)
+ : mtime_target (move (d), move (o), move (n), move (e))
{
m[0] = m[1] = m[2] = nullptr;
}
diff --git a/build2/cli/target.cxx b/build2/cli/target.cxx
index 5e12a04..3f09d30 100644
--- a/build2/cli/target.cxx
+++ b/build2/cli/target.cxx
@@ -53,7 +53,7 @@ namespace build2
dir_path d,
dir_path o,
string n,
- const string* e)
+ optional<string> e)
{
tracer trace ("cli::cli_cxx_factory");
@@ -66,7 +66,7 @@ namespace build2
targets.insert<cxx::cxx> (d, o, n, trace);
targets.insert<cxx::ixx> (d, o, n, trace);
- return new cli_cxx (move (d), move (o), move (n), e);
+ return new cli_cxx (move (d), move (o), move (n), move (e));
}
const target_type cli_cxx::static_type
diff --git a/build2/config/operation.cxx b/build2/config/operation.cxx
index 3370c2c..68b61c3 100644
--- a/build2/config/operation.cxx
+++ b/build2/config/operation.cxx
@@ -570,7 +570,7 @@ namespace build2
root.out_path (),
dir_path (), // Out tree.
"",
- nullptr,
+ nullopt,
trace).first);
if (!quiet)
diff --git a/build2/context b/build2/context
index cb83105..1dd9daf 100644
--- a/build2/context
+++ b/build2/context
@@ -16,8 +16,6 @@ namespace build2
{
class file;
- extern string_pool extension_pool;
-
// Current action (meta/operation).
//
// The names unlike info are available during boot but may not yet be
diff --git a/build2/context.cxx b/build2/context.cxx
index a21de2a..ba6629c 100644
--- a/build2/context.cxx
+++ b/build2/context.cxx
@@ -23,8 +23,6 @@ using namespace butl;
namespace build2
{
- string_pool extension_pool;
-
const string* current_mname;
const string* current_oname;
@@ -56,8 +54,6 @@ namespace build2
scopes.clear ();
var_pool.clear ();
- extension_pool.clear ();
-
// Reset meta/operation tables. Note that the order should match the id
// constants in <build2/operation>.
//
diff --git a/build2/dist/operation.cxx b/build2/dist/operation.cxx
index 47e188c..9535566 100644
--- a/build2/dist/operation.cxx
+++ b/build2/dist/operation.cxx
@@ -160,7 +160,7 @@ namespace build2
move (d),
move (out),
p.leaf ().base ().string (),
- &extension_pool.find (p.extension ()), // Specified.
+ p.extension (), // Specified.
trace);
}
};
diff --git a/build2/file.cxx b/build2/file.cxx
index 9e957a9..2889cf7 100644
--- a/build2/file.cxx
+++ b/build2/file.cxx
@@ -1112,8 +1112,11 @@ namespace build2
{
path n (*tk.dir);
n /= *tk.name;
- if (tk.ext != nullptr)
+ if (tk.ext)
+ {
+ n += '.';
n += *tk.ext;
+ }
process_path pp (process::try_path_search (n, true));
@@ -1126,9 +1129,9 @@ namespace build2
targets.insert<exe> (
tt,
p.directory (),
- dir_path (), // No out (out of project).
+ dir_path (), // No out (out of project).
p.leaf ().base ().string (),
- &extension_pool.find (p.extension ()), // Specified.
+ p.extension (), // Always specified.
trace));
if (t.path ().empty ())
diff --git a/build2/parser.cxx b/build2/parser.cxx
index 6025082..9ce916e 100644
--- a/build2/parser.cxx
+++ b/build2/parser.cxx
@@ -91,7 +91,7 @@ namespace build2
tracer& tr)
: p_ (&p), t_ (p.target_)
{
- const string* e;
+ optional<string> e;
const target_type* ti (p.scope_->find_target_type (n, e));
if (ti == nullptr)
@@ -131,7 +131,7 @@ namespace build2
// Find or insert.
//
p.target_ = &targets.insert (
- *ti, move (d), move (out), move (n.value), e, tr).first;
+ *ti, move (d), move (out), move (n.value), move (e), tr).first;
}
~enter_target ()
@@ -642,7 +642,7 @@ namespace build2
for (auto& pn: pns)
{
- const string* e;
+ optional<string> e;
const target_type* ti (scope_->find_target_type (pn, e));
if (ti == nullptr)
@@ -672,7 +672,7 @@ namespace build2
move (pn.dir),
dir_path (),
move (pn.value),
- e,
+ move (e),
*scope_,
trace).first);
@@ -3560,7 +3560,7 @@ namespace build2
scope_->out_path (),
dir_path (), // Out tree target.
"",
- nullptr,
+ nullopt,
trace) != targets.end ())
return;
@@ -3573,7 +3573,7 @@ namespace build2
scope_->out_path (),
dir_path (),
"",
- nullptr,
+ nullopt,
trace).first);
prerequisite& p (
@@ -3608,7 +3608,7 @@ namespace build2
move (d),
move (out),
p.leaf ().base ().string (),
- &extension_pool.find (p.extension ()), // Always specified.
+ p.extension (), // Always specified.
trace);
}
diff --git a/build2/prerequisite b/build2/prerequisite
index b259557..5dfd1aa 100644
--- a/build2/prerequisite
+++ b/build2/prerequisite
@@ -31,11 +31,11 @@ namespace build2
target_key tk; // .dir and .out can be relative.
mutable scope_type* scope; // Can be NULL if tk.dir is absolute.
+ static const optional<string> nullproj;
+
template <typename T>
bool is_a () const {return tk.is_a<T> ();}
bool is_a (const target_type& tt) const {return tk.is_a (tt);}
-
- static const optional<string> nullproj;
};
inline bool
@@ -90,14 +90,14 @@ namespace build2
//
const optional<string> proj;
const target_type_type& type;
- const dir_path dir; // Normalized absolute or relative (to scope).
- const dir_path out; // Empty, normalized absolute, or relative.
+ const dir_path dir; // Normalized absolute or relative (to scope).
+ const dir_path out; // Empty, normalized absolute, or relative.
const string name;
- const string* ext; // NULL if unspecified.
+ const optional<string> ext; // Absent if unspecified.
scope_type& scope;
- target_type* target; // NULL if not yet resolved. Note that this should
- // always be the "primary target", not a member of
- // a target group.
+ target_type* target; // NULL if not yet resolved. Note that this
+ // should always be the "primary target", not
+ // a member of a target group.
public:
prerequisite (optional<string> p,
@@ -105,14 +105,14 @@ namespace build2
dir_path d,
dir_path o,
string n,
- const string* e,
+ optional<string> e,
scope_type& s)
: proj (move (p)),
type (t),
dir (move (d)),
out (move (o)),
name (move (n)),
- ext (e),
+ ext (move (e)),
scope (s),
target (nullptr) {}
@@ -188,7 +188,7 @@ namespace build2
dir_path dir,
dir_path out,
string name,
- const string* ext,
+ optional<string> ext,
scope&,
tracer&);
diff --git a/build2/prerequisite.cxx b/build2/prerequisite.cxx
index 82d6ea2..bcd4123 100644
--- a/build2/prerequisite.cxx
+++ b/build2/prerequisite.cxx
@@ -56,7 +56,7 @@ namespace build2
dir_path dir,
dir_path out,
string name,
- const string* ext,
+ optional<string> ext,
scope& s,
tracer& trace) -> pair<prerequisite&, bool>
{
@@ -66,8 +66,13 @@ namespace build2
// Find or insert.
//
- auto r (
- emplace (move (proj), tt, move (dir), move (out), move (name), ext, s));
+ auto r (emplace (move (proj),
+ tt,
+ move (dir),
+ move (out),
+ move (name),
+ ext, // Note: cannot move.
+ s));
prerequisite& p (const_cast<prerequisite&> (*r.first));
// Update extension if the existing prerequisite has it unspecified.
@@ -78,7 +83,7 @@ namespace build2
diag_record r (trace);
r << "assuming prerequisite " << p << " is the same as the "
<< "one with ";
- if (ext == nullptr)
+ if (!ext)
r << "unspecified extension";
else if (ext->empty ())
r << "no extension";
@@ -86,8 +91,8 @@ namespace build2
r << "extension " << *ext;
});
- if (ext != nullptr)
- p.ext = ext;
+ if (ext)
+ const_cast<optional<string>&> (p.ext) = move (ext);
}
return pair<prerequisite&, bool> (p, r.second);
diff --git a/build2/scope b/build2/scope
index 6b5af22..f22383a 100644
--- a/build2/scope
+++ b/build2/scope
@@ -218,7 +218,7 @@ namespace build2
// necessarily normalized). Return NULL if not found.
//
const target_type*
- find_target_type (name&, const string*& ext) const;
+ find_target_type (name&, optional<string>& ext) const;
// Dynamically derive a new target type from an existing one. Return the
// reference to the target type and an indicator of whether it was
diff --git a/build2/scope.cxx b/build2/scope.cxx
index 9950042..8d0841b 100644
--- a/build2/scope.cxx
+++ b/build2/scope.cxx
@@ -547,9 +547,9 @@ namespace build2
static const string file_tt ("file");
const target_type* scope::
- find_target_type (name& n, const string*& ext) const
+ find_target_type (name& n, optional<string>& ext) const
{
- ext = nullptr;
+ ext = nullopt;
string& v (n.value);
@@ -613,7 +613,7 @@ namespace build2
if (j != string::npos)
{
- ext = &extension_pool.find (v.c_str () + j + 1);
+ ext = string (v.c_str () + j + 1);
v.resize (j);
}
}
@@ -626,7 +626,7 @@ namespace build2
dir_path d,
dir_path o,
string n,
- const string* e)
+ optional<string> e)
{
// Pass our type to the base factory so that it can detect that it is
// being called to construct a derived target. This can be used, for
@@ -639,7 +639,7 @@ namespace build2
const target_type* bt (t.base);
for (; bt->factory == &derived_tt_factory; bt = bt->base) ;
- target* r (bt->factory (t, move (d), move (o), move (n), e));
+ target* r (bt->factory (t, move (d), move (o), move (n), move (e)));
r->derived_type = &t;
return r;
}
diff --git a/build2/search.cxx b/build2/search.cxx
index 75d94a0..50318a7 100644
--- a/build2/search.cxx
+++ b/build2/search.cxx
@@ -8,6 +8,7 @@
#include <build2/scope>
#include <build2/target>
+#include <build2/context>
#include <build2/prerequisite>
#include <build2/diagnostics>
@@ -76,14 +77,14 @@ namespace build2
// Figure out the extension. Pretty similar logic to file::derive_path().
//
- const string* ext (ctk.ext);
+ optional<string> ext (ctk.ext);
- if (ext == nullptr)
+ if (!ext)
{
if (auto f = ctk.type->extension)
- ext = f (ctk, *cpk.scope, true); // Already from the pool.
+ ext = f (ctk, *cpk.scope, true);
- if (ext == nullptr)
+ if (!ext)
{
// What should we do here, fail or say we didn't find anything?
// Current think is that if the target type couldn't find the default
diff --git a/build2/target b/build2/target
index 48c5ebc..421c20a 100644
--- a/build2/target
+++ b/build2/target
@@ -144,10 +144,10 @@ namespace build2
// when src == out). We also treat out of project targets as being in the
// out tree.
//
- const dir_path dir; // Absolute and normalized.
- const dir_path out; // Empty or absolute and normalized.
- const string name;
- const string* ext; // Extension. NULL - unspecified, empty - no extension.
+ const dir_path dir; // Absolute and normalized.
+ const dir_path out; // Empty or absolute and normalized.
+ const string name;
+ optional<string> ext; // Absent - unspecified, empty - no extension.
const dir_path&
out_dir () const {return out.empty () ? dir : out;}
@@ -259,8 +259,8 @@ namespace build2
target (const target&) = delete;
target& operator= (const target&) = delete;
- target (dir_path d, dir_path o, string n, const string* e)
- : dir (move (d)), out (move (o)), name (move (n)), ext (e) {}
+ target (dir_path d, dir_path o, string n, optional<string> e)
+ : dir (move (d)), out (move (o)), name (move (n)), ext (move (e)) {}
// Reset the target before matching it to a rule. The default
// implementation clears the auxilary data and prerequisite_targets.
@@ -986,7 +986,7 @@ namespace build2
const dir_path& dir,
const dir_path& out,
const string& name,
- const string* ext,
+ const optional<string>& ext,
tracer& trace) const
{
return find (target_key {&type, &dir, &out, &name, ext}, trace);
@@ -1000,7 +1000,7 @@ namespace build2
find (const dir_path& dir, const dir_path& out, const string& name) const
{
auto i (map_.find (
- target_key {&T::static_type, &dir, &out, &name, nullptr}));
+ target_key {&T::static_type, &dir, &out, &name, nullopt}));
return i != map_.end () ? static_cast<T*> (i->second.get ()) : nullptr;
}
@@ -1012,7 +1012,7 @@ namespace build2
dir_path dir,
dir_path out,
string name,
- const string* ext,
+ optional<string> ext,
tracer&);
template <typename T>
@@ -1021,11 +1021,11 @@ namespace build2
dir_path dir,
dir_path out,
string name,
- const string* ext,
+ optional<string> ext,
tracer& t)
{
return static_cast<T&> (
- insert (tt, move (dir), move (out), move (name), ext, t).first);
+ insert (tt, move (dir), move (out), move (name), move (ext), t).first);
}
template <typename T>
@@ -1033,7 +1033,7 @@ namespace build2
insert (const dir_path& dir,
const dir_path& out,
const string& name,
- const string* ext,
+ const optional<string>& ext,
tracer& t)
{
return static_cast<T&> (
@@ -1048,7 +1048,7 @@ namespace build2
tracer& t)
{
return static_cast<T&> (
- insert (T::static_type, dir, out, name, nullptr, t).first);
+ insert (T::static_type, dir, out, name, nullopt, t).first);
}
void
@@ -1344,32 +1344,32 @@ namespace build2
dir_path d,
dir_path o,
string n,
- const string* e)
+ optional<string> e)
{
- return new T (move (d), move (o), move (n), e);
+ return new T (move (d), move (o), move (n), move (e));
}
// Return fixed target extension.
//
template <const char* ext>
- const string*
+ optional<string>
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 char* var, const char* def>
- const string*
+ optional<string>
target_extension_var (const target_key&, scope&, bool);
// Always return NULL extension.
//
- const string*
+ optional<string>
target_extension_null (const target_key&, scope&, bool);
// Assert if called.
//
- const string*
+ optional<string>
target_extension_assert (const target_key&, scope&, bool);
// Target print functions.
diff --git a/build2/target-key b/build2/target-key
index f0ea80b..7905f8a 100644
--- a/build2/target-key
+++ b/build2/target-key
@@ -26,7 +26,9 @@ namespace build2
const dir_path* const dir; // Can be relative if part of prerequisite_key.
const dir_path* const out; // Can be relative if part of prerequisite_key.
const string* const name;
- const string* const& ext;
+ const optional<string>& ext;
+
+ static const optional<string> nullext;
template <typename T>
bool is_a () const {return type->is_a<T> ();}
@@ -47,15 +49,14 @@ namespace build2
inline bool
operator== (const target_key& x, const target_key& y)
{
- // Unspecified and specified extension are assumed equal. The extension
- // strings are from the pool, so we can just compare pointers.
+ // Unspecified and specified extension are assumed equal.
//
return
x.type == y.type &&
*x.dir == *y.dir &&
*x.out == *y.out &&
*x.name == *y.name &&
- (x.ext == nullptr || y.ext == nullptr || x.ext == y.ext);
+ (!x.ext || !y.ext || *x.ext == *y.ext);
}
inline bool
diff --git a/build2/target-type b/build2/target-type
index 3bbc73c..cddb9e2 100644
--- a/build2/target-type
+++ b/build2/target-type
@@ -41,8 +41,8 @@ namespace build2
const char* name;
const target_type* base;
target* (*factory) (
- const target_type&, dir_path, dir_path, string, const string*);
- const string* (*extension) (const target_key&, scope&, bool search);
+ const target_type&, dir_path, dir_path, string, optional<string>);
+ optional<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 d083f22..40967c3 100644
--- a/build2/target.cxx
+++ b/build2/target.cxx
@@ -15,6 +15,10 @@ using namespace std;
namespace build2
{
+ // target_key
+ //
+ const optional<string> target_key::nullext = nullopt;
+
// target_type
//
bool target_type::
@@ -207,13 +211,13 @@ namespace build2
// Update the extension if the existing target has it unspecified.
//
- const string* ext (k.ext);
+ const optional<string>& ext (k.ext);
if (t.ext != ext)
{
l5 ([&]{
diag_record r (trace);
r << "assuming target " << t << " is the same as the one with ";
- if (ext == nullptr)
+ if (!ext)
r << "unspecified extension";
else if (ext->empty ())
r << "no extension";
@@ -221,7 +225,7 @@ namespace build2
r << "extension " << *ext;
});
- if (ext != nullptr)
+ if (ext)
t.ext = ext;
}
}
@@ -234,7 +238,7 @@ namespace build2
dir_path dir,
dir_path out,
string name,
- const string* ext,
+ optional<string> ext,
tracer& trace)
{
iterator i (find (target_key {&tt, &dir, &out, &name, ext}, trace));
@@ -243,7 +247,7 @@ namespace build2
if (r)
{
unique_ptr<target> pt (
- tt.factory (tt, move (dir), move (out), move (name), ext));
+ tt.factory (tt, move (dir), move (out), move (name), move (ext)));
i = map_.emplace (
make_pair (target_key {&tt, &pt->dir, &pt->out, &pt->name, pt->ext},
move (pt))).first;
@@ -285,13 +289,13 @@ namespace build2
// it if there is one. For 2 we print 'foo.?' if it hasn't yet been
// assigned and 'foo.' if it is assigned as "no extension" (empty).
//
- if (ev > 0 && (ev > 1 || (k.ext != nullptr && !k.ext->empty ())))
+ if (ev > 0 && (ev > 1 || (k.ext && !k.ext->empty ())))
{
- os << '.' << (k.ext != nullptr ? *k.ext : "?");
+ os << '.' << (k.ext ? *k.ext : "?");
}
}
else
- assert (k.ext == nullptr);
+ assert (!k.ext);
}
else
os << *k.dir;
@@ -338,7 +342,7 @@ namespace build2
//
assert (de == nullptr || type ().extension != nullptr);
- if (ext == nullptr)
+ if (!ext)
{
// If the target type has the extension function then try that first.
// The reason for preferring it over what's been provided by the caller
@@ -346,12 +350,12 @@ namespace build2
// the user can use to override extensions.
//
if (auto f = type ().extension)
- ext = f (key (), base_scope (), search); // Already from the pool.
+ ext = f (key (), base_scope (), search);
- if (ext == nullptr)
+ if (!ext)
{
if (de != nullptr)
- ext = &extension_pool.find (de);
+ ext = de;
else
fail << "no default extension for target " << *this;
}
@@ -452,13 +456,13 @@ namespace build2
return t;
}
- const string*
+ optional<string>
target_extension_null (const target_key&, scope&, bool)
{
- return nullptr;
+ return nullopt;
}
- const string*
+ optional<string>
target_extension_assert (const target_key&, scope&, bool)
{
assert (false); // Attempt to obtain the default extension.
@@ -521,7 +525,7 @@ namespace build2
dir_path d,
dir_path o,
string n,
- const string* e)
+ optional<string> e)
{
// A generic file target type doesn't imply any extension while a very
// specific one (say man1) may have a fixed extension. So if one wasn't
@@ -533,9 +537,9 @@ namespace build2
move (d),
move (o),
move (n),
- (e != nullptr || ext == nullptr || tt.factory != &file_factory<T, ext>
- ? e
- : &extension_pool.find (ext)));
+ (e || ext == nullptr || tt.factory != &file_factory<T, ext>
+ ? move (e)
+ : string (ext)));
}
extern const char file_ext_var[] = "extension"; // VC14 rejects constexpr.
@@ -585,7 +589,7 @@ namespace build2
false
};
- static const string*
+ static optional<string>
exe_extension (const target_key&, scope&, bool search)
{
// If we are searching for an executable that is not a target, then
@@ -593,14 +597,14 @@ namespace build2
// a target, then we expect the rule to use target machine extension.
//
return search
- ? &extension_pool.find (
+ ? optional<string> (
#ifdef _WIN32
"exe"
#else
""
#endif
)
- : nullptr;
+ : nullopt;
}
const target_type exe::static_type
@@ -619,21 +623,21 @@ namespace build2
dir_path d,
dir_path o,
string n,
- const string* e)
+ optional<string> e)
{
- if (e == nullptr)
- e = &extension_pool.find (n == "buildfile" ? "" : "build");
+ if (!e)
+ e = (n == "buildfile" ? string () : "build");
- return new buildfile (move (d), move (o), move (n), e);
+ return new buildfile (move (d), move (o), move (n), move (e));
}
- static const string*
+ static optional<string>
buildfile_target_extension (const target_key& tk, scope&, bool)
{
// If the name is special 'buildfile', then there is no extension,
// otherwise it is .build.
//
- return &extension_pool.find (*tk.name == "buildfile" ? "" : "build");
+ return *tk.name == "buildfile" ? string () : "build";
}
const target_type buildfile::static_type
@@ -663,12 +667,12 @@ namespace build2
dir_path d,
dir_path o,
string n,
- const string* e)
+ optional<string> e)
{
- if (e == nullptr)
+ if (!e)
fail << "man target '" << n << "' must include extension (man section)";
- return new man (move (d), move (o), move (n), e);
+ return new man (move (d), move (o), move (n), move (e));
}
const target_type man::static_type
diff --git a/build2/target.txx b/build2/target.txx
index bc63c75..66acfb8 100644
--- a/build2/target.txx
+++ b/build2/target.txx
@@ -3,7 +3,6 @@
// license : MIT; see accompanying LICENSE file
#include <build2/scope>
-#include <build2/context> // extension_pool
#include <build2/diagnostics>
#include <build2/prerequisite>
@@ -34,14 +33,14 @@ namespace build2
//
//
template <const char* ext>
- const string*
+ optional<string>
target_extension_fix (const target_key&, scope&, bool)
{
- return &extension_pool.find (ext);
+ return string (ext);
}
template <const char* var, const char* def>
- const string*
+ optional<string>
target_extension_var (const target_key& tk, scope& s, bool)
{
// Include target type/pattern-specific variables.
@@ -51,10 +50,9 @@ namespace build2
// Help the user here and strip leading '.' from the extension.
//
const string& e (cast<string> (l));
- return &extension_pool.find (
- !e.empty () && e.front () == '.' ? string (e, 1) : e);
+ return !e.empty () && e.front () == '.' ? string (e, 1) : e;
}
- return def != nullptr ? &extension_pool.find (def) : nullptr;
+ return def != nullptr ? optional<string> (def) : nullopt;
}
}
diff --git a/build2/test/target.cxx b/build2/test/target.cxx
index af3c89b..44f65aa 100644
--- a/build2/test/target.cxx
+++ b/build2/test/target.cxx
@@ -16,21 +16,21 @@ namespace build2
dir_path d,
dir_path o,
string n,
- const string* e)
+ optional<string> e)
{
- if (e == nullptr)
- e = &extension_pool.find (n == "testscript" ? "" : "test");
+ if (!e)
+ e = (n == "testscript" ? string () : "test");
- return new testscript (move (d), move (o), move (n), e);
+ return new testscript (move (d), move (o), move (n), move (e));
}
- static const string*
+ static optional<string>
testscript_target_extension (const target_key& tk, scope&, bool)
{
// If the name is special 'testscript', then there is no extension,
// otherwise it is .test.
//
- return &extension_pool.find (*tk.name == "testscript" ? "" : "test");
+ return *tk.name == "testscript" ? string () : "test";
}
const target_type testscript::static_type
diff --git a/build2/utility b/build2/utility
index 464c1fe..b162a9d 100644
--- a/build2/utility
+++ b/build2/utility
@@ -437,17 +437,6 @@ namespace build2
unsigned int
to_version (const string&);
- // Pools (@@ perhaps move into a separate header).
- //
- struct string_pool: std::unordered_set<std::string>
- {
- const std::string&
- find (const char* s) {return *emplace (s).first;}
-
- const std::string&
- find (const std::string& s) {return *emplace (s).first;}
- };
-
// Initialize build2 global state (verbosity, home/work directories, etc).
// Should be called early in main() once.
//
diff --git a/unit-tests/test/script/parser/driver.cxx b/unit-tests/test/script/parser/driver.cxx
index e167505..271fd2c 100644
--- a/unit-tests/test/script/parser/driver.cxx
+++ b/unit-tests/test/script/parser/driver.cxx
@@ -9,7 +9,7 @@
#include <build2/utility>
#include <build2/target>
-#include <build2/context>
+#include <build2/context> // reset()
#include <build2/scheduler>
#include <build2/test/target>
@@ -186,16 +186,15 @@ namespace build2
targets.insert<file> (work,
dir_path (),
"driver",
- &extension_pool.find (""),
+ string (),
trace));
testscript& st (
- targets.insert<testscript> (
- work,
- dir_path (),
- name.leaf ().base ().string (),
- &extension_pool.find (name.leaf ().extension ()),
- trace));
+ targets.insert<testscript> (work,
+ dir_path (),
+ name.leaf ().base ().string (),
+ name.leaf ().extension (),
+ trace));
tt.path (path ("driver"));
st.path (name);