[llvm] r351120 - [llvm-ar] Flatten thin archives.

Jordan Rupprecht via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 14 13:11:46 PST 2019


Author: rupprecht
Date: Mon Jan 14 13:11:46 2019
New Revision: 351120

URL: http://llvm.org/viewvc/llvm-project?rev=351120&view=rev
Log:
[llvm-ar] Flatten thin archives.

Summary:
Normal behavior for GNU ar is to flatten thin archives when adding them to another thin archive, i.e. add the members directly instead of nesting the archive.

Some refactoring done as part of this patch to ease things:
 - Consolidate `addMember`/`addLibMember` methods
 - Rename `addMember` to `addChildMember` to make it more visibly different at the call site that an archive child is passed instead of a regular member
 - Pass in a separate vector and splice it back into position instead of passing a vector + optional Pos (which makes expanding libs tricky)

This fixes PR37530 as raised by https://github.com/ClangBuiltLinux/linux/issues/279.

Reviewers: mstorsjo, pcc, ruiu

Reviewed By: mstorsjo

Subscribers: llvm-commits, tpimh, nickdesaulniers

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

Added:
    llvm/trunk/test/tools/llvm-ar/Inputs/a-plus-b.a
    llvm/trunk/test/tools/llvm-ar/Inputs/a.txt
    llvm/trunk/test/tools/llvm-ar/Inputs/b.txt
    llvm/trunk/test/tools/llvm-ar/Inputs/c.txt
    llvm/trunk/test/tools/llvm-ar/Inputs/d.txt
    llvm/trunk/test/tools/llvm-ar/Inputs/nested-thin-archive.a
    llvm/trunk/test/tools/llvm-ar/flatten-thin-archive-recursive.test
    llvm/trunk/test/tools/llvm-ar/flatten-thin-archive.test
Modified:
    llvm/trunk/tools/llvm-ar/llvm-ar.cpp

Added: llvm/trunk/test/tools/llvm-ar/Inputs/a-plus-b.a
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-ar/Inputs/a-plus-b.a?rev=351120&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-ar/Inputs/a-plus-b.a (added)
+++ llvm/trunk/test/tools/llvm-ar/Inputs/a-plus-b.a Mon Jan 14 13:11:46 2019
@@ -0,0 +1,6 @@
+!<thin>
+//                                              14        `
+a.txt/
+b.txt/
+/0              0           0     0     644     11        `
+/7              0           0     0     644     11        `

Added: llvm/trunk/test/tools/llvm-ar/Inputs/a.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-ar/Inputs/a.txt?rev=351120&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-ar/Inputs/a.txt (added)
+++ llvm/trunk/test/tools/llvm-ar/Inputs/a.txt Mon Jan 14 13:11:46 2019
@@ -0,0 +1 @@
+a-contents

Added: llvm/trunk/test/tools/llvm-ar/Inputs/b.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-ar/Inputs/b.txt?rev=351120&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-ar/Inputs/b.txt (added)
+++ llvm/trunk/test/tools/llvm-ar/Inputs/b.txt Mon Jan 14 13:11:46 2019
@@ -0,0 +1 @@
+b-contents

Added: llvm/trunk/test/tools/llvm-ar/Inputs/c.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-ar/Inputs/c.txt?rev=351120&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-ar/Inputs/c.txt (added)
+++ llvm/trunk/test/tools/llvm-ar/Inputs/c.txt Mon Jan 14 13:11:46 2019
@@ -0,0 +1 @@
+c-contents

Added: llvm/trunk/test/tools/llvm-ar/Inputs/d.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-ar/Inputs/d.txt?rev=351120&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-ar/Inputs/d.txt (added)
+++ llvm/trunk/test/tools/llvm-ar/Inputs/d.txt Mon Jan 14 13:11:46 2019
@@ -0,0 +1 @@
+d-contents

Added: llvm/trunk/test/tools/llvm-ar/Inputs/nested-thin-archive.a
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-ar/Inputs/nested-thin-archive.a?rev=351120&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-ar/Inputs/nested-thin-archive.a (added)
+++ llvm/trunk/test/tools/llvm-ar/Inputs/nested-thin-archive.a Mon Jan 14 13:11:46 2019
@@ -0,0 +1,7 @@
+!<thin>
+//                                              20        `
+a-plus-b.a/
+c.txt/
+
+/0              0           0     0     644     202       `
+/12             0           0     0     644     11        `

