Subject: [bug#38276] Fix kernel-headers path in clang

From: Carl Dong <[email-masked]>
Date: Tue, 19 Nov 2019 16:52:25 +0000

Hi Mathieu!

I have been using the Guix clang with the following patch, which should accomplish what you want and also allow for the proper handling of --sysroot. I included an extended explanation in the comments in the patch. Let me know what you think! :-)

Cheers,
Carl Dong
[email-masked]
"I fight for the users”

-----

diff --git a/gnu/packages/llvm.scm b/gnu/packages/llvm.scm
index 9ee5062429..33fb53d65e 100644
--- a/gnu/packages/llvm.scm
+++ b/gnu/packages/llvm.scm
@@ -186,7 +186,12 @@ compiler.  In LLVM this library is called \"compiler-rt\".")
 
              ;; Find libgcc_s, crtbegin.o, and crtend.o.
              (string-append "-DGCC_INSTALL_PREFIX="
-                            (assoc-ref %build-inputs "gcc-lib")))
+                            (assoc-ref %build-inputs "gcc-lib"))
+
+             ;; Use a sane default include directory.
+             (string-append "-DC_INCLUDE_DIRS="
+                            (assoc-ref %build-inputs "libc")
+                            "/include"))
 
        ;; Don't use '-g' during the build to save space.
        #:build-type "Release"
