Skip to content

Commit 4d85444

Browse files
committed
[clang-cl] Always interpret the LIB env var as separated with semicolons
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
1 parent ead7c3c commit 4d85444

File tree

4 files changed

+15
-9
lines changed

4 files changed

+15
-9
lines changed

clang/lib/Driver/Driver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2085,7 +2085,7 @@ bool Driver::DiagnoseInputExistence(const DerivedArgList &Args, StringRef Value,
20852085

20862086
if (IsCLMode()) {
20872087
if (!llvm::sys::path::is_absolute(Twine(Value)) &&
2088-
llvm::sys::Process::FindInEnvPath("LIB", Value))
2088+
llvm::sys::Process::FindInEnvPath("LIB", Value, ';'))
20892089
return true;
20902090

20912091
if (Args.hasArg(options::OPT__SLASH_link) && Ty == types::TY_Object) {

clang/test/Driver/cl-inputs.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@
3232
// WARN-NOT: note
3333

3434
// MSYS2_ARG_CONV_EXCL tells MSYS2 to skip conversion of the specified argument.
35-
// 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
35+
// Add a dummy "other" entry to the path as well, to check that it's split
36+
// around semicolons even on unix.
37+
// 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
3638
// TPlib: warning: cl-test.lib: 'linker' input unused
3739
// TPlib: warning: argument unused during compilation: '/TP'
3840
// TPlib-NOT: cl-test.lib

llvm/include/llvm/Support/Process.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "llvm/Support/Chrono.h"
3030
#include "llvm/Support/DataTypes.h"
3131
#include "llvm/Support/Error.h"
32+
#include "llvm/Support/Program.h"
3233
#include <system_error>
3334

3435
namespace llvm {
@@ -107,10 +108,12 @@ class Process {
107108
/// considered.
108109
static Optional<std::string> FindInEnvPath(StringRef EnvName,
109110
StringRef FileName,
110-
ArrayRef<std::string> IgnoreList);
111+
ArrayRef<std::string> IgnoreList,
112+
char Separator = EnvPathSeparator);
111113

112114
static Optional<std::string> FindInEnvPath(StringRef EnvName,
113-
StringRef FileName);
115+
StringRef FileName,
116+
char Separator = EnvPathSeparator);
114117

115118
// This functions ensures that the standard file descriptors (input, output,
116119
// and error) are properly mapped to a file descriptor before we use any of

llvm/lib/Support/Process.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,22 @@ using namespace sys;
2828
//=== independent code.
2929
//===----------------------------------------------------------------------===//
3030

31-
Optional<std::string> Process::FindInEnvPath(StringRef EnvName,
32-
StringRef FileName) {
33-
return FindInEnvPath(EnvName, FileName, {});
31+
Optional<std::string>
32+
Process::FindInEnvPath(StringRef EnvName, StringRef FileName, char Separator) {
33+
return FindInEnvPath(EnvName, FileName, {}, Separator);
3434
}
3535

3636
Optional<std::string> Process::FindInEnvPath(StringRef EnvName,
3737
StringRef FileName,
38-
ArrayRef<std::string> IgnoreList) {
38+
ArrayRef<std::string> IgnoreList,
39+
char Separator) {
3940
assert(!path::is_absolute(FileName));
4041
Optional<std::string> FoundPath;
4142
Optional<std::string> OptPath = Process::GetEnv(EnvName);
4243
if (!OptPath.hasValue())
4344
return FoundPath;
4445

45-
const char EnvPathSeparatorStr[] = {EnvPathSeparator, '\0'};
46+
const char EnvPathSeparatorStr[] = {Separator, '\0'};
4647
SmallVector<StringRef, 8> Dirs;
4748
SplitString(OptPath.getValue(), Dirs, EnvPathSeparatorStr);
4849

0 commit comments

Comments
 (0)