Skip to content

Commit

Permalink
[clang-cl] Always interpret the LIB env var as separated with semicolons
Browse files Browse the repository at this point in the history
When cross compiling with clang-cl, clang splits the INCLUDE env
variable around semicolons (clang/lib/Driver/ToolChains/MSVC.cpp,
MSVCToolChain::AddClangSystemIncludeArgs) and lld splits the
LIB variable similarly (lld/COFF/Driver.cpp,
LinkerDriver::addLibSearchPaths). Therefore, the consensus for
cross compilation with clang-cl and lld-link seems to be to use
semicolons, despite path lists normally being separated by colons
on unix and EnvPathSeparator being set to that.

Therefore, handle the LIB variable similarly in Clang, when
handling lib file arguments when driving linking via Clang.

This fixes commands like "clang-cl test.c -Fetest.exe kernel32.lib" in
a cross compilation setting. Normally, most users call (lld-)link
directly, but meson happens to use this command syntax for
has_function() tests.

Differential Revision: https://reviews.llvm.org/D88002
  • Loading branch information
mstorsjo committed Sep 21, 2020
1 parent ead7c3c commit 4d85444
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 9 deletions.
2 changes: 1 addition & 1 deletion clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2085,7 +2085,7 @@ bool Driver::DiagnoseInputExistence(const DerivedArgList &Args, StringRef Value,

if (IsCLMode()) {
if (!llvm::sys::path::is_absolute(Twine(Value)) &&
llvm::sys::Process::FindInEnvPath("LIB", Value))
llvm::sys::Process::FindInEnvPath("LIB", Value, ';'))
return true;

if (Args.hasArg(options::OPT__SLASH_link) && Ty == types::TY_Object) {
Expand Down
4 changes: 3 additions & 1 deletion clang/test/Driver/cl-inputs.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@
// WARN-NOT: note

// MSYS2_ARG_CONV_EXCL tells MSYS2 to skip conversion of the specified argument.
// RUN: env LIB=%S/Inputs/cl-libs MSYS2_ARG_CONV_EXCL="/TP;/c" %clang_cl /c /TP cl-test.lib -### 2>&1 | FileCheck -check-prefix=TPlib %s
// Add a dummy "other" entry to the path as well, to check that it's split
// around semicolons even on unix.
// RUN: env LIB="other;%S/Inputs/cl-libs" MSYS2_ARG_CONV_EXCL="/TP;/c" %clang_cl /c /TP cl-test.lib -### 2>&1 | FileCheck -check-prefix=TPlib %s
// TPlib: warning: cl-test.lib: 'linker' input unused
// TPlib: warning: argument unused during compilation: '/TP'
// TPlib-NOT: cl-test.lib
Expand Down
7 changes: 5 additions & 2 deletions llvm/include/llvm/Support/Process.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "llvm/Support/Chrono.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Program.h"
#include <system_error>

namespace llvm {
Expand Down Expand Up @@ -107,10 +108,12 @@ class Process {
/// considered.
static Optional<std::string> FindInEnvPath(StringRef EnvName,
StringRef FileName,
ArrayRef<std::string> IgnoreList);
ArrayRef<std::string> IgnoreList,
char Separator = EnvPathSeparator);

static Optional<std::string> FindInEnvPath(StringRef EnvName,
StringRef FileName);
StringRef FileName,
char Separator = EnvPathSeparator);

// This functions ensures that the standard file descriptors (input, output,
// and error) are properly mapped to a file descriptor before we use any of
Expand Down
11 changes: 6 additions & 5 deletions llvm/lib/Support/Process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,22 @@ using namespace sys;
//=== independent code.
//===----------------------------------------------------------------------===//

Optional<std::string> Process::FindInEnvPath(StringRef EnvName,
StringRef FileName) {
return FindInEnvPath(EnvName, FileName, {});
Optional<std::string>
Process::FindInEnvPath(StringRef EnvName, StringRef FileName, char Separator) {
return FindInEnvPath(EnvName, FileName, {}, Separator);
}

Optional<std::string> Process::FindInEnvPath(StringRef EnvName,
StringRef FileName,
ArrayRef<std::string> IgnoreList) {
ArrayRef<std::string> IgnoreList,
char Separator) {
assert(!path::is_absolute(FileName));
Optional<std::string> FoundPath;
Optional<std::string> OptPath = Process::GetEnv(EnvName);
if (!OptPath.hasValue())
return FoundPath;

const char EnvPathSeparatorStr[] = {EnvPathSeparator, '\0'};
const char EnvPathSeparatorStr[] = {Separator, '\0'};
SmallVector<StringRef, 8> Dirs;
SplitString(OptPath.getValue(), Dirs, EnvPathSeparatorStr);

Expand Down

0 comments on commit 4d85444

Please sign in to comment.