@@ -197,8 +202,6 @@ compiler.  In LLVM this library is called \"compiler-rt\".")
                    (lambda* (#:key inputs #:allow-other-keys)
                      (let ((libc (assoc-ref inputs "libc"))
                            (compiler-rt (assoc-ref inputs "clang-runtime"))
-                           (gcc (assoc-ref inputs "gcc"))
-                           (kernel-headers (assoc-ref inputs "kernel-headers"))
                            (version
                             (string->number
                              ,(version-major (package-version clang-runtime)))))
@@ -218,10 +221,7 @@ compiler.  In LLVM this library is called \"compiler-rt\".")
                             ;; Make sure libc's libdir is on the search path, to
                             ;; allow crt1.o & co. to be found.
                             (("@GLIBC_LIBDIR@")
-                             (string-append libc "/lib"))
-                            (("@C_EXTRA_INCLUDE_DIRS@")
-                             (string-append libc "/include" ":"
-                                            kernel-headers "/include"))))
+                             (string-append libc "/lib"))))
                          (else
                           (substitute* "lib/Driver/Tools.cpp"
                             ;; Patch the 'getLinuxDynamicLinker' function so that
diff --git a/gnu/packages/patches/clang-3.5-libc-search-path.patch b/gnu/packages/patches/clang-3.5-libc-search-path.patch
index 54fb9be7d8..50e4480239 100644
--- a/gnu/packages/patches/clang-3.5-libc-search-path.patch
+++ b/gnu/packages/patches/clang-3.5-libc-search-path.patch
@@ -8,7 +8,7 @@ to make sure Clang also works on non-GuixSD systems.
 
 --- cfe-3.6.0.src/lib/Driver/ToolChains.cpp	2015-02-18 22:03:07.000000000 +0100
 +++ cfe-3.6.0.src/lib/Driver/ToolChains.cpp	2015-06-19 16:37:20.459701044 +0200
-@@ -3040,6 +3040,9 @@
+@@ -2931,6 +2931,9 @@ Linux::Linux(const Driver &D, const llvm
  
    Linker = GetLinkerPath();
  
@@ -18,7 +18,7 @@ to make sure Clang also works on non-GuixSD systems.
    Distro Distro = DetectDistro(Arch);
  
    if (IsOpenSUSE(Distro) || IsUbuntu(Distro)) {
-@@ -3082,6 +3085,7 @@
+@@ -2973,6 +2976,7 @@ Linux::Linux(const Driver &D, const llvm
  
    if (IsOpenSUSE(Distro))
      ExtraOpts.push_back("--enable-new-dtags");
@@ -26,49 +26,41 @@ to make sure Clang also works on non-GuixSD systems.
  
    // The selection of paths to try here is designed to match the patterns which
    // the GCC driver itself uses, as this is part of the GCC-compatible driver.
-@@ -3194,6 +3198,10 @@
+@@ -3043,14 +3047,12 @@ Linux::Linux(const Driver &D, const llvm
+     addPathIfExists(D.Dir + "/../" + OSLibDir, Paths);
+   }
  
-   addPathIfExists(SysRoot + "/lib", Paths);
-   addPathIfExists(SysRoot + "/usr/lib", Paths);
-+
+-  addPathIfExists(SysRoot + "/lib/" + MultiarchTriple, Paths);
+-  addPathIfExists(SysRoot + "/lib/../" + OSLibDir, Paths);
+-  addPathIfExists(SysRoot + "/usr/lib/" + MultiarchTriple, Paths);
+-  addPathIfExists(SysRoot + "/usr/lib/../" + OSLibDir, Paths);
+-
+   // Try walking via the GCC triple path in case of biarch or multiarch GCC
+   // installations with strange symlinks.
+   if (GCCInstallation.isValid()) {
++    // The following code would end up adding things like
++    // "/usr/lib/x86_64-unknown-linux-gnu/../../lib64" to the search path.
++#if 0
+     addPathIfExists(SysRoot + "/usr/lib/" + GCCInstallation.getTriple().str() +
+                     "/../../" + OSLibDir, Paths);
+ 
+@@ -3060,6 +3062,7 @@ Linux::Linux(const Driver &D, const llvm
+       addPathIfExists(GCCInstallation.getInstallPath() +
+                       BiarchSibling.gccSuffix(), Paths);
+     }
++#endif
+ 
+     // See comments above on the multilib variant for details of why this is
+     // included even from outside the sysroot.
+@@ -3083,8 +3086,9 @@ Linux::Linux(const Driver &D, const llvm
+   if (StringRef(D.Dir).startswith(SysRoot))
+     addPathIfExists(D.Dir + "/../lib", Paths);
+ 
+-  addPathIfExists(SysRoot + "/lib", Paths);
+-  addPathIfExists(SysRoot + "/usr/lib", Paths);
 +  // Add libc's lib/ directory to the search path, so that crt1.o, crti.o,
 +  // and friends can be found.
 +  addPathIfExists("@GLIBC_LIBDIR@", Paths);
  }
  
  bool Linux::HasNativeLLVMSupport() const {
-@@ -3384,6 +3392,34 @@
-   addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include");
- 
-   addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
-+
-+  // Check for configure-time "extra" C include directories. When constructing a
-+  // toolchain, @C_EXTRA_INCLUDE_DIRS@ should be replaced with something like a
-+  // colon-separated string of the include dirs of libc and kernel headers.
-+  //
-+  // The reason why we use this mechanism instead of C_INCLUDE_DIRS above is
-+  // because when a user supplies clang with --sysroot, the normal expectation
-+  // is that clang will detect and add the proper $SYSROOT/$MULTIARCHINCL,
-+  // $SYSROOT/include, and $SYSROOT/usr/include to its list of search paths.
-+  // However, if C_INCLUDE_DIRS is not empty, this function will return early
-+  // and not attempt to add the aforementioned search paths, which is not
-+  // desirable.
-+  //
-+  // By adding our configure-time "extra" C include directories here, after
-+  // we've added $SYSROOT/include and $SYSROOT/usr/include, we make sure that IF
-+  // --sysroot is supplied on the command line, we pick up the expected search
-+  // paths in the $SYSROOT, and that they come before our configure-time "extra"
-+  // C include directories.
-+  StringRef CExtraIncludeDirs("@C_EXTRA_INCLUDE_DIRS@");
-+  if (CExtraIncludeDirs != "") {
-+      SmallVector<StringRef, 5> dirs;
-+      CExtraIncludeDirs.split(dirs, ":");
-+      for (StringRef dir : dirs) {
-+          StringRef Prefix =
-+              llvm::sys::path::is_absolute(dir) ? StringRef(SysRoot) : "";
-+          addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
-+      }
-+  }
- }
- 
- /// \brief Helper to add the variant paths of a libstdc++ installation.
diff --git a/gnu/packages/patches/clang-3.8-libc-search-path.patch b/gnu/packages/patches/clang-3.8-libc-search-path.patch
index 243d167755..0f7d0a4add 100644
--- a/gnu/packages/patches/clang-3.8-libc-search-path.patch
+++ b/gnu/packages/patches/clang-3.8-libc-search-path.patch
@@ -29,49 +29,41 @@ changes in clang 3.8.
  
    // The selection of paths to try here is designed to match the patterns which
    // the GCC driver itself uses, as this is part of the GCC-compatible driver.
-@@ -3817,6 +3821,10 @@
+@@ -3771,14 +3775,12 @@
+     addPathIfExists(D, D.Dir + "/../" + OSLibDir, Paths);
+   }
  
-   addPathIfExists(D, SysRoot + "/lib", Paths);
-   addPathIfExists(D, SysRoot + "/usr/lib", Paths);
-+
+-  addPathIfExists(D, SysRoot + "/lib/" + MultiarchTriple, Paths);
+-  addPathIfExists(D, SysRoot + "/lib/../" + OSLibDir, Paths);
+-  addPathIfExists(D, SysRoot + "/usr/lib/" + MultiarchTriple, Paths);
+-  addPathIfExists(D, SysRoot + "/usr/lib/../" + OSLibDir, Paths);
+-
+   // Try walking via the GCC triple path in case of biarch or multiarch GCC
+   // installations with strange symlinks.
+   if (GCCInstallation.isValid()) {
++    // The following code would end up adding things like
++    // "/usr/lib/x86_64-unknown-linux-gnu/../../lib64" to the search path.
++#if 0
+     addPathIfExists(D,
+                     SysRoot + "/usr/lib/" + GCCInstallation.getTriple().str() +
+                         "/../../" + OSLibDir,
+@@ -3791,6 +3793,7 @@
+                              BiarchSibling.gccSuffix(),
+                       Paths);
+     }
++#endif
+ 
+     // See comments above on the multilib variant for details of why this is
+     // included even from outside the sysroot.
+@@ -3815,8 +3818,9 @@
+   if (StringRef(D.Dir).startswith(SysRoot))
+     addPathIfExists(D, D.Dir + "/../lib", Paths);
+ 
+-  addPathIfExists(D, SysRoot + "/lib", Paths);
+-  addPathIfExists(D, SysRoot + "/usr/lib", Paths);
 +  // Add libc's lib/ directory to the search path, so that crt1.o, crti.o,
 +  // and friends can be found.
 +  addPathIfExists(D, "@GLIBC_LIBDIR@", Paths);
  }
  
  bool Linux::HasNativeLLVMSupport() const { return true; }
-@@ -4026,6 +4034,34 @@
-   addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include");
- 
-   addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
-+
-+  // Check for configure-time "extra" C include directories. When constructing a
-+  // toolchain, @C_EXTRA_INCLUDE_DIRS@ should be replaced with something like a
-+  // colon-separated string of the include dirs of libc and kernel headers.
-+  //
-+  // The reason why we use this mechanism instead of C_INCLUDE_DIRS above is
-+  // because when a user supplies clang with --sysroot, the normal expectation
-+  // is that clang will detect and add the proper $SYSROOT/$MULTIARCHINCL,
-+  // $SYSROOT/include, and $SYSROOT/usr/include to its list of search paths.
-+  // However, if C_INCLUDE_DIRS is not empty, this function will return early
-+  // and not attempt to add the aforementioned search paths, which is not
-+  // desirable.
-+  //
-+  // By adding our configure-time "extra" C include directories here, after
-+  // we've added $SYSROOT/include and $SYSROOT/usr/include, we make sure that IF
-+  // --sysroot is supplied on the command line, we pick up the expected search
-+  // paths in the $SYSROOT, and that they come before our configure-time "extra"
-+  // C include directories.
-+  StringRef CExtraIncludeDirs("@C_EXTRA_INCLUDE_DIRS@");
-+  if (CExtraIncludeDirs != "") {
-+      SmallVector<StringRef, 5> dirs;
-+      CExtraIncludeDirs.split(dirs, ":");
-+      for (StringRef dir : dirs) {
-+          StringRef Prefix =
-+              llvm::sys::path::is_absolute(dir) ? StringRef(SysRoot) : "";
-+          addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
-+      }
-+  }
- }
- 
- 
diff --git a/gnu/packages/patches/clang-6.0-libc-search-path.patch b/gnu/packages/patches/clang-6.0-libc-search-path.patch
index d80c798467..a62e8063c2 100644
--- a/gnu/packages/patches/clang-6.0-libc-search-path.patch
+++ b/gnu/packages/patches/clang-6.0-libc-search-path.patch
@@ -8,17 +8,18 @@ to make sure Clang also works on non-GuixSD systems.
 
 --- cfe-6.0.0.src/lib/Driver/ToolChains/Linux.cpp
 +++ cfe-6.0.0.src/lib/Driver/ToolChains/Linux.cpp
-@@ -208,6 +208,9 @@
+@@ -207,7 +207,9 @@
+   PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" +
                           GCCInstallation.getTriple().str() + "/bin")
                         .str());
- 
+-
 +  // Comment out the distro-specific tweaks so that they don't bite when
 +  // using Guix on a foreign distro.
 +#if 0
    Distro Distro(D.getVFS());
  
    if (Distro.IsAlpineLinux()) {
-@@ -255,6 +258,7 @@
+@@ -255,6 +257,7 @@
  
    if (IsAndroid || Distro.IsOpenSUSE())
      ExtraOpts.push_back("--enable-new-dtags");
@@ -26,49 +27,41 @@ to make sure Clang also works on non-GuixSD systems.
  
    // The selection of paths to try here is designed to match the patterns which
    // the GCC driver itself uses, as this is part of the GCC-compatible driver.
-@@ -375,6 +379,10 @@
+@@ -329,14 +332,12 @@
+     addPathIfExists(D, D.Dir + "/../" + OSLibDir, Paths);
+   }
+ 
+-  addPathIfExists(D, SysRoot + "/lib/" + MultiarchTriple, Paths);
+-  addPathIfExists(D, SysRoot + "/lib/../" + OSLibDir, Paths);
+-  addPathIfExists(D, SysRoot + "/usr/lib/" + MultiarchTriple, Paths);
+-  addPathIfExists(D, SysRoot + "/usr/lib/../" + OSLibDir, Paths);
+-
+   // Try walking via the GCC triple path in case of biarch or multiarch GCC
+   // installations with strange symlinks.
+   if (GCCInstallation.isValid()) {
++    // The following code would end up adding things like
++    // "/usr/lib/x86_64-unknown-linux-gnu/../../lib64" to the search path.
++#if 0
+     addPathIfExists(D,
+                     SysRoot + "/usr/lib/" + GCCInstallation.getTriple().str() +
+                         "/../../" + OSLibDir,
+@@ -349,6 +350,7 @@
+                              BiarchSibling.gccSuffix(),
+                       Paths);
+     }
++#endif
  
-   addPathIfExists(D, SysRoot + "/lib", Paths);
-   addPathIfExists(D, SysRoot + "/usr/lib", Paths);
-+
+     // See comments above on the multilib variant for details of why this is
+     // included even from outside the sysroot.
+@@ -373,8 +375,9 @@
+   if (StringRef(D.Dir).startswith(SysRoot))
+     addPathIfExists(D, D.Dir + "/../lib", Paths);
+ 
+-  addPathIfExists(D, SysRoot + "/lib", Paths);
+-  addPathIfExists(D, SysRoot + "/usr/lib", Paths);
 +  // Add libc's lib/ directory to the search path, so that crt1.o, crti.o,
 +  // and friends can be found.
 +  addPathIfExists(D, "@GLIBC_LIBDIR@", Paths);
  }
  
  bool Linux::HasNativeLLVMSupport() const { return true; }
