Initial support for writing thin archives.
authorRafael Espindola <rafael.espindola@gmail.com>
Wed, 15 Jul 2015 05:47:46 +0000 (05:47 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Wed, 15 Jul 2015 05:47:46 +0000 (05:47 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@242269 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Object/ArchiveWriter.h
lib/LibDriver/LibDriver.cpp
lib/Object/ArchiveWriter.cpp
test/Object/archive-format.test
tools/llvm-ar/llvm-ar.cpp

index 3648d0c77fb5f0cb158adae2210d8c0ca5ea039a..9d1dd61bf6623c463fdb3a4c6f5ba11d6c6af684 100644 (file)
@@ -43,7 +43,8 @@ public:
 
 std::pair<StringRef, std::error_code>
 writeArchive(StringRef ArcName, std::vector<NewArchiveIterator> &NewMembers,
-             bool WriteSymtab, object::Archive::Kind Kind, bool Deterministic);
+             bool WriteSymtab, object::Archive::Kind Kind, bool Deterministic,
+             bool Thin);
 }
 
 #endif
index b33a22ff0cf8fd236f70aca034411eedc7f798bc..9814875020405e64c7d3a57203aa42da65ef735b 100644 (file)
@@ -142,7 +142,7 @@ int llvm::libDriverMain(llvm::ArrayRef<const char*> ArgsArr) {
   std::pair<StringRef, std::error_code> Result =
       llvm::writeArchive(getOutputPath(&Args, Members[0]), Members,
                          /*WriteSymtab=*/true, object::Archive::K_GNU,
-                         /*Deterministic*/ true);
+                         /*Deterministic*/ true, /*Thin*/ false);
 
   if (Result.second) {
     if (Result.first.empty())
index dd7af472565010f7f59e67428a92083966abe534..bcd5382d91e3307a33471202ef14f28c957896db 100644 (file)
@@ -135,15 +135,19 @@ static void printBSDMemberHeader(raw_fd_ostream &Out, StringRef Name,
     Out.write(uint8_t(0));
 }
 
+static bool useStringTable(bool Thin, StringRef Name) {
+  return Thin || Name.size() >= 16;
+}
+
 static void
-printMemberHeader(raw_fd_ostream &Out, object::Archive::Kind Kind,
+printMemberHeader(raw_fd_ostream &Out, object::Archive::Kind Kind, bool Thin,
                   StringRef Name,
                   std::vector<unsigned>::iterator &StringMapIndexIter,
                   const sys::TimeValue &ModTime, unsigned UID, unsigned GID,
                   unsigned Perms, unsigned Size) {
   if (Kind == object::Archive::K_BSD)
     return printBSDMemberHeader(Out, Name, ModTime, UID, GID, Perms, Size);
-  if (Name.size() < 16)
+  if (!useStringTable(Thin, Name))
     return printGNUSmallMemberHeader(Out, Name, ModTime, UID, GID, Perms, Size);
   Out << '/';
   printWithSpacePadding(Out, *StringMapIndexIter++, 15);
@@ -152,11 +156,12 @@ printMemberHeader(raw_fd_ostream &Out, object::Archive::Kind Kind,
 
 static void writeStringTable(raw_fd_ostream &Out,
                              ArrayRef<NewArchiveIterator> Members,
-                             std::vector<unsigned> &StringMapIndexes) {
+                             std::vector<unsigned> &StringMapIndexes,
+                             bool Thin) {
   unsigned StartOffset = 0;
   for (const NewArchiveIterator &I : Members) {
     StringRef Name = I.getName();
-    if (Name.size() < 16)
+    if (!useStringTable(Thin, Name))
       continue;
     if (StartOffset == 0) {
       printWithSpacePadding(Out, "//", 58);
@@ -266,9 +271,11 @@ writeSymbolTable(raw_fd_ostream &Out, object::Archive::Kind Kind,
   return BodyStartOffset + 4;
 }
 
-std::pair<StringRef, std::error_code> llvm::writeArchive(
-    StringRef ArcName, std::vector<NewArchiveIterator> &NewMembers,
-    bool WriteSymtab, object::Archive::Kind Kind, bool Deterministic) {
+std::pair<StringRef, std::error_code>
+llvm::writeArchive(StringRef ArcName,
+                   std::vector<NewArchiveIterator> &NewMembers,
+                   bool WriteSymtab, object::Archive::Kind Kind,
+                   bool Deterministic, bool Thin) {
   SmallString<128> TmpArchive;
   int TmpArchiveFD;
   if (auto EC = sys::fs::createUniqueFile(ArcName + ".temp-archive-%%%%%%%.a",
@@ -277,7 +284,10 @@ std::pair<StringRef, std::error_code> llvm::writeArchive(
 
   tool_output_file Output(TmpArchive, TmpArchiveFD);
   raw_fd_ostream &Out = Output.os();
-  Out << "!<arch>\n";
+  if (Thin)
+    Out << "!<thin>\n";
+  else
+    Out << "!<arch>\n";
 
   std::vector<unsigned> MemberOffsetRefs;
 
@@ -328,7 +338,7 @@ std::pair<StringRef, std::error_code> llvm::writeArchive(
 
   std::vector<unsigned> StringMapIndexes;
   if (Kind != object::Archive::K_BSD)
-    writeStringTable(Out, NewMembers, StringMapIndexes);
+    writeStringTable(Out, NewMembers, StringMapIndexes, Thin);
 
   unsigned MemberNum = 0;
   unsigned NewMemberNum = 0;
@@ -366,16 +376,17 @@ std::pair<StringRef, std::error_code> llvm::writeArchive(
     if (I.isNewMember()) {
       StringRef FileName = I.getNew();
       const sys::fs::file_status &Status = NewMemberStatus[NewMemberNum++];
-      printMemberHeader(Out, Kind, sys::path::filename(FileName),
+      printMemberHeader(Out, Kind, Thin, sys::path::filename(FileName),
                         StringMapIndexIter, ModTime, UID, GID, Perms,
                         Status.getSize());
     } else {
       object::Archive::child_iterator OldMember = I.getOld();
-      printMemberHeader(Out, Kind, I.getName(), StringMapIndexIter, ModTime,
-                        UID, GID, Perms, OldMember->getSize());
+      printMemberHeader(Out, Kind, Thin, I.getName(), StringMapIndexIter,
+                        ModTime, UID, GID, Perms, OldMember->getSize());
     }
 
-    Out << File.getBuffer();
+    if (!Thin)
+      Out << File.getBuffer();
 
     if (Out.tell() % 2)
       Out << '\n';
index 40af9a33d8d7f72514c2503d3a24da2fa5d75dc1..376eb053c6d2e3ca8aaa5a4a807a9e20842aded8 100644 (file)
@@ -27,3 +27,14 @@ BSD-NEXT: #1/20           0           0     0     644     24        `
 BSD-NEXT: 0123456789abcde{{.....}}bar.
 BSD-SAME: #1/16           0           0     0     644     20        `
 BSD-NEXT: 0123456789abcdefzed.
+
+RUN: rm -f %t.a
+RUN: llvm-ar --format=gnu rcT %t.a 0123456789abcde 0123456789abcdef
+RUN: cat %t.a | FileCheck -strict-whitespace --check-prefix=THIN %s
+THIN: !<thin>
+THIN-NEXT: //                                              36        `
+THIN-NEXT: 0123456789abcde/
+THIN-NEXT: 0123456789abcdef/{{$}}
+THIN: {{^$}}
+THIN: /0              0           0     0     644     4         `
+THIN-NEXT: /17             0           0     0     644     4         `
index 2c9668c63b8cc18fcc3f0e2b6298d0439433523b..0e3c4fdc2ce90b59df3b6a35b7886d668938f697 100644 (file)
@@ -130,6 +130,7 @@ static bool OnlyUpdate = false;    ///< 'u' modifier
 static bool Verbose = false;       ///< 'v' modifier
 static bool Symtab = true;         ///< 's' modifier
 static bool Deterministic = true;  ///< 'D' and 'U' modifiers
+static bool Thin = false;          ///< 'T' modifier
 
 // Relative Positional Argument (for insert/move). This variable holds
 // the name of the archive member to which the 'a', 'b' or 'i' modifier
@@ -252,6 +253,9 @@ static ArchiveOperation parseCommandLine() {
     case 'U':
       Deterministic = false;
       break;
+    case 'T':
+      Thin = true;
+      break;
     default:
       cl::PrintHelpMessage();
     }
@@ -590,15 +594,15 @@ performWriteOperation(ArchiveOperation Operation, object::Archive *OldArchive,
     break;
   }
   if (NewMembersP) {
-    std::pair<StringRef, std::error_code> Result =
-        writeArchive(ArchiveName, *NewMembersP, Symtab, Kind, Deterministic);
+    std::pair<StringRef, std::error_code> Result = writeArchive(
+        ArchiveName, *NewMembersP, Symtab, Kind, Deterministic, Thin);
     failIfError(Result.second, Result.first);
     return;
   }
   std::vector<NewArchiveIterator> NewMembers =
       computeNewArchiveMembers(Operation, OldArchive);
   auto Result =
-      writeArchive(ArchiveName, NewMembers, Symtab, Kind, Deterministic);
+      writeArchive(ArchiveName, NewMembers, Symtab, Kind, Deterministic, Thin);
   failIfError(Result.second, Result.first);
 }