]> granicus.if.org Git - llvm/commitdiff
[llvm-ar] Make llvm-lib behave more like the MSVC archiver
authorReid Kleckner <rnk@google.com>
Mon, 12 Jun 2017 19:45:35 +0000 (19:45 +0000)
committerReid Kleckner <rnk@google.com>
Mon, 12 Jun 2017 19:45:35 +0000 (19:45 +0000)
Summary:
Use the filepath used to open the archive member as the archive member
name instead of the file basename. This path might be absolute or
relative.  This is important because the archive member name will show
up in the PDB, and we want our PDBs to look as much like MSVC's as
possible.

This also helps avoid an issue in our PDB module descriptor writing
code, which assumes that all module names are unique. Relative paths
still aren't guaranteed to be unique, but they're much better than
basenames, which definitely aren't unique.

Reviewers: ruiu, zturner

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D33575

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305223 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Object/ArchiveWriter.h
lib/Object/ArchiveWriter.cpp
test/LibDriver/use-paths.test [new file with mode: 0644]
tools/llvm-ar/llvm-ar.cpp

index 3e84a5814d796403b247c41b1e15f499940ddcf2..1ed758d40df2e4d38e989511e04e8860faae11db 100644 (file)
@@ -22,6 +22,7 @@ namespace llvm {
 
 struct NewArchiveMember {
   std::unique_ptr<MemoryBuffer> Buf;
+  StringRef MemberName;
   sys::TimePoint<std::chrono::seconds> ModTime;
   unsigned UID = 0, GID = 0, Perms = 0644;
 
index e1c35ed6a6a0c08326306f47fa2fdf115242529d..4034f9039ddaab728684c73246e4103431876c19 100644 (file)
@@ -36,7 +36,8 @@
 using namespace llvm;
 
 NewArchiveMember::NewArchiveMember(MemoryBufferRef BufRef)
-    : Buf(MemoryBuffer::getMemBuffer(BufRef, false)) {}
+    : Buf(MemoryBuffer::getMemBuffer(BufRef, false)),
+      MemberName(BufRef.getBufferIdentifier()) {}
 
 Expected<NewArchiveMember>
 NewArchiveMember::getOldMember(const object::Archive::Child &OldMember,
@@ -48,6 +49,7 @@ NewArchiveMember::getOldMember(const object::Archive::Child &OldMember,
   NewArchiveMember M;
   assert(M.IsNew == false);
   M.Buf = MemoryBuffer::getMemBuffer(*BufOrErr, false);
+  M.MemberName = M.Buf->getBufferIdentifier();
   if (!Deterministic) {
     auto ModTimeOrErr = OldMember.getLastModified();
     if (!ModTimeOrErr)
@@ -97,6 +99,7 @@ Expected<NewArchiveMember> NewArchiveMember::getFile(StringRef FileName,
   NewArchiveMember M;
   M.IsNew = true;
   M.Buf = std::move(*MemberBufferOrErr);
+  M.MemberName = M.Buf->getBufferIdentifier();
   if (!Deterministic) {
     M.ModTime = std::chrono::time_point_cast<std::chrono::seconds>(
         Status.getLastModificationTime());
@@ -185,7 +188,7 @@ printBSDMemberHeader(raw_fd_ostream &Out, StringRef Name,
 }
 
 static bool useStringTable(bool Thin, StringRef Name) {
-  return Thin || Name.size() >= 16;
+  return Thin || Name.size() >= 16 || Name.contains('/');
 }
 
 static void
@@ -239,7 +242,7 @@ static void writeStringTable(raw_fd_ostream &Out, StringRef ArcName,
   unsigned StartOffset = 0;
   for (const NewArchiveMember &M : Members) {
     StringRef Path = M.Buf->getBufferIdentifier();
-    StringRef Name = sys::path::filename(Path);
+    StringRef Name = M.MemberName;
     if (!useStringTable(Thin, Name))
       continue;
     if (StartOffset == 0) {
@@ -423,9 +426,8 @@ llvm::writeArchive(StringRef ArcName,
     if (Kind == object::Archive::K_DARWIN)
       Padding = OffsetToAlignment(M.Buf->getBufferSize(), 8);
 
-    printMemberHeader(Out, Kind, Thin,
-                      sys::path::filename(M.Buf->getBufferIdentifier()),
-                      StringMapIndexIter, M.ModTime, M.UID, M.GID, M.Perms,
+    printMemberHeader(Out, Kind, Thin, M.MemberName, StringMapIndexIter,
+                      M.ModTime, M.UID, M.GID, M.Perms,
                       M.Buf->getBufferSize() + Padding);
 
     if (!Thin)
diff --git a/test/LibDriver/use-paths.test b/test/LibDriver/use-paths.test
new file mode 100644 (file)
index 0000000..971c216
--- /dev/null
@@ -0,0 +1,24 @@
+llvm-lib should behave like "link.exe /lib" and use relative paths to describe
+archive members.
+
+First, get in a clean working directory.
+RUN: rm -rf %t && mkdir -p %t && cd %t
+
+Make foo/a.obj and foo/b.obj.
+RUN: mkdir foo
+RUN: llvm-mc -triple=x86_64-pc-windows-msvc -filetype=obj -o foo/a.obj %S/Inputs/a.s
+RUN: llvm-mc -triple=x86_64-pc-windows-msvc -filetype=obj -o foo/b.obj %S/Inputs/b.s
+
+RUN: llvm-lib -out:foo.lib foo/a.obj foo/b.obj
+RUN: llvm-ar t foo.lib | FileCheck %s
+
+FIXME: We should probably use backslashes on Windows to better match MSVC tools.
+CHECK: foo/a.obj
+CHECK: foo/b.obj
+
+Do it again with absolute paths and see that we get something.
+RUN: llvm-lib -out:foo.lib %t/foo/a.obj %t/foo/b.obj
+RUN: llvm-ar t foo.lib | FileCheck %s --check-prefix=ABS
+
+ABS: {{.*}}/foo/a.obj
+ABS: {{.*}}/foo/b.obj
index 074c3ae3c677b7dc6d1afe82e69d7ea868a0f674..500507fd496687b7815e329a622e524fa774449c 100644 (file)
@@ -473,6 +473,10 @@ static void addMember(std::vector<NewArchiveMember> &Members,
   Expected<NewArchiveMember> NMOrErr =
       NewArchiveMember::getFile(FileName, Deterministic);
   failIfError(NMOrErr.takeError(), FileName);
+
+  // Use the basename of the object path for the member name.
+  NMOrErr->MemberName = sys::path::filename(NMOrErr->MemberName);
+
   if (Pos == -1)
     Members.push_back(std::move(*NMOrErr));
   else