Skip to content
This repository was archived by the owner on Apr 23, 2020. It is now read-only.

Commit 0e34c35

Browse files
committed
[llvm-ar] Make llvm-lib behave more like the MSVC archiver
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
1 parent b31b7dc commit 0e34c35

File tree

4 files changed

+37
-6
lines changed

4 files changed

+37
-6
lines changed

include/llvm/Object/ArchiveWriter.h

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ namespace llvm {
2222

2323
struct NewArchiveMember {
2424
std::unique_ptr<MemoryBuffer> Buf;
25+
StringRef MemberName;
2526
sys::TimePoint<std::chrono::seconds> ModTime;
2627
unsigned UID = 0, GID = 0, Perms = 0644;
2728

lib/Object/ArchiveWriter.cpp

+8-6
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@
3636
using namespace llvm;
3737

3838
NewArchiveMember::NewArchiveMember(MemoryBufferRef BufRef)
39-
: Buf(MemoryBuffer::getMemBuffer(BufRef, false)) {}
39+
: Buf(MemoryBuffer::getMemBuffer(BufRef, false)),
40+
MemberName(BufRef.getBufferIdentifier()) {}
4041

4142
Expected<NewArchiveMember>
4243
NewArchiveMember::getOldMember(const object::Archive::Child &OldMember,
@@ -48,6 +49,7 @@ NewArchiveMember::getOldMember(const object::Archive::Child &OldMember,
4849
NewArchiveMember M;
4950
assert(M.IsNew == false);
5051
M.Buf = MemoryBuffer::getMemBuffer(*BufOrErr, false);
52+
M.MemberName = M.Buf->getBufferIdentifier();
5153
if (!Deterministic) {
5254
auto ModTimeOrErr = OldMember.getLastModified();
5355
if (!ModTimeOrErr)
@@ -97,6 +99,7 @@ Expected<NewArchiveMember> NewArchiveMember::getFile(StringRef FileName,
9799
NewArchiveMember M;
98100
M.IsNew = true;
99101
M.Buf = std::move(*MemberBufferOrErr);
102+
M.MemberName = M.Buf->getBufferIdentifier();
100103
if (!Deterministic) {
101104
M.ModTime = std::chrono::time_point_cast<std::chrono::seconds>(
102105
Status.getLastModificationTime());
@@ -185,7 +188,7 @@ printBSDMemberHeader(raw_fd_ostream &Out, StringRef Name,
185188
}
186189

187190
static bool useStringTable(bool Thin, StringRef Name) {
188-
return Thin || Name.size() >= 16;
191+
return Thin || Name.size() >= 16 || Name.contains('/');
189192
}
190193

191194
static void
@@ -239,7 +242,7 @@ static void writeStringTable(raw_fd_ostream &Out, StringRef ArcName,
239242
unsigned StartOffset = 0;
240243
for (const NewArchiveMember &M : Members) {
241244
StringRef Path = M.Buf->getBufferIdentifier();
242-
StringRef Name = sys::path::filename(Path);
245+
StringRef Name = M.MemberName;
243246
if (!useStringTable(Thin, Name))
244247
continue;
245248
if (StartOffset == 0) {
@@ -423,9 +426,8 @@ llvm::writeArchive(StringRef ArcName,
423426
if (Kind == object::Archive::K_DARWIN)
424427
Padding = OffsetToAlignment(M.Buf->getBufferSize(), 8);
425428

426-
printMemberHeader(Out, Kind, Thin,
427-
sys::path::filename(M.Buf->getBufferIdentifier()),
428-
StringMapIndexIter, M.ModTime, M.UID, M.GID, M.Perms,
429+
printMemberHeader(Out, Kind, Thin, M.MemberName, StringMapIndexIter,
430+
M.ModTime, M.UID, M.GID, M.Perms,
429431
M.Buf->getBufferSize() + Padding);
430432

431433
if (!Thin)

test/LibDriver/use-paths.test

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
llvm-lib should behave like "link.exe /lib" and use relative paths to describe
2+
archive members.
3+
4+
First, get in a clean working directory.
5+
RUN: rm -rf %t && mkdir -p %t && cd %t
6+
7+
Make foo/a.obj and foo/b.obj.
8+
RUN: mkdir foo
9+
RUN: llvm-mc -triple=x86_64-pc-windows-msvc -filetype=obj -o foo/a.obj %S/Inputs/a.s
10+
RUN: llvm-mc -triple=x86_64-pc-windows-msvc -filetype=obj -o foo/b.obj %S/Inputs/b.s
11+
12+
RUN: llvm-lib -out:foo.lib foo/a.obj foo/b.obj
13+
RUN: llvm-ar t foo.lib | FileCheck %s
14+
15+
FIXME: We should probably use backslashes on Windows to better match MSVC tools.
16+
CHECK: foo/a.obj
17+
CHECK: foo/b.obj
18+
19+
Do it again with absolute paths and see that we get something.
20+
RUN: llvm-lib -out:foo.lib %t/foo/a.obj %t/foo/b.obj
21+
RUN: llvm-ar t foo.lib | FileCheck %s --check-prefix=ABS
22+
23+
ABS: {{.*}}/foo/a.obj
24+
ABS: {{.*}}/foo/b.obj

tools/llvm-ar/llvm-ar.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,10 @@ static void addMember(std::vector<NewArchiveMember> &Members,
473473
Expected<NewArchiveMember> NMOrErr =
474474
NewArchiveMember::getFile(FileName, Deterministic);
475475
failIfError(NMOrErr.takeError(), FileName);
476+
477+
// Use the basename of the object path for the member name.
478+
NMOrErr->MemberName = sys::path::filename(NMOrErr->MemberName);
479+
476480
if (Pos == -1)
477481
Members.push_back(std::move(*NMOrErr));
478482
else

0 commit comments

Comments
 (0)