[clang] support relative roots to vfs overlays

This diff adds support for relative roots to VFS overlays. The directory root
will be made absolute from the current working directory and will be used to
determine the path style to use. This supports the use of VFS overlays with
remote build systems that might use a different working directory for each
compilation.

Reviewed By: benlangmuir

Differential Revision: https://reviews.llvm.org/D116174
This commit is contained in:
Richard Howell 2022-01-19 10:12:32 -08:00 committed by Ellis Hoag
parent 88d81770f1
commit 4f61749e16
5 changed files with 60 additions and 8 deletions

View File

@ -0,0 +1,17 @@
{
'version': 0,
'fallthrough': true,
'overlay-relative': true,
'roots': [
{ 'name': 'virtual',
'type': 'directory',
'contents': [
{
'external-contents': 'actual_header.h',
'type': 'file',
'name': 'virtual_header.h',
}
]
}
]
}

View File

@ -0,0 +1,3 @@
// RUN: %clang_cc1 -Werror -ivfsoverlay %S/Inputs/vfsoverlay-root-relative.yaml -I virtual -fsyntax-only %s
#include "virtual_header.h"

View File

@ -547,6 +547,9 @@ class RedirectingFileSystemParser;
/// }
/// \endverbatim
///
/// The roots may be absolute or relative. If relative they will be made
/// absolute against the current working directory.
///
/// All configuration options are optional.
/// 'case-sensitive': <boolean, default=(true for Posix, false for Windows)>
/// 'use-external-names': <boolean, default=true>

View File

@ -1649,10 +1649,19 @@ private:
sys::path::Style::windows_backslash)) {
path_style = sys::path::Style::windows_backslash;
} else {
assert(NameValueNode && "Name presence should be checked earlier");
error(NameValueNode,
// Relative VFS root entries are made absolute to the current working
// directory, then we can determine the path style from that.
auto EC = sys::fs::make_absolute(Name);
if (EC) {
assert(NameValueNode && "Name presence should be checked earlier");
error(
NameValueNode,
"entry with relative path at the root level is not discoverable");
return nullptr;
return nullptr;
}
path_style = sys::path::is_absolute(Name, sys::path::Style::posix)
? sys::path::Style::posix
: sys::path::Style::windows_backslash;
}
}

View File

@ -2164,6 +2164,11 @@ TEST_F(VFSFromYAMLTest, RecursiveDirectoryIterationLevel) {
TEST_F(VFSFromYAMLTest, RelativePaths) {
IntrusiveRefCntPtr<DummyFileSystem> Lower(new DummyFileSystem());
std::error_code EC;
SmallString<128> CWD;
EC = llvm::sys::fs::current_path(CWD);
ASSERT_FALSE(EC);
// Filename at root level without a parent directory.
IntrusiveRefCntPtr<vfs::FileSystem> FS = getFromYAMLString(
"{ 'roots': [\n"
@ -2172,16 +2177,26 @@ TEST_F(VFSFromYAMLTest, RelativePaths) {
" }\n"
"] }",
Lower);
EXPECT_EQ(nullptr, FS.get());
ASSERT_TRUE(FS.get() != nullptr);
SmallString<128> ExpectedPathNotInDir("file-not-in-directory.h");
llvm::sys::fs::make_absolute(ExpectedPathNotInDir);
checkContents(FS->dir_begin(CWD, EC), {ExpectedPathNotInDir});
// Relative file path.
FS = getFromYAMLString("{ 'roots': [\n"
" { 'type': 'file', 'name': 'relative/file/path.h',\n"
" { 'type': 'file', 'name': 'relative/path.h',\n"
" 'external-contents': '//root/external/file'\n"
" }\n"
"] }",
Lower);
EXPECT_EQ(nullptr, FS.get());
ASSERT_TRUE(FS.get() != nullptr);
SmallString<128> Parent("relative");
llvm::sys::fs::make_absolute(Parent);
auto I = FS->dir_begin(Parent, EC);
ASSERT_FALSE(EC);
// Convert to POSIX path for comparison of windows paths
ASSERT_EQ("relative/path.h",
getPosixPath(std::string(I->path().substr(CWD.size() + 1))));
// Relative directory path.
FS = getFromYAMLString(
@ -2191,9 +2206,14 @@ TEST_F(VFSFromYAMLTest, RelativePaths) {
" }\n"
"] }",
Lower);
EXPECT_EQ(nullptr, FS.get());
ASSERT_TRUE(FS.get() != nullptr);
SmallString<128> Root("relative/directory");
llvm::sys::fs::make_absolute(Root);
I = FS->dir_begin(Root, EC);
ASSERT_FALSE(EC);
ASSERT_EQ("path.h", std::string(I->path().substr(Root.size() + 1)));
EXPECT_EQ(3, NumDiagnostics);
EXPECT_EQ(0, NumDiagnostics);
}
TEST_F(VFSFromYAMLTest, NonFallthroughDirectoryIteration) {