[llvm] r273373 - llvm-ar: be more clever about default format

Saleem Abdulrasool via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 21 21:03:28 PDT 2016


Author: compnerd
Date: Tue Jun 21 23:03:28 2016
New Revision: 273373

URL: http://llvm.org/viewvc/llvm-project?rev=273373&view=rev
Log:
llvm-ar: be more clever about default format

Try to be more clever about selecting the default format.  When an existing
archive is used, use the type of the archive to determine the format.  When
existing members are present, use the first member's format to determine the
format to use.  If we are creating an empty archive (MRI mode) or are adding
non-object members, default to the current behaviour of using the host type due
to the lack of a better alternative.  This aids in cross-compilation on Darwin
to non-Darwin platforms which rely on GNU format archives.

Modified:
    llvm/trunk/tools/llvm-ar/llvm-ar.cpp

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=273373&r1=273372&r2=273373&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-ar/llvm-ar.cpp (original)
+++ llvm/trunk/tools/llvm-ar/llvm-ar.cpp Tue Jun 21 23:03:28 2016
@@ -19,6 +19,7 @@
 #include "llvm/LibDriver/LibDriver.h"
 #include "llvm/Object/Archive.h"
 #include "llvm/Object/ArchiveWriter.h"
+#include "llvm/Object/MachO.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Errc.h"
@@ -575,21 +576,86 @@ computeNewArchiveMembers(ArchiveOperatio
   return Ret;
 }
 
+static object::Archive::Kind getDefaultForHost() {
+  return Triple(sys::getProcessTriple()).isOSDarwin() ? object::Archive::K_BSD
+                                                      : object::Archive::K_GNU;
+}
+
+static object::Archive::Kind
+getKindFromMember(const NewArchiveIterator &Member) {
+  if (Member.isNewMember()) {
+    object::Archive::Kind Kind = getDefaultForHost();
+
+    sys::fs::file_status Status;
+    if (auto OptionalFD = Member.getFD(Status)) {
+      auto OptionalMB = MemoryBuffer::getOpenFile(*OptionalFD, Member.getName(),
+                                                  Status.getSize(), false);
+      if (OptionalMB) {
+        MemoryBufferRef MemoryBuffer = (*OptionalMB)->getMemBufferRef();
+
+        Expected<std::unique_ptr<object::ObjectFile>> OptionalObject =
+            object::ObjectFile::createObjectFile(MemoryBuffer);
+
+        if (OptionalObject)
+          Kind = isa<object::MachOObjectFile>(**OptionalObject)
+              ? object::Archive::K_BSD
+              : object::Archive::K_GNU;
+
+        // squelch the error in case we had a non-object file
+        consumeError(OptionalObject.takeError());
+      }
+
+      if (close(*OptionalFD) != 0)
+        failIfError(std::error_code(errno, std::generic_category()),
+                    "failed to close file");
+    }
+
+    return Kind;
+  } else {
+    const object::Archive::Child &OldMember = Member.getOld();
+    if (OldMember.getParent()->isThin())
+      return object::Archive::Kind::K_GNU;
+
+    auto OptionalMB = OldMember.getMemoryBufferRef();
+    failIfError(OptionalMB.getError());
+
+    Expected<std::unique_ptr<object::ObjectFile>> OptionalObject =
+        object::ObjectFile::createObjectFile(*OptionalMB);
+
+    if (OptionalObject)
+      return isa<object::MachOObjectFile>(*OptionalObject->get())
+                 ? object::Archive::K_BSD
+                 : object::Archive::K_GNU;
+
+    // squelch the error in case we had a non-object file
+    consumeError(OptionalObject.takeError());
+    return getDefaultForHost();
+  }
+}
+
 static void
 performWriteOperation(ArchiveOperation Operation,
                       object::Archive *OldArchive,
                       std::unique_ptr<MemoryBuffer> OldArchiveBuf,
                       std::vector<NewArchiveIterator> *NewMembersP) {
+  std::vector<NewArchiveIterator> NewMembers;
+  if (!NewMembersP)
+    NewMembers = computeNewArchiveMembers(Operation, OldArchive);
+
   object::Archive::Kind Kind;
   switch (FormatOpt) {
-  case Default: {
-    Triple T(sys::getProcessTriple());
-    if (T.isOSDarwin() && !Thin)
-      Kind = object::Archive::K_BSD;
-    else
+  case Default:
+    if (Thin)
       Kind = object::Archive::K_GNU;
+    else if (OldArchive)
+      Kind = OldArchive->kind();
+    else if (NewMembersP)
+      Kind = NewMembersP->size() ? getKindFromMember(NewMembersP->front())
+                                 : getDefaultForHost();
+    else
+      Kind = NewMembers.size() ? getKindFromMember(NewMembers.front())
+                               : getDefaultForHost();
     break;
-  }
   case GNU:
     Kind = object::Archive::K_GNU;
     break;
@@ -599,18 +665,10 @@ performWriteOperation(ArchiveOperation O
     Kind = object::Archive::K_BSD;
     break;
   }
-  if (NewMembersP) {
-    std::pair<StringRef, std::error_code> Result = writeArchive(
-        ArchiveName, *NewMembersP, Symtab, Kind, Deterministic, Thin,
-        std::move(OldArchiveBuf));
-    failIfError(Result.second, Result.first);
-    return;
-  }
-  std::vector<NewArchiveIterator> NewMembers =
-      computeNewArchiveMembers(Operation, OldArchive);
-  auto Result =
-      writeArchive(ArchiveName, NewMembers, Symtab, Kind, Deterministic, Thin,
-      std::move(OldArchiveBuf));
+
+  std::pair<StringRef, std::error_code> Result =
+      writeArchive(ArchiveName, NewMembersP ? *NewMembersP : NewMembers, Symtab,
+                   Kind, Deterministic, Thin, std::move(OldArchiveBuf));
   failIfError(Result.second, Result.first);
 }
 




More information about the llvm-commits mailing list