[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