lld-link: Add --rsp-quoting= flag.
This ports https://reviews.llvm.org/D19425 from clang / https://reviews.llvm.org/D22015 from the ELF port to COFF lld. This can be useful when linking COFF files on a posix host. https://reviews.llvm.org/D37452 llvm-svn: 312594
This commit is contained in:
parent
79cdf36a2c
commit
a05cbb8b95
|
|
@ -202,6 +202,7 @@ static bool isDecorated(StringRef Sym) {
|
|||
// specified by /defaultlib.
|
||||
void LinkerDriver::parseDirectives(StringRef S) {
|
||||
ArgParser Parser;
|
||||
// .drectve is always tokenized using Windows shell rules.
|
||||
opt::InputArgList Args = Parser.parse(S);
|
||||
|
||||
for (auto *Arg : Args) {
|
||||
|
|
|
|||
|
|
@ -48,18 +48,17 @@ public:
|
|||
|
||||
class ArgParser {
|
||||
public:
|
||||
// Parses command line options.
|
||||
llvm::opt::InputArgList parse(llvm::ArrayRef<const char *> Args);
|
||||
|
||||
// Concatenate LINK environment varirable and given arguments and parse them.
|
||||
// Concatenate LINK environment variable and given arguments and parse them.
|
||||
llvm::opt::InputArgList parseLINK(std::vector<const char *> Args);
|
||||
|
||||
// Tokenizes a given string and then parses as command line options.
|
||||
llvm::opt::InputArgList parse(StringRef S) { return parse(tokenize(S)); }
|
||||
|
||||
private:
|
||||
// Parses command line options.
|
||||
llvm::opt::InputArgList parse(llvm::ArrayRef<const char *> Args);
|
||||
|
||||
std::vector<const char *> tokenize(StringRef S);
|
||||
std::vector<const char *> replaceResponseFiles(std::vector<const char *>);
|
||||
|
||||
COFFOptTable Table;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -38,8 +38,6 @@
|
|||
|
||||
using namespace llvm::COFF;
|
||||
using namespace llvm;
|
||||
using llvm::cl::ExpandResponseFiles;
|
||||
using llvm::cl::TokenizeWindowsCommandLine;
|
||||
using llvm::sys::Process;
|
||||
|
||||
namespace lld {
|
||||
|
|
@ -718,20 +716,40 @@ static const llvm::opt::OptTable::Info InfoTable[] = {
|
|||
|
||||
COFFOptTable::COFFOptTable() : OptTable(InfoTable, true) {}
|
||||
|
||||
// Parses a given list of options.
|
||||
opt::InputArgList ArgParser::parse(ArrayRef<const char *> ArgsArr) {
|
||||
// First, replace respnose files (@<file>-style options).
|
||||
std::vector<const char *> Argv = replaceResponseFiles(ArgsArr);
|
||||
static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &Args) {
|
||||
if (auto *Arg = Args.getLastArg(OPT_rsp_quoting)) {
|
||||
StringRef S = Arg->getValue();
|
||||
if (S != "windows" && S != "posix")
|
||||
error("invalid response file quoting: " + S);
|
||||
if (S == "windows")
|
||||
return cl::TokenizeWindowsCommandLine;
|
||||
return cl::TokenizeGNUCommandLine;
|
||||
}
|
||||
// The COFF linker always defaults to Windows quoting.
|
||||
return cl::TokenizeWindowsCommandLine;
|
||||
}
|
||||
|
||||
// Parses a given list of options.
|
||||
opt::InputArgList ArgParser::parse(ArrayRef<const char *> Argv) {
|
||||
// Make InputArgList from string vectors.
|
||||
unsigned MissingIndex;
|
||||
unsigned MissingCount;
|
||||
opt::InputArgList Args = Table.ParseArgs(Argv, MissingIndex, MissingCount);
|
||||
SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size());
|
||||
|
||||
// We need to get the quoting style for response files before parsing all
|
||||
// options so we parse here before and ignore all the options but
|
||||
// --rsp-quoting.
|
||||
opt::InputArgList Args = Table.ParseArgs(Vec, MissingIndex, MissingCount);
|
||||
|
||||
// Expand response files (arguments in the form of @<filename>)
|
||||
// and then parse the argument again.
|
||||
cl::ExpandResponseFiles(Saver, getQuotingStyle(Args), Vec);
|
||||
Args = Table.ParseArgs(Vec, MissingIndex, MissingCount);
|
||||
|
||||
// Print the real command line if response files are expanded.
|
||||
if (Args.hasArg(OPT_verbose) && ArgsArr.size() != Argv.size()) {
|
||||
if (Args.hasArg(OPT_verbose) && Argv.size() != Vec.size()) {
|
||||
std::string Msg = "Command line:";
|
||||
for (const char *S : Argv)
|
||||
for (const char *S : Vec)
|
||||
Msg += " " + std::string(S);
|
||||
message(Msg);
|
||||
}
|
||||
|
|
@ -746,17 +764,17 @@ opt::InputArgList ArgParser::parse(ArrayRef<const char *> ArgsArr) {
|
|||
// link.exe has an interesting feature. If LINK or _LINK_ environment
|
||||
// variables exist, their contents are handled as command line strings.
|
||||
// So you can pass extra arguments using them.
|
||||
opt::InputArgList ArgParser::parseLINK(std::vector<const char *> Args) {
|
||||
opt::InputArgList ArgParser::parseLINK(std::vector<const char *> Argv) {
|
||||
// Concatenate LINK env and command line arguments, and then parse them.
|
||||
if (Optional<std::string> S = Process::GetEnv("LINK")) {
|
||||
std::vector<const char *> V = tokenize(*S);
|
||||
Args.insert(Args.begin(), V.begin(), V.end());
|
||||
Argv.insert(Argv.begin(), V.begin(), V.end());
|
||||
}
|
||||
if (Optional<std::string> S = Process::GetEnv("_LINK_")) {
|
||||
std::vector<const char *> V = tokenize(*S);
|
||||
Args.insert(Args.begin(), V.begin(), V.end());
|
||||
Argv.insert(Argv.begin(), V.begin(), V.end());
|
||||
}
|
||||
return parse(Args);
|
||||
return parse(Argv);
|
||||
}
|
||||
|
||||
std::vector<const char *> ArgParser::tokenize(StringRef S) {
|
||||
|
|
@ -765,15 +783,6 @@ std::vector<const char *> ArgParser::tokenize(StringRef S) {
|
|||
return std::vector<const char *>(Tokens.begin(), Tokens.end());
|
||||
}
|
||||
|
||||
// Creates a new command line by replacing options starting with '@'
|
||||
// character. '@<filename>' is replaced by the file's contents.
|
||||
std::vector<const char *>
|
||||
ArgParser::replaceResponseFiles(std::vector<const char *> Argv) {
|
||||
SmallVector<const char *, 256> Tokens(Argv.data(), Argv.data() + Argv.size());
|
||||
ExpandResponseFiles(Saver, TokenizeWindowsCommandLine, Tokens);
|
||||
return std::vector<const char *>(Tokens.begin(), Tokens.end());
|
||||
}
|
||||
|
||||
void printHelp(const char *Argv0) {
|
||||
COFFOptTable Table;
|
||||
Table.PrintHelp(outs(), Argv0, "LLVM Linker", false);
|
||||
|
|
|
|||
|
|
@ -101,6 +101,8 @@ def help_q : Flag<["/?", "-?"], "">, Alias<help>;
|
|||
def nopdb : F<"nopdb">, HelpText<"Disable PDB generation for DWARF users">;
|
||||
def nosymtab : F<"nosymtab">;
|
||||
def msvclto : F<"msvclto">;
|
||||
def rsp_quoting : Joined<["--"], "rsp-quoting=">,
|
||||
HelpText<"Quoting style for response files, 'windows' (default) or 'posix'">;
|
||||
|
||||
// Flags for debugging
|
||||
def lldmap : F<"lldmap">;
|
||||
|
|
|
|||
|
|
@ -3,5 +3,23 @@
|
|||
# RUN: echo /out:%t.exe /entry:main %t.obj > %t.rsp
|
||||
# RUN: lld-link @%t.rsp /heap:0x3000
|
||||
# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
|
||||
|
||||
CHECK: SizeOfHeapReserve: 12288
|
||||
|
||||
# RUN: not lld-link --rsp-quoting=foobar @%t.rsp 2>&1 | \
|
||||
# RUN: FileCheck --check-prefix=INVRSP %s
|
||||
INVRSP: invalid response file quoting: foobar
|
||||
|
||||
# RUN: echo "blah\foo" > %t.rsp
|
||||
# RUN: not lld-link @%t.rsp 2>&1 | \
|
||||
# RUN: FileCheck --check-prefix=DEFRSP %s
|
||||
DEFRSP: error: could not open blah\foo
|
||||
|
||||
# RUN: echo "blah\foo" > %t.rsp
|
||||
# RUN: not lld-link --rsp-quoting=windows @%t.rsp 2>&1 | \
|
||||
# RUN: FileCheck --check-prefix=WINRSP %s
|
||||
WINRSP: error: could not open blah\foo
|
||||
|
||||
# RUN: echo "blah\foo" > %t.rsp
|
||||
# RUN: not lld-link --rsp-quoting=posix @%t.rsp 2>&1 | \
|
||||
# RUN: FileCheck --check-prefix=POSRSP %s
|
||||
POSRSP: error: could not open blahfoo
|
||||
|
|
|
|||
Loading…
Reference in New Issue