aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2018-03-21 10:38:22 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2018-03-21 10:38:22 +0200
commit903eeb2c681f2008602bf48265ec628e4fdc9225 (patch)
treef60cb2964320ba3ed64df8a49ffa89966533f8c8
parentfc8da2b2cc0a7ad497c810b54e53d68a11cb1887 (diff)
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.
-rw-r--r--build2/cc/link-rule.cxx15
-rw-r--r--build2/utility.hxx14
-rw-r--r--build2/utility.ixx18
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<file> ();
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<exe> (); // 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 <typename T>
inline void
append_options (cstrings& args, T& s, const variable& var, const char* e)