[llvm] d9a9192 - [llvm-libtool-darwin] Add support for -filelist option

Sameer Arora via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 7 14:30:04 PDT 2020


Author: Sameer Arora
Date: 2020-08-07T14:29:24-07:00
New Revision: d9a9192984fafb6a81616aafcdcf388fba7b8e14

URL: https://github.com/llvm/llvm-project/commit/d9a9192984fafb6a81616aafcdcf388fba7b8e14
DIFF: https://github.com/llvm/llvm-project/commit/d9a9192984fafb6a81616aafcdcf388fba7b8e14.diff

LOG: [llvm-libtool-darwin] Add support for -filelist option

Add support for `-filelist` option for llvm-libtool-darwin. `-filelist`
option allows for passing in a file containing a list of filenames.

Reviewed by jhenderson, smeenai

Differential Revision: https://reviews.llvm.org/D84206

Added: 
    llvm/test/tools/llvm-libtool-darwin/filelist.test

Modified: 
    llvm/docs/CommandGuide/llvm-libtool-darwin.rst
    llvm/test/tools/llvm-libtool-darwin/invalid-input-output-args.test
    llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/docs/CommandGuide/llvm-libtool-darwin.rst b/llvm/docs/CommandGuide/llvm-libtool-darwin.rst
index 6bae95c3a669..9ff876eccce2 100644
--- a/llvm/docs/CommandGuide/llvm-libtool-darwin.rst
+++ b/llvm/docs/CommandGuide/llvm-libtool-darwin.rst
@@ -46,6 +46,13 @@ OPTIONS
 
  Produces a static library from the input files.
 
+.. option:: -filelist <listfile[,dirname]>
+
+ Read input file names from `<listfile>`. File names are specified in `<listfile>`
+ one per line, separated only by newlines. Whitespace on a line is assumed
+ to be part of the filename. If the directory name, `dirname`, is also
+ specified then it is prepended to each file name in the `<listfile>`.
+
 EXIT STATUS
 -----------
 

