Peter Collingbourne | bc05163 | 2015-06-09 21:50:22 +0000 | [diff] [blame] | 1 | //===- LibDriver.cpp - lib.exe-compatible driver --------------------------===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // Defines an interface to a lib.exe-compatible driver that also understands |
| 11 | // bitcode files. Used by llvm-lib and lld-link2 /lib. |
| 12 | // |
| 13 | //===----------------------------------------------------------------------===// |
| 14 | |
| 15 | #include "llvm/LibDriver/LibDriver.h" |
| 16 | #include "llvm/ADT/STLExtras.h" |
| 17 | #include "llvm/Object/ArchiveWriter.h" |
| 18 | #include "llvm/Option/Arg.h" |
| 19 | #include "llvm/Option/ArgList.h" |
| 20 | #include "llvm/Option/Option.h" |
| 21 | #include "llvm/Support/CommandLine.h" |
Rafael Espindola | 454adf6 | 2015-06-13 12:49:52 +0000 | [diff] [blame] | 22 | #include "llvm/Support/StringSaver.h" |
Peter Collingbourne | bc05163 | 2015-06-09 21:50:22 +0000 | [diff] [blame] | 23 | #include "llvm/Support/Path.h" |
| 24 | #include "llvm/Support/raw_ostream.h" |
| 25 | |
| 26 | using namespace llvm; |
| 27 | |
| 28 | namespace { |
| 29 | |
| 30 | enum { |
| 31 | OPT_INVALID = 0, |
| 32 | #define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11) OPT_##ID, |
| 33 | #include "Options.inc" |
| 34 | #undef OPTION |
| 35 | }; |
| 36 | |
| 37 | #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; |
| 38 | #include "Options.inc" |
| 39 | #undef PREFIX |
| 40 | |
| 41 | static const llvm::opt::OptTable::Info infoTable[] = { |
| 42 | #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10) \ |
| 43 | { \ |
| 44 | X1, X2, X9, X10, OPT_##ID, llvm::opt::Option::KIND##Class, X8, X7, \ |
| 45 | OPT_##GROUP, OPT_##ALIAS, X6 \ |
| 46 | }, |
| 47 | #include "Options.inc" |
| 48 | #undef OPTION |
| 49 | }; |
| 50 | |
| 51 | class LibOptTable : public llvm::opt::OptTable { |
| 52 | public: |
| 53 | LibOptTable() : OptTable(infoTable, llvm::array_lengthof(infoTable), true) {} |
| 54 | }; |
| 55 | |
Alexander Kornienko | 70bc5f1 | 2015-06-19 15:57:42 +0000 | [diff] [blame] | 56 | } // namespace |
Peter Collingbourne | bc05163 | 2015-06-09 21:50:22 +0000 | [diff] [blame] | 57 | |
| 58 | static std::string getOutputPath(llvm::opt::InputArgList *Args) { |
| 59 | if (auto *Arg = Args->getLastArg(OPT_out)) |
| 60 | return Arg->getValue(); |
| 61 | for (auto *Arg : Args->filtered(OPT_INPUT)) { |
| 62 | if (!StringRef(Arg->getValue()).endswith_lower(".obj")) |
| 63 | continue; |
| 64 | SmallString<128> Val = StringRef(Arg->getValue()); |
| 65 | llvm::sys::path::replace_extension(Val, ".lib"); |
| 66 | return Val.str(); |
| 67 | } |
| 68 | llvm_unreachable("internal error"); |
| 69 | } |
| 70 | |
Peter Collingbourne | bc05163 | 2015-06-09 21:50:22 +0000 | [diff] [blame] | 71 | int llvm::libDriverMain(int Argc, const char **Argv) { |
| 72 | SmallVector<const char *, 20> NewArgv(Argv, Argv + Argc); |
Rafael Espindola | 454adf6 | 2015-06-13 12:49:52 +0000 | [diff] [blame] | 73 | BumpPtrAllocator Alloc; |
| 74 | BumpPtrStringSaver Saver(Alloc); |
Peter Collingbourne | bc05163 | 2015-06-09 21:50:22 +0000 | [diff] [blame] | 75 | cl::ExpandResponseFiles(Saver, cl::TokenizeWindowsCommandLine, NewArgv); |
| 76 | Argv = &NewArgv[0]; |
| 77 | Argc = static_cast<int>(NewArgv.size()); |
| 78 | |
| 79 | LibOptTable Table; |
| 80 | unsigned MissingIndex; |
| 81 | unsigned MissingCount; |
| 82 | std::unique_ptr<llvm::opt::InputArgList> Args( |
| 83 | Table.ParseArgs(&Argv[1], &Argv[Argc], MissingIndex, MissingCount)); |
| 84 | if (MissingCount) { |
| 85 | llvm::errs() << "missing arg value for \"" |
| 86 | << Args->getArgString(MissingIndex) |
| 87 | << "\", expected " << MissingCount |
| 88 | << (MissingCount == 1 ? " argument.\n" : " arguments.\n"); |
| 89 | return 1; |
| 90 | } |
| 91 | for (auto *Arg : Args->filtered(OPT_UNKNOWN)) |
| 92 | llvm::errs() << "ignoring unknown argument: " << Arg->getSpelling() << "\n"; |
| 93 | |
| 94 | if (Args->filtered_begin(OPT_INPUT) == Args->filtered_end()) { |
| 95 | llvm::errs() << "no input files.\n"; |
| 96 | return 1; |
| 97 | } |
| 98 | |
| 99 | std::vector<llvm::NewArchiveIterator> Members; |
| 100 | for (auto *Arg : Args->filtered(OPT_INPUT)) |
| 101 | Members.emplace_back(Arg->getValue(), |
| 102 | llvm::sys::path::filename(Arg->getValue())); |
| 103 | |
| 104 | std::pair<StringRef, std::error_code> Result = llvm::writeArchive( |
| 105 | getOutputPath(Args.get()), Members, /*WriteSymtab=*/true); |
| 106 | if (Result.second) { |
| 107 | if (Result.first.empty()) |
| 108 | Result.first = Argv[0]; |
| 109 | llvm::errs() << Result.first << ": " << Result.second.message() << "\n"; |
| 110 | return 1; |
| 111 | } |
| 112 | |
| 113 | return 0; |
| 114 | } |