mstorsjo created this revision.
mstorsjo added reviewers: rnk, amccarth, thakis, hans.
Herald added subscribers: llvm-commits, hiraditya.
Herald added projects: clang, LLVM.
mstorsjo requested review of this revision.

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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D88002

Files:
  clang/lib/Driver/Driver.cpp
  clang/test/Driver/cl-inputs.c
  llvm/include/llvm/Support/Process.h
  llvm/lib/Support/Process.cpp


Index: llvm/lib/Support/Process.cpp
===================================================================
--- llvm/lib/Support/Process.cpp
+++ llvm/lib/Support/Process.cpp
@@ -28,21 +28,22 @@
 //===          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);
 
Index: llvm/include/llvm/Support/Process.h
===================================================================
--- llvm/include/llvm/Support/Process.h
+++ llvm/include/llvm/Support/Process.h
@@ -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 {
@@ -107,10 +108,12 @@
   /// 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
Index: clang/test/Driver/cl-inputs.c
===================================================================
--- clang/test/Driver/cl-inputs.c
+++ clang/test/Driver/cl-inputs.c
@@ -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
Index: clang/lib/Driver/Driver.cpp
===================================================================
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -2085,7 +2085,7 @@
 
   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) {


Index: llvm/lib/Support/Process.cpp
===================================================================
--- llvm/lib/Support/Process.cpp
+++ llvm/lib/Support/Process.cpp
@@ -28,21 +28,22 @@
 //===          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);
 
Index: llvm/include/llvm/Support/Process.h
===================================================================
--- llvm/include/llvm/Support/Process.h
+++ llvm/include/llvm/Support/Process.h
@@ -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 {
@@ -107,10 +108,12 @@
   /// 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
Index: clang/test/Driver/cl-inputs.c
===================================================================
--- clang/test/Driver/cl-inputs.c
+++ clang/test/Driver/cl-inputs.c
@@ -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
Index: clang/lib/Driver/Driver.cpp
===================================================================
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -2085,7 +2085,7 @@
 
   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) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to