aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2020-06-02 07:35:44 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2020-06-02 07:35:44 +0200
commita3ed04f37c47e2eaa83d87dda2ec4ab060a7a2d0 (patch)
tree1ca68321bc7203cfef635dab6820f35435279ee0
parentdcbd81ad1c303dd2b9ef54e8e7e485bb17c6de49 (diff)
Add process_path_ex with program stable name and checksum
-rw-r--r--libbuild2/bin/init.cxx30
-rw-r--r--libbuild2/c/init.cxx8
-rw-r--r--libbuild2/cc/module.cxx2
-rw-r--r--libbuild2/context.hxx2
-rw-r--r--libbuild2/cxx/init.cxx8
-rw-r--r--libbuild2/functions-process-path.cxx23
-rw-r--r--libbuild2/types.hxx24
-rw-r--r--libbuild2/variable.cxx222
-rw-r--r--libbuild2/variable.hxx24
-rw-r--r--libbuild2/variable.ixx20
10 files changed, 305 insertions, 58 deletions
diff --git a/libbuild2/bin/init.cxx b/libbuild2/bin/init.cxx
index 4af3c1d..a1ac61e 100644
--- a/libbuild2/bin/init.cxx
+++ b/libbuild2/bin/init.cxx
@@ -574,11 +574,8 @@ namespace build2
{
auto& vp (rs.var_pool ());
- vp.insert<process_path> ("bin.ar.path");
- vp.insert<process_path> ("bin.ranlib.path");
-
- vp.insert<path> ("config.bin.ar");
- vp.insert<path> ("config.bin.ranlib");
+ vp.insert<path> ("config.bin.ar");
+ vp.insert<path> ("config.bin.ranlib");
}
// Configuration.
@@ -672,7 +669,8 @@ namespace build2
}
}
- rs.assign<process_path> ("bin.ar.path") = move (ari.ar_path);
+ rs.assign<process_path_ex> ("bin.ar.path") =
+ process_path_ex (move (ari.ar_path), "ar", ari.ar_checksum);
rs.assign<string> ("bin.ar.id") = move (ari.ar_id);
rs.assign<string> ("bin.ar.signature") = move (ari.ar_signature);
rs.assign<string> ("bin.ar.checksum") = move (ari.ar_checksum);
@@ -689,8 +687,12 @@ namespace build2
if (ranlib != nullptr)
{
- rs.assign<process_path> ("bin.ranlib.path") = move (ari.ranlib_path);
- rs.assign<string> ("bin.ranlib.id") = move (ari.ranlib_id);
+ rs.assign<process_path_ex> ("bin.ranlib.path") =
+ process_path_ex (move (ari.ranlib_path),
+ "ranlib",
+ ari.ranlib_checksum);
+ rs.assign<string> ("bin.ranlib.id") =
+ move (ari.ranlib_id);
rs.assign<string> ("bin.ranlib.signature") =
move (ari.ranlib_signature);
rs.assign<string> ("bin.ranlib.checksum") =
@@ -741,8 +743,7 @@ namespace build2
{
auto& vp (rs.var_pool ());
- vp.insert<process_path> ("bin.ld.path");
- vp.insert<path> ("config.bin.ld");
+ vp.insert<path> ("config.bin.ld");
}
// Configuration.
@@ -804,7 +805,8 @@ namespace build2
<< " checksum " << ldi.checksum;
}
- rs.assign<process_path> ("bin.ld.path") = move (ldi.path);
+ rs.assign<process_path_ex> ("bin.ld.path") =
+ process_path_ex (move (ldi.path), "ld", ldi.checksum);
rs.assign<string> ("bin.ld.id") = move (ldi.id);
rs.assign<string> ("bin.ld.signature") = move (ldi.signature);
rs.assign<string> ("bin.ld.checksum") = move (ldi.checksum);
@@ -881,8 +883,7 @@ namespace build2
{
auto& vp (rs.var_pool ());
- vp.insert<process_path> ("bin.rc.path");
- vp.insert<path> ("config.bin.rc");
+ vp.insert<path> ("config.bin.rc");
}
// Configuration.
@@ -926,7 +927,8 @@ namespace build2
<< " checksum " << rci.checksum;
}
- rs.assign<process_path> ("bin.rc.path") = move (rci.path);
+ rs.assign<process_path_ex> ("bin.rc.path") =
+ process_path_ex (move (rci.path), "rc", rci.checksum);
rs.assign<string> ("bin.rc.id") = move (rci.id);
rs.assign<string> ("bin.rc.signature") = move (rci.signature);
rs.assign<string> ("bin.rc.checksum") = move (rci.checksum);
diff --git a/libbuild2/c/init.cxx b/libbuild2/c/init.cxx
index 5eea8de..5a70b54 100644
--- a/libbuild2/c/init.cxx
+++ b/libbuild2/c/init.cxx
@@ -177,10 +177,10 @@ namespace build2
vp.insert<strings> ("config.c.libs"),
nullptr /* config.c.translatable_headers */,
- vp.insert<process_path> ("c.path"),
- vp.insert<strings> ("c.mode"),
- vp.insert<dir_paths> ("c.sys_lib_dirs"),
- vp.insert<dir_paths> ("c.sys_inc_dirs"),
+ vp.insert<process_path_ex> ("c.path"),
+ vp.insert<strings> ("c.mode"),
+ vp.insert<dir_paths> ("c.sys_lib_dirs"),
+ vp.insert<dir_paths> ("c.sys_inc_dirs"),
vp.insert<string> ("c.std"),
diff --git a/libbuild2/cc/module.cxx b/libbuild2/cc/module.cxx
index a485b46..a80d770 100644
--- a/libbuild2/cc/module.cxx
+++ b/libbuild2/cc/module.cxx
@@ -197,7 +197,7 @@ namespace build2
// Assign values to variables that describe the compiler.
//
- rs.assign (x_path) = process_path (xi.path, false /* init */);
+ rs.assign (x_path) = process_path_ex (xi.path, x_name, xi.checksum);
const strings& xm (cast<strings> (rs.assign (x_mode) = move (mode)));
rs.assign (x_id) = xi.id.string ();
diff --git a/libbuild2/context.hxx b/libbuild2/context.hxx
index 5f6e810..e4d4d4c 100644
--- a/libbuild2/context.hxx
+++ b/libbuild2/context.hxx
@@ -377,6 +377,8 @@ namespace build2
// If the <var-prefix>.name variable is missing, it is set to the target
// name as imported.
//
+ // See also process_path_ex.
+ //
const variable* var_import_metadata;
const variable* var_export_metadata;
diff --git a/libbuild2/cxx/init.cxx b/libbuild2/cxx/init.cxx
index 265bbc0..65d13cf 100644
--- a/libbuild2/cxx/init.cxx
+++ b/libbuild2/cxx/init.cxx
@@ -427,10 +427,10 @@ namespace build2
//
&vp.insert<strings> ("config.cxx.translatable_headers"),
- vp.insert<process_path> ("cxx.path"),
- vp.insert<strings> ("cxx.mode"),
- vp.insert<dir_paths> ("cxx.sys_lib_dirs"),
- vp.insert<dir_paths> ("cxx.sys_inc_dirs"),
+ vp.insert<process_path_ex> ("cxx.path"),
+ vp.insert<strings> ("cxx.mode"),
+ vp.insert<dir_paths> ("cxx.sys_lib_dirs"),
+ vp.insert<dir_paths> ("cxx.sys_inc_dirs"),
vp.insert<string> ("cxx.std"),
diff --git a/libbuild2/functions-process-path.cxx b/libbuild2/functions-process-path.cxx
index 15bec81..86d4445 100644
--- a/libbuild2/functions-process-path.cxx
+++ b/libbuild2/functions-process-path.cxx
@@ -11,14 +11,23 @@ namespace build2
void
process_path_functions (function_map& m)
{
- function_family f (m, "process_path");
+ {
+ function_family f (m, "process_path");
+
+ // As discussed in value_traits<process_path>, we always have recall.
+ //
+ f["recall"] = &process_path::recall;
+ f["effect"] = [](process_path p)
+ {
+ return move (p.effect.empty () ? p.recall : p.effect);
+ };
+ }
- // As discussed in value_traits<process_path>, we always have recall.
- //
- f["recall"] = &process_path::recall;
- f["effect"] = [](process_path p)
{
- return move (p.effect.empty () ? p.recall : p.effect);
- };
+ function_family f (m, "process_path_ex");
+
+ f["name"] = &process_path_ex::name;
+ f["checksum"] = &process_path_ex::checksum;
+ }
}
}
diff --git a/libbuild2/types.hxx b/libbuild2/types.hxx
index 6582c3a..65e0918 100644
--- a/libbuild2/types.hxx
+++ b/libbuild2/types.hxx
@@ -283,6 +283,30 @@ namespace build2
using butl::process_path;
using butl::process_error;
+ // Extended process_path with additional information.
+ //
+ // See also {import,export}.metadata.
+ //
+ struct process_path_ex: process_path
+ {
+ optional<string> name; // Stable name for diagnostics.
+ optional<string> checksum; // Checksum for change tracking.
+
+ using process_path::process_path;
+
+ process_path_ex (const process_path& p, string n, optional<string> c = {})
+ : process_path (p, false /* init */),
+ name (std::move (n)),
+ checksum (std::move (c)) {}
+
+ process_path_ex (process_path&& p, string n, optional<string> c = {})
+ : process_path (std::move (p)),
+ name (std::move (n)),
+ checksum (std::move (c)) {}
+
+ process_path_ex () = default;
+ };
+
// <libbutl/fdstream.mxx>
//
using butl::auto_fd;
diff --git a/libbuild2/variable.cxx b/libbuild2/variable.cxx
index 14803cb..ed710af 100644
--- a/libbuild2/variable.cxx
+++ b/libbuild2/variable.cxx
@@ -839,7 +839,7 @@ namespace build2
return name_pair (move (n), r != nullptr ? move (*r) : name ());
}
- void
+ static void
name_pair_assign (value& v, names&& ns, const variable* var)
{
using traits = value_traits<name_pair>;
@@ -911,8 +911,9 @@ namespace build2
// process_path value
//
- process_path value_traits<process_path>::
- convert (name&& n, name* r)
+ template <typename T>
+ static T
+ process_path_convert (name&& n, name* r, const char* what)
{
if ( n.untyped () && n.unqualified () && !n.empty () &&
(r == nullptr || (r->untyped () && r->unqualified () && !r->empty ())))
@@ -933,15 +934,21 @@ namespace build2
ep /= r->value;
}
- process_path pp (nullptr, move (rp), move (ep));
+ T pp (nullptr, move (rp), move (ep));
pp.initial = pp.recall.string ().c_str ();
return pp;
}
- throw_invalid_argument (n, r, "process_path");
+ throw_invalid_argument (n, r, what);
}
- void
+ process_path value_traits<process_path>::
+ convert (name&& n, name* r)
+ {
+ return process_path_convert<process_path> (move (n), r, "process_path");
+ }
+
+ static void
process_path_assign (value& v, names&& ns, const variable* var)
{
using traits = value_traits<process_path>;
@@ -969,23 +976,24 @@ namespace build2
dr << " in variable " << var->name;
}
- void
+ template <typename T>
+ static void
process_path_copy_ctor (value& l, const value& r, bool m)
{
- const auto& rhs (r.as<process_path> ());
+ const auto& rhs (r.as<T> ());
if (m)
- new (&l.data_) process_path (move (const_cast<process_path&> (rhs)));
+ new (&l.data_) T (move (const_cast<T&> (rhs)));
else
{
auto& lhs (
- *new (&l.data_) process_path (
+ *new (&l.data_) T (
nullptr, path (rhs.recall), path (rhs.effect)));
lhs.initial = lhs.recall.string ().c_str ();
}
}
- void
+ static void
process_path_copy_assign (value& l, const value& r, bool m)
{
auto& lhs (l.as<process_path> ());
@@ -1001,26 +1009,31 @@ namespace build2
}
}
+ static void
+ process_path_reverse_impl (const process_path& x, names& s)
+ {
+ s.push_back (name (x.recall.directory (),
+ string (),
+ x.recall.leaf ().string ()));
+
+ if (!x.effect.empty ())
+ {
+ s.back ().pair = '@';
+ s.push_back (name (x.effect.directory (),
+ string (),
+ x.effect.leaf ().string ()));
+ }
+ }
+
static names_view
process_path_reverse (const value& v, names& s)
{
- const process_path& x (v.as<process_path> ());
+ const auto& x (v.as<process_path> ());
if (!x.empty ())
{
s.reserve (x.effect.empty () ? 1 : 2);
-
- s.push_back (name (x.recall.directory (),
- string (),
- x.recall.leaf ().string ()));
-
- if (!x.effect.empty ())
- {
- s.back ().pair = '@';
- s.push_back (name (x.effect.directory (),
- string (),
- x.effect.leaf ().string ()));
- }
+ process_path_reverse_impl (x, s);
}
return s;
@@ -1035,7 +1048,7 @@ namespace build2
nullptr, // No base.
nullptr, // No element.
&default_dtor<process_path>,
- &process_path_copy_ctor,
+ &process_path_copy_ctor<process_path>,
&process_path_copy_assign,
&process_path_assign,
nullptr, // Append not supported.
@@ -1046,6 +1059,165 @@ namespace build2
&default_empty<process_path>
};
+ // process_path_ex value
+ //
+ process_path_ex value_traits<process_path_ex>::
+ convert (names&& ns)
+ {
+ if (ns.empty ())
+ return process_path_ex ();
+
+ bool p (ns[0].pair);
+
+ process_path_ex pp (
+ process_path_convert<process_path_ex> (
+ move (ns[0]), p ? &ns[1] : nullptr, "process_path_ex"));
+
+ for (auto i (ns.begin () + (p ? 2 : 1)); i != ns.end (); ++i)
+ {
+ if (!i->pair)
+ throw invalid_argument ("non-pair in process_path_ex value");
+
+ if (!i->simple ())
+ throw_invalid_argument (*i, nullptr, "process_path_ex");
+
+ const string& k ((i++)->value);
+
+ if (k == "name")
+ {
+ if (!i->simple ())
+ throw_invalid_argument (*i, nullptr, "process_path_ex name");
+
+ pp.name = move (i->value);
+ }
+ else if (k == "checksum")
+ {
+ if (!i->simple ())
+ throw_invalid_argument (*i, nullptr, "process_path_ex checksum");
+
+ pp.checksum = move (i->value);
+ }
+ else
+ throw invalid_argument (
+ "unknown key '" + k + "' in process_path_ex value");
+ }
+
+ return pp;
+ }
+
+ static void
+ process_path_ex_assign (value& v, names&& ns, const variable* var)
+ {
+ using traits = value_traits<process_path_ex>;
+
+ try
+ {
+ traits::assign (v, traits::convert (move (ns)));
+ }
+ catch (const invalid_argument& e)
+ {
+ // Note: ns is not guaranteed to be valid.
+ //
+ diag_record dr (fail);
+ dr << "invalid process_path_ex value";
+
+ if (var != nullptr)
+ dr << " in variable " << var->name;
+
+ dr << ": " << e;
+ }
+ }
+
+ static void
+ process_path_ex_copy_ex (value& l, const value& r, bool m)
+ {
+ auto& lhs (l.as<process_path_ex> ());
+
+ if (m)
+ {
+ const auto& rhs (const_cast<value&> (r).as<process_path_ex> ());
+
+ lhs.name = move (rhs.name);
+ lhs.checksum = move (rhs.checksum);
+ }
+ else
+ {
+ const auto& rhs (r.as<process_path_ex> ());
+
+ lhs.name = rhs.name;
+ lhs.checksum = rhs.checksum;
+ }
+ }
+
+ static void
+ process_path_ex_copy_ctor (value& l, const value& r, bool m)
+ {
+ process_path_copy_ctor<process_path_ex> (l, r, m);
+
+ if (!m)
+ process_path_ex_copy_ex (l, r, false);
+ }
+
+ static void
+ process_path_ex_copy_assign (value& l, const value& r, bool m)
+ {
+ process_path_copy_assign (l, r, m);
+ process_path_ex_copy_ex (l, r, m);
+ }
+
+ static names_view
+ process_path_ex_reverse (const value& v, names& s)
+ {
+ const auto& x (v.as<process_path_ex> ());
+
+ if (!x.empty ())
+ {
+ s.reserve ((x.effect.empty () ? 1 : 2) +
+ (x.name ? 2 : 0) +
+ (x.checksum ? 2 : 0));
+
+ process_path_reverse_impl (x, s);
+
+ if (x.name)
+ {
+ s.push_back (name ("name"));
+ s.back ().pair = '@';
+ s.push_back (name (*x.name));
+ }
+
+ if (x.checksum)
+ {
+ s.push_back (name ("checksum"));
+ s.back ().pair = '@';
+ s.push_back (name (*x.checksum));
+ }
+ }
+
+ return s;
+ }
+
+ const char* const value_traits<process_path_ex>::type_name =
+ "process_path_ex";
+
+ const value_type value_traits<process_path_ex>::value_type
+ {
+ type_name,
+ sizeof (process_path_ex),
+ &value_traits< // Base (assuming direct cast works
+ process_path>::value_type, // for both).
+ nullptr, // No element.
+ &default_dtor<process_path_ex>,
+ &process_path_ex_copy_ctor,
+ &process_path_ex_copy_assign,
+ &process_path_ex_assign,
+ nullptr, // Append not supported.
+ nullptr, // Prepend not supported.
+ &process_path_ex_reverse,
+ nullptr, // No cast (cast data_ directly).
+ &simple_compare<process_path>, // For now compare as process_path.
+ &default_empty<process_path_ex>
+ };
+
// target_triplet value
//
target_triplet value_traits<target_triplet>::
diff --git a/libbuild2/variable.hxx b/libbuild2/variable.hxx
index 409a4aa..e5d8e72 100644
--- a/libbuild2/variable.hxx
+++ b/libbuild2/variable.hxx
@@ -881,8 +881,8 @@ namespace build2
static_assert (sizeof (process_path) <= value::size_,
"insufficient space");
- // This one is represented as a @-pair of names. As a result it cannot
- // be stored in a container.
+ // Represented as a @-pair of names. As a result it cannot be stored in a
+ // container.
//
static process_path convert (name&&, name*);
static void assign (value&, process_path&&);
@@ -894,6 +894,26 @@ namespace build2
static const build2::value_type value_type;
};
+ // process_path_ex
+ //
+ template <>
+ struct LIBBUILD2_SYMEXPORT value_traits<process_path_ex>
+ {
+ static_assert (sizeof (process_path_ex) <= value::size_,
+ "insufficient space");
+
+ // Represented as a @-pair of names corresponding to process_path followed
+ // by the name@ and checksum@ pairs. So it's a container-like.
+ //
+ static process_path_ex convert (names&&);
+ static void assign (value&, process_path_ex&&);
+ static bool empty (const process_path_ex& x) {return x.empty ();}
+
+ static const bool empty_value = true;
+ static const char* const type_name;
+ static const build2::value_type value_type;
+ };
+
// target_triplet
//
template <>
diff --git a/libbuild2/variable.ixx b/libbuild2/variable.ixx
index 50cce78..84bf20c 100644
--- a/libbuild2/variable.ixx
+++ b/libbuild2/variable.ixx
@@ -614,7 +614,7 @@ namespace build2
inline void value_traits<process_path>::
assign (value& v, process_path&& x)
{
- // Convert the value to its "self-sufficient" form.
+ // Convert the value to its "self-sufficient" form (see also below).
//
if (x.recall.empty ())
x.recall = path (x.initial);
@@ -638,6 +638,24 @@ namespace build2
return r;
}
+ // process_path_ex value
+ //
+ inline void value_traits<process_path_ex>::
+ assign (value& v, process_path_ex&& x)
+ {
+ // Convert the value to its "self-sufficient" form (see also above).
+ //
+ if (x.recall.empty ())
+ x.recall = path (x.initial);
+
+ x.initial = x.recall.string ().c_str ();
+
+ if (v)
+ v.as<process_path_ex> () = move (x);
+ else
+ new (&v.data_) process_path_ex (move (x));
+ }
+
// target_triplet value
//
inline void value_traits<target_triplet>::