-@@ -710,6 +718,34 @@
-   addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include");
- 
-   addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
-+
-+  // Check for configure-time "extra" C include directories. When constructing a
-+  // toolchain, @C_EXTRA_INCLUDE_DIRS@ should be replaced with something like a
-+  // colon-separated string of the include dirs of libc and kernel headers.
-+  //
-+  // The reason why we use this mechanism instead of C_INCLUDE_DIRS above is
-+  // because when a user supplies clang with --sysroot, the normal expectation
-+  // is that clang will detect and add the proper $SYSROOT/$MULTIARCHINCL,
-+  // $SYSROOT/include, and $SYSROOT/usr/include to its list of search paths.
-+  // However, if C_INCLUDE_DIRS is not empty, this function will return early
-+  // and not attempt to add the aforementioned search paths, which is not
-+  // desirable.
-+  //
-+  // By adding our configure-time "extra" C include directories here, after
-+  // we've added $SYSROOT/include and $SYSROOT/usr/include, we make sure that IF
-+  // --sysroot is supplied on the command line, we pick up the expected search
-+  // paths in the $SYSROOT, and that they come before our configure-time "extra"
-+  // C include directories.
-+  StringRef CExtraIncludeDirs("@C_EXTRA_INCLUDE_DIRS@");
-+  if (CExtraIncludeDirs != "") {
-+      SmallVector<StringRef, 5> dirs;
-+      CExtraIncludeDirs.split(dirs, ":");
-+      for (StringRef dir : dirs) {
-+          StringRef Prefix =
-+              llvm::sys::path::is_absolute(dir) ? StringRef(SysRoot) : "";
-+          addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
-+      }
-+  }
- }
- 
- static std::string DetectLibcxxIncludePath(StringRef base) {
diff --git a/gnu/packages/patches/clang-7.0-libc-search-path.patch b/gnu/packages/patches/clang-7.0-libc-search-path.patch
index 445b5d17ac..07ff8c90bd 100644
--- a/gnu/packages/patches/clang-7.0-libc-search-path.patch
+++ b/gnu/packages/patches/clang-7.0-libc-search-path.patch
@@ -8,7 +8,7 @@ to make sure Clang also works on non-GuixSD systems.
 
 --- a/lib/Driver/ToolChains/Linux.cpp
 +++ b/lib/Driver/ToolChains/Linux.cpp
-@@ -225,7 +225,9 @@
+@@ -225,7 +225,9 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
    PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" +
                           GCCInstallation.getTriple().str() + "/bin")
                         .str());