diff  --git a/llvm/test/tools/llvm-libtool-darwin/filelist.test b/llvm/test/tools/llvm-libtool-darwin/filelist.test
new file mode 100644
index 000000000000..5e70309cbe48
--- /dev/null
+++ b/llvm/test/tools/llvm-libtool-darwin/filelist.test
@@ -0,0 +1,108 @@
+## This test checks that the -filelist option works correctly.
+
+# RUN: yaml2obj %S/Inputs/input1.yaml -o %t-input1.o
+# RUN: yaml2obj %S/Inputs/input2.yaml -o %t-input2.o
+
+## Passing files in a listfile:
+# RUN: echo %t-input1.o >  %t.files.txt
+# RUN: echo %t-input2.o >> %t.files.txt
+# RUN: llvm-libtool-darwin -static -o %t.lib -filelist %t.files.txt
+
+## Check that binaries are present:
+# RUN: llvm-ar t %t.lib | \
+# RUN:   FileCheck %s --check-prefix=CHECK-NAMES --implicit-check-not={{.}} -DPREFIX=%basename_t.tmp
+
+# CHECK-NAMES:      [[PREFIX]]-input1.o
+# CHECK-NAMES-NEXT: [[PREFIX]]-input2.o
+
+## Check that symbols are present:
+# RUN: llvm-nm --print-armap %t.lib | \
+# RUN:   FileCheck %s --check-prefix=CHECK-SYMBOLS -DPREFIX=%basename_t.tmp --match-full-lines
+
+# CHECK-SYMBOLS:      Archive map
+# CHECK-SYMBOLS-NEXT: _symbol1 in [[PREFIX]]-input1.o
+# CHECK-SYMBOLS-NEXT: _symbol2 in [[PREFIX]]-input2.o
+# CHECK-SYMBOLS-EMPTY:
+
+# RUN: rm -rf %t/dirname && mkdir -p %t/dirname
+# RUN: yaml2obj %S/Inputs/input1.yaml -o %t/dirname/%basename_t.tmp-input1.o
+# RUN: echo %basename_t.tmp-input1.o > %t.files.txt
+
+## Passing in dirname:
+# RUN: llvm-libtool-darwin -static -o %t.lib -filelist %t.files.txt,%t/dirname
+# RUN: llvm-ar t %t.lib | \
+# RUN:   FileCheck %s --check-prefix=DIRNAME-NAMES --implicit-check-not={{.}} -DPREFIX=%basename_t.tmp
+# RUN: llvm-nm --print-armap %t.lib | \
+# RUN:   FileCheck %s --check-prefix=DIRNAME-SYMBOLS -DPREFIX=%basename_t.tmp --match-full-lines
+
+# DIRNAME-NAMES:      [[PREFIX]]-input1.o
+
+# DIRNAME-SYMBOLS:      Archive map
+# DIRNAME-SYMBOLS-NEXT: _symbol1 in [[PREFIX]]-input1.o
+# DIRNAME-SYMBOLS-EMPTY:
+
+## Passing both -filelist option and object file as input:
+# RUN: llvm-libtool-darwin -static -o %t.lib -filelist %t.files.txt,%t/dirname %t-input2.o
+# RUN: llvm-ar t %t.lib | \
+# RUN:   FileCheck %s --check-prefix=REVERSE-NAMES --implicit-check-not={{.}} -DPREFIX=%basename_t.tmp
+# RUN: llvm-nm --print-armap %t.lib | \
+# RUN:   FileCheck %s --check-prefix=REVERSE-SYMBOLS -DPREFIX=%basename_t.tmp --match-full-lines
+
+# REVERSE-NAMES:      [[PREFIX]]-input2.o
+# REVERSE-NAMES-NEXT: [[PREFIX]]-input1.o
+
+# REVERSE-SYMBOLS:      Archive map
+# REVERSE-SYMBOLS-NEXT: _symbol2 in [[PREFIX]]-input2.o
+# REVERSE-SYMBOLS-NEXT: _symbol1 in [[PREFIX]]-input1.o
+# REVERSE-SYMBOLS-EMPTY:
+
+## Check that an error is thrown when a file in the filelist doesn't exist in the cwd and no dirname is specified:
+# RUN: echo 'no-such-file' > %t.invalid-list.txt
+# RUN: not llvm-libtool-darwin -static -o %t.lib -filelist %t.invalid-list.txt 2>&1 | \
+# RUN:   FileCheck %s --check-prefix=FILE-ERROR -DFILE=no-such-file
+
+# FILE-ERROR: error: '[[FILE]]': {{[nN]}}o such file or directory
+
+## Check that an error is thrown when the directory exists but does not contain the requested file:
+# RUN: not llvm-libtool-darwin -static -o %t.lib -filelist %t.invalid-list.txt,%t/dirname 2>&1 | \
+# RUN:   FileCheck %s --check-prefix=DIR-ERROR -DDIR=%t/dirname -DFILE=no-such-file
+
+# DIR-ERROR: error: '[[DIR]]{{[/\\]}}[[FILE]]': {{[nN]}}o such file or directory
+
+## Check that an error is thrown when a file is in the cwd but dirname is specified:
+# RUN: yaml2obj %S/Inputs/input2.yaml -o %basename_t.tmp-input2.o
+# RUN: echo %basename_t.tmp-input2.o > %t.files-cwd.txt
+# RUN: not llvm-libtool-darwin -static -o %t.lib -filelist %t.files-cwd.txt,%t/dirname 2>&1 | \
+# RUN:   FileCheck %s --check-prefix=DIR-ERROR -DDIR=%t/dirname -DFILE=%basename_t.tmp-input2.o
+
+## Check that an error is thrown when the directory doesn't exist:
+# RUN: not llvm-libtool-darwin -static -o %t.lib -filelist %t.files-cwd.txt,%t/Invalid-Dir 2>&1 | \
+# RUN:   FileCheck %s --check-prefix=DIR-ERROR -DDIR=%t/Invalid-Dir -DFILE=%basename_t.tmp-input2.o
+
+## Check that an error is thrown when the filelist is empty:
+# RUN: touch %t.empty-list
+# RUN: not llvm-libtool-darwin -static -o %t.lib -filelist %t.empty-list 2>&1 | \
+# RUN:   FileCheck %s --check-prefix=EMPTY-ERROR -DFILE=%t.empty-list
+
+# EMPTY-ERROR: error: file list file: '[[FILE]]' is empty
+
+## Check that an error is thrown when the filelist contains a blank line:
+# RUN: echo %t-input2.o > %t.blank-line.txt
+# RUN: echo '' >> %t.blank-line.txt
+# RUN: not llvm-libtool-darwin -static -o %t.lib -filelist %t.blank-line.txt 2>&1 | \
+# RUN:   FileCheck %s --check-prefix=EMPTY-FILENAME -DFILE=%t.blank-line.txt
+
+# EMPTY-FILENAME: error: file list file: '[[FILE]]': filename cannot be empty
+
+## Check that an error is thrown when the filelist contains a line with only spaces:
+# RUN: echo %t-input2.o > %t.space-line.txt
+# RUN: echo "     " >> %t.space-line.txt
+# RUN: not llvm-libtool-darwin -static -o %t.lib -filelist %t.space-line.txt 2>&1 | \
+# RUN:   FileCheck %s --check-prefix=FILE-ERROR -DFILE='     ' --strict-whitespace
+
+## Filelist option specified more than once:
+# RUN: touch %t.list1.txt and %t.list2.txt
+# RUN: not llvm-libtool-darwin -static -o %t.lib -filelist %t.list1.txt -filelist %t.list2.txt 2>&1 | \
+# RUN:   FileCheck %s --check-prefix=DUPLICATE-ERROR
+
+# DUPLICATE-ERROR: for the --filelist option: may only occur zero or one times!

diff  --git a/llvm/test/tools/llvm-libtool-darwin/invalid-input-output-args.test b/llvm/test/tools/llvm-libtool-darwin/invalid-input-output-args.test
index 66ee65b26244..31ff43f62400 100644
--- a/llvm/test/tools/llvm-libtool-darwin/invalid-input-output-args.test
+++ b/llvm/test/tools/llvm-libtool-darwin/invalid-input-output-args.test
@@ -4,7 +4,7 @@
 # RUN: not llvm-libtool-darwin -static -o %t.lib 2>&1 | \
 # RUN:   FileCheck %s --check-prefix=NO-INPUT
 
-# NO-INPUT: Must specify at least 1 positional argument
+# NO-INPUT: error: no input files specified
 
 ## Missing output file:
 # RUN: not llvm-libtool-darwin -static %t.input 2>&1 | \

diff  --git a/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp b/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp
index bd1d9ac07c69..d5eccafbe46f 100644
--- a/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp
+++ b/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp
@@ -16,6 +16,7 @@
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/LineIterator.h"
 #include "llvm/Support/WithColor.h"
 
 using namespace llvm;
@@ -29,7 +30,7 @@ static cl::opt<std::string> OutputFile("o", cl::desc("Specify output filename"),
 
 static cl::list<std::string> InputFiles(cl::Positional,
                                         cl::desc("<input files>"),
-                                        cl::OneOrMore,
+                                        cl::ZeroOrMore,
                                         cl::cat(LibtoolCategory));
 
 enum class Operation { Static };
@@ -41,6 +42,44 @@ static cl::opt<Operation> LibraryOperation(
                    "Produce a statically linked library from the input files")),
     cl::Required, cl::cat(LibtoolCategory));
 
+static cl::opt<std::string>
+    FileList("filelist",
+             cl::desc("Pass in file containing a list of filenames"),
+             cl::value_desc("listfile[,dirname]"), cl::cat(LibtoolCategory));
+
+static Error processFileList() {
+  StringRef FileName, DirName;
+  std::tie(FileName, DirName) = StringRef(FileList).rsplit(",");
+
+  ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
+      MemoryBuffer::getFileOrSTDIN(FileName, /*FileSize=*/-1,
+                                   /*RequiresNullTerminator=*/false);
+  if (std::error_code EC = FileOrErr.getError())
+    return createFileError(FileName, errorCodeToError(EC));
+  const MemoryBuffer &Ref = *FileOrErr.get();
+
+  line_iterator I(Ref, /*SkipBlanks=*/false);
+  if (I.is_at_eof())
+    return createStringError(std::errc::invalid_argument,
+                             "file list file: '%s' is empty",
+                             FileName.str().c_str());
+  for (; !I.is_at_eof(); ++I) {
+    StringRef Line = *I;
+    if (Line.empty())
+      return createStringError(std::errc::invalid_argument,
+                               "file list file: '%s': filename cannot be empty",
+                               FileName.str().c_str());
+
+    SmallString<128> Path;
+    if (!DirName.empty())
+      sys::path::append(Path, DirName, Line);
+    else
+      sys::path::append(Path, Line);
+    InputFiles.push_back(static_cast<std::string>(Path));
+  }
+  return Error::success();
+}
+
 static Error verifyMachOObject(const NewArchiveMember &Member) {
   auto MBRef = Member.Buf->getMemBufferRef();
   Expected<std::unique_ptr<object::ObjectFile>> ObjOrErr =
@@ -135,12 +174,25 @@ int main(int Argc, char **Argv) {
   InitLLVM X(Argc, Argv);
   cl::HideUnrelatedOptions({&LibtoolCategory, &ColorCategory});
   cl::ParseCommandLineOptions(Argc, Argv, "llvm-libtool-darwin\n");
+  if (!FileList.empty()) {
+    if (Error E = processFileList()) {
+      WithColor::defaultErrorHandler(std::move(E));
+      return EXIT_FAILURE;
+    }
+  }
+
+  if (InputFiles.empty()) {
+    Error E = createStringError(std::errc::invalid_argument,
+                                "no input files specified");
+    WithColor::defaultErrorHandler(std::move(E));
+    return EXIT_FAILURE;
+  }
 
   switch (LibraryOperation) {
   case Operation::Static:
     if (Error E = createStaticLibrary()) {
       WithColor::defaultErrorHandler(std::move(E));
-      exit(EXIT_FAILURE);
+      return EXIT_FAILURE;
     }
     break;
   }


        


More information about the llvm-commits mailing list