aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Support/CommandLine.cpp
diff options
context:
space:
mode:
authorJack Andersen <jackoalan@gmail.com>2021-12-30 13:42:13 -0500
committerJack Andersen <jackoalan@gmail.com>2021-12-30 13:43:47 -0500
commit9d37d0ea34858288faf6351b9bdc0a0b91107c82 (patch)
tree7c5a48bac384bc613e35da027f7d87c427af8452 /llvm/lib/Support/CommandLine.cpp
parent890e8c8f7e9e448a870224068d6b4181d96a293d (diff)
downloadllvm-9d37d0ea34858288faf6351b9bdc0a0b91107c82.zip
llvm-9d37d0ea34858288faf6351b9bdc0a0b91107c82.tar.gz
llvm-9d37d0ea34858288faf6351b9bdc0a0b91107c82.tar.bz2
[Support] Expand `<CFGDIR>` as the base directory in configuration files.
Extends response file expansion to recognize `<CFGDIR>` and expand to the current file's directory. This makes it much easier to author clang config files rooted in portable, potentially not-installed SDK directories. A typical use case may be something like the following: ``` # sample_sdk.cfg --target=sample -isystem <CFGDIR>/include -L <CFGDIR>/lib -T <CFGDIR>/ldscripts/link.ld ``` Reviewed By: sepavloff Differential Revision: https://reviews.llvm.org/D115604
Diffstat (limited to 'llvm/lib/Support/CommandLine.cpp')
-rw-r--r--llvm/lib/Support/CommandLine.cpp74
1 files changed, 58 insertions, 16 deletions
diff --git a/llvm/lib/Support/CommandLine.cpp b/llvm/lib/Support/CommandLine.cpp
index 4153a69..481ba56 100644
--- a/llvm/lib/Support/CommandLine.cpp
+++ b/llvm/lib/Support/CommandLine.cpp
@@ -1078,11 +1078,45 @@ static bool hasUTF8ByteOrderMark(ArrayRef<char> S) {
return (S.size() >= 3 && S[0] == '\xef' && S[1] == '\xbb' && S[2] == '\xbf');
}
+// Substitute <CFGDIR> with the file's base path.
+static void ExpandBasePaths(StringRef BasePath, StringSaver &Saver,
+ const char *&Arg) {
+ assert(sys::path::is_absolute(BasePath));
+ constexpr StringLiteral Token("<CFGDIR>");
+ const StringRef ArgString(Arg);
+
+ SmallString<128> ResponseFile;
+ StringRef::size_type StartPos = 0;
+ for (StringRef::size_type TokenPos = ArgString.find(Token);
+ TokenPos != StringRef::npos;
+ TokenPos = ArgString.find(Token, StartPos)) {
+ // Token may appear more than once per arg (e.g. comma-separated linker
+ // args). Support by using path-append on any subsequent appearances.
+ const StringRef LHS = ArgString.substr(StartPos, TokenPos - StartPos);
+ if (ResponseFile.empty())
+ ResponseFile = LHS;
+ else
+ llvm::sys::path::append(ResponseFile, LHS);
+ ResponseFile.append(BasePath);
+ StartPos = TokenPos + Token.size();
+ }
+
+ if (!ResponseFile.empty()) {
+ // Path-append the remaining arg substring if at least one token appeared.
+ const StringRef Remaining = ArgString.substr(StartPos);
+ if (!Remaining.empty())
+ llvm::sys::path::append(ResponseFile, Remaining);
+ Arg = Saver.save(ResponseFile.str()).data();
+ }
+}
+
// FName must be an absolute path.
-static llvm::Error ExpandResponseFile(
- StringRef FName, StringSaver &Saver, TokenizerCallback Tokenizer,
- SmallVectorImpl<const char *> &NewArgv, bool MarkEOLs, bool RelativeNames,
- llvm::vfs::FileSystem &FS) {
+static llvm::Error ExpandResponseFile(StringRef FName, StringSaver &Saver,
+ TokenizerCallback Tokenizer,
+ SmallVectorImpl<const char *> &NewArgv,
+ bool MarkEOLs, bool RelativeNames,
+ bool ExpandBasePath,
+ llvm::vfs::FileSystem &FS) {
assert(sys::path::is_absolute(FName));
llvm::ErrorOr<std::unique_ptr<MemoryBuffer>> MemBufOrErr =
FS.getBufferForFile(FName);
@@ -1116,8 +1150,15 @@ static llvm::Error ExpandResponseFile(
// file, replace the included response file names with their full paths
// obtained by required resolution.
for (auto &Arg : NewArgv) {
+ if (!Arg)
+ continue;
+
+ // Substitute <CFGDIR> with the file's base path.
+ if (ExpandBasePath)
+ ExpandBasePaths(BasePath, Saver, Arg);
+
// Skip non-rsp file arguments.
- if (!Arg || Arg[0] != '@')
+ if (Arg[0] != '@')
continue;
StringRef FileName(Arg + 1);
@@ -1129,7 +1170,7 @@ static llvm::Error ExpandResponseFile(
ResponseFile.push_back('@');
ResponseFile.append(BasePath);
llvm::sys::path::append(ResponseFile, FileName);
- Arg = Saver.save(ResponseFile.c_str()).data();
+ Arg = Saver.save(ResponseFile.str()).data();
}
return Error::success();
}
@@ -1138,7 +1179,7 @@ static llvm::Error ExpandResponseFile(
/// StringSaver and tokenization strategy.
bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
SmallVectorImpl<const char *> &Argv, bool MarkEOLs,
- bool RelativeNames,
+ bool RelativeNames, bool ExpandBasePath,
llvm::Optional<llvm::StringRef> CurrentDir,
llvm::vfs::FileSystem &FS) {
bool AllExpanded = true;
@@ -1218,7 +1259,7 @@ bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
SmallVector<const char *, 0> ExpandedArgv;
if (llvm::Error Err =
ExpandResponseFile(FName, Saver, Tokenizer, ExpandedArgv, MarkEOLs,
- RelativeNames, FS)) {
+ RelativeNames, ExpandBasePath, 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.
@@ -1250,11 +1291,11 @@ bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
SmallVectorImpl<const char *> &Argv, bool MarkEOLs,
- bool RelativeNames,
+ bool RelativeNames, bool ExpandBasePath,
llvm::Optional<StringRef> CurrentDir) {
return ExpandResponseFiles(Saver, std::move(Tokenizer), Argv, MarkEOLs,
- RelativeNames, std::move(CurrentDir),
- *vfs::getRealFileSystem());
+ RelativeNames, ExpandBasePath,
+ std::move(CurrentDir), *vfs::getRealFileSystem());
}
bool cl::expandResponseFiles(int Argc, const char *const *Argv,
@@ -1281,16 +1322,17 @@ bool cl::readConfigFile(StringRef CfgFile, StringSaver &Saver,
llvm::sys::path::append(AbsPath, CfgFile);
CfgFile = AbsPath.str();
}
- if (llvm::Error Err =
- ExpandResponseFile(CfgFile, Saver, cl::tokenizeConfigFile, Argv,
- /*MarkEOLs=*/false, /*RelativeNames=*/true,
- *llvm::vfs::getRealFileSystem())) {
+ if (llvm::Error Err = ExpandResponseFile(
+ CfgFile, Saver, cl::tokenizeConfigFile, Argv,
+ /*MarkEOLs=*/false, /*RelativeNames=*/true, /*ExpandBasePath=*/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);
+ /*MarkEOLs=*/false, /*RelativeNames=*/true,
+ /*ExpandBasePath=*/true, llvm::None);
}
static void initCommonOptions();