Subject: [PATCH 1/3] gnu: Add llvm-15.

From: Maxim Cournoyer <[email-masked]>
Date: Sun, 13 Nov 2022 00:01:58 -0500

* gnu/packages/llvm.scm (llvm-15): New variable.
* gnu/packages/patches/clang-15.0-libc-search-path.patch: New file.
* gnu/local.mk: Register it.
---
 gnu/local.mk                                  |  1 +
 gnu/packages/llvm.scm                         | 69 +++++++++++++-
 .../patches/clang-15.0-libc-search-path.patch | 95 +++++++++++++++++++
 3 files changed, 163 insertions(+), 2 deletions(-)
 create mode 100644 gnu/packages/patches/clang-15.0-libc-search-path.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index e3e02314bb..6b6ada17a5 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -976,6 +976,7 @@ dist_patch_DATA =						\
   %D%/packages/patches/clang-12.0-libc-search-path.patch	\
   %D%/packages/patches/clang-13.0-libc-search-path.patch	\
   %D%/packages/patches/clang-14.0-libc-search-path.patch	\
+  %D%/packages/patches/clang-15.0-libc-search-path.patch	\
   %D%/packages/patches/clang-runtime-asan-build-fixes.patch	\
   %D%/packages/patches/clang-runtime-esan-build-fixes.patch	\
   %D%/packages/patches/clang-runtime-9-libsanitizer-mode-field.patch	\
