Просмотр исходного кода

Build archives with only the basename as the name of members. (#6546)

This both better matches the behavior of `ar`, and avoids the full path
being long and in many cases containing unstable path components.
Chandler Carruth 4 месяцев назад
Родитель
Сommit
90e2359eee
2 измененных файлов с 51 добавлено и 0 удалено
  1. 7 0
      toolchain/driver/clang_runtimes.cpp
  2. 44 0
      toolchain/driver/clang_runtimes_test.cpp

+ 7 - 0
toolchain/driver/clang_runtimes.cpp

@@ -32,6 +32,7 @@
 #include "llvm/Support/Error.h"
 #include "llvm/Support/FormatAdapters.h"
 #include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/Path.h"
 #include "llvm/Support/ThreadPool.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/TargetParser/Host.h"
@@ -208,6 +209,12 @@ auto ClangRuntimesBuilderBase::ArchiveBuilder::CompileMember(
                                llvm::fmt_consume(obj_result.takeError())));
   }
 
+  // Only use the basename as the member name to match the behavior of `ar`. We
+  // also specifically use the LLVM path function rather than the standard
+  // library as it allows us to get the filename within the member-owned
+  // filename storage.
+  obj_result->MemberName = llvm::sys::path::filename(obj_result->MemberName);
+
   // Unlink the object file once we've read it -- we only want to retain the
   // copy inside the archive member and there's no advantage to using
   // thin-archives or something else that leaves the object file in place.

+ 44 - 0
toolchain/driver/clang_runtimes_test.cpp

@@ -33,6 +33,7 @@
 namespace Carbon {
 namespace {
 
+using ::testing::Each;
 using ::testing::Eq;
 using ::testing::HasSubstr;
 using ::testing::IsSupersetOf;
@@ -61,6 +62,12 @@ MATCHER_P(TextSymbolNamed, name_matcher, "") {
   return true;
 }
 
+// NOLINTNEXTLINE(modernize-use-trailing-return-type): Macro based function.
+MATCHER(IsBasename, "") {
+  std::filesystem::path path = arg;
+  return path == path.filename();
+}
+
 class ClangRuntimesTest : public ::testing::Test {
  public:
   // Helper to get the `llvm-nm` listing of defined symbols for an archive.
@@ -93,6 +100,28 @@ class ClangRuntimesTest : public ::testing::Test {
     EXPECT_THAT(nm_list, HasSubstr(symbol_substr));
   }
 
+  // Helper to get the names of archive members.
+  auto ListArchiveMemberNames(const std::filesystem::path& archive_path)
+      -> llvm::SmallVector<std::string> {
+    llvm::SmallVector<std::string> result;
+
+    auto archive_buffer_result =
+        llvm::MemoryBuffer::getFile(archive_path.native());
+    CARBON_CHECK(!archive_buffer_result.getError(), "Unable to open {0}: {1}",
+                 archive_path, archive_buffer_result.getError().message());
+    auto archive = llvm::cantFail(llvm::object::Archive::create(
+        archive_buffer_result.get()->getMemBufferRef()));
+
+    llvm::Error error = llvm::Error::success();
+    for (const auto& child : archive->children(error)) {
+      result.push_back(child.getName()->str());
+    }
+    CARBON_CHECK(!error, "Error reading members of archive {0}: {1}",
+                 archive_path, error);
+
+    return result;
+  }
+
   InstallPaths install_paths_ =
       InstallPaths::MakeForBazelRunfiles(Testing::GetExePath());
   llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs_ =
@@ -177,6 +206,11 @@ TEST_F(ClangRuntimesTest, ResourceDir) {
   if (!target_triple_.isOSWindows()) {
     EXPECT_THAT(builtins_symbols, Not(HasSubstr("chkstk")));
   }
+
+  // Check that member names don't contain full paths, as that is the
+  // canonical format produced by `ar`.
+  auto member_names = ListArchiveMemberNames(builtins_path);
+  EXPECT_THAT(member_names, Each(IsBasename()));
 }
 
 TEST_F(ClangRuntimesTest, Libunwind) {
@@ -196,6 +230,11 @@ TEST_F(ClangRuntimesTest, Libunwind) {
   ExpectSymbol(libunwind_symbols, "_Unwind_Backtrace");
   ExpectSymbol(libunwind_symbols, "__unw_getcontext");
   ExpectSymbol(libunwind_symbols, "__unw_get_proc_info");
+
+  // Check that member names don't contain full paths, as that is the
+  // canonical format produced by `ar`.
+  auto member_names = ListArchiveMemberNames(libunwind_path);
+  EXPECT_THAT(member_names, Each(IsBasename()));
 }
 
 TEST_F(ClangRuntimesTest, Libcxx) {
@@ -232,6 +271,11 @@ TEST_F(ClangRuntimesTest, Libcxx) {
   ExpectSymbol(libcxx_symbols, "__cxa_demangle");
   ExpectSymbol(libcxx_symbols, "__cxa_get_globals");
   ExpectSymbol(libcxx_symbols, "_ZSt9terminatev");
+
+  // Check that member names don't contain full paths, as that is the
+  // canonical format produced by `ar`.
+  auto member_names = ListArchiveMemberNames(libcxx_path);
+  EXPECT_THAT(member_names, Each(IsBasename()));
 }
 
 }  // namespace