aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbuild2/c/init.cxx1
-rw-r--r--libbuild2/cc/common.hxx4
-rw-r--r--libbuild2/cc/compile-rule.cxx7
-rw-r--r--libbuild2/cc/link-rule.cxx11
-rw-r--r--libbuild2/cc/module.cxx14
-rw-r--r--libbuild2/cc/module.hxx2
-rw-r--r--libbuild2/config/utility.hxx4
-rw-r--r--libbuild2/cxx/init.cxx1
-rw-r--r--libbuild2/utility.hxx29
-rw-r--r--libbuild2/utility.ixx67
10 files changed, 134 insertions, 6 deletions
diff --git a/libbuild2/c/init.cxx b/libbuild2/c/init.cxx
index afd8f88..1636816 100644
--- a/libbuild2/c/init.cxx
+++ b/libbuild2/c/init.cxx
@@ -343,6 +343,7 @@ namespace build2
cast<process_path> (rs[cm.x_path]),
cast<strings> (rs[cm.x_mode]),
cast<target_triplet> (rs[cm.x_target]),
+ cm.env_checksum,
false, // No C modules yet.
false, // No __symexport support since no modules.
diff --git a/libbuild2/cc/common.hxx b/libbuild2/cc/common.hxx
index 612d081..758c675 100644
--- a/libbuild2/cc/common.hxx
+++ b/libbuild2/cc/common.hxx
@@ -170,6 +170,8 @@ namespace build2
const string& tsys; // x.target.system
const string& tclass; // x.target.class
+ const string& env_checksum; // config_module::env_checksum
+
bool modules; // x.features.modules
bool symexport; // x.features.symexport
@@ -230,6 +232,7 @@ namespace build2
const process_path& path,
const strings& mode,
const target_triplet& tgt,
+ const string& env_cs,
bool fm,
bool fs,
const dir_paths& sld,
@@ -250,6 +253,7 @@ namespace build2
cmaj (mj), cmin (mi),
cpath (path), cmode (mode),
ctgt (tgt), tsys (ctgt.system), tclass (ctgt.class_),
+ env_checksum (env_cs),
modules (fm),
symexport (fs),
importable_headers (nullptr),
diff --git a/libbuild2/cc/compile-rule.cxx b/libbuild2/cc/compile-rule.cxx
index b5016bc..ce586bb 100644
--- a/libbuild2/cc/compile-rule.cxx
+++ b/libbuild2/cc/compile-rule.cxx
@@ -197,7 +197,7 @@ namespace build2
compile_rule::
compile_rule (data&& d)
: common (move (d)),
- rule_id (string (x) += ".compile 4")
+ rule_id (string (x) += ".compile 5")
{
static_assert (sizeof (match_data) <= target::data_size,
"insufficient space");
@@ -929,6 +929,11 @@ namespace build2
if (dd.expect (cast<string> (rs[x_checksum])) != nullptr)
l4 ([&]{trace << "compiler mismatch forcing update of " << t;});
+ // Then the compiler environment checksum.
+ //
+ if (dd.expect (env_checksum) != nullptr)
+ l4 ([&]{trace << "environment mismatch forcing update of " << t;});
+
// Then the options checksum.
//
// The idea is to keep them exactly as they are passed to the compiler
diff --git a/libbuild2/cc/link-rule.cxx b/libbuild2/cc/link-rule.cxx
index 9c72969..0ab61b1 100644
--- a/libbuild2/cc/link-rule.cxx
+++ b/libbuild2/cc/link-rule.cxx
@@ -37,7 +37,7 @@ namespace build2
link_rule::
link_rule (data&& d)
: common (move (d)),
- rule_id (string (x) += ".link 2")
+ rule_id (string (x) += ".link 3")
{
static_assert (sizeof (match_data) <= target::data_size,
"insufficient space");
@@ -2427,10 +2427,13 @@ namespace build2
l4 ([&]{trace << "linker mismatch forcing update of " << t;});
}
- // Hash and compare any changes to the environment.
+ // Then the linker environment checksum (original and our modifications).
//
- if (dd.expect (env_cs.string ()) != nullptr)
- l4 ([&]{trace << "environment mismatch forcing update of " << t;});
+ {
+ bool e (dd.expect (env_checksum) != nullptr);
+ if (dd.expect (env_cs.string ()) != nullptr || e)
+ l4 ([&]{trace << "environment mismatch forcing update of " << t;});
+ }
// Next check the target. While it might be incorporated into the linker
// checksum, it also might not (e.g., VC link.exe).
diff --git a/libbuild2/cc/module.cxx b/libbuild2/cc/module.cxx
index 5bb3f60..7ef8cd5 100644
--- a/libbuild2/cc/module.cxx
+++ b/libbuild2/cc/module.cxx
@@ -202,8 +202,22 @@ namespace build2
}
}
+ // Hash the environment (used for change detection).
+ //
+ // Note that for simplicity we use the combined checksum for both
+ // compilation and linking (which may compile, think LTO).
+ //
+ {
+ sha256 cs;
+ hash_environment (cs, xi.compiler_environment);
+ hash_environment (cs, xi.platform_environment);
+ env_checksum = cs.string ();
+ }
+
// Assign values to variables that describe the compiler.
//
+ // @@ TODO: env_checksum.
+ //
rs.assign (x_path) = process_path_ex (xi.path, x_name, xi.checksum);
const strings& xm (cast<strings> (rs.assign (x_mode) = move (mode)));
diff --git a/libbuild2/cc/module.hxx b/libbuild2/cc/module.hxx
index f9d435d..ed6ec41 100644
--- a/libbuild2/cc/module.hxx
+++ b/libbuild2/cc/module.hxx
@@ -59,6 +59,8 @@ namespace build2
const compiler_info* x_info;
+ string env_checksum; // Environment checksum (also in x.path).
+
// Temporary storage for data::sys_*_dirs_*.
//
size_t sys_lib_dirs_mode;
diff --git a/libbuild2/config/utility.hxx b/libbuild2/config/utility.hxx
index 382c22f..8dc0650 100644
--- a/libbuild2/config/utility.hxx
+++ b/libbuild2/config/utility.hxx
@@ -112,6 +112,8 @@ namespace build2
// directly). The module's load() function is a natural place to do
// that.
//
+ // See also build2::hash_environment().
+ //
inline void
save_environment (scope& rs, const string& var)
{
@@ -146,7 +148,7 @@ namespace build2
}
}
- // A NULL-terminated list of variables.
+ // A NULL-terminated list of variables (may itself be NULL).
//
inline void
save_environment (scope& rs, const char* const* vars)
diff --git a/libbuild2/cxx/init.cxx b/libbuild2/cxx/init.cxx
index 0bbab52..74dc3ed 100644
--- a/libbuild2/cxx/init.cxx
+++ b/libbuild2/cxx/init.cxx
@@ -720,6 +720,7 @@ namespace build2
cast<process_path> (rs[cm.x_path]),
cast<strings> (rs[cm.x_mode]),
cast<target_triplet> (rs[cm.x_target]),
+ cm.env_checksum,
modules,
symexport,
diff --git a/libbuild2/utility.hxx b/libbuild2/utility.hxx
index 6616f78..b4a8ce4 100644
--- a/libbuild2/utility.hxx
+++ b/libbuild2/utility.hxx
@@ -802,6 +802,35 @@ namespace build2
const cstrings&,
bool = false);
+ // Hash environment variable (its name and value) normally to be used as a
+ // checksum. See also config::save_environment().
+ //
+ void
+ hash_environment (sha256&, const char* name);
+
+ void
+ hash_environment (sha256&, const string& name);
+
+ void
+ hash_environment (sha256&, initializer_list<const char*> names);
+
+ string
+ hash_environment (initializer_list<const char*> names);
+
+ void
+ hash_environment (sha256&, const strings& names);
+
+ string
+ hash_environment (const strings& names);
+
+ // A NULL-terminated list of variables (may itself be NULL).
+ //
+ void
+ hash_environment (sha256&, const char* const* names);
+
+ string
+ hash_environment (const char* const* names);
+
// Find in the string the stem separated from other characters with the
// specified separators or begin/end of the string. Return the stem's
// position or npos if not found.
diff --git a/libbuild2/utility.ixx b/libbuild2/utility.ixx
index 9a77fae..3f9d34b 100644
--- a/libbuild2/utility.ixx
+++ b/libbuild2/utility.ixx
@@ -241,6 +241,73 @@ namespace build2
return find_option_prefixes (ps, s[var], ic);
}
+ // hash_environment()
+ //
+ inline void
+ hash_environment (sha256& cs, const char* n)
+ {
+ cs.append (n);
+
+ if (optional<string> v = getenv (n))
+ cs.append (*v);
+ }
+
+ inline void
+ hash_environment (sha256& cs, const string& n)
+ {
+ hash_environment (cs, n.c_str ());
+ }
+
+ inline void
+ hash_environment (sha256& cs, initializer_list<const char*> ns)
+ {
+ for (const char* n: ns)
+ hash_environment (cs, n);
+ }
+
+ inline string
+ hash_environment (initializer_list<const char*> ns)
+ {
+ sha256 cs;
+ hash_environment (cs, ns);
+ return cs.string ();
+ }
+
+ inline void
+ hash_environment (sha256& cs, const strings& ns)
+ {
+ for (const string& n: ns)
+ hash_environment (cs, n);
+ }
+
+ inline string
+ hash_environment (const strings& ns)
+ {
+ sha256 cs;
+ hash_environment (cs, ns);
+ return cs.string ();
+ }
+
+ inline void
+ hash_environment (sha256& cs, const char* const* ns)
+ {
+ if (ns != nullptr)
+ {
+ for (; *ns != nullptr; ++ns)
+ hash_environment (cs, *ns);
+ }
+ }
+
+ inline string
+ hash_environment (const char* const* ns)
+ {
+ sha256 cs;
+ hash_environment (cs, ns);
+ return cs.string ();
+ }
+
+ // find_stem()
+ //
inline size_t
find_stem (const string& s, size_t s_p, size_t s_n,
const char* stem, const char* seps)