From 903eeb2c681f2008602bf48265ec628e4fdc9225 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 21 Mar 2018 10:38:22 +0200 Subject: Strip out_root when hashing linker input paths This allows moving out_root of simple projects (no rpath, -I$out_root, or similar) without causing a re-link which we use for testing. --- build2/cc/link-rule.cxx | 15 ++++++++------- build2/utility.hxx | 14 ++++++++++++++ build2/utility.ixx | 18 ++++++++++++++++++ 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/build2/cc/link-rule.cxx b/build2/cc/link-rule.cxx index 04e2e7d..4379362 100644 --- a/build2/cc/link-rule.cxx +++ b/build2/cc/link-rule.cxx @@ -1034,10 +1034,11 @@ namespace build2 struct data { - sha256& cs; - bool& update; - timestamp mt; - } d {cs, update, mt}; + sha256& cs; + const dir_path& out_root; + bool& update; + timestamp mt; + } d {cs, bs.root_scope ()->out_path (), update, mt}; auto lib = [&d, this] (const file* l, const string& p, lflags f, bool) { @@ -1055,7 +1056,7 @@ namespace build2 l = &l->member->as (); d.cs.append (f); - d.cs.append (l->path ().string ()); + hash_path (d.cs, l->path (), d.out_root); } else d.cs.append (p); @@ -1593,7 +1594,7 @@ namespace build2 f = nullptr; // Timestamp checked by hash_libraries(). } else - cs.append (f->path ().string ()); + hash_path (cs, f->path (), rs.out_path ()); } else f = pt->is_a (); // Consider executable mtime (e.g., linker). @@ -1607,7 +1608,7 @@ namespace build2 // Treat it as input for both MinGW and VC (mtime checked above). // if (!manifest.empty ()) - cs.append (manifest.string ()); + hash_path (cs, manifest, rs.out_path ()); // Treat .libs as inputs, not options. // diff --git a/build2/utility.hxx b/build2/utility.hxx index ea47c03..e5c21e7 100644 --- a/build2/utility.hxx +++ b/build2/utility.hxx @@ -403,6 +403,20 @@ namespace build2 extern const path empty_path; extern const dir_path empty_dir_path; + // Hash a path potentially without the specific directory prefix. + // + // If prefix is not empty and is a super-path of the path to hash, then only + // hash the suffix. Note that both paths are assumed to be normalized. + // + // This functionality is normally used to strip out_root from target paths + // being hashed in order to avoid updates in case out_root was moved. Note + // that this should only be done if the result of the update does not + // include the out_root path in any form (as could be the case, for example, + // for debug information, __FILE__ macro expansion, rpath, etc). + // + void + hash_path (sha256&, const path&, const dir_path& prefix = dir_path ()); + // Append all the values from a variable to the C-string list. T is either // target or scope. The variable is expected to be of type strings. // diff --git a/build2/utility.ixx b/build2/utility.ixx index a726b0c..d0fe80c 100644 --- a/build2/utility.ixx +++ b/build2/utility.ixx @@ -33,6 +33,24 @@ namespace build2 return e - b; } + inline void + hash_path (sha256& cs, const path& p, const dir_path& prefix) + { + // Note: for efficiency we don't use path::leaf() and "skip" the prefix + // without copying. + // + const char* s (p.string ().c_str ()); + + if (!prefix.empty () && p.sub (prefix)) + { + s += prefix.size (); // Does not include trailing slash except for root. + if (path::traits::is_separator (*s)) + ++s; + } + + cs.append (s); + } + template inline void append_options (cstrings& args, T& s, const variable& var, const char* e) -- cgit v1.1