blob: 57dfea357a3178efcbcae44c7b9260f6108de8e7 [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".
93static std::string relative_to_root(StringRef Path) {
94 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);
104 if (Path.endswith(":"))
105 Res = Root.drop_back();
106 else if (Path.startswith("//"))
107 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 Ueyamaaa00e962016-04-30 21:40:04 +0000113// Copies file Src to {Config->Reproduce}/Src.
114// Returns the new path relative to Config->Reproduce.
115static std::string copyFile(StringRef Src) {
116 std::string Relpath = relative_to_root(Src);
117 SmallString<128> Dest;
118 path::append(Dest, Config->Reproduce, Relpath);
119
Rui Ueyamacf0dd1e2016-04-26 20:41:32 +0000120 SmallString<128> Dir(Dest);
121 path::remove_filename(Dir);
Rui Ueyamaaa00e962016-04-30 21:40:04 +0000122 if (std::error_code EC = sys::fs::create_directories(Dir))
Rui Ueyamacf0dd1e2016-04-26 20:41:32 +0000123 error(EC, Dir + ": can't create directory");
Rui Ueyamacf0dd1e2016-04-26 20:41:32 +0000124 if (std::error_code EC = sys::fs::copy_file(Src, Dest))
125 error(EC, "failed to copy file: " + Dest);
Rui Ueyamaaa00e962016-04-30 21:40:04 +0000126 return Relpath;
127}
128
129// Quote a given string if it contains a space character.
130static std::string quote(StringRef S) {
131 if (S.find(' ') == StringRef::npos)
132 return S;
133 return ("\"" + S + "\"").str();
134}
135
136// Copies all input files to Config->Reproduce directory and
137// create a response file as "response.txt", so that you can re-run
138// the same command with the same inputs just by executing
139// "ld.lld @response.txt". Used by --reproduce. This feature is
140// supposed to be used by users to report an issue to LLD developers.
141void elf::saveLinkerInputs(const llvm::opt::InputArgList &Args) {
142 // Create the output directory.
143 if (std::error_code EC = sys::fs::create_directories(
144 Config->Reproduce, /*IgnoreExisting=*/false)) {
145 error(EC, Config->Reproduce + ": can't create directory");
146 return;
147 }
148
149 // Open "response.txt".
150 SmallString<128> Path;
151 path::append(Path, Config->Reproduce, "response.txt");
152 std::error_code EC;
153 raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::F_None);
154 check(EC);
155
156 // Dump the command line to response.txt while copying files
157 // and rewriting paths.
158 for (auto *Arg : Args) {
159 switch (Arg->getOption().getID()) {
160 case OPT_reproduce:
161 break;
162 case OPT_script:
163 OS << "--script ";
164 // fallthrough
165 case OPT_INPUT: {
166 StringRef Path = Arg->getValue();
167 if (fs::exists(Path))
168 OS << quote(copyFile(Path)) << "\n";
169 else
170 OS << quote(Path) << "\n";
171 break;
172 }
173 default:
174 OS << Arg->getAsString(Args) << "\n";
175 }
176 }
Rui Ueyamacf0dd1e2016-04-26 20:41:32 +0000177}
178
Rafael Espindolae0df00b2016-02-28 00:25:54 +0000179std::string elf::findFromSearchPaths(StringRef Path) {
Rui Ueyama52a15092015-10-11 03:28:42 +0000180 for (StringRef Dir : Config->SearchPaths) {
181 std::string FullPath = buildSysrootedPath(Dir, Path);
182 if (sys::fs::exists(FullPath))
183 return FullPath;
184 }
185 return "";
186}
187
Rui Ueyama4b02ca92015-10-11 03:28:39 +0000188// Searches a given library from input search paths, which are filled
189// from -L command line switches. Returns a path to an existent library file.
Rafael Espindolae0df00b2016-02-28 00:25:54 +0000190std::string elf::searchLibrary(StringRef Path) {
Rui Ueyama319d7302016-03-29 20:53:21 +0000191 if (Path.startswith(":"))
192 return findFromSearchPaths(Path.substr(1));
193 if (!Config->Static) {
194 std::string S = findFromSearchPaths(("lib" + Path + ".so").str());
Rui Ueyama52a15092015-10-11 03:28:42 +0000195 if (!S.empty())
196 return S;
Rui Ueyama4b02ca92015-10-11 03:28:39 +0000197 }
Rui Ueyama319d7302016-03-29 20:53:21 +0000198 return findFromSearchPaths(("lib" + Path + ".a").str());
Rui Ueyama4b02ca92015-10-11 03:28:39 +0000199}
200
201// Makes a path by concatenating Dir and File.
202// If Dir starts with '=' the result will be preceded by Sysroot,
203// which can be set with --sysroot command line switch.
Rafael Espindolae0df00b2016-02-28 00:25:54 +0000204std::string elf::buildSysrootedPath(StringRef Dir, StringRef File) {
Rui Ueyama4b02ca92015-10-11 03:28:39 +0000205 SmallString<128> Path;
206 if (Dir.startswith("="))
207 sys::path::append(Path, Config->Sysroot, Dir.substr(1), File);
208 else
209 sys::path::append(Path, Dir, File);
210 return Path.str();
211}