Commit 6713d85d authored by Tom Anderson's avatar Tom Anderson Committed by Commit Bot

Generate relative paths for build.ninja and build.ninja.d

BUG=787223
R=dpranke@chromium.org

Change-Id: I1c3aada842bba899c20d5e2c1b0dceb818f118d2
Reviewed-on: https://chromium-review.googlesource.com/784093Reviewed-by: default avatarBrett Wilson <brettw@chromium.org>
Reviewed-by: default avatarDirk Pranke <dpranke@chromium.org>
Commit-Queue: Thomas Anderson <thomasanderson@chromium.org>
Cr-Commit-Position: refs/heads/master@{#521012}
parent 567580e2
......@@ -412,6 +412,37 @@ bool MakeAbsolutePathRelativeIfPossible(const base::StringPiece& source_root,
#endif
}
base::FilePath MakeAbsoluteFilePathRelativeIfPossible(
const base::FilePath& base,
const base::FilePath& target) {
DCHECK(base.IsAbsolute());
DCHECK(target.IsAbsolute());
std::vector<base::FilePath::StringType> base_components;
std::vector<base::FilePath::StringType> target_components;
base.GetComponents(&base_components);
target.GetComponents(&target_components);
#if defined(OS_WIN)
// On Windows, it's impossible to have a relative path from C:\foo to D:\bar,
// so return the target as an aboslute path instead.
if (base_components[0] != target_components[0])
return target;
#endif
size_t i;
for (i = 0; i < base_components.size() && i < target_components.size(); i++) {
if (base_components[i] != target_components[i])
break;
}
std::vector<base::FilePath::StringType> relative_components;
for (size_t j = i; j < base_components.size(); j++)
relative_components.push_back(base::FilePath::kParentDirectory);
for (size_t j = i; j < target_components.size(); j++)
relative_components.push_back(target_components[j]);
base::FilePath relative(base::FilePath::kCurrentDirectory);
for (const auto& component : relative_components)
relative = relative.Append(component);
return relative;
}
void NormalizePath(std::string* path, const base::StringPiece& source_root) {
char* pathbuf = path->empty() ? nullptr : &(*path)[0];
......
......@@ -116,6 +116,16 @@ bool MakeAbsolutePathRelativeIfPossible(const base::StringPiece& source_root,
const base::StringPiece& path,
std::string* dest);
// Given two absolute paths |base| and |target|, returns a relative path to
// |target| as if the current directory was |base|. The relative path returned
// is minimal. For example, if "../../a/b/" and "../b" are both valid, then the
// latter will be returned. On Windows, it's impossible to have a relative path
// from C:\foo to D:\bar, so the absolute path |target| is returned instead for
// this case.
base::FilePath MakeAbsoluteFilePathRelativeIfPossible(
const base::FilePath& base,
const base::FilePath& target);
// Collapses "." and sequential "/"s and evaluates "..". |path| may be
// system-absolute, source-absolute, or relative. If |path| is source-absolute
// and |source_root| is non-empty, |path| may be system absolute after this
......
......@@ -173,6 +173,43 @@ TEST(FilesystemUtils, MakeAbsolutePathRelativeIfPossible) {
#endif
}
TEST(FilesystemUtils, MakeAbsoluteFilePathRelativeIfPossible) {
#if defined(OS_WIN)
EXPECT_EQ(
base::FilePath(L"out\\Debug"),
MakeAbsoluteFilePathRelativeIfPossible(
base::FilePath(L"C:\\src"), base::FilePath(L"C:\\src\\out\\Debug")));
EXPECT_EQ(
base::FilePath(L"..\\.."),
MakeAbsoluteFilePathRelativeIfPossible(
base::FilePath(L"C:\\src\\out\\Debug"), base::FilePath(L"C:\\src")));
EXPECT_EQ(base::FilePath(L"."),
MakeAbsoluteFilePathRelativeIfPossible(base::FilePath(L"C:\\src"),
base::FilePath(L"C:\\src")));
EXPECT_EQ(base::FilePath(L"..\\..\\..\\u\\v\\w"),
MakeAbsoluteFilePathRelativeIfPossible(
base::FilePath(L"C:\\a\\b\\c\\x\\y\\z"),
base::FilePath(L"C:\\a\\b\\c\\u\\v\\w")));
EXPECT_EQ(base::FilePath(L"D:\\bar"),
MakeAbsoluteFilePathRelativeIfPossible(base::FilePath(L"C:\\foo"),
base::FilePath(L"D:\\bar")));
#else
EXPECT_EQ(base::FilePath("out/Debug"),
MakeAbsoluteFilePathRelativeIfPossible(
base::FilePath("/src"), base::FilePath("/src/out/Debug")));
EXPECT_EQ(base::FilePath("../.."),
MakeAbsoluteFilePathRelativeIfPossible(
base::FilePath("/src/out/Debug"), base::FilePath("/src")));
EXPECT_EQ(base::FilePath("."),
MakeAbsoluteFilePathRelativeIfPossible(base::FilePath("/src"),
base::FilePath("/src")));
EXPECT_EQ(
base::FilePath("../../../u/v/w"),
MakeAbsoluteFilePathRelativeIfPossible(base::FilePath("/a/b/c/x/y/z"),
base::FilePath("/a/b/c/u/v/w")));
#endif
}
TEST(FilesystemUtils, NormalizePath) {
std::string input;
......
......@@ -48,10 +48,15 @@ struct Counts {
};
std::string GetSelfInvocationCommand(const BuildSettings* build_settings) {
base::FilePath executable;
PathService::Get(base::FILE_EXE, &executable);
const base::FilePath build_path =
build_settings->build_dir().Resolve(build_settings->root_path());
base::CommandLine cmdline(executable.NormalizePathSeparatorsTo('/'));
base::FilePath exe_path;
PathService::Get(base::FILE_EXE, &exe_path);
if (build_path.IsAbsolute())
exe_path = MakeAbsoluteFilePathRelativeIfPossible(build_path, exe_path);
base::CommandLine cmdline(exe_path.NormalizePathSeparatorsTo('/'));
// Use "." for the directory to generate. When Ninja runs the command it
// will have the build directory as the current one. Coding it explicitly
......@@ -59,8 +64,12 @@ std::string GetSelfInvocationCommand(const BuildSettings* build_settings) {
cmdline.AppendArg("gen");
cmdline.AppendArg(".");
base::FilePath root_path = build_settings->root_path();
if (build_path.IsAbsolute())
root_path = MakeAbsoluteFilePathRelativeIfPossible(build_path, root_path);
cmdline.AppendSwitchPath(std::string("--") + switches::kRoot,
build_settings->root_path());
root_path.NormalizePathSeparatorsTo('/'));
// Successful automatic invocations shouldn't print output.
cmdline.AppendSwitch(std::string("-") + switches::kQuiet);
......@@ -267,8 +276,13 @@ void NinjaBuildWriter::WriteNinjaRules() {
std::set<base::FilePath> fileset(input_files.begin(), input_files.end());
fileset.insert(other_files.begin(), other_files.end());
for (const auto& other_file : fileset)
dep_out_ << " " << FilePathToUTF8(other_file);
const base::FilePath build_path =
build_settings_->build_dir().Resolve(build_settings_->root_path());
for (const auto& other_file : fileset) {
const base::FilePath file =
MakeAbsoluteFilePathRelativeIfPossible(build_path, other_file);
dep_out_ << " " << FilePathToUTF8(file.NormalizePathSeparatorsTo('/'));
}
out_ << std::endl;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment