jackoalan updated this revision to Diff 393781.
jackoalan added a comment.

Fix ResponseFiles test for Windows.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D115604/new/

https://reviews.llvm.org/D115604

Files:
  clang/docs/UsersManual.rst
  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
@@ -784,9 +784,9 @@
 TEST(CommandLineTest, ResponseFiles) {
   vfs::InMemoryFileSystem FS;
 #ifdef _WIN32
-  const char *TestRoot = "C:\\";
+  StringRef TestRoot = "C:\\";
 #else
-  const char *TestRoot = "/";
+  StringRef TestRoot = "/";
 #endif
   FS.setCurrentWorkingDirectory(TestRoot);
 
@@ -796,8 +796,10 @@
              llvm::MemoryBuffer::getMemBuffer("-option_1 -option_2\n"
                                               "@incdir/resp2\n"
                                               "-option_3=abcd\n"
-                                              "@incdir/resp3\n"
-                                              "-option_4=efjk\n"));
+                                              "@<@>/incdir/resp3\n"
+                                              "-option_4=efjk\n"
+                                              "-option_5=<@>\n"
+                                              "-option_6=<@>/sub\n"));
 
   // Directory for included file.
   llvm::StringRef IncDir = "incdir";
@@ -807,14 +809,16 @@
   llvm::sys::path::append(IncludedFileName2, IncDir, "resp2");
   FS.addFile(IncludedFileName2, 0,
              MemoryBuffer::getMemBuffer("-option_21 -option_22\n"
-                                        "-option_23=abcd\n"));
+                                        "-option_23=abcd\n"
+                                        "-option_24=<@>\n"));
 
   // Create second included response file of second level.
   llvm::SmallString<128> IncludedFileName3;
   llvm::sys::path::append(IncludedFileName3, IncDir, "resp3");
   FS.addFile(IncludedFileName3, 0,
              MemoryBuffer::getMemBuffer("-option_31 -option_32\n"
-                                        "-option_33=abcd\n"));
+                                        "-option_33=abcd\n"
+                                        "-option_34=<@>\n"));
 
   // Prepare 'file' with reference to response file.
   SmallString<128> IncRef;
@@ -828,13 +832,21 @@
   llvm::StringSaver Saver(A);
   ASSERT_TRUE(llvm::cl::ExpandResponseFiles(
       Saver, llvm::cl::TokenizeGNUCommandLine, Argv, false, true,
-      /*CurrentDir=*/StringRef(TestRoot), FS));
-  EXPECT_THAT(Argv, testing::Pointwise(
-                        StringEquality(),
-                        {"test/test", "-flag_1", "-option_1", "-option_2",
-                         "-option_21", "-option_22", "-option_23=abcd",
-                         "-option_3=abcd", "-option_31", "-option_32",
-                         "-option_33=abcd", "-option_4=efjk", "-flag_2"}));
+      /*CurrentDir=*/TestRoot, FS));
+
+  std::string ExpectedOption24 = ("-option_24=" + TestRoot + "incdir").str();
+  std::string ExpectedOption34 = ("-option_34=" + TestRoot + "incdir").str();
+  std::string ExpectedOption5 = ("-option_5=" + TestRoot).str();
+  std::string ExpectedOption6 = ("-option_6=" + TestRoot + "sub").str();
+
+  EXPECT_THAT(
+      Argv, testing::Pointwise(
+                StringEquality(),
+                {"test/test", "-flag_1", "-option_1", "-option_2", "-option_21",
+                 "-option_22", "-option_23=abcd", ExpectedOption24.c_str(),
+                 "-option_3=abcd", "-option_31", "-option_32",
+                 "-option_33=abcd", ExpectedOption34.c_str(), "-option_4=efjk",
+                 ExpectedOption5.c_str(), ExpectedOption6.c_str(), "-flag_2"}));
 }
 
 TEST(CommandLineTest, RecursiveResponseFiles) {
@@ -1045,15 +1057,17 @@
   TempFile ConfigFile(TestCfg, "",
                       "# Comment\n"
                       "-option_1\n"
+                      "-option_2=<@>/dir1\n"
                       "@subconfig\n"
-                      "-option_3=abcd\n"
-                      "-option_4=\\\n"
+                      "-option_5=abcd\n"
+                      "-option_6=\\\n"
                       "cdef\n");
 
   llvm::SmallString<128> TestCfg2;
   llvm::sys::path::append(TestCfg2, TestDir.path(), "subconfig");
   TempFile ConfigFile2(TestCfg2, "",
-                       "-option_2\n"
+                       "-option_3\n"
+                       "-option_4=<@>/dir2\n"
                        "\n"
                        "   # comment\n");
 
@@ -1071,11 +1085,15 @@
   bool Result = llvm::cl::readConfigFile(ConfigFile.path(), Saver, Argv);
 
   EXPECT_TRUE(Result);
-  EXPECT_EQ(Argv.size(), 4U);
+  EXPECT_EQ(Argv.size(), 6U);
   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=abcd");
+  EXPECT_STREQ(Argv[5], "-option_6=cdef");
 }
 
 TEST(CommandLineTest, PositionalEatArgsError) {
Index: llvm/lib/Support/CommandLine.cpp
===================================================================
--- llvm/lib/Support/CommandLine.cpp
+++ llvm/lib/Support/CommandLine.cpp
@@ -1078,6 +1078,38 @@
   return (S.size() >= 3 && S[0] == '\xef' && S[1] == '\xbb' && S[2] == '\xbf');
 }
 
+// Substitute <@> with the response file base path.
+static void ExpandResponseDirTokens(StringRef BasePath, StringSaver &Saver,
+                                    const char *&Arg) {
+  assert(sys::path::is_absolute(BasePath));
+  constexpr StringLiteral Token("<@>");
+  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)) {
+    // Although it typically does not make sense to use <@> more than once per
+    // arg, support it 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 <@> 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,
@@ -1116,8 +1148,14 @@
   // file, replace the included response file names with their full paths
   // obtained by required resolution.
   for (auto &Arg : NewArgv) {
+    if (!Arg)
+      continue;
+
+    // Substitute <@> with the response file base path.
+    ExpandResponseDirTokens(BasePath, Saver, Arg);
+
     // Skip non-rsp file arguments.
-    if (!Arg || Arg[0] != '@')
+    if (Arg[0] != '@')
       continue;
 
     StringRef FileName(Arg + 1);
@@ -1129,7 +1167,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();
 }
Index: clang/docs/UsersManual.rst
===================================================================
--- clang/docs/UsersManual.rst
+++ clang/docs/UsersManual.rst
@@ -917,6 +917,18 @@
 `~/.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 `<@>` token may be
+used. This will expand to the absolute path of the directory containing the
+configuration file. A typical use-case may be a portable, potentially
+not-installed cross-compilation SDK directory:
+
+::
+
+    --target=sample
+    -isystem <@>/include
+    -L <@>/lib
+    -T <@>/ldscripts/link.ld
+
 Language and Target-Independent Features
 ========================================
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to