Skip to content

Commit

Permalink
llvm-lib: Implement /list flag
Browse files Browse the repository at this point in the history
Differential Revision: https://reviews.llvm.org/D57952

llvm-svn: 353620
  • Loading branch information
nico committed Feb 9, 2019
1 parent 7467510 commit a2f6093
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 0 deletions.
46 changes: 46 additions & 0 deletions llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,47 @@ static std::string findInputFile(StringRef File, ArrayRef<StringRef> Paths) {
return "";
}

static void fatalOpenError(llvm::Error E, Twine File) {
if (!E)
return;
handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EIB) {
llvm::errs() << "error opening '" << File << "': " << EIB.message() << '\n';
exit(1);
});
}

static void doList(opt::InputArgList& Args) {
// lib.exe prints the contents of the first archive file.
std::unique_ptr<MemoryBuffer> B;
for (auto *Arg : Args.filtered(OPT_INPUT)) {
// Create or open the archive object.
ErrorOr<std::unique_ptr<MemoryBuffer>> MaybeBuf =
MemoryBuffer::getFile(Arg->getValue(), -1, false);
fatalOpenError(errorCodeToError(MaybeBuf.getError()), Arg->getValue());

if (identify_magic(MaybeBuf.get()->getBuffer()) == file_magic::archive) {
B = std::move(MaybeBuf.get());
break;
}
}

// lib.exe doesn't print an error if no .lib files are passed.
if (!B)
return;

Error Err = Error::success();
object::Archive Archive(B.get()->getMemBufferRef(), Err);
fatalOpenError(std::move(Err), B->getBufferIdentifier());

for (auto &C : Archive.children(Err)) {
Expected<StringRef> NameOrErr = C.getName();
fatalOpenError(NameOrErr.takeError(), B->getBufferIdentifier());
StringRef Name = NameOrErr.get();
llvm::outs() << Name << '\n';
}
fatalOpenError(std::move(Err), B->getBufferIdentifier());
}

int llvm::libDriverMain(ArrayRef<const char *> ArgsArr) {
BumpPtrAllocator Alloc;
StringSaver Saver(Alloc);
Expand Down Expand Up @@ -130,6 +171,11 @@ int llvm::libDriverMain(ArrayRef<const char *> ArgsArr) {
if (!Args.hasArgNoClaim(OPT_INPUT))
return 0;

if (Args.hasArg(OPT_lst)) {
doList(Args);
return 0;
}

std::vector<StringRef> SearchPaths = getSearchPaths(&Args, Saver);

// Create a NewArchiveMember for each input file.
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/ToolDrivers/llvm-lib/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ class P<string name, string help> :
Joined<["/", "-", "-?"], name#":">, HelpText<help>;

def libpath: P<"libpath", "Object file search path">;

// Can't be called "list" since that's a keyword.
def lst : F<"list">, HelpText<"List contents of .lib file on stdout">;
def out : P<"out", "Path to file to write output">;

def llvmlibthin : F<"llvmlibthin">,
Expand Down
14 changes: 14 additions & 0 deletions llvm/test/tools/llvm-lib/list.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
RUN: rm -rf %t && mkdir -p %t
RUN: llvm-mc -triple=x86_64-pc-windows-msvc -filetype=obj -o %t/a.obj %S/Inputs/a.s
RUN: llvm-mc -triple=x86_64-pc-windows-msvc -filetype=obj -o %t/b.obj %S/Inputs/b.s

RUN: rm -f %t/l.lib
RUN: llvm-lib /out:%t/foo.lib %t/a.obj %t/b.obj

# This should ignore the two .obj files, then print the first .lib file,
# then ignore the 2nd one.
RUN: llvm-lib /list %t/a.obj %t/b.obj %t/foo.lib %t/foo.lib | FileCheck %s

CHECK: a.obj
CHECK: b.obj
CHECK-NOT: a.obj

0 comments on commit a2f6093

Please sign in to comment.