Added: llvm/trunk/test/tools/llvm-ar/flatten-thin-archive-recursive.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-ar/flatten-thin-archive-recursive.test?rev=351120&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-ar/flatten-thin-archive-recursive.test (added)
+++ llvm/trunk/test/tools/llvm-ar/flatten-thin-archive-recursive.test Mon Jan 14 13:11:46 2019
@@ -0,0 +1,13 @@
+# Since llvm-ar cannot create thin archives that contain any thin archives,
+# nested-thin-archive.a is a manually constructed thin archive that contains
+# another (unflattened) thin archive.
+# This test ensures that flat archives are recursively flattened.
+
+RUN: rm -f %t.a
+RUN: llvm-ar rcsT %t.a %S/Inputs/nested-thin-archive.a %S/Inputs/d.txt
+RUN: llvm-ar t %t.a | FileCheck %s
+
+CHECK:      a.txt
+CHECK-NEXT: b.txt
+CHECK-NEXT: c.txt
+CHECK-NEXT: d.txt

Added: llvm/trunk/test/tools/llvm-ar/flatten-thin-archive.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-ar/flatten-thin-archive.test?rev=351120&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-ar/flatten-thin-archive.test (added)
+++ llvm/trunk/test/tools/llvm-ar/flatten-thin-archive.test Mon Jan 14 13:11:46 2019
@@ -0,0 +1,18 @@
+# This test creates a thin archive that contains a thin archive, a regular
+# archive, and a file.
+#
+# The inner thin archive should be flattened, but the regular archive should
+# not. The order of members in the archive should match the input order, with
+# flattened members appearing together.
+
+RUN: touch %t-a.txt %t-b.txt %t-c.txt %t-d.txt %t-e.txt
+RUN: rm -f %t-a-plus-b.a %t.a
+RUN: llvm-ar rcsT %t-a-plus-b.a %t-a.txt %t-b.txt
+RUN: llvm-ar rcs %t-d-plus-e.a %t-d.txt %t-e.txt
+RUN: llvm-ar rcsT %t.a %t-a-plus-b.a %t-c.txt %t-d-plus-e.a
+RUN: llvm-ar t %t.a | FileCheck %s
+
+CHECK:      a.txt
+CHECK-NEXT: b.txt
+CHECK-NEXT: c.txt
+CHECK-NEXT: -d-plus-e.a

Modified: llvm/trunk/tools/llvm-ar/llvm-ar.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-ar/llvm-ar.cpp?rev=351120&r1=351119&r2=351120&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-ar/llvm-ar.cpp (original)
+++ llvm/trunk/tools/llvm-ar/llvm-ar.cpp Mon Jan 14 13:11:46 2019
@@ -536,52 +536,53 @@ static void performReadOperation(Archive
   exit(1);
 }
 
