diff mbox series

[bug#54239,v2,1/5] gnu: Add cross-llvm.

Message ID 499e5dba47ef40df93a8b33fbb8e41cc2354e7a1.1646387919.git.julien@lepiller.eu
State New
Headers show
Series [bug#54239,v2,1/5] gnu: Add cross-llvm. | expand

Checks

Context Check Description
cbaines/comparison success View comparision
cbaines/git branch success View Git branch
cbaines/applying patch success View Laminar job
cbaines/issue success View issue
cbaines/comparison success View comparision
cbaines/git branch success View Git branch
cbaines/applying patch success View Laminar job
cbaines/issue success View issue

Commit Message

Julien Lepiller March 4, 2022, 9:59 a.m. UTC
* gnu/packages/llvm.scm (cross-llvm): New variable.
---
 gnu/packages/llvm.scm | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

Comments

Pierre Langlois March 4, 2022, 7:34 p.m. UTC | #1
Hi Julien,

Julien Lepiller <julien@lepiller.eu> writes:

> * gnu/packages/llvm.scm (cross-llvm): New variable.

Do you really need to define a cross package for LLVM? In my experience
it was possible to use the same llvm libraries for native and cross
compilation. By default LLVM builds support for all supported targets
(provided they are not "experimental" IIRC).

Whereas for the clang package, at the moment it does have to be built
for a specific target IIUC. I hope that one day we could have the same
clang for native and cross compilation in Guix, but I don't think it can
work without some serious re-design of how cross-compilation works. I've
been trying to think about it but I don't yet have a good understanding
of it.

Thanks,
Pierre
Julien Lepiller March 5, 2022, 8:24 a.m. UTC | #2
Le Fri, 04 Mar 2022 19:34:07 +0000,
Pierre Langlois <pierre.langlois@gmx.com> a écrit :

> Hi Julien,
> 
> Julien Lepiller <julien@lepiller.eu> writes:
> 
> > * gnu/packages/llvm.scm (cross-llvm): New variable.  
> 
> Do you really need to define a cross package for LLVM? In my
> experience it was possible to use the same llvm libraries for native
> and cross compilation. By default LLVM builds support for all
> supported targets (provided they are not "experimental" IIRC).

No, I don't think it's required.  I only need it so I can define a
default target that's different from the host.

> 
> Whereas for the clang package, at the moment it does have to be built
> for a specific target IIUC. I hope that one day we could have the same
> clang for native and cross compilation in Guix, but I don't think it
> can work without some serious re-design of how cross-compilation
> works. I've been trying to think about it but I don't yet have a good
> understanding of it.

You can use --target to control which target clang builds for (although
I don't know if our clang package can work like that). I wanted to have
a default target though, because passing --target all the time is
cumbersome and we would have to adjust all recipes to pass the flag.
With the default target set appropriately, (clang-for-target) will
always produce binaries for the correct architecture, whether
cross-compiling or not.

> 
> Thanks,
> Pierre
>
Pierre Langlois March 5, 2022, 1:02 p.m. UTC | #3
Julien Lepiller <julien@lepiller.eu> writes:

> Le Fri, 04 Mar 2022 19:34:07 +0000,
> Pierre Langlois <pierre.langlois@gmx.com> a écrit :
>
>> Hi Julien,
>> 
>> Julien Lepiller <julien@lepiller.eu> writes:
>> 
>> > * gnu/packages/llvm.scm (cross-llvm): New variable.  
>> 
>> Do you really need to define a cross package for LLVM? In my
>> experience it was possible to use the same llvm libraries for native
>> and cross compilation. By default LLVM builds support for all
>> supported targets (provided they are not "experimental" IIRC).
>
> No, I don't think it's required.  I only need it so I can define a
> default target that's different from the host.
>
>> 
>> Whereas for the clang package, at the moment it does have to be built
>> for a specific target IIUC. I hope that one day we could have the same
>> clang for native and cross compilation in Guix, but I don't think it
>> can work without some serious re-design of how cross-compilation
>> works. I've been trying to think about it but I don't yet have a good
>> understanding of it.
>
> You can use --target to control which target clang builds for (although
> I don't know if our clang package can work like that). I wanted to have
> a default target though, because passing --target all the time is
> cumbersome and we would have to adjust all recipes to pass the flag.
> With the default target set appropriately, (clang-for-target) will
> always produce binaries for the correct architecture, whether
> cross-compiling or not.
>

Ah I see, that makes sense!  I suppose a possible alternative could be
to define a wrapper around clang to pass the `--target=<triplet>' option
by default, but that might be a bit ugly (although we already have a
ld-wrapper).

Thanks,
Pierre
Pierre Langlois March 5, 2022, 2 p.m. UTC | #4
Julien Lepiller <julien@lepiller.eu> writes:

> * gnu/packages/llvm.scm (cross-llvm): New variable.
> ---
>  gnu/packages/llvm.scm | 21 +++++++++++++++++++--
>  1 file changed, 19 insertions(+), 2 deletions(-)
>
> diff --git a/gnu/packages/llvm.scm b/gnu/packages/llvm.scm
> index eb949bed1b..d6e9846699 100644
> --- a/gnu/packages/llvm.scm
> +++ b/gnu/packages/llvm.scm
> @@ -18,7 +18,7 @@
>  ;;; Copyright © 2020 Jakub Kądziołka <kuba@kadziolka.net>
>  ;;; Copyright © 2021 Maxime Devos <maximedevos@telenet.be>
>  ;;; Copyright © 2020, 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com>
> -;;; Copyright © 2021 Julien Lepiller <julien@lepiller.eu>
> +;;; Copyright © 2021, 2022 Julien Lepiller <julien@lepiller.eu>
>  ;;; Copyright © 2021 Lars-Dominik Braun <lars@6xq.net>
>  ;;; Copyright © 2021 Guillaume Le Vaillant <glv@posteo.net>
>  ;;; Copyright © 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com>
> @@ -74,7 +74,8 @@ (define-module (gnu packages llvm)
>    #:use-module (srfi srfi-1)
>    #:use-module (ice-9 match)
>    #:export (make-lld-wrapper
> -            system->llvm-target))
> +            system->llvm-target
> +            cross-llvm))
>  
>  (define* (system->llvm-target #:optional
>                                (system (or (and=> (%current-target-system)
> @@ -99,6 +100,22 @@ (define* (system->llvm-target #:optional
>               ("i686"        => "X86")
>               ("i586"        => "X86"))))
>  
> +(define (cross-llvm llvm target)
> +  "Return a native LLVM package that targets a different system.  The resulting
> +libraries are running on the host but target a different system by default.
> +This packge can be used to control clang's default target."
> +  (package
> +    (inherit llvm)
> +    (arguments
> +     (substitute-keyword-arguments (package-arguments llvm)
> +      ((#:configure-flags flags)
> +       #~(append
> +           (list
> +             (string-append "-DLLVM_DEFAULT_TARGET_TRIPLE=" #$target)
> +             (string-append "-DLLVM_TARGET_ARCH="
> +                            #$(system->llvm-target (gnu-triplet->nix-system target))))


While playing with trying to use this series to build a WebAssembly
cross-compiler, I /think/ we have a bug here, and also in master, when
it comes to setting LLVM_TARGET_ARCH.

It's a bit confusing though, the documentation is as follows:

--8<---------------cut here---------------start------------->8---
LLVM_TARGET_ARCH:STRING
    LLVM target to use for native code generation. This is required for
    JIT generation. It defaults to “host”, meaning that it shall pick
    the architecture of the machine where LLVM is being built. If you
    are cross-compiling, set it to the target architecture name.
--8<---------------cut here---------------end--------------->8---

It's not clear what naming scheme the variable needs, is it the internal
LLVM target name or the triplet? I think it's architecture part of the
triplet...ish? But instead we pass it the internal target name.

It still works at the moment because whenever LLVM_TARGET_ARCH is used,
the cmake code looks quite permissive and tries to do the right thing by
turning the string lowercase and matching common names (hence the "...ish" :-) ).

https://github.com/llvm/llvm-project/blob/24f88f57de588817bd21e799e2ac1069c025674c/llvm/cmake/config-ix.cmake#L420

So if I try and add WebAssembly into the mix, the architecure name is
wasm32, but the LLVM target is called WebAssembly, and the lowercase
version of it doesn't work :-( 

| nix-system | LLVM target | LLVM target lowercase | Does it match? |
|------------+-------------+-----------------------+----------------|
| aarch64    | AArch64     | aarch64               | Y              |
| armhf      | ARM         | arm                   | Y              |
| mips64el   | Mips        | mips                  | Y              |
| powerpc    | PowerPC     | powerpc               | Y              |
| riscv      | RISCV       | riscv                 | Y              |
| x86_64     | X86         | x86                   | Y              |
| i686       | X86         | x86                   | Y              |
| i586       | X86         | x86                   | Y              |
|------------+-------------+-----------------------+----------------|
| wasm32     | WebAssembly | webassembly           | N :-(          |


I /think/ we might want to use the nix-system instead of the LLVM target
for LLVM_TARGET_ARCH:

--8<---------------cut here---------------start------------->8---
(string-append "-DLLVM_TARGET_ARCH=" #$(gnu-triplet->nix-system target)))
--8<---------------cut here---------------end--------------->8---

But I'm not sure, it might not work for mips64el for example, so we
could need yet-another-mapping.

Given it works as it is today with the current set of supported targets,
we don't necessarily need to fix it now. I'll be happy to take a look
later when eventually adding support for the wasm32-wasi toolchain in
Guix.

Thanks,
Pierre
diff mbox series

Patch

diff --git a/gnu/packages/llvm.scm b/gnu/packages/llvm.scm
index eb949bed1b..d6e9846699 100644
--- a/gnu/packages/llvm.scm
+++ b/gnu/packages/llvm.scm
@@ -18,7 +18,7 @@ 
 ;;; Copyright © 2020 Jakub Kądziołka <kuba@kadziolka.net>
 ;;; Copyright © 2021 Maxime Devos <maximedevos@telenet.be>
 ;;; Copyright © 2020, 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com>
-;;; Copyright © 2021 Julien Lepiller <julien@lepiller.eu>
+;;; Copyright © 2021, 2022 Julien Lepiller <julien@lepiller.eu>
 ;;; Copyright © 2021 Lars-Dominik Braun <lars@6xq.net>
 ;;; Copyright © 2021 Guillaume Le Vaillant <glv@posteo.net>
 ;;; Copyright © 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com>
@@ -74,7 +74,8 @@  (define-module (gnu packages llvm)
   #:use-module (srfi srfi-1)
   #:use-module (ice-9 match)
   #:export (make-lld-wrapper
-            system->llvm-target))
+            system->llvm-target
+            cross-llvm))
 
 (define* (system->llvm-target #:optional
                               (system (or (and=> (%current-target-system)
@@ -99,6 +100,22 @@  (define* (system->llvm-target #:optional
              ("i686"        => "X86")
              ("i586"        => "X86"))))
 
+(define (cross-llvm llvm target)
+  "Return a native LLVM package that targets a different system.  The resulting
+libraries are running on the host but target a different system by default.
+This packge can be used to control clang's default target."
+  (package
+    (inherit llvm)
+    (arguments
+     (substitute-keyword-arguments (package-arguments llvm)
+      ((#:configure-flags flags)
+       #~(append
+           (list
+             (string-append "-DLLVM_DEFAULT_TARGET_TRIPLE=" #$target)
+             (string-append "-DLLVM_TARGET_ARCH="
+                            #$(system->llvm-target (gnu-triplet->nix-system target))))
+           #$flags))))))
+
 (define (llvm-uri component version)
   ;; LLVM release candidate file names are formatted 'tool-A.B.C-rcN/tool-A.B.CrcN.src.tar.xz'
   ;; so we specify the version as A.B.C-rcN and delete the hyphen when referencing the file name.