[Support] add vfs support for ExpandResponseFiles

Summary: add vfs support for `ExpandResponseFiles`.

Patch By: liu hui(@lh123)

Reviewers: kadircet, espindola, alexshap, rupprecht, jhenderson

Reviewed By: kadircet

Subscribers: mgorny, sammccall, merge_guards_bot, emaste, sbc100, arichardson, hiraditya, aheejin, jakehehrlich, MaskRay, rupprecht, seiya, cfe-commits, llvm-commits

Tags: #clang, #llvm

Differential Revision: https://reviews.llvm.org/D70769
This commit is contained in:
Kadir Cetinkaya 2019-11-29 12:14:24 +01:00
parent 689c114863
commit 3ee277b86b
No known key found for this signature in database
GPG Key ID: E39E36B8D2057ED6
2 changed files with 50 additions and 21 deletions

View File

@ -29,6 +29,7 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <climits>
@ -1964,10 +1965,13 @@ bool readConfigFile(StringRef CfgFileName, StringSaver &Saver,
/// with nullptrs in the Argv vector.
/// \param [in] RelativeNames true if names of nested response files must be
/// resolved relative to including file.
/// \param [in] FS File system used for all file access when running the tool.
/// \return true if all @files were expanded successfully or there were none.
bool ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
SmallVectorImpl<const char *> &Argv,
bool MarkEOLs = false, bool RelativeNames = false);
bool ExpandResponseFiles(
StringSaver &Saver, TokenizerCallback Tokenizer,
SmallVectorImpl<const char *> &Argv, bool MarkEOLs = false,
bool RelativeNames = false,
llvm::vfs::FileSystem &FS = *llvm::vfs::getRealFileSystem());
/// Mark all options not part of this category as cl::ReallyHidden.
///

View File

@ -29,6 +29,7 @@
#include "llvm/Config/config.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
@ -37,6 +38,7 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/StringSaver.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdlib>
#include <map>
@ -1043,14 +1045,18 @@ static bool hasUTF8ByteOrderMark(ArrayRef<char> S) {
return (S.size() >= 3 && S[0] == '\xef' && S[1] == '\xbb' && S[2] == '\xbf');
}
static bool ExpandResponseFile(StringRef FName, StringSaver &Saver,
static llvm::Error ExpandResponseFile(StringRef FName, StringSaver &Saver,
TokenizerCallback Tokenizer,
SmallVectorImpl<const char *> &NewArgv,
bool MarkEOLs, bool RelativeNames) {
ErrorOr<std::unique_ptr<MemoryBuffer>> MemBufOrErr =
MemoryBuffer::getFile(FName);
bool MarkEOLs, bool RelativeNames,
llvm::vfs::FileSystem &FS) {
llvm::ErrorOr<std::string> CurrDirOrErr = FS.getCurrentWorkingDirectory();
if (!CurrDirOrErr)
return llvm::errorCodeToError(CurrDirOrErr.getError());
llvm::ErrorOr<std::unique_ptr<MemoryBuffer>> MemBufOrErr =
FS.getBufferForFile(FName);
if (!MemBufOrErr)
return false;
return llvm::errorCodeToError(MemBufOrErr.getError());
MemoryBuffer &MemBuf = *MemBufOrErr.get();
StringRef Str(MemBuf.getBufferStart(), MemBuf.getBufferSize());
@ -1059,7 +1065,8 @@ static bool ExpandResponseFile(StringRef FName, StringSaver &Saver,
std::string UTF8Buf;
if (hasUTF16ByteOrderMark(BufRef)) {
if (!convertUTF16ToUTF8String(BufRef, UTF8Buf))
return false;
return llvm::createStringError(std::errc::illegal_byte_sequence,
"Could not convert UTF16 to UTF8");
Str = StringRef(UTF8Buf);
}
// If we see UTF-8 BOM sequence at the beginning of a file, we shall remove
@ -1084,9 +1091,7 @@ static bool ExpandResponseFile(StringRef FName, StringSaver &Saver,
SmallString<128> ResponseFile;
ResponseFile.append(1, '@');
if (llvm::sys::path::is_relative(FName)) {
SmallString<128> curr_dir;
llvm::sys::fs::current_path(curr_dir);
ResponseFile.append(curr_dir.str());
ResponseFile.append(CurrDirOrErr.get());
}
llvm::sys::path::append(
ResponseFile, llvm::sys::path::parent_path(FName), FileName);
@ -1095,14 +1100,14 @@ static bool ExpandResponseFile(StringRef FName, StringSaver &Saver,
}
}
return true;
return Error::success();
}
/// Expand response files on a command line recursively using the given
/// StringSaver and tokenization strategy.
bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
SmallVectorImpl<const char *> &Argv,
bool MarkEOLs, bool RelativeNames) {
SmallVectorImpl<const char *> &Argv, bool MarkEOLs,
bool RelativeNames, llvm::vfs::FileSystem &FS) {
bool AllExpanded = true;
struct ResponseFileRecord {
const char *File;
@ -1139,8 +1144,20 @@ bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
}
const char *FName = Arg + 1;
auto IsEquivalent = [FName](const ResponseFileRecord &RFile) {
return sys::fs::equivalent(RFile.File, FName);
auto IsEquivalent = [FName, &FS](const ResponseFileRecord &RFile) {
llvm::ErrorOr<llvm::vfs::Status> LHS = FS.status(FName);
if (!LHS) {
// TODO: The error should be propagated up the stack.
llvm::consumeError(llvm::errorCodeToError(LHS.getError()));
return false;
}
llvm::ErrorOr<llvm::vfs::Status> RHS = FS.status(RFile.File);
if (!RHS) {
// TODO: The error should be propagated up the stack.
llvm::consumeError(llvm::errorCodeToError(RHS.getError()));
return false;
}
return LHS->equivalent(*RHS);
};
// Check for recursive response files.
@ -1155,10 +1172,13 @@ bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
// Replace this response file argument with the tokenization of its
// contents. Nested response files are expanded in subsequent iterations.
SmallVector<const char *, 0> ExpandedArgv;
if (!ExpandResponseFile(FName, Saver, Tokenizer, ExpandedArgv, MarkEOLs,
RelativeNames)) {
if (llvm::Error Err =
ExpandResponseFile(FName, Saver, Tokenizer, ExpandedArgv, MarkEOLs,
RelativeNames, FS)) {
// We couldn't read this file, so we leave it in the argument stream and
// move on.
// TODO: The error should be propagated up the stack.
llvm::consumeError(std::move(Err));
AllExpanded = false;
++I;
continue;
@ -1186,9 +1206,14 @@ bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
bool cl::readConfigFile(StringRef CfgFile, StringSaver &Saver,
SmallVectorImpl<const char *> &Argv) {
if (!ExpandResponseFile(CfgFile, Saver, cl::tokenizeConfigFile, Argv,
/*MarkEOLs*/ false, /*RelativeNames*/ true))
if (llvm::Error Err =
ExpandResponseFile(CfgFile, Saver, cl::tokenizeConfigFile, Argv,
/*MarkEOLs*/ false, /*RelativeNames*/ true,
*llvm::vfs::getRealFileSystem())) {
// TODO: The error should be propagated up the stack.
llvm::consumeError(std::move(Err));
return false;
}
return ExpandResponseFiles(Saver, cl::tokenizeConfigFile, Argv,
/*MarkEOLs*/ false, /*RelativeNames*/ true);
}