-static void addMember(std::vector<NewArchiveMember> &Members,
-                      StringRef FileName, int Pos = -1) {
-  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
-    Members[Pos] = std::move(*NMOrErr);
-}
-
-static void addMember(std::vector<NewArchiveMember> &Members,
-                      const object::Archive::Child &M, int Pos = -1) {
+static void addChildMember(std::vector<NewArchiveMember> &Members,
+                           const object::Archive::Child &M,
+                           bool FlattenArchive = false) {
   if (Thin && !M.getParent()->isThin())
     fail("Cannot convert a regular archive to a thin one");
   Expected<NewArchiveMember> NMOrErr =
       NewArchiveMember::getOldMember(M, Deterministic);
   failIfError(NMOrErr.takeError());
-  if (Pos == -1)
-    Members.push_back(std::move(*NMOrErr));
-  else
-    Members[Pos] = std::move(*NMOrErr);
+  if (FlattenArchive &&
+      identify_magic(NMOrErr->Buf->getBuffer()) == file_magic::archive) {
+    Expected<StringRef> FileNameOrErr = M.getName();
+    failIfError(FileNameOrErr.takeError());
+    object::Archive &Lib = readLibrary(*FileNameOrErr);
+    // When creating thin archives, only flatten if the member is also thin.
+    if (!Thin || Lib.isThin()) {
+      Error Err = Error::success();
+      // Only Thin archives are recursively flattened.
+      for (auto &Child : Lib.children(Err))
+        addChildMember(Members, Child, /*FlattenArchive=*/Thin);
+      failIfError(std::move(Err));
+      return;
+    }
+  }
+  Members.push_back(std::move(*NMOrErr));
 }
 
-static void addLibMember(std::vector<NewArchiveMember> &Members,
-                         StringRef FileName) {
+static void addMember(std::vector<NewArchiveMember> &Members,
+                      StringRef FileName, bool FlattenArchive = false) {
   Expected<NewArchiveMember> NMOrErr =
       NewArchiveMember::getFile(FileName, Deterministic);
   failIfError(NMOrErr.takeError(), FileName);
-  if (identify_magic(NMOrErr->Buf->getBuffer()) == file_magic::archive) {
+  if (FlattenArchive &&
+      identify_magic(NMOrErr->Buf->getBuffer()) == file_magic::archive) {
     object::Archive &Lib = readLibrary(FileName);
-    Error Err = Error::success();
-
-    for (auto &Child : Lib.children(Err))
-      addMember(Members, Child);
-
-    failIfError(std::move(Err));
-  } else {
-    // Use the basename of the object path for the member name.
-    NMOrErr->MemberName = sys::path::filename(NMOrErr->MemberName);
-    Members.push_back(std::move(*NMOrErr));
+    // When creating thin archives, only flatten if the member is also thin.
+    if (!Thin || Lib.isThin()) {
+      Error Err = Error::success();
+      // Only Thin archives are recursively flattened.
+      for (auto &Child : Lib.children(Err))
+        addChildMember(Members, Child, /*FlattenArchive=*/Thin);
+      failIfError(std::move(Err));
+      return;
+    }
   }
+  // Use the basename of the object path for the member name.
+  NMOrErr->MemberName = sys::path::filename(NMOrErr->MemberName);
+  Members.push_back(std::move(*NMOrErr));
 }
 
 enum InsertAction {
@@ -670,7 +671,7 @@ computeNewArchiveMembers(ArchiveOperatio
           computeInsertAction(Operation, Child, Name, MemberI);
       switch (Action) {
       case IA_AddOldMember:
-        addMember(Ret, Child);
+        addChildMember(Ret, Child);
         break;
       case IA_AddNewMember:
         addMember(Ret, *MemberI);
@@ -678,7 +679,7 @@ computeNewArchiveMembers(ArchiveOperatio
       case IA_Delete:
         break;
       case IA_MoveOldMember:
-        addMember(Moved, Child);
+        addChildMember(Moved, Child);
         break;
       case IA_MoveNewMember:
         addMember(Moved, *MemberI);
@@ -709,17 +710,16 @@ computeNewArchiveMembers(ArchiveOperatio
   if (AddLibrary) {
     assert(Operation == QuickAppend);
     for (auto &Member : Members)
-      addLibMember(Ret, Member);
+      addMember(Ret, Member, /*FlattenArchive=*/true);
     return Ret;
   }
 
-  for (unsigned I = 0; I != Members.size(); ++I)
-    Ret.insert(Ret.begin() + InsertPos, NewArchiveMember());
-  Pos = InsertPos;
-  for (auto &Member : Members) {
-    addMember(Ret, Member, Pos);
-    ++Pos;
-  }
+  std::vector<NewArchiveMember> NewMembers;
+  for (auto &Member : Members)
+    addMember(NewMembers, Member, /*FlattenArchive=*/Thin);
+  Ret.reserve(Ret.size() + NewMembers.size());
+  std::move(NewMembers.begin(), NewMembers.end(),
+            std::inserter(Ret, std::next(Ret.begin(), InsertPos)));
 
   return Ret;
 }
@@ -897,7 +897,7 @@ static void runMRIScript() {
       {
         Error Err = Error::success();
         for (auto &Member : Lib.children(Err))
-          addMember(NewMembers, Member);
+          addChildMember(NewMembers, Member);
         failIfError(std::move(Err));
       }
       break;




More information about the llvm-commits mailing list