diff --git a/gnu/packages/llvm.scm b/gnu/packages/llvm.scm
index 324149116b..0a35aed7c6 100644
--- a/gnu/packages/llvm.scm
+++ b/gnu/packages/llvm.scm
@@ -545,10 +545,12 @@ (define (make-clang-toolchain clang libomp)
               ("libc-static" ,glibc "static")))))
 
 (define %llvm-monorepo-hashes
-  '(("14.0.6" . "14f8nlvnmdkp9a9a79wv67jbmafvabczhah8rwnqrgd5g3hfxxxx")))
+  '(("14.0.6" . "14f8nlvnmdkp9a9a79wv67jbmafvabczhah8rwnqrgd5g3hfxxxx")
+    ("15.0.4" . "0j5kx4s970qzcjr83kk6776zzjqfshl61x9fagqz8kjxcjbpg8cj")))
 
 (define %llvm-patches
-  '(("14.0.6" . ("clang-14.0-libc-search-path.patch"))))
+  '(("14.0.6" . ("clang-14.0-libc-search-path.patch"))
+    ("15.0.4" . ("clang-15.0-libc-search-path.patch"))))
 
 (define (llvm-monorepo version)
   (origin
@@ -560,6 +562,69 @@ (define (llvm-monorepo version)
     (sha256 (base32 (assoc-ref %llvm-monorepo-hashes version)))
     (patches (map search-patch (assoc-ref %llvm-patches version)))))
 
+;;; TODO: Make the base llvm all other LLVM inherit from on core-updates.
+(define-public llvm-15
+  (package
+    (name "llvm")
+    (version "15.0.4")
+    (source (llvm-monorepo version))
+    (build-system cmake-build-system)
+    (outputs '("out" "opt-viewer"))
+    (arguments
+     (list
+      #:configure-flags
+      #~(list
+         ;; These options are required for cross-compiling LLVM according
+         ;; to <https://llvm.org/docs/HowToCrossCompileLLVM.html>.
+         #$@(if (%current-target-system)
+                #~((string-append "-DLLVM_TABLEGEN="
+                                  #+(file-append this-package
+                                                 "/bin/llvm-tblgen"))
+                   #$(string-append "-DLLVM_DEFAULT_TARGET_TRIPLE="
+                                    (%current-target-system))
+                   #$(string-append "-DLLVM_TARGET_ARCH="
+                                    (system->llvm-target))
+                   #$(string-append "-DLLVM_TARGETS_TO_BUILD="
+                                    (system->llvm-target)))
+                '())
+         ;; Note: sadly, the build system refuses the use of
+         ;; -DBUILD_SHARED_LIBS=ON and the large static archives are needed to
+         ;; build clang-runtime, so we cannot delete them.
+         "-DLLVM_BUILD_LLVM_DYLIB=ON"
+         "-DLLVM_LINK_LLVM_DYLIB=ON"
+         "-DLLVM_ENABLE_FFI=ON"
+         "-DLLVM_ENABLE_RTTI=ON"        ;for some third-party utilities
+         "-DLLVM_INSTALL_UTILS=ON"      ;needed for rustc
+         "-DLLVM_PARALLEL_LINK_JOBS=1") ;cater to smaller build machines
+      ;; Don't use '-g' during the build, to save space.
+      #:build-type "Release"
+      #:phases
+      #~(modify-phases %standard-phases
+          (add-after 'unpack 'change-directory
+            (lambda _
+              (chdir "llvm")))
+          (add-after 'install 'install-opt-viewer
+            (lambda* (#:key outputs #:allow-other-keys)
+              (let* ((opt-viewer-share (string-append #$output:opt-viewer
+                                                      "/share")))
+                (mkdir-p opt-viewer-share)
+                (rename-file (string-append #$output "/share/opt-viewer")
+                             opt-viewer-share)))))))
+    (native-inputs (list python-wrapper perl))
+    (inputs (list libffi))
+    (propagated-inputs (list zlib))     ;to use output from llvm-config
+    (home-page "https://www.llvm.org")
+    (synopsis "Optimizing compiler infrastructure")
+    (description
+     "LLVM is a compiler infrastructure designed for compile-time, link-time,
+runtime, and idle-time optimization of programs from arbitrary programming
+languages.  It currently supports compilation of C and C++ programs, using
+front-ends derived from GCC 4.0.1.  A new front-end for the C family of
+languages is in development.  The compiler infrastructure includes mirror sets
+of programming tools as well as libraries with equivalent functionality.")
+    (license license:asl2.0)
+    (properties `((release-monitoring-url . ,%llvm-release-monitoring-url)))))
+
 (define-public llvm-14
   (package
     (name "llvm")
diff --git a/gnu/packages/patches/clang-15.0-libc-search-path.patch b/gnu/packages/patches/clang-15.0-libc-search-path.patch
new file mode 100644
index 0000000000..20726859b2
--- /dev/null
+++ b/gnu/packages/patches/clang-15.0-libc-search-path.patch
@@ -0,0 +1,95 @@
+Clang attempts to guess file names based on the OS and distro (yes!),
+but unfortunately, that doesn't work for us.
+
+This patch makes it easy to insert libc's $libdir so that Clang passes the
+correct absolute file name of crt1.o etc. to 'ld'.  It also disables all
+the distro-specific stuff and removes the hard-coded FHS directory names
+to make sure Clang also works on foreign distros.
+
+diff --git a/clang/lib/Driver/Distro.cpp b/clang/libDriver/Distro.cpp
+index 1898667..35de813 100644
+--- a/clang/lib/Driver/Distro.cpp
++++ b/clang/libDriver/Distro.cpp
+@@ -97,6 +97,10 @@ static Distro::DistroType DetectLsbRelease(llvm::vfs::FileSystem &VFS) {
+ }
+ 
+ static Distro::DistroType DetectDistro(llvm::vfs::FileSystem &VFS) {
++  // The compiler should always behave the same, even when used via Guix on a
++  // foreign distro.
++  return Distro::UnknownDistro;
++
+   Distro::DistroType Version = Distro::UnknownDistro;
+ 
+   // Newer freedesktop.org's compilant systemd-based systems
+diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/libDriver/ToolChains/Cuda.cpp
+index 7ad990d..e4da4d4 100644
+--- a/clang/lib/Driver/ToolChains/Cuda.cpp
++++ b/clang/libDriver/ToolChains/Cuda.cpp
+@@ -117,6 +117,9 @@ CudaInstallationDetector::CudaInstallationDetector(
+     const Driver &D, const llvm::Triple &HostTriple,
+     const llvm::opt::ArgList &Args)
+     : D(D) {
++  // Don't look for CUDA in /usr.
++  return;
++
+   struct Candidate {
+     std::string Path;
+     bool StrictChecking;
+diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/libDriver/ToolChains/Linux.cpp
+index ceb1a98..9d7a14a 100644
+--- a/clang/lib/Driver/ToolChains/Linux.cpp
++++ b/clang/libDriver/ToolChains/Linux.cpp
+@@ -188,6 +188,10 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
+ 
+   Generic_GCC::PushPPaths(PPaths);
+ 
++  // 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(), Triple);
+ 
+   if (Distro.IsAlpineLinux() || Triple.isAndroid()) {
+@@ -256,6 +260,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
+ 
+   if (IsAndroid || Distro.IsOpenSUSE())
+     ExtraOpts.push_back("--enable-new-dtags");
++#endif
+ 
+   // 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.
+@@ -276,6 +281,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
+   }
+   Generic_GCC::AddMultilibPaths(D, SysRoot, OSLibDir, MultiarchTriple, Paths);
+ 
++#if 0
+   addPathIfExists(D, concat(SysRoot, "/lib", MultiarchTriple), Paths);
+   addPathIfExists(D, concat(SysRoot, "/lib/..", OSLibDir), Paths);
+ 
+@@ -304,9 +310,11 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
+     addPathIfExists(D, concat(SysRoot, "/", OSLibDir, ABIName), Paths);
+     addPathIfExists(D, concat(SysRoot, "/usr", OSLibDir, ABIName), Paths);
+   }
++#endif
+ 
+   Generic_GCC::AddMultiarchPaths(D, SysRoot, OSLibDir, Paths);
+ 
++#if 0
+   // The deprecated -DLLVM_ENABLE_PROJECTS=libcxx configuration installs
+   // libc++.so in D.Dir+"/../lib/". Detect this path.
+   // TODO Remove once LLVM_ENABLE_PROJECTS=libcxx is unsupported.
+@@ -316,6 +324,14 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
+ 
+   addPathIfExists(D, concat(SysRoot, "/lib"), Paths);
+   addPathIfExists(D, concat(SysRoot, "/usr/lib"), Paths);
++#endif
++
++  // 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);
++
++  // Add GCC's lib/ directory so libstdc++.so can be found.
++  addPathIfExists(D, GCCInstallation.getParentLibPath(), Paths);
+ }
+ 
+ ToolChain::RuntimeLibType Linux::GetDefaultRuntimeLibType() const {
-- 
2.38.1