blob: 8174722d22bc311b6b580f3ea099e8d57642a314 [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;
Rui Ueyamacf0dd1e2016-04-26 20:41:32 +000026using namespace llvm::sys;
Michael J. Spencer84487f12015-07-24 21:03:07 +000027
28using namespace lld;
Rafael Espindolae0df00b2016-02-28 00:25:54 +000029using namespace lld::elf;
Michael J. Spencer84487f12015-07-24 21:03:07 +000030
31// Create OptTable
32
33// Create prefix string literals used in Options.td
34#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
35#include "Options.inc"
36#undef PREFIX
37
38// Create table mapping all options defined in Options.td
Rui Ueyama8fe7ce52016-04-02 19:15:26 +000039static const opt::OptTable::Info OptInfo[] = {
Michael J. Spencer84487f12015-07-24 21:03:07 +000040#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10) \
41 { \
42 X1, X2, X9, X10, OPT_##ID, opt::Option::KIND##Class, X8, X7, OPT_##GROUP, \
43 OPT_##ALIAS, X6 \
Rui Ueyama8fe7ce52016-04-02 19:15:26 +000044 },
Michael J. Spencer84487f12015-07-24 21:03:07 +000045#include "Options.inc"
46#undef OPTION
47};
48
Rui Ueyama8fe7ce52016-04-02 19:15:26 +000049ELFOptTable::ELFOptTable() : OptTable(OptInfo) {}
Michael J. Spencer84487f12015-07-24 21:03:07 +000050
51// Parses a given list of options.
Rui Ueyama15fa0352016-03-15 18:20:50 +000052opt::InputArgList ELFOptTable::parse(ArrayRef<const char *> Argv) {
Michael J. Spencer84487f12015-07-24 21:03:07 +000053 // Make InputArgList from string vectors.
Michael J. Spencer84487f12015-07-24 21:03:07 +000054 unsigned MissingIndex;
55 unsigned MissingCount;
56
Rui Ueyamaeeb22f82015-09-25 15:37:33 +000057 // Expand response files. '@<filename>' is replaced by the file's contents.
58 SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size());
Rui Ueyama15fa0352016-03-15 18:20:50 +000059 StringSaver Saver(Alloc);
Rui Ueyamaeeb22f82015-09-25 15:37:33 +000060 llvm::cl::ExpandResponseFiles(Saver, llvm::cl::TokenizeGNUCommandLine, Vec);
61
62 // Parse options and then do error checking.
Rui Ueyama15fa0352016-03-15 18:20:50 +000063 opt::InputArgList Args = this->ParseArgs(Vec, MissingIndex, MissingCount);
Michael J. Spencer84487f12015-07-24 21:03:07 +000064 if (MissingCount)
George Rimar57610422016-03-11 14:43:02 +000065 error(Twine("missing arg value for \"") + Args.getArgString(MissingIndex) +
Michael J. Spencer84487f12015-07-24 21:03:07 +000066 "\", expected " + Twine(MissingCount) +
67 (MissingCount == 1 ? " argument.\n" : " arguments"));
Rui Ueyamad5b5ab72015-09-24 18:55:33 +000068
69 iterator_range<opt::arg_iterator> Unknowns = Args.filtered(OPT_UNKNOWN);
70 for (auto *Arg : Unknowns)
George Rimar57610422016-03-11 14:43:02 +000071 warning("warning: unknown argument: " + Arg->getSpelling());
Rui Ueyamad5b5ab72015-09-24 18:55:33 +000072 if (Unknowns.begin() != Unknowns.end())
George Rimar57610422016-03-11 14:43:02 +000073 error("unknown argument(s) found");
Michael J. Spencer84487f12015-07-24 21:03:07 +000074 return Args;
75}
Rui Ueyama4b02ca92015-10-11 03:28:39 +000076
Rui Ueyama1eb9f442016-02-28 03:18:09 +000077void elf::printHelp(const char *Argv0) {
78 ELFOptTable Table;
79 Table.PrintHelp(outs(), Argv0, "lld", false);
80}
81
Rui Ueyama1abcf372016-02-28 03:18:07 +000082void elf::printVersion() {
83 outs() << "LLD " << getLLDVersion();
84 std::string S = getLLDRepositoryVersion();
85 if (!S.empty())
Rui Ueyama5bc2acd2016-03-13 23:07:42 +000086 outs() << " " << S;
87 outs() << "\n";
Rui Ueyama1abcf372016-02-28 03:18:07 +000088}
89
Rui Ueyamaaa00e962016-04-30 21:40:04 +000090// Makes a given pathname an absolute path first, and then remove
91// beginning /. For example, "../foo.o" is converted to "home/john/foo.o",
92// assuming that the current directory is "/home/john/bar".
Rui Ueyama9aea9572016-04-30 22:23:29 +000093static std::string relativeToRoot(StringRef Path) {
Rui Ueyamaaa00e962016-04-30 21:40:04 +000094 SmallString<128> Abs = Path;
95 if (std::error_code EC = fs::make_absolute(Abs))
96 fatal("make_absolute failed: " + EC.message());
97 path::remove_dots(Abs, /*remove_dot_dot=*/true);
Rui Ueyamacf0dd1e2016-04-26 20:41:32 +000098
Rui Ueyamaaa00e962016-04-30 21:40:04 +000099 // This is Windows specific. root_name() returns a drive letter
100 // (e.g. "c:") or a UNC name (//net). We want to keep it as part
101 // of the result.
Rui Ueyamacf0dd1e2016-04-26 20:41:32 +0000102 SmallString<128> Res;
Rui Ueyamaaa00e962016-04-30 21:40:04 +0000103 StringRef Root = path::root_name(Path);
Rui Ueyama38aa57d2016-04-30 22:20:27 +0000104 if (Root.endswith(":"))
Rui Ueyamaaa00e962016-04-30 21:40:04 +0000105 Res = Root.drop_back();
Rui Ueyama38aa57d2016-04-30 22:20:27 +0000106 else if (Root.startswith("//"))
Rui Ueyamaaa00e962016-04-30 21:40:04 +0000107 Res = Root.substr(2);
108
109 path::append(Res, path::relative_path(Abs));
Rui Ueyamacf0dd1e2016-04-26 20:41:32 +0000110 return Res.str();
111}
112
Rui Ueyama9aea9572016-04-30 22:23:29 +0000113static std::string getDestPath(StringRef Path) {
114 std::string Relpath = relativeToRoot(Path);
Rui Ueyamaaa00e962016-04-30 21:40:04 +0000115 SmallString<128> Dest;
116 path::append(Dest, Config->Reproduce, Relpath);
Rui Ueyama9aea9572016-04-30 22:23:29 +0000117 return Dest.str();
118}
Rui Ueyamaaa00e962016-04-30 21:40:04 +0000119
Rui Ueyama9aea9572016-04-30 22:23:29 +0000120// Copies file Src to {Config->Reproduce}/Src.
121void elf::copyInputFile(StringRef Src) {
122 std::string Dest = getDestPath(Src);
Rui Ueyamacf0dd1e2016-04-26 20:41:32 +0000123 SmallString<128> Dir(Dest);
124 path::remove_filename(Dir);
Rui Ueyama9aea9572016-04-30 22:23:29 +0000125 if (std::error_code EC = sys::fs::create_directories(Dir)) {
Rui Ueyamacf0dd1e2016-04-26 20:41:32 +0000126 error(EC, Dir + ": can't create directory");
Rui Ueyama9aea9572016-04-30 22:23:29 +0000127 return;
128 }
Rui Ueyamacf0dd1e2016-04-26 20:41:32 +0000129 if (std::error_code EC = sys::fs::copy_file(Src, Dest))
130 error(EC, "failed to copy file: " + Dest);
Rui Ueyamaaa00e962016-04-30 21:40:04 +0000131}
132
133// Quote a given string if it contains a space character.
134static std::string quote(StringRef S) {
135 if (S.find(' ') == StringRef::npos)
136 return S;
137 return ("\"" + S + "\"").str();
138}
139
140// Copies all input files to Config->Reproduce directory and
141// create a response file as "response.txt", so that you can re-run
142// the same command with the same inputs just by executing
143// "ld.lld @response.txt". Used by --reproduce. This feature is
144// supposed to be used by users to report an issue to LLD developers.
Rui Ueyama9aea9572016-04-30 22:23:29 +0000145void elf::createResponseFile(const llvm::opt::InputArgList &Args) {
Rui Ueyamaaa00e962016-04-30 21:40:04 +0000146 // Create the output directory.
147 if (std::error_code EC = sys::fs::create_directories(
148 Config->Reproduce, /*IgnoreExisting=*/false)) {
149 error(EC, Config->Reproduce + ": can't create directory");
150 return;
151 }
152
153 // Open "response.txt".
154 SmallString<128> Path;
155 path::append(Path, Config->Reproduce, "response.txt");
156 std::error_code EC;
157 raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::F_None);
158 check(EC);
159
160 // Dump the command line to response.txt while copying files
161 // and rewriting paths.
162 for (auto *Arg : Args) {
163 switch (Arg->getOption().getID()) {
164 case OPT_reproduce:
165 break;
166 case OPT_script:
167 OS << "--script ";
168 // fallthrough
169 case OPT_INPUT: {
170 StringRef Path = Arg->getValue();
171 if (fs::exists(Path))
Rui Ueyama9aea9572016-04-30 22:23:29 +0000172 OS << quote(getDestPath(Path)) << "\n";
Rui Ueyamaaa00e962016-04-30 21:40:04 +0000173 else
174 OS << quote(Path) << "\n";
175 break;
176 }
177 default:
178 OS << Arg->getAsString(Args) << "\n";
179 }
180 }
Rui Ueyamacf0dd1e2016-04-26 20:41:32 +0000181}
182
Rafael Espindolae0df00b2016-02-28 00:25:54 +0000183std::string elf::findFromSearchPaths(StringRef Path) {
Rui Ueyama52a15092015-10-11 03:28:42 +0000184 for (StringRef Dir : Config->SearchPaths) {
185 std::string FullPath = buildSysrootedPath(Dir, Path);
186 if (sys::fs::exists(FullPath))
187 return FullPath;
188 }
189 return "";
190}
191
Rui Ueyama4b02ca92015-10-11 03:28:39 +0000192// Searches a given library from input search paths, which are filled
193// from -L command line switches. Returns a path to an existent library file.
Rafael Espindolae0df00b2016-02-28 00:25:54 +0000194std::string elf::searchLibrary(StringRef Path) {
Rui Ueyama319d7302016-03-29 20:53:21 +0000195 if (Path.startswith(":"))
196 return findFromSearchPaths(Path.substr(1));
197 if (!Config->Static) {
198 std::string S = findFromSearchPaths(("lib" + Path + ".so").str());
Rui Ueyama52a15092015-10-11 03:28:42 +0000199 if (!S.empty())
200 return S;
Rui Ueyama4b02ca92015-10-11 03:28:39 +0000201 }
Rui Ueyama319d7302016-03-29 20:53:21 +0000202 return findFromSearchPaths(("lib" + Path + ".a").str());
Rui Ueyama4b02ca92015-10-11 03:28:39 +0000203}
204
205// Makes a path by concatenating Dir and File.
206// If Dir starts with '=' the result will be preceded by Sysroot,
207// which can be set with --sysroot command line switch.
Rafael Espindolae0df00b2016-02-28 00:25:54 +0000208std::string elf::buildSysrootedPath(StringRef Dir, StringRef File) {
Rui Ueyama4b02ca92015-10-11 03:28:39 +0000209 SmallString<128> Path;
210 if (Dir.startswith("="))
211 sys::path::append(Path, Config->Sysroot, Dir.substr(1), File);
212 else
213 sys::path::append(Path, Dir, File);
214 return Path.str();
215}