Skip to content

Commit

Permalink
[llvm-libtool-darwin] Add support for -V option
Browse files Browse the repository at this point in the history
The -V option in cctools' libtool prints out the version number and
performs any specified operation. Add this option to LLVM's version.
cctools is more forgiving of invalid command lines when -V is specified,
but I think it's better to give errors instead of silently producing no
output.

Unfortunately, when -V is present, options that would otherwise be
required aren't anymore, so we need to perform some manual argument
validation.

Reviewed By: alexshap

Differential Revision: https://reviews.llvm.org/D86359
  • Loading branch information
smeenai committed Aug 24, 2020
1 parent 47b0262 commit 68bae34
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 6 deletions.
Expand Up @@ -10,7 +10,7 @@
# RUN: not llvm-libtool-darwin -static %t.input 2>&1 | \
# RUN: FileCheck %s --check-prefix=NO-OUTPUT

# NO-OUTPUT: for the -o option: must be specified at least once!
# NO-OUTPUT: for the -o option: must be specified

## Missing argument to -o:
# RUN: not llvm-libtool-darwin -static %t.input -o 2>&1 | \
Expand All @@ -22,7 +22,7 @@
# RUN: not llvm-libtool-darwin -static %t.input -o %t.lib1 -o %t.lib2 2>&1 | \
# RUN: FileCheck %s --check-prefix=DOUBLE-OUTPUT

# DOUBLE-OUTPUT: for the -o option: must occur exactly one time!
# DOUBLE-OUTPUT: for the -o option: may only occur zero or one times!

## Input file not found:
# RUN: not llvm-libtool-darwin -static -o %t.lib %t.missing 2>&1 | \
Expand Down
Expand Up @@ -2,4 +2,4 @@
# RUN: not llvm-libtool-darwin -o %t.lib %t.input 2>&1 | \
# RUN: FileCheck %s --check-prefix=MISSING-OPERATION

# MISSING-OPERATION: Library Type: option: must be specified at least once!
# MISSING-OPERATION: Library Type: option: must be specified
25 changes: 25 additions & 0 deletions llvm/test/tools/llvm-libtool-darwin/version.test
@@ -0,0 +1,25 @@
## Test the -V flag, which prints the version number to stdout. It also allows
## for no operation to be specified, but if an operation is specified, it should
## still occur and regular argument parsing errors should be surfaced (unlike
## cctools libtool, which silences all argument parsing errors when -V is
## specified).

## Test -V by itself
# RUN: llvm-libtool-darwin -V | FileCheck %s
## The specific version number, vendor string, etc. will differ across
## environments, so this is the most specific we can get.
# CHECK: LLVM version

## Parsing errors should not be surfaced when no operation is specified
# RUN: llvm-libtool-darwin -V -D -U | FileCheck %s

## Regular errors should occur when an operation is specified
# RUN: not llvm-libtool-darwin -V -static 2>&1 | FileCheck --check-prefix=ERROR %s
# ERROR: for the -o option: must be specified

## A valid command line should print the version and perform the operation
# RUN: yaml2obj %S/Inputs/input1.yaml -o %t-input1.o
# RUN: yaml2obj %S/Inputs/input2.yaml -o %t-input2.o
# RUN: llvm-libtool-darwin -static -o %t.lib %t-input1.o %t-input2.o -V | FileCheck %s
# RUN: llvm-libtool-darwin -static -o %t2.lib %t-input1.o %t-input2.o
# RUN: cmp %t.lib %t2.lib
32 changes: 29 additions & 3 deletions llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp
Expand Up @@ -32,7 +32,7 @@ typedef std::map<uint64_t, std::vector<NewArchiveMember>>
cl::OptionCategory LibtoolCategory("llvm-libtool-darwin Options");

static cl::opt<std::string> OutputFile("o", cl::desc("Specify output filename"),
cl::value_desc("filename"), cl::Required,
cl::value_desc("filename"),
cl::cat(LibtoolCategory));

static cl::list<std::string> InputFiles(cl::Positional,
Expand All @@ -44,14 +44,14 @@ static cl::opt<std::string> ArchType(
"arch_only", cl::desc("Specify architecture type for output library"),
cl::value_desc("arch_type"), cl::ZeroOrMore, cl::cat(LibtoolCategory));

enum class Operation { Static };
enum class Operation { None, Static };

static cl::opt<Operation> LibraryOperation(
cl::desc("Library Type: "),
cl::values(
clEnumValN(Operation::Static, "static",
"Produce a statically linked library from the input files")),
cl::Required, cl::cat(LibtoolCategory));
cl::init(Operation::None), cl::cat(LibtoolCategory));

static cl::opt<bool> DeterministicOption(
"D", cl::desc("Use zero for timestamps and UIDs/GIDs (Default)"),
Expand Down Expand Up @@ -81,6 +81,10 @@ static cl::list<std::string> LibrarySearchDirs(
" libraries"),
cl::ZeroOrMore, cl::Prefix, cl::cat(LibtoolCategory));

static cl::opt<bool>
VersionOption("V", cl::desc("Print the version number and exit"),
cl::cat(LibtoolCategory));

static const std::array<std::string, 3> StandardSearchDirs{
"/lib",
"/usr/lib",
Expand Down Expand Up @@ -444,6 +448,23 @@ static Expected<Config> parseCommandLine(int Argc, char **Argv) {
Config C;
cl::ParseCommandLineOptions(Argc, Argv, "llvm-libtool-darwin\n");

if (LibraryOperation == Operation::None) {
if (!VersionOption) {
std::string Error;
raw_string_ostream Stream(Error);
LibraryOperation.error("must be specified", "", Stream);
return createStringError(std::errc::invalid_argument, Error.c_str());
}
return C;
}

if (OutputFile.empty()) {
std::string Error;
raw_string_ostream Stream(Error);
OutputFile.error("must be specified", "o", Stream);
return createStringError(std::errc::invalid_argument, Error.c_str());
}

if (DeterministicOption && NonDeterministicOption)
return createStringError(std::errc::invalid_argument,
"cannot specify both -D and -U flags");
Expand Down Expand Up @@ -483,8 +504,13 @@ int main(int Argc, char **Argv) {
return EXIT_FAILURE;
}

if (VersionOption)
cl::PrintVersionMessage();

Config C = *ConfigOrErr;
switch (LibraryOperation) {
case Operation::None:
break;
case Operation::Static:
if (Error E = createStaticLibrary(C)) {
WithColor::defaultErrorHandler(std::move(E));
Expand Down

0 comments on commit 68bae34

Please sign in to comment.