Hi, A couple of comments from me while testing this trying to build a cross-toolchain with llvm-13. Hope this is helpful! Julien Lepiller writes: > * gnu/packages/llvm.scm (cross-clang): New variable. > --- > gnu/packages/llvm.scm | 144 +++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 143 insertions(+), 1 deletion(-) > > diff --git a/gnu/packages/llvm.scm b/gnu/packages/llvm.scm > index d6e9846699..c277e2ac35 100644 > --- a/gnu/packages/llvm.scm > +++ b/gnu/packages/llvm.scm > @@ -54,6 +54,7 @@ (define-module (gnu packages llvm) > #:use-module (guix build-system trivial) > #:use-module (gnu packages) > #:use-module (gnu packages base) > + #:use-module (gnu packages cross-base) > #:use-module (gnu packages gcc) > #:use-module (gnu packages bootstrap) ;glibc-dynamic-linker > #:use-module (gnu packages check) ;python-lit > @@ -75,7 +76,9 @@ (define-module (gnu packages llvm) > #:use-module (ice-9 match) > #:export (make-lld-wrapper > system->llvm-target > - cross-llvm)) > + cross-llvm > + cross-clang > + clang-for-target)) > > (define* (system->llvm-target #:optional > (system (or (and=> (%current-target-system) > @@ -1023,6 +1026,145 @@ (define-public clang-runtime clang-runtime-13) > (define-public clang clang-13) > (define-public clang-toolchain clang-toolchain-13) > > +(define* (cross-clang target > + #:key > + (libc (cross-libc target)) > + (xgcc (cross-gcc target > + #:xbinutils (cross-binutils target) > + #:libc (cross-libc target))) > + (clang clang)) > + "Return a cross-clang compiler for target." > + (define cross-clang-aux > + (mlambda (target libc xgcc clang) > + (package > + (inherit clang) > + (name (string-append "clang-cross-" target)) > + (version (package-version clang)) > + ;; Support the same variables as clang, even in cross-compilation context. > + ;; Clang does not make a difference between native and cross-compilation. > + (search-paths > + (list > + (search-path-specification > + (variable "CROSS_LIBRARY_PATH") > + (files '("lib"))) > + (search-path-specification > + (variable "CROSS_C_INCLUDE_PATH") > + (files '("include"))) > + (search-path-specification > + (variable "CROSS_CPLUS_INCLUDE_PATH") > + (files '("include/c++" "include"))))) > + (native-search-paths '()) > + (arguments > + (substitute-keyword-arguments (package-arguments clang) > + ((#:configure-flags _) > + `(list "-DCLANG_INCLUDE_TESTS=True" > + (string-append "-DGCC_INSTALL_PREFIX=" > + (assoc-ref %build-inputs "cross-gcc-lib")) > + (string-append "-DC_INCLUDE_DIRS=" > + (assoc-ref %build-inputs "target-libc") > + "/include"))) > + ((#:phases phases) > + `(modify-phases ,phases > + (add-after 'unpack 'add-missing-libdir > + (lambda _ > + ;; cross-gcc installs its libraries in /lib instead of > + ;; lib. > + (substitute* "lib/Driver/ToolChain.cpp" > + (("\"-L\"\\) \\+ LibPath\\)\\);") > + ,(string-append "\"-L\") + LibPath)); > + CmdArgs.push_back(Args.MakeArgString(StringRef(\"-L\") + " > + "StringRef(GCC_INSTALL_PREFIX) + StringRef(\"/" > + target "/lib\"))); > + CmdArgs.push_back(Args.MakeArgString(StringRef(\"-rpath=\") + " > + "StringRef(GCC_INSTALL_PREFIX) + StringRef(\"/" > + target "/lib\")));"))))) > + (add-after 'unpack 'support-cross-include-path > + (lambda _ > + (substitute* "lib/Driver/ToolChains/Clang.cpp" > + (("C_INCLUDE_PATH") "CROSS_C_INCLUDE_PATH") > + (("CPLUS_INCLUDE_PATH") "CROSS_CPLUS_INCLUDE_PATH")))) > + (add-after 'unpack 'support-cross-library-path > + (lambda _ > + ;; LIBRARY_PATH is only supported for native builds, but we still > + ;; need it (or CROSS_LIBRARY_PATH to be precise) when > + ;; cross-compiling > + (substitute* "lib/Driver/ToolChains/CommonArgs.cpp" > + (("LIBRARY_PATH\"") > + "LIBRARY_PATH\"); > + } else { > + addDirectoryList(Args, CmdArgs, \"-L\", \"CROSS_LIBRARY_PATH\"")))) Testing this with llvm-13, this substitution doesn't look quite right and causes the build to fail, they might have removed braces between versions: https://github.com/llvm/llvm-project/blob/release/13.x/clang/lib/Driver/ToolChains/CommonArgs.cpp#L236 Doing a blame points to this commit, which suggest it's changed with LLVM 10 release I believe. https://github.com/llvm/llvm-project/commit/7dbdc8de183e7aa2dc0a9c3a4f473142ddd460bf, > + (replace 'set-glibc-file-names > + (lambda* (#:key inputs #:allow-other-keys) > + (let ((libc (assoc-ref inputs "target-libc")) > + (compiler-rt (assoc-ref inputs "clang-runtime")) Quick question, compiler-rt here is the host's runtime right? Do we not need to cross-compile it as well? It's not always clear to me what is part of compiler-rt vs libc vs libgcc, it could be target-dependent. For example when trying to target WebAssembly, I needed a cross-compiled compiler-rt to provide the libclang_rt.builtins-wasm32.a library. > + (gcc (assoc-ref inputs "cross-gcc"))) > + (setenv "LIBRARY_PATH" > + (string-append > + (assoc-ref inputs "libc") "/lib:" (getenv "LIBRARY_PATH"))) > + ,@(cond > + ((version>=? version "6.0") > + `(;; Link to libclang_rt files from clang-runtime. > + (substitute* "lib/Driver/ToolChain.cpp" > + (("getDriver\\(\\)\\.ResourceDir") > + (string-append "\"" compiler-rt "\""))) > + > + ;; Make "LibDir" refer to /lib so that it > + ;; uses the right dynamic linker file name. > + (substitute* "lib/Driver/ToolChains/Linux.cpp" > + (("(^[[:blank:]]+LibDir = ).*" _ declaration) > + (string-append declaration "\"" libc "/lib\";\n")) > + > + ;; Make clang look for libstdc++ in the right > + ;; location. > + (("LibStdCXXIncludePathCandidates\\[\\] = \\{") > + (string-append > + "LibStdCXXIncludePathCandidates[] = { \"" gcc > + "/include/c++\",")) > + > + ;; Make sure libc's libdir is on the search path, to > + ;; allow crt1.o & co. to be found. > + (("@GLIBC_LIBDIR@") > + (string-append libc "/lib"))))) > + (else > + `((substitute* "lib/Driver/Tools.cpp" > + ;; Patch the 'getLinuxDynamicLinker' function so that > + ;; it uses the right dynamic linker file name. > + (("/lib64/ld-linux-x86-64.so.2") > + (string-append libc ,(glibc-dynamic-linker)))) > + > + ;; Link to libclang_rt files from clang-runtime. > + ;; This substitution needed slight adjustment in 3.8. > + ,@(if (version>=? version "3.8") > + '((substitute* "lib/Driver/Tools.cpp" > + (("TC\\.getDriver\\(\\)\\.ResourceDir") > + (string-append "\"" compiler-rt "\"")))) > + '((substitute* "lib/Driver/ToolChain.cpp" > + (("getDriver\\(\\)\\.ResourceDir") > + (string-append "\"" compiler-rt "\""))))) > + > + ;; Make sure libc's libdir is on the search path, to > + ;; allow crt1.o & co. to be found. > + (substitute* "lib/Driver/ToolChains.cpp" > + (("@GLIBC_LIBDIR@") > + (string-append libc "/lib"))))))))))))) > + (inputs > + `(("target-libc" ,libc) > + ("cross-gcc-lib" ,xgcc "lib") > + ("cross-gcc" ,xgcc) > + ,@(package-inputs clang))) > + (propagated-inputs > + (modify-inputs (package-propagated-inputs clang) > + (replace "llvm" > + (cross-llvm > + (car (assoc-ref (package-propagated-inputs clang) "llvm")) > + target))))))) > + (cross-clang-aux target libc xgcc clang)) > + > +(define* (clang-for-target #:optional (clang clang)) > + (if (%current-target-system) > + (cross-clang (%current-target-system) #:clang clang) > + clang)) > + > (define-public llvm-for-rocm > (package > ;; Actually based on LLVM 13 as of v4.3, but llvm-12 works just fine.