diff options
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/include/llvm/Object/ArchiveWriter.h | 1 | ||||
| -rw-r--r-- | llvm/lib/Object/ArchiveWriter.cpp | 71 | ||||
| -rw-r--r-- | llvm/test/tools/llvm-ar/flatten-thin-archive-directories.test | 15 | ||||
| -rw-r--r-- | llvm/test/tools/llvm-ar/flatten-thin-archive.test | 2 | ||||
| -rw-r--r-- | llvm/tools/llvm-ar/llvm-ar.cpp | 57 | 
5 files changed, 79 insertions, 67 deletions
diff --git a/llvm/include/llvm/Object/ArchiveWriter.h b/llvm/include/llvm/Object/ArchiveWriter.h index 4e796eb1adf..cca97e73484 100644 --- a/llvm/include/llvm/Object/ArchiveWriter.h +++ b/llvm/include/llvm/Object/ArchiveWriter.h @@ -26,7 +26,6 @@ struct NewArchiveMember {    sys::TimePoint<std::chrono::seconds> ModTime;    unsigned UID = 0, GID = 0, Perms = 0644; -  bool IsNew = false;    NewArchiveMember() = default;    NewArchiveMember(MemoryBufferRef BufRef); diff --git a/llvm/lib/Object/ArchiveWriter.cpp b/llvm/lib/Object/ArchiveWriter.cpp index d27233ec2f4..5650ca88f0c 100644 --- a/llvm/lib/Object/ArchiveWriter.cpp +++ b/llvm/lib/Object/ArchiveWriter.cpp @@ -48,7 +48,6 @@ NewArchiveMember::getOldMember(const object::Archive::Child &OldMember,      return BufOrErr.takeError();    NewArchiveMember M; -  assert(M.IsNew == false);    M.Buf = MemoryBuffer::getMemBuffer(*BufOrErr, false);    M.MemberName = M.Buf->getBufferIdentifier();    if (!Deterministic) { @@ -98,7 +97,6 @@ Expected<NewArchiveMember> NewArchiveMember::getFile(StringRef FileName,      return errorCodeToError(std::error_code(errno, std::generic_category()));    NewArchiveMember M; -  M.IsNew = true;    M.Buf = std::move(*MemberBufferOrErr);    M.MemberName = M.Buf->getBufferIdentifier();    if (!Deterministic) { @@ -191,35 +189,6 @@ static bool useStringTable(bool Thin, StringRef Name) {    return Thin || Name.size() >= 16 || Name.contains('/');  } -// Compute the relative path from From to To. -static std::string computeRelativePath(StringRef From, StringRef To) { -  if (sys::path::is_absolute(From) || sys::path::is_absolute(To)) -    return To; - -  StringRef DirFrom = sys::path::parent_path(From); -  auto FromI = sys::path::begin(DirFrom); -  auto ToI = sys::path::begin(To); -  while (*FromI == *ToI) { -    ++FromI; -    ++ToI; -  } - -  SmallString<128> Relative; -  for (auto FromE = sys::path::end(DirFrom); FromI != FromE; ++FromI) -    sys::path::append(Relative, ".."); - -  for (auto ToE = sys::path::end(To); ToI != ToE; ++ToI) -    sys::path::append(Relative, *ToI); - -#ifdef _WIN32 -  // Replace backslashes with slashes so that the path is portable between *nix -  // and Windows. -  std::replace(Relative.begin(), Relative.end(), '\\', '/'); -#endif - -  return Relative.str(); -} -  static bool is64BitKind(object::Archive::Kind Kind) {    switch (Kind) {    case object::Archive::K_GNU: @@ -234,27 +203,11 @@ static bool is64BitKind(object::Archive::Kind Kind) {    llvm_unreachable("not supported for writting");  } -static void addToStringTable(raw_ostream &Out, StringRef ArcName, -                             const NewArchiveMember &M, bool Thin) { -  StringRef ID = M.Buf->getBufferIdentifier(); -  if (Thin) { -    if (M.IsNew) -      Out << computeRelativePath(ArcName, ID); -    else -      Out << ID; -  } else -    Out << M.MemberName; -  Out << "/\n"; -} - -static void printMemberHeader(raw_ostream &Out, uint64_t Pos, -                              raw_ostream &StringTable, -                              StringMap<uint64_t> &MemberNames, -                              object::Archive::Kind Kind, bool Thin, -                              StringRef ArcName, const NewArchiveMember &M, -                              sys::TimePoint<std::chrono::seconds> ModTime, -                              unsigned Size) { - +static void +printMemberHeader(raw_ostream &Out, uint64_t Pos, raw_ostream &StringTable, +                  StringMap<uint64_t> &MemberNames, object::Archive::Kind Kind, +                  bool Thin, const NewArchiveMember &M, +                  sys::TimePoint<std::chrono::seconds> ModTime, unsigned Size) {    if (isBSDLike(Kind))      return printBSDMemberHeader(Out, Pos, M.MemberName, ModTime, M.UID, M.GID,                                  M.Perms, Size); @@ -265,12 +218,12 @@ static void printMemberHeader(raw_ostream &Out, uint64_t Pos,    uint64_t NamePos;    if (Thin) {      NamePos = StringTable.tell(); -    addToStringTable(StringTable, ArcName, M, Thin); +    StringTable << M.MemberName << "/\n";    } else {      auto Insertion = MemberNames.insert({M.MemberName, uint64_t(0)});      if (Insertion.second) {        Insertion.first->second = StringTable.tell(); -      addToStringTable(StringTable, ArcName, M, Thin); +      StringTable << M.MemberName << "/\n";      }      NamePos = Insertion.first->second;    } @@ -432,8 +385,8 @@ getSymbols(MemoryBufferRef Buf, raw_ostream &SymNames, bool &HasObject) {  static Expected<std::vector<MemberData>>  computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames, -                  object::Archive::Kind Kind, bool Thin, StringRef ArcName, -                  bool Deterministic, ArrayRef<NewArchiveMember> NewMembers) { +                  object::Archive::Kind Kind, bool Thin, bool Deterministic, +                  ArrayRef<NewArchiveMember> NewMembers) {    static char PaddingData[8] = {'\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'};    // This ignores the symbol table, but we only need the value mod 8 and the @@ -520,8 +473,8 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,        ModTime = sys::toTimePoint(FilenameCount[M.MemberName]++);      else        ModTime = M.ModTime; -    printMemberHeader(Out, Pos, StringTable, MemberNames, Kind, Thin, ArcName, -                      M, ModTime, Buf.getBufferSize() + MemberPadding); +    printMemberHeader(Out, Pos, StringTable, MemberNames, Kind, Thin, M, +                      ModTime, Buf.getBufferSize() + MemberPadding);      Out.flush();      Expected<std::vector<unsigned>> Symbols = @@ -553,7 +506,7 @@ Error llvm::writeArchive(StringRef ArcName,    raw_svector_ostream StringTable(StringTableBuf);    Expected<std::vector<MemberData>> DataOrErr = computeMemberData( -      StringTable, SymNames, Kind, Thin, ArcName, Deterministic, NewMembers); +      StringTable, SymNames, Kind, Thin, Deterministic, NewMembers);    if (Error E = DataOrErr.takeError())      return E;    std::vector<MemberData> &Data = *DataOrErr; diff --git a/llvm/test/tools/llvm-ar/flatten-thin-archive-directories.test b/llvm/test/tools/llvm-ar/flatten-thin-archive-directories.test new file mode 100644 index 00000000000..6b5fc28658a --- /dev/null +++ b/llvm/test/tools/llvm-ar/flatten-thin-archive-directories.test @@ -0,0 +1,15 @@ +# This test creates a thin archive in a directory and adds it to a thin archive +# in the parent directory. The relative path should be included when flattening +# the archive. + +RUN: mkdir -p %t/foo +RUN: touch %t/foo/a.txt +RUN: rm -f %t/archive.a %t/foo/archive.a + +# These tests must be run in the same directory as %t/archive.a. cd %t is +# included on each line to make debugging this test case easier. +RUN: cd %t && llvm-ar rcST foo/archive.a foo/a.txt +RUN: cd %t && llvm-ar rcST archive.a foo/archive.a +RUN: cd %t && llvm-ar t archive.a | FileCheck %s --match-full-lines + +CHECK: foo/a.txt diff --git a/llvm/test/tools/llvm-ar/flatten-thin-archive.test b/llvm/test/tools/llvm-ar/flatten-thin-archive.test index 430f48fe7c4..a80edd9d50c 100644 --- a/llvm/test/tools/llvm-ar/flatten-thin-archive.test +++ b/llvm/test/tools/llvm-ar/flatten-thin-archive.test @@ -6,7 +6,7 @@  # 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: rm -f %t-a-plus-b.a %t-d-plus-e.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 diff --git a/llvm/tools/llvm-ar/llvm-ar.cpp b/llvm/tools/llvm-ar/llvm-ar.cpp index 0119ec502e5..6e0be0a8158 100644 --- a/llvm/tools/llvm-ar/llvm-ar.cpp +++ b/llvm/tools/llvm-ar/llvm-ar.cpp @@ -193,6 +193,9 @@ static std::string ArchiveName;  // on the command line.  static std::vector<StringRef> Members; +// Static buffer to hold StringRefs. +static BumpPtrAllocator Alloc; +  // Extract the member filename from the command line for the [relpos] argument  // associated with a, b, and i modifiers  static void getRelPos() { @@ -537,6 +540,35 @@ static void performReadOperation(ArchiveOperation Operation,    exit(1);  } +// Compute the relative path from From to To. +static std::string computeRelativePath(StringRef From, StringRef To) { +  if (sys::path::is_absolute(From) || sys::path::is_absolute(To)) +    return To; + +  StringRef DirFrom = sys::path::parent_path(From); +  auto FromI = sys::path::begin(DirFrom); +  auto ToI = sys::path::begin(To); +  while (*FromI == *ToI) { +    ++FromI; +    ++ToI; +  } + +  SmallString<128> Relative; +  for (auto FromE = sys::path::end(DirFrom); FromI != FromE; ++FromI) +    sys::path::append(Relative, ".."); + +  for (auto ToE = sys::path::end(To); ToI != ToE; ++ToI) +    sys::path::append(Relative, *ToI); + +#ifdef _WIN32 +  // Replace backslashes with slashes so that the path is portable between *nix +  // and Windows. +  std::replace(Relative.begin(), Relative.end(), '\\', '/'); +#endif + +  return Relative.str(); +} +  static void addChildMember(std::vector<NewArchiveMember> &Members,                             const object::Archive::Child &M,                             bool FlattenArchive = false) { @@ -545,6 +577,15 @@ static void addChildMember(std::vector<NewArchiveMember> &Members,    Expected<NewArchiveMember> NMOrErr =        NewArchiveMember::getOldMember(M, Deterministic);    failIfError(NMOrErr.takeError()); +  // If the child member we're trying to add is thin, use the path relative to +  // the archive it's in, so the file resolves correctly. +  if (Thin && FlattenArchive) { +    StringSaver Saver(Alloc); +    Expected<std::string> FileNameOrErr = M.getFullName(); +    failIfError(FileNameOrErr.takeError()); +    NMOrErr->MemberName = +        Saver.save(computeRelativePath(ArchiveName, *FileNameOrErr)); +  }    if (FlattenArchive &&        identify_magic(NMOrErr->Buf->getBuffer()) == file_magic::archive) {      Expected<std::string> FileNameOrErr = M.getFullName(); @@ -568,6 +609,13 @@ static void addMember(std::vector<NewArchiveMember> &Members,    Expected<NewArchiveMember> NMOrErr =        NewArchiveMember::getFile(FileName, Deterministic);    failIfError(NMOrErr.takeError(), FileName); +  StringSaver Saver(Alloc); +  // For regular archives, use the basename of the object path for the member +  // name. For thin archives, use the full relative paths so the file resolves +  // correctly. +  NMOrErr->MemberName = +      Thin ? Saver.save(computeRelativePath(ArchiveName, FileName)) +           : sys::path::filename(NMOrErr->MemberName);    if (FlattenArchive &&        identify_magic(NMOrErr->Buf->getBuffer()) == file_magic::archive) {      object::Archive &Lib = readLibrary(FileName); @@ -581,8 +629,6 @@ static void addMember(std::vector<NewArchiveMember> &Members,        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));  } @@ -672,7 +718,7 @@ computeNewArchiveMembers(ArchiveOperation Operation,            computeInsertAction(Operation, Child, Name, MemberI);        switch (Action) {        case IA_AddOldMember: -        addChildMember(Ret, Child); +        addChildMember(Ret, Child, /*FlattenArchive=*/Thin);          break;        case IA_AddNewMember:          addMember(Ret, *MemberI); @@ -680,7 +726,7 @@ computeNewArchiveMembers(ArchiveOperation Operation,        case IA_Delete:          break;        case IA_MoveOldMember: -        addChildMember(Moved, Child); +        addChildMember(Moved, Child, /*FlattenArchive=*/Thin);          break;        case IA_MoveNewMember:          addMember(Moved, *MemberI); @@ -899,7 +945,7 @@ static void runMRIScript() {        {          Error Err = Error::success();          for (auto &Member : Lib.children(Err)) -          addChildMember(NewMembers, Member); +          addChildMember(NewMembers, Member, /*FlattenArchive=*/Thin);          failIfError(std::move(Err));        }        break; @@ -951,7 +997,6 @@ static bool handleGenericOption(StringRef arg) {  static int ar_main(int argc, char **argv) {    SmallVector<const char *, 0> Argv(argv, argv + argc); -  BumpPtrAllocator Alloc;    StringSaver Saver(Alloc);    cl::ExpandResponseFiles(Saver, cl::TokenizeGNUCommandLine, Argv);    for (size_t i = 1; i < Argv.size(); ++i) {  | 

