Absolute path fixes for gn.
To avoid collisions object files and other build ouput is now prefixed
with ABS_PATH and the full path of the input file.
E.g. /some/path/foo.cc maps to //out/obj/ABS_PATH/some/path/foo.o
In addition there are several fixes for absolute paths on Windows:
The drive letter colon is skipped when parsing labels.
Transform C:\ to /C:\ where needed.
BUG=445454
NOPRESUBMIT=true
Review URL: https://codereview.chromium.org/857163002
Cr-Commit-Position: refs/heads/master@{#315531}
diff --git a/tools/gn/filesystem_utils.cc b/tools/gn/filesystem_utils.cc
index 89e8a30..7495b05c 100644
--- a/tools/gn/filesystem_utils.cc
+++ b/tools/gn/filesystem_utils.cc
@@ -520,6 +520,22 @@
std::string MakeRelativePath(const std::string& input,
const std::string& dest) {
+#if defined(OS_WIN)
+ // Make sure that absolute |input| path starts with a slash if |dest| path
+ // does. Otherwise skipping common prefixes won't work properly. Ensure the
+ // same for |dest| path too.
+ if (IsPathAbsolute(input) && !IsSlash(input[0]) && IsSlash(dest[0])) {
+ std::string corrected_input(1, dest[0]);
+ corrected_input.append(input);
+ return MakeRelativePath(corrected_input, dest);
+ }
+ if (IsPathAbsolute(dest) && !IsSlash(dest[0]) && IsSlash(input[0])) {
+ std::string corrected_dest(1, input[0]);
+ corrected_dest.append(dest);
+ return MakeRelativePath(input, corrected_dest);
+ }
+#endif
+
std::string ret;
// Skip the common prefixes of the source and dest as long as they end in
@@ -732,6 +748,19 @@
size_t build_dir_size = build_dir.size();
result.value().append(&source_dir.value()[build_dir_size],
source_dir.value().size() - build_dir_size);
+ } else {
+ result.value().append("ABS_PATH");
+#if defined(OS_WIN)
+ // Windows absolute path contains ':' after drive letter. Remove it to
+ // avoid inserting ':' in the middle of path (eg. "ABS_PATH/C:/").
+ std::string src_dir_value = source_dir.value();
+ const auto colon_pos = src_dir_value.find(':');
+ if (colon_pos != std::string::npos)
+ src_dir_value.erase(src_dir_value.begin() + colon_pos);
+#else
+ const std::string& src_dir_value = source_dir.value();
+#endif
+ result.value().append(src_dir_value);
}
}
return result;