@@ -19,7 +19,7 @@ to make sure Clang also works on non-GuixSD systems.
    Distro Distro(D.getVFS());
  
    if (Distro.IsAlpineLinux()) {
-@@ -284,6 +286,7 @@
+@@ -284,6 +286,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
  
    if (IsAndroid || Distro.IsOpenSUSE())
      ExtraOpts.push_back("--enable-new-dtags");
@@ -27,49 +27,56 @@ to make sure Clang also works on non-GuixSD systems.
  
    // The selection of paths to try here is designed to match the patterns which
    // the GCC driver itself uses, as this is part of the GCC-compatible driver.
-@@ -431,6 +434,10 @@
+@@ -342,7 +345,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
+     // the cross. Note that GCC does include some of these directories in some
+     // configurations but this seems somewhere between questionable and simply
+     // a bug.
+-    if (StringRef(LibPath).startswith(SysRoot)) {
++    if (0) {
+       addPathIfExists(D, LibPath + "/" + MultiarchTriple, Paths);
+       addPathIfExists(D, LibPath + "/../" + OSLibDir, Paths);
+     }
+@@ -361,6 +364,8 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
+   addPathIfExists(D, SysRoot + "/lib/" + MultiarchTriple, Paths);
+   addPathIfExists(D, SysRoot + "/lib/../" + OSLibDir, Paths);
  
-   addPathIfExists(D, SysRoot + "/lib", Paths);
-   addPathIfExists(D, SysRoot + "/usr/lib", Paths);
-+
++  // This requires the commented distro tweaks above.
++#if 0
+   if (IsAndroid) {
+     // Android sysroots contain a library directory for each supported OS
+     // version as well as some unversioned libraries in the usual multiarch
+@@ -389,10 +394,14 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
+     addPathIfExists(D, SysRoot + "/" + OSLibDir + "/" + ABIName, Paths);
+     addPathIfExists(D, SysRoot + "/usr/" + OSLibDir + "/" + ABIName, Paths);
+   }
++#endif
+ 
+   // Try walking via the GCC triple path in case of biarch or multiarch GCC
+   // installations with strange symlinks.
+   if (GCCInstallation.isValid()) {
++    // The following code would end up adding things like
++    // "/usr/lib/x86_64-unknown-linux-gnu/../../lib64" to the search path.
++#if 0
+     addPathIfExists(D,
+                     SysRoot + "/usr/lib/" + GCCInstallation.getTriple().str() +
+                         "/../../" + OSLibDir,
+@@ -405,6 +414,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
+                              BiarchSibling.gccSuffix(),
+                       Paths);
+     }
++#endif
+ 
+     // See comments above on the multilib variant for details of why this is
+     // included even from outside the sysroot.
+@@ -429,8 +439,9 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
+   if (StringRef(D.Dir).startswith(SysRoot))
+     addPathIfExists(D, D.Dir + "/../lib", Paths);
+ 
+-  addPathIfExists(D, SysRoot + "/lib", Paths);
+-  addPathIfExists(D, SysRoot + "/usr/lib", Paths);
 +  // Add libc's lib/ directory to the search path, so that crt1.o, crti.o,
 +  // and friends can be found.
 +  addPathIfExists(D, "@GLIBC_LIBDIR@", Paths);
  }
  
  bool Linux::HasNativeLLVMSupport() const { return true; }
-@@ -794,6 +801,34 @@
-   addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include");
- 
-   addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
-+
-+  // Check for configure-time "extra" C include directories. When constructing a
-+  // toolchain, @C_EXTRA_INCLUDE_DIRS@ should be replaced with something like a
-+  // colon-separated string of the include dirs of libc and kernel headers.
-+  //
-+  // The reason why we use this mechanism instead of C_INCLUDE_DIRS above is
-+  // because when a user supplies clang with --sysroot, the normal expectation
-+  // is that clang will detect and add the proper $SYSROOT/$MULTIARCHINCL,
-+  // $SYSROOT/include, and $SYSROOT/usr/include to its list of search paths.
-+  // However, if C_INCLUDE_DIRS is not empty, this function will return early
-+  // and not attempt to add the aforementioned search paths, which is not
-+  // desirable.
-+  //
-+  // By adding our configure-time "extra" C include directories here, after
-+  // we've added $SYSROOT/include and $SYSROOT/usr/include, we make sure that IF
-+  // --sysroot is supplied on the command line, we pick up the expected search
-+  // paths in the $SYSROOT, and that they come before our configure-time "extra"
-+  // C include directories.
-+  StringRef CExtraIncludeDirs("@C_EXTRA_INCLUDE_DIRS@");
-+  if (CExtraIncludeDirs != "") {
-+      SmallVector<StringRef, 5> dirs;
-+      CExtraIncludeDirs.split(dirs, ":");
-+      for (StringRef dir : dirs) {
-+          StringRef Prefix =
-+              llvm::sys::path::is_absolute(dir) ? StringRef(SysRoot) : "";
-+          addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
-+      }
-+  }
- }
- 
- static std::string DetectLibcxxIncludePath(StringRef base) {