blob: a662b3cfca5b0d118650cbc8cbb01e1cfceeae95 [file] [log] [blame]
Michael J. Spencer84487f12015-07-24 21:03:07 +00001//===- DriverUtils.cpp ----------------------------------------------------===//
2//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains utility functions for the driver. Because there
11// are so many small functions, we created this separate file to make
12// Driver.cpp less cluttered.
13//
14//===----------------------------------------------------------------------===//
15
16#include "Driver.h"
Rafael Espindola192e1fa2015-08-06 15:08:23 +000017#include "Error.h"
Rui Ueyama1abcf372016-02-28 03:18:07 +000018#include "lld/Config/Version.h"
Michael J. Spencer84487f12015-07-24 21:03:07 +000019#include "llvm/ADT/STLExtras.h"
Rui Ueyamaeeb22f82015-09-25 15:37:33 +000020#include "llvm/Support/CommandLine.h"
Rui Ueyama4b02ca92015-10-11 03:28:39 +000021#include "llvm/Support/FileSystem.h"
22#include "llvm/Support/Path.h"
Rui Ueyamac6e1b972015-10-11 18:19:01 +000023#include "llvm/Support/StringSaver.h"
Michael J. Spencer84487f12015-07-24 21:03:07 +000024
25using namespace llvm;
26
27using namespace lld;
Rafael Espindolae0df00b2016-02-28 00:25:54 +000028using namespace lld::elf;
Michael J. Spencer84487f12015-07-24 21:03:07 +000029
30// Create OptTable
31
32// Create prefix string literals used in Options.td
33#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
34#include "Options.inc"
35#undef PREFIX
36
37// Create table mapping all options defined in Options.td
38static const opt::OptTable::Info infoTable[] = {
39#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10) \
40 { \
41 X1, X2, X9, X10, OPT_##ID, opt::Option::KIND##Class, X8, X7, OPT_##GROUP, \
42 OPT_##ALIAS, X6 \
43 } \
44 ,
45#include "Options.inc"
46#undef OPTION
47};
48
49class ELFOptTable : public opt::OptTable {
50public:
Craig Topperf88d22972015-10-21 16:31:56 +000051 ELFOptTable() : OptTable(infoTable) {}
Michael J. Spencer84487f12015-07-24 21:03:07 +000052};
53
54// Parses a given list of options.
Rafael Espindolae0df00b2016-02-28 00:25:54 +000055opt::InputArgList elf::parseArgs(llvm::BumpPtrAllocator *A,
56 ArrayRef<const char *> Argv) {
Michael J. Spencer84487f12015-07-24 21:03:07 +000057 // Make InputArgList from string vectors.
58 ELFOptTable Table;
59 unsigned MissingIndex;
60 unsigned MissingCount;
61
Rui Ueyamaeeb22f82015-09-25 15:37:33 +000062 // Expand response files. '@<filename>' is replaced by the file's contents.
63 SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size());
Rui Ueyamac6e1b972015-10-11 18:19:01 +000064 StringSaver Saver(*A);
Rui Ueyamaeeb22f82015-09-25 15:37:33 +000065 llvm::cl::ExpandResponseFiles(Saver, llvm::cl::TokenizeGNUCommandLine, Vec);
66
67 // Parse options and then do error checking.
68 opt::InputArgList Args = Table.ParseArgs(Vec, MissingIndex, MissingCount);
Michael J. Spencer84487f12015-07-24 21:03:07 +000069 if (MissingCount)
Rui Ueyama21eecb42016-02-02 21:13:09 +000070 error(Twine("missing arg value for \"") + Args.getArgString(MissingIndex) +
Michael J. Spencer84487f12015-07-24 21:03:07 +000071 "\", expected " + Twine(MissingCount) +
72 (MissingCount == 1 ? " argument.\n" : " arguments"));
Rui Ueyamad5b5ab72015-09-24 18:55:33 +000073
74 iterator_range<opt::arg_iterator> Unknowns = Args.filtered(OPT_UNKNOWN);
75 for (auto *Arg : Unknowns)
76 warning("warning: unknown argument: " + Arg->getSpelling());
77 if (Unknowns.begin() != Unknowns.end())
Rui Ueyama21eecb42016-02-02 21:13:09 +000078 error("unknown argument(s) found");
Michael J. Spencer84487f12015-07-24 21:03:07 +000079 return Args;
80}
Rui Ueyama4b02ca92015-10-11 03:28:39 +000081
Rui Ueyama1eb9f442016-02-28 03:18:09 +000082void elf::printHelp(const char *Argv0) {
83 ELFOptTable Table;
84 Table.PrintHelp(outs(), Argv0, "lld", false);
85}
86
Rui Ueyama1abcf372016-02-28 03:18:07 +000087void elf::printVersion() {
88 outs() << "LLD " << getLLDVersion();
89 std::string S = getLLDRepositoryVersion();
90 if (!S.empty())
91 outs() << " " << S << "\n";
92}
93
Rafael Espindolae0df00b2016-02-28 00:25:54 +000094std::string elf::findFromSearchPaths(StringRef Path) {
Rui Ueyama52a15092015-10-11 03:28:42 +000095 for (StringRef Dir : Config->SearchPaths) {
96 std::string FullPath = buildSysrootedPath(Dir, Path);
97 if (sys::fs::exists(FullPath))
98 return FullPath;
99 }
100 return "";
101}
102
Rui Ueyama4b02ca92015-10-11 03:28:39 +0000103// Searches a given library from input search paths, which are filled
104// from -L command line switches. Returns a path to an existent library file.
Rafael Espindolae0df00b2016-02-28 00:25:54 +0000105std::string elf::searchLibrary(StringRef Path) {
Rui Ueyama4b02ca92015-10-11 03:28:39 +0000106 std::vector<std::string> Names;
107 if (Path[0] == ':') {
108 Names.push_back(Path.drop_front());
109 } else {
110 if (!Config->Static)
111 Names.push_back(("lib" + Path + ".so").str());
112 Names.push_back(("lib" + Path + ".a").str());
113 }
Rui Ueyama52a15092015-10-11 03:28:42 +0000114 for (const std::string &Name : Names) {
115 std::string S = findFromSearchPaths(Name);
116 if (!S.empty())
117 return S;
Rui Ueyama4b02ca92015-10-11 03:28:39 +0000118 }
Rui Ueyama21eecb42016-02-02 21:13:09 +0000119 return "";
Rui Ueyama4b02ca92015-10-11 03:28:39 +0000120}
121
122// Makes a path by concatenating Dir and File.
123// If Dir starts with '=' the result will be preceded by Sysroot,
124// which can be set with --sysroot command line switch.
Rafael Espindolae0df00b2016-02-28 00:25:54 +0000125std::string elf::buildSysrootedPath(StringRef Dir, StringRef File) {
Rui Ueyama4b02ca92015-10-11 03:28:39 +0000126 SmallString<128> Path;
127 if (Dir.startswith("="))
128 sys::path::append(Path, Config->Sysroot, Dir.substr(1), File);
129 else
130 sys::path::append(Path, Dir, File);
131 return Path.str();
132}