jackoalan updated this revision to Diff 396055.
jackoalan added a comment.
Make expansion token a parameter of `ExpandResponseFiles` and limit use to
`readConfigFile`. Elaborate manual entry further and add entry to release notes.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D115604/new/
https://reviews.llvm.org/D115604
Files:
clang/docs/ReleaseNotes.rst
clang/docs/UsersManual.rst
llvm/include/llvm/Support/CommandLine.h
llvm/lib/Support/CommandLine.cpp
llvm/unittests/Support/CommandLineTest.cpp
Index: llvm/unittests/Support/CommandLineTest.cpp
===================================================================
--- llvm/unittests/Support/CommandLineTest.cpp
+++ llvm/unittests/Support/CommandLineTest.cpp
@@ -1038,25 +1038,34 @@
llvm::SmallVector<const char *, 1> Argv;
TempDir TestDir("unittest", /*Unique*/ true);
+ TempDir TestSubDir(TestDir.path("subdir"), /*Unique*/ false);
- llvm::SmallString<128> TestCfg;
- llvm::sys::path::append(TestCfg, TestDir.path(), "foo");
-
+ llvm::SmallString<128> TestCfg = TestDir.path("foo");
TempFile ConfigFile(TestCfg, "",
"# Comment\n"
"-option_1\n"
+ "-option_2=<CONFIG>/dir1\n"
"@subconfig\n"
- "-option_3=abcd\n"
- "-option_4=\\\n"
+ "-option_7=abcd\n"
+ "-option_8=\\\n"
"cdef\n");
- llvm::SmallString<128> TestCfg2;
- llvm::sys::path::append(TestCfg2, TestDir.path(), "subconfig");
+ llvm::SmallString<128> TestCfg2 = TestDir.path("subconfig");
TempFile ConfigFile2(TestCfg2, "",
- "-option_2\n"
+ "-option_3\n"
+ "-option_4=<CONFIG>/dir2\n"
+ "@subdir/subfoo\n"
"\n"
" # comment\n");
+ llvm::SmallString<128> TestCfg3 = TestSubDir.path("subfoo");
+ TempFile ConfigFile3(TestCfg3, "",
+ "-option_5=<CONFIG>/dir3\n"
+ "@<CONFIG>/subfoo2\n");
+
+ llvm::SmallString<128> TestCfg4 = TestSubDir.path("subfoo2");
+ TempFile ConfigFile4(TestCfg4, "", "-option_6=qwerty\n");
+
// Make sure the current directory is not the directory where config files
// resides. In this case the code that expands response files will not find
// 'subconfig' unless it resolves nested inclusions relative to the including
@@ -1071,11 +1080,18 @@
bool Result = llvm::cl::readConfigFile(ConfigFile.path(), Saver, Argv);
EXPECT_TRUE(Result);
- EXPECT_EQ(Argv.size(), 4U);
+ EXPECT_EQ(Argv.size(), 8U);
EXPECT_STREQ(Argv[0], "-option_1");
- EXPECT_STREQ(Argv[1], "-option_2");
- EXPECT_STREQ(Argv[2], "-option_3=abcd");
- EXPECT_STREQ(Argv[3], "-option_4=cdef");
+ EXPECT_STREQ(Argv[1],
+ ("-option_2=" + TestDir.path() + "/dir1").str().c_str());
+ EXPECT_STREQ(Argv[2], "-option_3");
+ EXPECT_STREQ(Argv[3],
+ ("-option_4=" + TestDir.path() + "/dir2").str().c_str());
+ EXPECT_STREQ(Argv[4],
+ ("-option_5=" + TestSubDir.path() + "/dir3").str().c_str());
+ EXPECT_STREQ(Argv[5], "-option_6=qwerty");
+ EXPECT_STREQ(Argv[6], "-option_7=abcd");
+ EXPECT_STREQ(Argv[7], "-option_8=cdef");
}
TEST(CommandLineTest, PositionalEatArgsError) {
Index: llvm/lib/Support/CommandLine.cpp
===================================================================
--- llvm/lib/Support/CommandLine.cpp
+++ llvm/lib/Support/CommandLine.cpp
@@ -1078,11 +1078,44 @@
return (S.size() >= 3 && S[0] == '\xef' && S[1] == '\xbb' && S[2] == '\xbf');
}
+// Substitute token with the file's base path.
+static void ExpandBasePaths(StringRef BasePath, StringRef Token,
+ StringSaver &Saver, const char *&Arg) {
+ assert(sys::path::is_absolute(BasePath));
+ 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,
+ llvm::vfs::FileSystem &FS,
+ StringRef ExpandBasePathToken) {
assert(sys::path::is_absolute(FName));
llvm::ErrorOr<std::unique_ptr<MemoryBuffer>> MemBufOrErr =
FS.getBufferForFile(FName);
@@ -1116,8 +1149,15 @@
// file, replace the included response file names with their full paths
// obtained by required resolution.
for (auto &Arg : NewArgv) {
+ if (!Arg)
+ continue;
+
+ // Substitute token with the file's base path.
+ if (!ExpandBasePathToken.empty())
+ ExpandBasePaths(BasePath, ExpandBasePathToken, Saver, Arg);
+
// Skip non-rsp file arguments.
- if (!Arg || Arg[0] != '@')
+ if (Arg[0] != '@')
continue;
StringRef FileName(Arg + 1);
@@ -1129,7 +1169,7 @@
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();
}
@@ -1140,7 +1180,8 @@
SmallVectorImpl<const char *> &Argv, bool MarkEOLs,
bool RelativeNames,
llvm::Optional<llvm::StringRef> CurrentDir,
- llvm::vfs::FileSystem &FS) {
+ llvm::vfs::FileSystem &FS,
+ StringRef ExpandBasePathToken) {
bool AllExpanded = true;
struct ResponseFileRecord {
std::string File;
@@ -1218,7 +1259,7 @@
SmallVector<const char *, 0> ExpandedArgv;
if (llvm::Error Err =
ExpandResponseFile(FName, Saver, Tokenizer, ExpandedArgv, MarkEOLs,
- RelativeNames, FS)) {
+ RelativeNames, FS, ExpandBasePathToken)) {
// 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.
@@ -1251,10 +1292,11 @@
bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
SmallVectorImpl<const char *> &Argv, bool MarkEOLs,
bool RelativeNames,
- llvm::Optional<StringRef> CurrentDir) {
+ llvm::Optional<StringRef> CurrentDir,
+ StringRef ExpandBasePathToken) {
return ExpandResponseFiles(Saver, std::move(Tokenizer), Argv, MarkEOLs,
RelativeNames, std::move(CurrentDir),
- *vfs::getRealFileSystem());
+ *vfs::getRealFileSystem(), ExpandBasePathToken);
}
bool cl::expandResponseFiles(int Argc, const char *const *Argv,
@@ -1281,16 +1323,18 @@
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())) {
+ constexpr StringLiteral ExpandBasePathToken("<CONFIG>");
+ if (llvm::Error Err = ExpandResponseFile(
+ CfgFile, Saver, cl::tokenizeConfigFile, Argv,
+ /*MarkEOLs=*/false, /*RelativeNames=*/true,
+ *llvm::vfs::getRealFileSystem(), ExpandBasePathToken)) {
// 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,
+ llvm::None, ExpandBasePathToken);
}
static void initCommonOptions();
Index: llvm/include/llvm/Support/CommandLine.h
===================================================================
--- llvm/include/llvm/Support/CommandLine.h
+++ llvm/include/llvm/Support/CommandLine.h
@@ -2103,12 +2103,15 @@
/// \param [in] FS File system used for all file access when running the tool.
/// \param [in] CurrentDir Path used to resolve relative rsp files. If set to
/// None, process' cwd is used instead.
+/// \param [in] ExpandBasePathToken If not empty, token which expands to the
+/// base path of the current response file.
/// \return true if all @files were expanded successfully or there were none.
bool ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
SmallVectorImpl<const char *> &Argv, bool MarkEOLs,
bool RelativeNames,
llvm::Optional<llvm::StringRef> CurrentDir,
- llvm::vfs::FileSystem &FS);
+ llvm::vfs::FileSystem &FS,
+ StringRef ExpandBasePathToken = {});
/// An overload of ExpandResponseFiles() that uses
/// llvm::vfs::getRealFileSystem().
@@ -2116,7 +2119,8 @@
StringSaver &Saver, TokenizerCallback Tokenizer,
SmallVectorImpl<const char *> &Argv, bool MarkEOLs = false,
bool RelativeNames = false,
- llvm::Optional<llvm::StringRef> CurrentDir = llvm::None);
+ llvm::Optional<llvm::StringRef> CurrentDir = llvm::None,
+ StringRef ExpandBasePathToken = {});
/// A convenience helper which concatenates the options specified by the
/// environment variable EnvVar and command line options, then expands response
Index: clang/docs/UsersManual.rst
===================================================================
--- clang/docs/UsersManual.rst
+++ clang/docs/UsersManual.rst
@@ -843,6 +843,8 @@
option tells Clang to put double-quotes around the entire filename, which
is the convention used by NMake and Jom.
+.. _configuration-files:
+
Configuration files
-------------------
@@ -917,6 +919,22 @@
`~/.llvm/target.cfg` contains the directive `@os/linux.opts`, the file
`linux.opts` is searched for in the directory `~/.llvm/os`.
+To generate paths relative to the configuration file, the `<CONFIG>` token may
+be used. This will expand to the absolute path of the directory containing the
+configuration file.
+
+A potential `<CONFIG>` use-case may be search paths in a portable (i.e. not
+installed) SDK directory for embedded development. The user may only need to
+specify a root configuration file to establish every aspect of the SDK with the
+compiler:
+
+::
+
+ --target=foo
+ -isystem <CONFIG>/include
+ -L <CONFIG>/lib
+ -T <CONFIG>/ldscripts/link.ld
+
Language and Target-Independent Features
========================================
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -63,6 +63,9 @@
- Maximum _ExtInt size was decreased from 16,777,215 bits to 8,388,608 bits.
Motivation for this was discussed in PR51829.
+- Configuration file syntax extended with ``<CONFIG>`` token. This expands to
+ the base path of the current config file. See :ref:`configuration-files` for
+ details.
New Compiler Flags
------------------
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits