[llvm] 1aed1e7 - [llvm-libtool-darwin] Add support for -l and -L

Sameer Arora via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 14 11:44:46 PDT 2020


Author: Sameer Arora
Date: 2020-08-14T11:44:17-07:00
New Revision: 1aed1e72e83d28889b6ca19f01266a733eda23ec

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

LOG: [llvm-libtool-darwin] Add support for -l and -L

Add support for passing in libraries via `-l` and `-L` options to
`llvm-libtool-darwin`.

Reviewed by jhenderson, smeenai

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

Added: 
    llvm/test/tools/llvm-libtool-darwin/L-and-l.test

Modified: 
    llvm/docs/CommandGuide/llvm-libtool-darwin.rst
    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 a5383c03da53..a3c7aba6cf50 100644
--- a/llvm/docs/CommandGuide/llvm-libtool-darwin.rst
+++ b/llvm/docs/CommandGuide/llvm-libtool-darwin.rst
@@ -50,6 +50,20 @@ OPTIONS
   Show help and usage for this command without grouping the options
   into categories.
 
+.. option:: -l <x>
+
+  Searches for the library libx.a in the library search path. If the string `<x>`
+  ends with '.o', then the library 'x' is searched for without prepending 'lib'
+  or appending '.a'. If the library is found, it is added to the list of input
+  files. Otherwise, an error is raised.
+
+.. option:: -L <dir>
+
+  Adds `<dir>` to the list of directories in which to search for libraries. The
+  directories are searched in the order in which they are specified with
+  :option:`-L` and before the default search path. The default search path
+  includes directories `/lib`, `/usr/lib` and `/usr/local/lib`.
+
 .. option:: -o <filename>
 
   Specify the output file name. Must be specified exactly once.

diff  --git a/llvm/test/tools/llvm-libtool-darwin/L-and-l.test b/llvm/test/tools/llvm-libtool-darwin/L-and-l.test
new file mode 100644
index 000000000000..182b923b4ec8
--- /dev/null
+++ b/llvm/test/tools/llvm-libtool-darwin/L-and-l.test
@@ -0,0 +1,135 @@
+## This test checks that -l and -L options work correctly.
+
+# RUN: yaml2obj %S/Inputs/input1.yaml -o %t-input1.o
+# RUN: yaml2obj %S/Inputs/input2.yaml -o %t-input2.o
+
+## Check that the library is recognised when it ends with '.o':
+# RUN: llvm-libtool-darwin -static -o %t.lib -l%basename_t.tmp-input1.o -l%basename_t.tmp-input2.o -L%T
+# RUN: llvm-ar t %t.lib | \
+# RUN:   FileCheck %s --check-prefix=CHECK-NAMES --implicit-check-not={{.}} -DPREFIX=%basename_t.tmp
+# RUN: llvm-nm --print-armap %t.lib | \
+# RUN:   FileCheck %s --check-prefix=CHECK-SYMBOLS -DPREFIX=%basename_t.tmp --match-full-lines
+
+# CHECK-NAMES:      [[PREFIX]]-input1.o
+# CHECK-NAMES-NEXT: [[PREFIX]]-input2.o
+
+# CHECK-SYMBOLS:      Archive map
+# CHECK-SYMBOLS-NEXT: _symbol1 in [[PREFIX]]-input1.o
+# CHECK-SYMBOLS-NEXT: _symbol2 in [[PREFIX]]-input2.o
+# CHECK-SYMBOLS-EMPTY:
+
+## Check that the library is recognised when prepended with 'lib' and appended with '.a':
+# RUN: rm -rf %t/dirname && mkdir -p %t/dirname
+# RUN: llvm-ar cr %t/dirname/libinput2.a %t-input2.o
+
+# RUN: llvm-libtool-darwin -static -o %t.lib -linput2 -L%t/dirname
+# RUN: llvm-ar t %t.lib | \
+# RUN:   FileCheck %s --check-prefix=SINGLE-NAMES --implicit-check-not={{.}} -DPREFIX=%basename_t.tmp
+# RUN: llvm-nm --print-armap %t.lib | \
+# RUN:   FileCheck %s --check-prefix=SINGLE-SYMBOLS -DPREFIX=%basename_t.tmp --match-full-lines
+
+# SINGLE-NAMES: [[PREFIX]]-input2.o
+
+# SINGLE-SYMBOLS:      Archive map
+# SINGLE-SYMBOLS-NEXT: _symbol2 in [[PREFIX]]-input2.o
+# SINGLE-SYMBOLS-EMPTY:
+
+## -l and -L option specified multiple times:
+# RUN: rm -rf %t/otherDirname && mkdir -p %t/otherDirname
+# RUN: llvm-ar cr %t/otherDirname/libinput1.a %t-input1.o
+
+# RUN: llvm-libtool-darwin -static -o %t.lib -linput2 -linput1 -L%t/dirname -L%t/otherDirname
+# RUN: llvm-ar t %t.lib | \
+# RUN:   FileCheck %s --check-prefix=OTHER-NAMES --implicit-check-not={{.}} -DPREFIX=%basename_t.tmp
+# RUN: llvm-nm --print-armap %t.lib | \
+# RUN:   FileCheck %s --check-prefix=OTHER-SYMBOLS -DPREFIX=%basename_t.tmp --match-full-lines
+
+# OTHER-NAMES:      [[PREFIX]]-input2.o
+# OTHER-NAMES-NEXT: [[PREFIX]]-input1.o
+
+# OTHER-SYMBOLS:      Archive map
+# OTHER-SYMBOLS-NEXT: _symbol2 in [[PREFIX]]-input2.o
+# OTHER-SYMBOLS-NEXT: _symbol1 in [[PREFIX]]-input1.o
+# OTHER-SYMBOLS-EMPTY:
+
+## Check that if multiple directories specified with -L have the same named file
+## in them, the file from the first directory is selected.
+# RUN: llvm-ar cr %t/otherDirname/libinput2.a %t-input1.o
+
+# RUN: llvm-libtool-darwin -static -o %t.lib -linput2 -L%t/dirname -L%t/otherDirname
+# RUN: llvm-ar t %t.lib | \
+# RUN:   FileCheck %s --check-prefix=SINGLE-NAMES --implicit-check-not={{.}} -DPREFIX=%basename_t.tmp
+# RUN: llvm-nm --print-armap %t.lib | \
+# RUN:   FileCheck %s --check-prefix=SINGLE-SYMBOLS -DPREFIX=%basename_t.tmp --match-full-lines
+
+## -l option combined with an input file:
+# RUN: llvm-libtool-darwin -static -o %t.lib %t-input1.o -linput2 -L%t/dirname
+# RUN: llvm-ar t %t.lib | \
+# RUN:   FileCheck %s --check-prefix=CHECK-NAMES --implicit-check-not={{.}} -DPREFIX=%basename_t.tmp
+# RUN: llvm-nm --print-armap %t.lib | \
+# RUN:   FileCheck %s --check-prefix=CHECK-SYMBOLS -DPREFIX=%basename_t.tmp --match-full-lines
+
+## Specify same -l option twice:
+## cctools' libtool raises a warning in this case.
+## The warning is not yet implemented for llvm-libtool-darwin.
+# RUN: llvm-libtool-darwin -static -o %t.lib -l%basename_t.tmp-input2.o -l%basename_t.tmp-input2.o -L%T
+# RUN: llvm-ar t %t.lib | \
+# RUN:   FileCheck %s --check-prefix=DOUBLE-NAMES --implicit-check-not={{.}} -DPREFIX=%basename_t.tmp
+# RUN: llvm-nm --print-armap %t.lib | \
+# RUN:   FileCheck %s --check-prefix=DOUBLE-SYMBOLS -DPREFIX=%basename_t.tmp --match-full-lines
+
+# DOUBLE-NAMES:      [[PREFIX]]-input2.o
+# DOUBLE-NAMES-NEXT: [[PREFIX]]-input2.o
+
+# DOUBLE-SYMBOLS:      Archive map
+# DOUBLE-SYMBOLS-NEXT: _symbol2 in [[PREFIX]]-input2.o
+# DOUBLE-SYMBOLS-NEXT: _symbol2 in [[PREFIX]]-input2.o
+# DOUBLE-SYMBOLS-EMPTY:
+
+## Check that an error is thrown when the input library cannot be found:
+# RUN: not llvm-libtool-darwin -static -o %t.lib -lfile-will-not-exist.o 2>&1 | \
+# RUN:   FileCheck %s --check-prefix=NOT-FOUND -DFILE=file-will-not-exist.o
+
+# NOT-FOUND: error: cannot locate file '[[FILE]]'
+
+## Check that an error is thrown when the input library cannot be found
+## (for a file prepended with 'lib' and appended with '.a'):
+# RUN: not llvm-libtool-darwin -static -o %t.lib -lfile-will-not-exist 2>&1 | \
+# RUN:   FileCheck %s --check-prefix=NOT-FOUND -DFILE=libfile-will-not-exist.a
+
+## Check that an error is thrown when the input library cannot be found
+## (since 'lib' and '.a' are added):
+# RUN: llvm-ar cr %t/dirname/file %t-input1.o
+# RUN: not llvm-libtool-darwin -static -o %t.lib -lfile -L%t/dirname 2>&1 | \
+# RUN:   FileCheck %s --check-prefix=NOT-FOUND -DFILE=libfile.a
+
+# RUN: llvm-ar cr %t/dirname/libfile.a %t-input1.o
+# RUN: not llvm-libtool-darwin -static -o %t.lib -llibfile.a -L%t/dirname 2>&1 | \
+# RUN:   FileCheck %s --check-prefix=NOT-FOUND -DFILE=liblibfile.a.a
+
+## Check that an error is thrown when the input library is not valid:
+# RUN: touch %t/dirname/not-valid.o
+# RUN: not llvm-libtool-darwin -static -o %t.lib -lnot-valid.o -L%t/dirname 2>&1 | \
+# RUN:   FileCheck %s --check-prefix=NOT-VALID -DFILE=not-valid.o
+
+# NOT-VALID: error: '[[FILE]]': The file was not recognized as a valid object file
+
+## Check that an error is thrown when the input library is not valid:
+## (for a file prepended with 'lib' and appended with '.a'):
+# RUN: touch %t/dirname/libnot-valid.a
+# RUN: not llvm-libtool-darwin -static -o %t.lib -lnot-valid -L%t/dirname 2>&1 | \
+# RUN:   FileCheck %s --check-prefix=NOT-VALID -DFILE=libnot-valid.a
+
+## Check that 'lib' and '.a' are not added to a file ending in '.o':
+# RUN: llvm-ar cr %t/dirname/libfoo.o.a %t-input1.o
+# RUN: not llvm-libtool-darwin -static -o %t.lib -lfoo.o -L%t/dirname 2>&1 | \
+# RUN:   FileCheck %s --check-prefix=NOT-FOUND -DFILE=foo.o
+
+## Check that 'lib' and '.a' are added to a file ending in any other extension
+## beside '.o' (e.g. '.ext'):
+# RUN: llvm-ar cr %t/dirname/libbar.ext.a %t-input2.o
+# RUN: llvm-libtool-darwin -static -o %t.lib -lbar.ext -L%t/dirname
+# RUN: llvm-ar t %t.lib | \
+# RUN:   FileCheck %s --check-prefix=SINGLE-NAMES --implicit-check-not={{.}} -DPREFIX=%basename_t.tmp
+# RUN: llvm-nm --print-armap %t.lib | \
+# RUN:   FileCheck %s --check-prefix=SINGLE-SYMBOLS -DPREFIX=%basename_t.tmp --match-full-lines

diff  --git a/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp b/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp
index e24167b28d78..a91f783519d4 100644
--- a/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp
+++ b/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp
@@ -66,12 +66,69 @@ static cl::opt<std::string>
              cl::desc("Pass in file containing a list of filenames"),
              cl::value_desc("listfile[,dirname]"), cl::cat(LibtoolCategory));
 
+static cl::list<std::string> Libraries(
+    "l",
+    cl::desc(
+        "l<x> searches for the library libx.a in the library search path. If"
+        " the string 'x' ends with '.o', then the library 'x' is searched for"
+        " without prepending 'lib' or appending '.a'"),
+    cl::ZeroOrMore, cl::Prefix, cl::cat(LibtoolCategory));
+
+static cl::list<std::string> LibrarySearchDirs(
+    "L",
+    cl::desc(
+        "L<dir> adds <dir> to the list of directories in which to search for"
+        " libraries"),
+    cl::ZeroOrMore, cl::Prefix, cl::cat(LibtoolCategory));
+
+static const std::array<std::string, 3> StandardSearchDirs{
+    "/lib",
+    "/usr/lib",
+    "/usr/local/lib",
+};
+
 struct Config {
   bool Deterministic = true; // Updated by 'D' and 'U' modifiers.
   uint32_t ArchCPUType;
   uint32_t ArchCPUSubtype;
 };
 
+static Expected<std::string> searchForFile(const Twine &FileName) {
+
+  auto FindLib =
+      [FileName](ArrayRef<std::string> SearchDirs) -> Optional<std::string> {
+    for (StringRef Dir : SearchDirs) {
+      SmallString<128> Path;
+      sys::path::append(Path, Dir, FileName);
+
+      if (sys::fs::exists(Path))
+        return std::string(Path);
+    }
+    return None;
+  };
+
+  Optional<std::string> Found = FindLib(LibrarySearchDirs);
+  if (!Found.hasValue())
+    Found = FindLib(StandardSearchDirs);
+  if (Found.hasValue())
+    return Found.getValue();
+
+  return createStringError(std::errc::invalid_argument,
+                           "cannot locate file '%s'", FileName.str().c_str());
+}
+
+static Error processCommandLineLibraries() {
+  for (StringRef BaseName : Libraries) {
+    Expected<std::string> FullPath = searchForFile(
+        BaseName.endswith(".o") ? BaseName.str() : "lib" + BaseName + ".a");
+    if (!FullPath)
+      return FullPath.takeError();
+    InputFiles.push_back(FullPath.get());
+  }
+
+  return Error::success();
+}
+
 static Error processFileList() {
   StringRef FileName, DirName;
   std::tie(FileName, DirName) = StringRef(FileList).rsplit(",");
@@ -393,6 +450,10 @@ static Expected<Config> parseCommandLine(int Argc, char **Argv) {
   else if (NonDeterministicOption)
     C.Deterministic = false;
 
+  if (!Libraries.empty())
+    if (Error E = processCommandLineLibraries())
+      return std::move(E);
+
   if (!FileList.empty())
     if (Error E = processFileList())
       return std::move(E);


        


More information about the llvm-commits mailing list