Fix mingw toolchain to honor sysroot on Linux and add tests.
authorYaron Keren <yaron.keren@gmail.com>
Tue, 21 Jul 2015 11:01:00 +0000 (11:01 +0000)
committerYaron Keren <yaron.keren@gmail.com>
Tue, 21 Jul 2015 11:01:00 +0000 (11:01 +0000)
It should now support three mingw distributions running on Windows
and three Linux distributions. The include directories for each are
listed in the comments.

llvm-svn: 242766

clang/lib/Driver/MinGWToolChain.cpp
clang/lib/Driver/ToolChains.h
clang/test/Driver/mingw-linux.cpp [new file with mode: 0644]
clang/test/Driver/mingw-win.cpp [new file with mode: 0644]

index ee19bb2..f4862ca 100644 (file)
@@ -20,35 +20,10 @@ using namespace clang::driver::toolchains;
 using namespace clang;
 using namespace llvm::opt;
 
-MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
-    : ToolChain(D, Triple, Args) {
-  getProgramPaths().push_back(getDriver().getInstalledDir());
-
-  llvm::SmallString<1024> LibDir;
-
-  // In Windows there aren't any standard install locations, we search
-  // for gcc on the PATH. In Linux the base is always /usr.
-#ifdef LLVM_ON_WIN32
-  if (getDriver().SysRoot.size())
-    Base = getDriver().SysRoot;
-  else if (llvm::ErrorOr<std::string> GPPName =
-               llvm::sys::findProgramByName("gcc"))
-    Base = llvm::sys::path::parent_path(
-        llvm::sys::path::parent_path(GPPName.get()));
-  else
-    Base = llvm::sys::path::parent_path(getDriver().getInstalledDir());
-  Base += llvm::sys::path::get_separator();
-#else
-  if (getDriver().SysRoot.size())
-    Base = getDriver().SysRoot;
-  else
-    Base = "/usr/";
-#endif
-
-  // By default Arch is for mingw-w64.
-  Arch = (getTriple().getArchName() + "-w64-mingw32").str();
+void MinGW::findGccLibDir() {
   // lib: Arch Linux, Ubuntu, Windows
   // lib64: openSUSE Linux
+  llvm::SmallString<1024> LibDir;
   for (StringRef Lib : {"lib", "lib64"}) {
     LibDir = Base;
     llvm::sys::path::append(LibDir, Lib, "gcc");
@@ -58,7 +33,6 @@ MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
     llvm::sys::fs::directory_iterator MingW64Entry(LibDir + Arch, EC);
     if (!EC) {
       GccLibDir = MingW64Entry->path();
-      Ver = llvm::sys::path::filename(GccLibDir);
       break;
     }
     // If mingw-w64 not found, try looking for mingw.org.
@@ -66,12 +40,41 @@ MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
     if (!EC) {
       GccLibDir = MingwOrgEntry->path();
       // Replace Arch with mingw32 arch.
-      Arch = "mingw32";
+      Arch = "mingw32//";
       break;
     }
   }
+}
+
+MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
+    : ToolChain(D, Triple, Args) {
+  getProgramPaths().push_back(getDriver().getInstalledDir());
+
+  // Default Arch is mingw-w64.
+  Arch = (getTriple().getArchName() + "-w64-mingw32" +
+          llvm::sys::path::get_separator()).str();
+
+// In Windows there aren't any standard install locations, we search
+// for gcc on the PATH. In Linux the base is always /usr.
+#ifdef LLVM_ON_WIN32
+  if (getDriver().SysRoot.size())
+    Base = getDriver().SysRoot;
+  else if (llvm::ErrorOr<std::string> GPPName =
+               llvm::sys::findProgramByName("gcc"))
+    Base = llvm::sys::path::parent_path(
+        llvm::sys::path::parent_path(GPPName.get()));
+  else
+    Base = llvm::sys::path::parent_path(getDriver().getInstalledDir());
+#else
+  Base = "/usr";
+#endif
 
-  Arch += llvm::sys::path::get_separator();
+  Base += llvm::sys::path::get_separator();
+  if (getDriver().SysRoot.size())
+    GccLibDir = getDriver().SysRoot;
+  else
+    findGccLibDir();
+  Ver = llvm::sys::path::filename(GccLibDir);
   // GccLibDir must precede Base/lib so that the
   // correct crtbegin.o ,cetend.o would be found.
   getFilePaths().push_back(GccLibDir);
@@ -123,6 +126,58 @@ bool MinGW::UseSEHExceptions() const {
   return getArch() == llvm::Triple::x86_64;
 }
 
+// Include directories for various hosts:
+
+// Windows, mingw.org
+// c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\r
+// c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\mingw32\r
+// c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\backward\r
+// c:\mingw\lib\gcc\mingw32\4.8.1\include\r
+// c:\mingw\include\r
+// c:\mingw\lib\gcc\mingw32\4.8.1\include-fixed\r
+// c:\mingw\mingw32\include
+
+// Windows, mingw-w64 mingw-builds
+// c:\mingw32\lib\gcc\i686-w64-mingw32\4.9.1\include\r
+// c:\mingw32\lib\gcc\i686-w64-mingw32\4.9.1\include-fixed\r
+// c:\mingw32\i686-w64-mingw32\include\r
+// c:\mingw32\i686-w64-mingw32\include\c++\r
+// c:\mingw32\i686-w64-mingw32\include\c++\i686-w64-mingw32\r
+// c:\mingw32\i686-w64-mingw32\include\c++\backward\r
+
+// Windows, mingw-w64 msys2
+// c:\msys64\mingw32\lib\gcc\i686-w64-mingw32\4.9.2\include\r
+// c:\msys64\mingw32\include\r
+// c:\msys64\mingw32\lib\gcc\i686-w64-mingw32\4.9.2\include-fixed\r
+// c:\msys64\mingw32\i686-w64-mingw32\include\r
+// c:\msys64\mingw32\include\c++\4.9.2\r
+// c:\msys64\mingw32\include\c++\4.9.2\i686-w64-mingw32\r
+// c:\msys64\mingw32\include\c++\4.9.2\backward
+
+// openSUSE
+// /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++
+// /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/x86_64-w64-mingw32
+// /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/backward
+// /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include
+// /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include-fixed
+// /usr/x86_64-w64-mingw32/sys-root/mingw/include
+
+// Arch Linux
+// /usr/i686-w64-mingw32/include/c++/5.1.0\r
+// /usr/i686-w64-mingw32/include/c++/5.1.0/i686-w64-mingw32\r
+// /usr/i686-w64-mingw32/include/c++/5.1.0/backward\r
+// /usr/lib/gcc/i686-w64-mingw32/5.1.0/include\r
+// /usr/lib/gcc/i686-w64-mingw32/5.1.0/include-fixed\r
+// /usr/i686-w64-mingw32/include
+
+// Ubuntu
+// /usr/include/c++/4.8\r
+// /usr/include/c++/4.8/x86_64-w64-mingw32\r
+// /usr/include/c++/4.8/backward\r
+// /usr/lib/gcc/x86_64-w64-mingw32/4.8/include\r
+// /usr/lib/gcc/x86_64-w64-mingw32/4.8/include-fixed\r
+// /usr/x86_64-w64-mingw32/include\r
+
 void MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
                                       ArgStringList &CC1Args) const {
   if (DriverArgs.hasArg(options::OPT_nostdinc))
@@ -157,19 +212,6 @@ void MinGW::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
       DriverArgs.hasArg(options::OPT_nostdincxx))
     return;
 
-  // C++ includes locations are different with almost every mingw distribution.
-  //
-  // Windows
-  // -------
-  // mingw-w64 mingw-builds: $sysroot/i686-w64-mingw32/include/c++
-  // mingw-w64 msys2:        $sysroot/include/c++/4.9.2
-  // mingw.org:              GccLibDir/include/c++
-  //
-  // Linux
-  // -----
-  // openSUSE:               GccLibDir/include/c++
-  // Arch:                   $sysroot/i686-w64-mingw32/include/c++/5.1.0
-  //
   llvm::SmallVector<llvm::SmallString<1024>, 4> CppIncludeBases;
   CppIncludeBases.emplace_back(Base);
   llvm::sys::path::append(CppIncludeBases[0], Arch, "include", "c++");
index 56a94ab..2d1e789 100644 (file)
@@ -556,6 +556,7 @@ private:
   std::string Arch;
   mutable std::unique_ptr<tools::gcc::Preprocessor> Preprocessor;
   mutable std::unique_ptr<tools::gcc::Compiler> Compiler;
+  void findGccLibDir();
 };
 
 class LLVM_LIBRARY_VISIBILITY OpenBSD : public Generic_ELF {
diff --git a/clang/test/Driver/mingw-linux.cpp b/clang/test/Driver/mingw-linux.cpp
new file mode 100644 (file)
index 0000000..f6b54c4
--- /dev/null
@@ -0,0 +1,20 @@
+// XFAIL: system-windows\r
+// RUN: %clang -target x86_64-pc-windows-gnu -c -### --sysroot=/dummy/x86_64-w64-mingw32/5.1.0 %s 2>&1 | FileCheck -check-prefix=CHECK %s\r
+\r
+// CHECK: /usr/x86_64-w64-mingw32/include/c++/\r
+// CHECK: /usr/x86_64-w64-mingw32/include/c++/x86_64-w64-mingw32/\r
+// CHECK: /usr/x86_64-w64-mingw32/include/c++/backward\r
+// CHECK: /usr/x86_64-w64-mingw32/include/c++/5.1.0/\r
+// CHECK: /usr/x86_64-w64-mingw32/include/c++/5.1.0/x86_64-w64-mingw32/\r
+// CHECK: /usr/x86_64-w64-mingw32/include/c++/5.1.0/backward\r
+// CHECK: /usr/include/c++/5.1.0/\r
+// CHECK: /usr/include/c++/5.1.0/x86_64-w64-mingw32/\r
+// CHECK: /usr/include/c++/5.1.0/backward\r
+// CHECK: /dummy/x86_64-w64-mingw32/5.1.0/include/c++/\r
+// CHECK: /dummy/x86_64-w64-mingw32/5.1.0/include/c++/x86_64-w64-mingw32/\r
+// CHECK: /dummy/x86_64-w64-mingw32/5.1.0/include/c++/backward\r
+// CHECK: /dummy/x86_64-w64-mingw32/5.1.0/include\r
+// CHECK: /usr/x86_64-w64-mingw32/sys-root/mingw/include\r
+// CHECK: /dummy/x86_64-w64-mingw32/5.1.0/include-fixed\r
+// CHECK: /usr/x86_64-w64-mingw32/include\r
+// CHECK: /usr/include\r
diff --git a/clang/test/Driver/mingw-win.cpp b/clang/test/Driver/mingw-win.cpp
new file mode 100644 (file)
index 0000000..60ee999
--- /dev/null
@@ -0,0 +1,19 @@
+// REQUIRES: system-windows\r
+// RUN: %clang -target i686-pc-windows-gnu -c -### --sysroot=c:\dummy %s 2>&1 | FileCheck -check-prefix=CHECK %s\r
+\r
+// CHECK: c:\\dummy\\i686-w64-mingw32\\include\\c++\r
+// CHECK: c:\\dummy\\i686-w64-mingw32\\include\\c++\\i686-w64-mingw32\\\r
+// CHECK: c:\\dummy\\i686-w64-mingw32\\include\\c++\\backward\r
+// CHECK: c:\\dummy\\i686-w64-mingw32\\include\\c++\\dummy\\\r
+// CHECK: c:\\dummy\\i686-w64-mingw32\\include\\c++\\dummy\\i686-w64-mingw32\\\r
+// CHECK: c:\\dummy\\i686-w64-mingw32\\include\\c++\\dummy\\backward\r
+// CHECK: c:\\dummy\\include\\c++\\dummy\\\r
+// CHECK: c:\\dummy\\include\\c++\\dummy\\i686-w64-mingw32\\\r
+// CHECK: c:\\dummy\\include\\c++\\dummy\\backward\r
+// CHECK: c:\\dummy\\include\\c++\\\r
+// CHECK: c:\\dummy\\include\\c++\\i686-w64-mingw32\\\r
+// CHECK: c:\\dummy\\include\\c++\\backward\r
+// CHECK: c:\\dummy\\include\r
+// CHECK: c:\\dummy\\include-fixed\r
+// CHECK: c:\\dummy\\i686-w64-mingw32\\include\r
+// CHECK: c:\\dummy\\include\r