diff options
author | Nico Weber <nicolasweber@gmx.de> | 2019-09-13 13:13:52 +0000 |
---|---|---|
committer | Nico Weber <nicolasweber@gmx.de> | 2019-09-13 13:13:52 +0000 |
commit | d48ea5da94165dbaba14b1281b74994fe970a7e0 (patch) | |
tree | 0f6a7804b6c93c6a00939ef6feb34b713ab1d9e8 | |
parent | 67503ba556cd4008179491db6d024ec0f9d9c9cd (diff) | |
download | bcm5719-llvm-d48ea5da94165dbaba14b1281b74994fe970a7e0.tar.gz bcm5719-llvm-d48ea5da94165dbaba14b1281b74994fe970a7e0.zip |
lld-link: Add a flag /lldignoreenv that makes lld-link ignore env vars.
This is useful for enforcing that builds are independent of the
environment; it can be used when all system library paths are added
via /libpath: already. It's similar ot cl.exe's /X flag.
Since it should also affect %LINK% (the other caller of
`Process::GetEnv` in lld/COFF), the early-option-parsing needs
to move around a bit. The options are:
- Add a manual loop over the argv ArrayRef and look for "/lldignoreenv".
This repeats the name of the flag in both Options.td and in
DriverUtils.cpp.
- Add yet another table.ParseArgs() call just for /lldignoreenv before
adding %LINK%.
- Use the existing early ParseArgs() that's there for --rsp-quoting and use
it for /lldignoreenv for %LINK% as well. This means --rsp-quoting
and /lldignoreenv can't be passed via %LINK%.
I went with the third approach.
Differential Revision: https://reviews.llvm.org/D67456
llvm-svn: 371852
-rw-r--r-- | lld/COFF/Driver.cpp | 5 | ||||
-rw-r--r-- | lld/COFF/Driver.h | 8 | ||||
-rw-r--r-- | lld/COFF/DriverUtils.cpp | 13 | ||||
-rw-r--r-- | lld/COFF/Options.td | 2 | ||||
-rw-r--r-- | lld/docs/ReleaseNotes.rst | 2 | ||||
-rw-r--r-- | lld/test/COFF/libpath.test | 13 | ||||
-rw-r--r-- | lld/test/COFF/linkenv.test | 5 |
7 files changed, 37 insertions, 11 deletions
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index b4457333eb5..b0214ce4c7c 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -1094,7 +1094,7 @@ void LinkerDriver::link(ArrayRef<const char *> argsArr) { // Parse command line options. ArgParser parser; - opt::InputArgList args = parser.parseLINK(argsArr); + opt::InputArgList args = parser.parse(argsArr); // Parse and evaluate -mllvm options. std::vector<const char *> v; @@ -1162,7 +1162,8 @@ void LinkerDriver::link(ArrayRef<const char *> argsArr) { searchPaths.push_back(""); for (auto *arg : args.filtered(OPT_libpath)) searchPaths.push_back(arg->getValue()); - addLibSearchPaths(); + if (!args.hasArg(OPT_lldignoreenv)) + addLibSearchPaths(); // Handle /ignore for (auto *arg : args.filtered(OPT_ignore)) { diff --git a/lld/COFF/Driver.h b/lld/COFF/Driver.h index 0fd61759540..cc2f25a6f95 100644 --- a/lld/COFF/Driver.h +++ b/lld/COFF/Driver.h @@ -43,8 +43,8 @@ public: class ArgParser { public: - // Concatenate LINK environment variable and given arguments and parse them. - llvm::opt::InputArgList parseLINK(std::vector<const char *> args); + // Parses command line options. + llvm::opt::InputArgList parse(llvm::ArrayRef<const char *> args); // Tokenizes a given string and then parses as command line options. llvm::opt::InputArgList parse(StringRef s) { return parse(tokenize(s)); } @@ -56,8 +56,8 @@ public: parseDirectives(StringRef s); private: - // Parses command line options. - llvm::opt::InputArgList parse(llvm::ArrayRef<const char *> args); + // Concatenate LINK environment variable. + void addLINK(SmallVector<const char *, 256> &argv); std::vector<const char *> tokenize(StringRef s); diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp index b525ffdae9c..e08b855740a 100644 --- a/lld/COFF/DriverUtils.cpp +++ b/lld/COFF/DriverUtils.cpp @@ -808,13 +808,17 @@ opt::InputArgList ArgParser::parse(ArrayRef<const char *> argv) { // 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. + // --rsp-quoting and /lldignoreenv. + // (This means --rsp-quoting can't be added through %LINK%.) opt::InputArgList args = table.ParseArgs(argv, missingIndex, missingCount); - // Expand response files (arguments in the form of @<filename>) - // and then parse the argument again. + + // Expand response files (arguments in the form of @<filename>) and insert + // flags from %LINK% and %_LINK_%, and then parse the argument again. SmallVector<const char *, 256> expandedArgv(argv.data(), argv.data() + argv.size()); + if (!args.hasArg(OPT_lldignoreenv)) + addLINK(expandedArgv); cl::ExpandResponseFiles(saver, getQuotingStyle(args), expandedArgv); args = table.ParseArgs(makeArrayRef(expandedArgv).drop_front(), missingIndex, missingCount); @@ -884,7 +888,7 @@ ArgParser::parseDirectives(StringRef s) { // 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 *> argv) { +void ArgParser::addLINK(SmallVector<const char *, 256> &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); @@ -894,7 +898,6 @@ opt::InputArgList ArgParser::parseLINK(std::vector<const char *> argv) { std::vector<const char *> v = tokenize(*s); argv.insert(std::next(argv.begin()), v.begin(), v.end()); } - return parse(argv); } std::vector<const char *> ArgParser::tokenize(StringRef s) { diff --git a/lld/COFF/Options.td b/lld/COFF/Options.td index 59e69ea5439..6b6555bc030 100644 --- a/lld/COFF/Options.td +++ b/lld/COFF/Options.td @@ -43,6 +43,8 @@ def lib : F<"lib">, HelpText<"Act like lib.exe; must be first argument if present">; def libpath : P<"libpath", "Additional library search path">; def linkrepro : P<"linkrepro", "Dump linker invocation and input files for debugging">; +def lldignoreenv : F<"lldignoreenv">, + HelpText<"Ignore environment variables like %LIB%">; def lldltocache : P<"lldltocache", "Path to ThinLTO cached object file directory">; def lldltocachepolicy : P<"lldltocachepolicy", "Pruning policy for the ThinLTO cache">; def lldsavetemps : F<"lldsavetemps">, diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst index e63f75bef90..9c91a64127c 100644 --- a/lld/docs/ReleaseNotes.rst +++ b/lld/docs/ReleaseNotes.rst @@ -32,6 +32,8 @@ COFF Improvements * /linkrepro: now takes the filename of the tar archive it writes, instead of the name of a directory that a file called "repro.tar" is created in, matching the behavior of ELF lld. +* The new `/lldignoreenv` flag makes lld-link ignore environment variables + like `%LIB%`. * ... MinGW Improvements diff --git a/lld/test/COFF/libpath.test b/lld/test/COFF/libpath.test index 77b4c546c99..baa8c2f2d50 100644 --- a/lld/test/COFF/libpath.test +++ b/lld/test/COFF/libpath.test @@ -24,3 +24,16 @@ CHECK2: a{{[/\\]}}std64.lib CHECK3: Reading {{.*}}a/std64.lib CHECK3-NOT: Reading {{.*}}b/std64.lib + +# RUN: env LIB=%t/a lld-link /out:%t.exe /entry:main /verbose \ +# RUN: std64.lib /subsystem:console %p/Inputs/hello64.obj \ +# RUN: 2> %t.log +# RUN: FileCheck -check-prefix=CHECK4 %s < %t.log + +CHECK4: a{{[/\\]}}std64.lib + +# This should fail because /lldignoreenv should make lld-link +# ignore the LIB env var. +# RUN: env LIB=%t/a not lld-link /out:%t.exe /entry:main /verbose \ +# RUN: std64.lib /subsystem:console %p/Inputs/hello64.obj \ +# RUN: /lldignoreenv diff --git a/lld/test/COFF/linkenv.test b/lld/test/COFF/linkenv.test index 6033094d6db..78d11fd5d0a 100644 --- a/lld/test/COFF/linkenv.test +++ b/lld/test/COFF/linkenv.test @@ -2,3 +2,8 @@ # RUN: env _LINK_=-help lld-link | FileCheck %s CHECK: OVERVIEW: LLVM Linker + +# RUN: env LINK=-help not lld-link /lldignoreenv 2>&1 | \ +# RUN: FileCheck --check-prefix=ERR %s + +ERR: error: no input files |