projects/guix·blob python-team · refs

845 lines · 36.9 KiB

1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2013-2018, 2020, 2023-2024 Ludovic Courtès <[email protected]>
3;;; Copyright © 2014, 2015, 2018 Mark H Weaver <[email protected]>
4;;; Copyright © 2016, 2019, 2023-2025 Janneke Nieuwenhuizen <[email protected]>
5;;; Copyright © 2016 Manolis Fragkiskos Ragkousis <[email protected]>
6;;; Copyright © 2018 Tobias Geerinckx-Rice <[email protected]>
7;;; Copyright © 2019, 2020, 2021 Marius Bakke <[email protected]>
8;;; Copyright © 2019 Carl Dong <[email protected]>
9;;; Copyright © 2020 Mathieu Othacehe <[email protected]>
10;;; Copyright © 2022 Maxim Cournoyer <[email protected]>
11;;; Copyright © 2023 Josselin Poiret <[email protected]>
12;;; Copyright © 2023 Foundation Devices, Inc. <[email protected]>
13;;;
14;;; This file is part of GNU Guix.
15;;;
16;;; GNU Guix is free software; you can redistribute it and/or modify it
17;;; under the terms of the GNU General Public License as published by
18;;; the Free Software Foundation; either version 3 of the License, or (at
19;;; your option) any later version.
20;;;
21;;; GNU Guix is distributed in the hope that it will be useful, but
22;;; WITHOUT ANY WARRANTY; without even the implied warranty of
23;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24;;; GNU General Public License for more details.
25;;;
26;;; You should have received a copy of the GNU General Public License
27;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
28
29(define-module (gnu packages cross-base)
30 #:use-module (gnu packages)
31 #:use-module (gnu packages autotools) ;; for config
32 #:use-module (gnu packages avr)
33 #:use-module (gnu packages gcc)
34 #:use-module (gnu packages base)
35 #:use-module (gnu packages bash)
36 #:use-module (gnu packages linux)
37 #:use-module (gnu packages hurd)
38 #:use-module (gnu packages mingw)
39 #:use-module (guix memoization)
40 #:use-module (guix platform)
41 #:use-module (guix packages)
42 #:use-module (guix diagnostics)
43 #:use-module (guix download)
44 #:use-module (guix i18n)
45 #:use-module (guix utils)
46 #:use-module (guix build-system gnu)
47 #:use-module (guix build-system trivial)
48 #:use-module (guix gexp)
49 #:use-module (srfi srfi-1)
50 #:use-module (srfi srfi-26)
51 #:use-module (ice-9 match)
52 #:use-module (ice-9 regex)
53 #:export (cross-binutils
54 cross-libc
55 cross-gcc
56 cross-mig
57 cross-kernel-headers
58 cross-gcc-toolchain))
59
60(define-syntax %xgcc
61 ;; GCC package used as the basis for cross-compilation. It doesn't have to
62 ;; be 'gcc' and can be a specific variant such as 'gcc-4.8'.
63 ;;
64 ;; Note: This is a macro so that we do not refer to 'gcc' from the top
65 ;; level, which would lead to circular-dependency issues.
66 (identifier-syntax gcc-14))
67
68(define %gcc-include-paths
69 ;; Environment variables for header search paths.
70 ;; Note: See <http://bugs.gnu.org/22186> for why not 'CPATH'.
71 '("C_INCLUDE_PATH"
72 "CPLUS_INCLUDE_PATH"
73 "OBJC_INCLUDE_PATH"
74 "OBJCPLUS_INCLUDE_PATH"))
75
76(define %gcc-cross-include-paths
77 ;; Search path for target headers when cross-compiling.
78 (map (cut string-append "CROSS_" <>) %gcc-include-paths))
79
80(define (cross p target)
81 (package (inherit p)
82 (name (string-append (package-name p) "-cross-" target))
83 (arguments
84 (substitute-keyword-arguments arguments
85 ((#:configure-flags flags #~'())
86 #~(cons #$(string-append "--target=" target)
87 #$flags))))))
88
89(define (contains-keyword? args)
90 "Check if ARGS contains a keyword object."
91 (find keyword? args))
92
93(define* (cross-binutils . args)
94 (if (or (= (length args) 1) (contains-keyword? args))
95 (apply cross-binutils* args)
96 (apply cross-binutils/deprecated args)))
97
98(define* (cross-binutils/deprecated target #:optional (binutils binutils))
99 (warning (G_ "'cross-binutils' must be used with keyword arguments~%"))
100 (cross-binutils* target #:binutils binutils))
101
102(define (cross-binutils-package target)
103 "Returns the default package to use for a cross-Binutils for TARGET."
104 (cond
105 ;; The xtensa-ath9k-elf target is used solely to build the firmware for
106 ;; ath9k devices, the patches to binutils have not been updated and
107 ;; only apply to [email protected].
108 ((string=? target "xtensa-ath9k-elf") binutils-2.33)
109 (else binutils)))
110
111(define* (cross-binutils* target
112 #:key
113 (binutils (cross-binutils-package target)))
114 "Return a cross-Binutils for TARGET using BINUTILS."
115 (let ((binutils (package
116 (inherit binutils)
117 (arguments
118 (substitute-keyword-arguments (package-arguments
119 binutils)
120 ((#:configure-flags flags)
121 ;; Build with `--with-sysroot' so that ld honors
122 ;; DT_RUNPATH entries when searching for a needed
123 ;; library. This works because as a side effect
124 ;; `genscripts.sh' sets `USE_LIBPATH=yes', which tells
125 ;; elf32.em to use DT_RUNPATH in its search list.
126 ;; See <http://sourceware.org/ml/binutils/2013-05/msg00312.html>.
127 ;;
128 ;; In theory choosing / as the sysroot could lead ld
129 ;; to pick up native libs instead of target ones. In
130 ;; practice the RUNPATH of target libs only refers to
131 ;; target libs, not native libs, so this is safe.
132 #~(cons "--with-sysroot=/" #$flags)))))))
133
134 ;; For xtensa-ath9k-elf, apply Qualcomm's patch.
135 (cross (cond ((string=? target "xtensa-ath9k-elf")
136 (package-with-patches binutils
137 (search-patches
138 "ath9k-htc-firmware-binutils.patch")))
139 ((target-mingw? target)
140 (package-with-extra-patches binutils
141 (search-patches
142 "binutils-cross-windres.patch"
143 "binutils-mingw-w64-deterministic.patch")))
144 (else binutils))
145 target)))
146
147(define (cross-gcc-arguments target xgcc libc)
148 "Return build system arguments for a cross-gcc for TARGET, using XGCC as the
149base compiler and using LIBC (which may be either a libc package or #f.)"
150 ;; Set the current target system so that 'glibc-dynamic-linker' returns the
151 ;; right name.
152 (parameterize ((%current-target-system target))
153 ;; Disable stripping as this can break binaries, with object files of
154 ;; libgcc.a showing up as having an unknown architecture. See
155 ;; <http://lists.fedoraproject.org/pipermail/arm/2010-August/000663.html>
156 ;; for instance.
157 (let ((args `(#:strip-binaries? #f
158 ,@(package-arguments xgcc))))
159 (substitute-keyword-arguments args
160 ((#:configure-flags flags)
161 #~(append (list #$(string-append "--target=" target)
162 #$@(if libc
163 #~( ;; Disable libcilkrts because it is not
164 ;; ported to GNU/Hurd.
165 "--disable-libcilkrts"
166 ;; When building a cross compiler, --with-sysroot is
167 ;; implicitly set to "$gcc_tooldir/sys-root". This does
168 ;; not work for us, because --with-native-system-header-dir
169 ;; is searched for relative to this location. Thus, we set
170 ;; it to "/" so GCC is able to find the target libc headers.
171 ;; This is safe because in practice GCC uses CROSS_CPATH
172 ;; & co to separate target and host libraries.
173 "--with-sysroot=/")
174 #~( ;; Disable features not needed at this stage.
175 "--disable-shared" "--enable-static"
176 "--enable-languages=c,c++"
177
178 ;; libstdc++ cannot be built at this stage
179 ;; ("Link tests are not allowed after
180 ;; GCC_NO_EXECUTABLES.").
181 "--disable-libstdc++-v3"
182
183 "--disable-threads" ;libgcc, would need libc
184 "--disable-libatomic"
185 "--disable-libmudflap"
186 "--disable-libgomp"
187 "--disable-libmpx"
188 "--disable-libssp"
189 "--disable-libquadmath"
190 "--disable-decimal-float" ;would need libc
191 "--disable-libcilkrts"
192
193 ;; When target is any OS other than 'none' these
194 ;; libraries will fail if there is no libc
195 ;; present. See
196 ;; <https://lists.gnu.org/archive/html/guix-devel/2016-02/msg01311.html>
197 "--disable-libitm"
198 "--disable-libvtv"
199 "--disable-libsanitizer"
200 ))
201
202 ;; Install cross-built libraries such as libgcc_s.so in
203 ;; the "lib" output.
204 #$@(if libc
205 #~((string-append "--with-toolexeclibdir="
206 (assoc-ref %outputs "lib")
207 "/" #$target "/lib"))
208 #~())
209
210
211 #$@(if (target-avr? target)
212 #~("--enable-multilib")
213 #~())
214
215
216 #$@(if (and libc (target-avr? target))
217 #~(;; By default GCC will attemp to compile
218 ;; some libraries for other languages (objc,
219 ;; fortran) but compilation fails for AVR.
220 "--enable-languages=c,c++"
221 (string-append "--with-native-system-header-dir="
222 #$libc "/" #$target "/include"))
223 #~()))
224
225 (remove
226 (lambda (flag)
227 (or (string-prefix? "--enable-languages" flag)
228 (and #$libc
229 #$(target-avr? target)
230 (string-prefix? "--with-native-system-header-dir"
231 flag))
232 (and #$(target-avr? target)
233 (string=? flag "--disable-multilib"))))
234 #$flags)))
235 ((#:make-flags flags)
236 (if libc
237 #~(let ((libc (assoc-ref %build-inputs "libc"))
238 (lib-prefix (if #$(target-avr? target)
239 (string-append "/" #$target)
240 "")))
241 ;; FLAGS_FOR_TARGET are needed for the target libraries to receive
242 ;; the -Bxxx for the startfiles.
243 (cons (string-append "FLAGS_FOR_TARGET=-B"
244 libc lib-prefix "/lib")
245 #$flags))
246 flags))
247 ((#:phases phases)
248 #~(cross-gcc-build-phases #$target #$phases))))))
249
250(define (cross-gcc-patches xgcc target)
251 "Return GCC patches needed for XGCC and TARGET."
252 (cond ((string-prefix? "xtensa-" target)
253 ;; Patch by Qualcomm needed to build the ath9k-htc firmware.
254 (search-patches "ath9k-htc-firmware-gcc.patch"))
255 ((target-mingw? target)
256 (append (if (not (version>=? (package-version xgcc) "13.0"))
257 (search-patches "gcc-4.9.3-mingw-gthr-default.patch")
258 '())
259 (if (version>=? (package-version xgcc) "7.0")
260 (search-patches "gcc-7-cross-mingw.patch")
261 '())))
262 (else '())))
263
264(define (cross-gcc-snippet target)
265 "Return GCC snippet needed for TARGET."
266 `(begin
267 ,@(if (target-mingw? target)
268 '((copy-recursively "libstdc++-v3/config/os/mingw32-w64"
269 "libstdc++-v3/config/os/newlib"))
270 '())
271 ;; TOOLDIR_BASE_PREFIX is erroneous when using a separate "lib"
272 ;; output. Specify it correctly, otherwise GCC won't find its shared
273 ;; libraries installed in the "lib" output. See:
274 ;; https://lists.gnu.org/archive/html/bug-guix/2020-03/msg00196.html.
275 (substitute* "gcc/Makefile.in"
276 (("-DTOOLDIR_BASE_PREFIX=[^ ]*")
277 "-DTOOLDIR_BASE_PREFIX=\\\"../../../../\\\""))
278 #t))
279
280(define (cross-gcc-search-paths target)
281 "Return list of GCC search path specifications needed for TARGET."
282 (cons (search-path-specification
283 (variable "CROSS_LIBRARY_PATH")
284 (files `("lib" "lib64"
285 ,@(list (string-append target "/lib")
286 (string-append target "/lib64")))))
287
288 (map (lambda (variable)
289 (search-path-specification
290 (variable variable)
291
292 ;; Add 'include/c++' here so that <cstdlib>'s
293 ;; "#include_next <stdlib.h>" finds GCC's
294 ;; <stdlib.h>, not libc's.
295 (files (match variable
296 ("CROSS_CPLUS_INCLUDE_PATH"
297 `("include/c++" "include"
298 ,@(list (string-append target "/include/c++")
299 (string-append target "/include"))))
300 (_
301 `("include"
302 ,(string-append target "/include")))))))
303 %gcc-cross-include-paths)))
304
305(define* (cross-gcc target
306 #:key
307 (xgcc %xgcc)
308 (xbinutils (cross-binutils target))
309 (libc #f))
310 "Return a cross-compiler for TARGET, where TARGET is a GNU triplet. Use
311XGCC as the base compiler. Use XBINUTILS as the associated cross-Binutils.
312If LIBC is false, then build a GCC that does not target a libc; otherwise,
313target that libc."
314 (package
315 (inherit xgcc)
316 (name (string-append "gcc-cross-"
317 (if libc "" "sans-libc-")
318 target))
319 (source
320 (origin
321 (inherit
322 (package-source xgcc))
323 (patches
324 (append
325 (origin-patches (package-source xgcc))
326 (append (cond
327 ((version>=? (package-version xgcc) "13.0")
328 (search-patches "gcc-13-cross-system-header-dir.patch"
329 "gcc-12-cross-environment-variables.patch"
330 "gcc-cross-gxx-include-dir.patch"))
331 ((version>=? (package-version xgcc) "12.0")
332 (search-patches "gcc-12-cross-environment-variables.patch"
333 "gcc-cross-gxx-include-dir.patch"))
334 ((version>=? (package-version xgcc) "10.0")
335 (search-patches "gcc-10-cross-environment-variables.patch"
336 "gcc-cross-gxx-include-dir.patch"))
337 ((version>=? (package-version xgcc) "8.0")
338 (search-patches "gcc-8-cross-environment-variables.patch"))
339 ((version>=? (package-version xgcc) "6.0")
340 (search-patches "gcc-7-cross-toolexeclibdir.patch"
341 "gcc-6-cross-environment-variables.patch"))
342 (else
343 (search-patches "gcc-cross-environment-variables.patch")))
344 (cross-gcc-patches xgcc target))))
345 (modules '((guix build utils)))
346 (snippet
347 (cross-gcc-snippet target))))
348
349 (outputs '("out" "lib"))
350
351 (arguments
352 `(#:implicit-inputs? #f
353 #:imported-modules ((gnu build cross-toolchain)
354 ,@%default-gnu-imported-modules)
355 #:modules ((guix build gnu-build-system)
356 (guix build utils)
357 (gnu build cross-toolchain)
358 (srfi srfi-1)
359 (srfi srfi-26)
360 (ice-9 regex))
361
362 ,@(cross-gcc-arguments target xgcc libc)))
363
364 (native-inputs
365 `(("ld-wrapper-cross" ,(make-ld-wrapper
366 (string-append "ld-wrapper-" target)
367 #:target (const target)
368 #:binutils xbinutils))
369 ("binutils-cross" ,xbinutils)
370
371 ,@(let ((inputs (append (package-inputs xgcc)
372 (fold alist-delete (%final-inputs)
373 '("libc" "libc:static"))
374
375 ;; Call it differently so that the builder can
376 ;; check whether the "libc" input is #f.
377 `(("libc-native"
378 ,@(assoc-ref (%final-inputs) "libc"))
379 ("libc-native:static"
380 ,@(assoc-ref (%final-inputs)
381 "libc:static"))))))
382 (cond
383 ((target-mingw? target)
384 (if libc
385 `(,@inputs
386 ("libc" ,libc))
387 `(,@inputs
388 ("mingw-source" ,(package-source mingw-w64)))))
389 ((and libc (target-avr? target))
390 `(,@inputs
391 ("libc" ,libc)))
392 (libc
393 `(,@inputs
394 ("libc" ,libc)
395 ("libc:static" ,libc "static")
396 ("xkernel-headers" ;the target headers
397 ,@(assoc-ref (package-propagated-inputs libc)
398 "kernel-headers"))))
399 (else inputs)))))
400
401 (inputs '())
402
403 ;; Only search target inputs, not host inputs.
404 (search-paths (cross-gcc-search-paths target))
405 (native-search-paths '())))
406
407(define* (cross-kernel-headers . args)
408 (if (or (= (length args) 1) (contains-keyword? args))
409 (apply cross-kernel-headers* args)
410 (apply cross-kernel-headers/deprecated args)))
411
412(define* (cross-kernel-headers/deprecated target
413 #:optional
414 (linux-headers
415 linux-libre-headers)
416 (xgcc (cross-gcc target))
417 (xbinutils (cross-binutils target)))
418 (warning (G_ "'cross-kernel-headers' must be used with keyword arguments~%"))
419 (cross-kernel-headers* target
420 #:linux-headers linux-headers
421 #:xgcc xgcc
422 #:xbinutils xbinutils))
423
424(define* (cross-gnumach-headers target
425 #:key
426 (xgcc (cross-gcc target))
427 (xbinutils (cross-binutils target)))
428 (package
429 (inherit gnumach-headers)
430 (name (string-append (package-name gnumach-headers)
431 "-cross-" target))
432 (arguments
433 (substitute-keyword-arguments arguments
434 ((#:phases phases #~%standard-phases)
435 #~(modify-phases #$phases
436 ;; Cheat by setting the host_cpu variable manually, since using
437 ;; --host= would require a working cross-compiler, which we don't
438 ;; have yet.
439 (add-after 'unpack 'substitute-host-cpu
440 (lambda _
441 (substitute* "configure.ac"
442 (("AC_CANONICAL_HOST")
443 #$(string-append
444 "host_cpu="
445 (match target
446 ((? target-x86-32?)
447 "i386")
448 ((? target-x86-64?)
449 "x86_64")))))))))))
450 (supported-systems %supported-systems)
451 (native-inputs
452 (modify-inputs native-inputs
453 (prepend xgcc xbinutils)))))
454
455(define* (cross-mig target
456 #:key
457 (xgcc (cross-gcc target))
458 (xbinutils (cross-binutils target)))
459 "Return a cross-mig for TARGET, where TARGET is a GNU triplet. Use XGCC as
460the base compiler. Use XBINUTILS as the associated cross-Binutils."
461 (define xgnumach-headers
462 (cross-gnumach-headers target
463 #:xgcc xgcc
464 #:xbinutils xbinutils))
465 (package
466 (inherit mig)
467 (name (string-append "mig-cross"))
468 (arguments
469 (substitute-keyword-arguments arguments
470 ((#:configure-flags flags #~'())
471 #~(list #$(string-append "--target=" target)))
472 ((#:tests? _ #f)
473 #f)
474 ((#:phases phases #~%standard-phases)
475 #~(modify-phases #$phases
476 (add-before 'configure 'set-cross-headers-path
477 (lambda* (#:key inputs #:allow-other-keys)
478 (let* ((mach #+xgnumach-headers)
479 (cpath (string-append mach "/include")))
480 (for-each (lambda (variable)
481 (setenv variable cpath))
482 '#$%gcc-cross-include-paths))))))))
483 (propagated-inputs
484 (list xgnumach-headers))
485 (inputs (modify-inputs inputs
486 (delete "gnumach-headers")))
487 (native-inputs
488 (modify-inputs native-inputs
489 (prepend xgcc xbinutils)))))
490
491(define* (cross-kernel-headers* target
492 #:key
493 (linux-headers linux-libre-headers)
494 (xgcc (cross-gcc target))
495 (xbinutils (cross-binutils target)))
496 "Return headers depending on TARGET."
497
498 (define xlinux-headers
499 (package
500 (inherit linux-headers)
501 (name (string-append (package-name linux-headers)
502 "-cross-" target))
503 (arguments
504 (substitute-keyword-arguments
505 `(#:implicit-cross-inputs? #f
506 ,@(package-arguments linux-headers))
507 ((#:phases phases)
508 `(modify-phases ,phases
509 (replace 'build
510 (lambda _
511 (setenv "ARCH" ,(platform-linux-architecture
512 (lookup-platform-by-target target)))
513 (format #t "`ARCH' set to `~a' (cross compiling)~%"
514 (getenv "ARCH"))
515
516 (invoke "make" ,(system->defconfig target))
517 (invoke "make" "mrproper"
518 ,@(if (version>=? (package-version linux-headers) "5.3")
519 '("headers")
520 '("headers_check")))))))))
521 (native-inputs `(("cross-gcc" ,xgcc)
522 ("cross-binutils" ,xbinutils)
523 ,@(package-native-inputs linux-headers)))))
524
525 (define xmig
526 (cross-mig target #:xgcc xgcc #:xbinutils xbinutils))
527
528 (define xgnumach-headers
529 (cross-gnumach-headers target #:xgcc xgcc #:xbinutils xbinutils))
530
531 (define xhurd-headers
532 (package
533 (inherit hurd-headers)
534 (name (string-append (package-name hurd-headers)
535 "-cross-" target))
536
537 (arguments
538 (substitute-keyword-arguments arguments
539 ((#:configure-flags flags)
540 `(cons* ,(string-append "--build=" (%current-system))
541 ,(string-append "--host=" target)
542 ,flags))))
543 (supported-systems %supported-systems)
544 (native-inputs `(("cross-gcc" ,xgcc)
545 ("cross-binutils" ,xbinutils)
546 ("cross-mig" ,xmig)
547 ,@(alist-delete "mig" (package-native-inputs hurd-headers))))))
548
549 (define xglibc/hurd-headers
550 (package
551 (inherit glibc/hurd-headers)
552 (name (string-append (package-name glibc/hurd-headers)
553 "-cross-" target))
554
555 (arguments
556 (substitute-keyword-arguments
557 `(#:modules ((guix build gnu-build-system)
558 (guix build utils)
559 (srfi srfi-26))
560 ,@(package-arguments glibc/hurd-headers))
561 ((#:phases phases)
562 `(modify-phases ,phases
563 (add-after 'unpack 'set-cross-headers-path
564 (lambda* (#:key inputs #:allow-other-keys)
565 (let* ((mach (assoc-ref inputs "gnumach-headers"))
566 (hurd (assoc-ref inputs "hurd-headers"))
567 (cpath (string-append mach "/include:"
568 hurd "/include")))
569 (for-each (cut setenv <> cpath)
570 ',%gcc-cross-include-paths)
571 #t)))))
572 ((#:configure-flags flags)
573 `(cons* ,(string-append "--build=" (%current-system))
574 ,(string-append "--host=" target)
575 ,flags))))
576 (supported-systems %supported-systems)
577 (propagated-inputs `(("gnumach-headers" ,xgnumach-headers)
578 ("hurd-headers" ,xhurd-headers)))
579
580 (native-inputs `(("cross-gcc" ,xgcc)
581 ("cross-binutils" ,xbinutils)
582 ("cross-mig" ,xmig)
583 ,@(alist-delete "mig"(package-native-inputs glibc/hurd-headers))))))
584
585 (define xhurd-minimal
586 (package
587 (inherit hurd-minimal)
588 (name (string-append (package-name hurd-minimal)
589 "-cross-" target))
590 (arguments
591 (substitute-keyword-arguments
592 `(#:modules ((guix build gnu-build-system)
593 (guix build utils)
594 (srfi srfi-26))
595 ,@(package-arguments hurd-minimal))
596 ((#:configure-flags flags)
597 `(cons* ,(string-append "--build=" (%current-system))
598 ,(string-append "--host=" target)
599 ,flags))
600 ((#:phases phases)
601 #~(modify-phases #$phases
602 (add-after 'unpack 'delete-shared-target
603 ;; Cannot create shared libraries due to missing crt1.o
604 (lambda _
605 (substitute* "Makeconf"
606 (("(targets := \\$\\(libname\\)\\.a) \\$\\(libname\\)\\.so" all static)
607 static)
608 (("\\$\\(DESTDIR\\)\\$\\(libdir\\)/\\$\\(libname\\)\\.so\\.\\$\\(hurd-version\\)")
609 "")
610 (("^libs: .*\\.so\\..*" all)
611 (string-append "# " all)))))
612 (add-before 'configure 'set-cross-headers-path
613 (lambda* (#:key inputs #:allow-other-keys)
614 (let* ((glibc-headers (assoc-ref inputs "cross-glibc-hurd-headers"))
615 (mach-headers (assoc-ref inputs "cross-gnumach-headers"))
616 (cpath (string-append glibc-headers "/include"
617 ":" mach-headers "/include")))
618 (for-each (cut setenv <> cpath)
619 '#$%gcc-cross-include-paths)
620 #t)))))))
621 (supported-systems %supported-systems)
622 (inputs `(("cross-glibc-hurd-headers" ,xglibc/hurd-headers)
623 ("cross-gnumach-headers" ,xgnumach-headers)))
624
625 (native-inputs `(("cross-gcc" ,xgcc)
626 ("cross-binutils" ,xbinutils)
627 ("cross-mig" ,xmig)
628 ,@(alist-delete "mig"
629 (package-native-inputs hurd-minimal))))))
630
631 (define xhurd-core-headers
632 (package
633 (inherit hurd-core-headers)
634 (name (string-append (package-name hurd-core-headers)
635 "-cross-" target))
636 (supported-systems %supported-systems)
637 (arguments
638 `(#:target #f
639 ;; The headers are an input to the cross compiled glibc.
640 ;; These are cross compiled manually, so set target to #f
641 ;; to avoid having to disable implicit-cross-inputs in all of them.
642 ,@arguments))
643 (inputs `(("gnumach-headers" ,xgnumach-headers)
644 ("hurd-headers" ,xhurd-headers)
645 ("hurd-minimal" ,xhurd-minimal)))))
646
647 (if (target-hurd? target)
648 xhurd-core-headers
649 xlinux-headers))
650
651(define* (cross-libc . args)
652 (if (or (= (length args) 1) (contains-keyword? args))
653 (apply cross-libc* args)
654 (apply cross-libc/deprecated args)))
655
656(define* (cross-libc/deprecated target
657 #:optional
658 (libc (libc-for-target target))
659 (xgcc (cross-gcc target))
660 (xbinutils (cross-binutils target))
661 (xheaders (cross-kernel-headers target)))
662 (warning (G_ "'cross-libc' must be used with keyword arguments~%"))
663 (cross-libc* target
664 #:libc libc
665 #:xgcc xgcc
666 #:xbinutils xbinutils
667 #:xheaders xheaders))
668
669(define* (cross-libc* target
670 #:key
671 (libc (libc-for-target target))
672 (xgcc (cross-gcc target))
673 (xbinutils (cross-binutils target))
674 (xheaders (cross-kernel-headers target))
675 (static-bash (static-bash-for-glibc target))
676 (with-winpthreads? #t))
677 "Return LIBC cross-built for TARGET, a GNU triplet. Use XGCC and XBINUTILS
678and the cross tool chain. If TARGET doesn't have a standard C library #f is
679returned."
680 (match target
681 ((? target-mingw?)
682 (let ((machine (substring target 0 (string-index target #\-))))
683 (make-mingw-w64 machine
684 #:xgcc xgcc
685 #:xbinutils xbinutils
686 #:with-winpthreads? #t)))
687 ((or (? target-linux?) (? target-hurd?))
688 (package
689 (inherit libc)
690 (name (string-append "glibc-cross-" target
691 (if static-bash "" "-intermediate")))
692 (arguments
693 (parameterize ((%current-target-system target))
694 (substitute-keyword-arguments
695 `( ;; Disable stripping (see above.)
696 #:strip-binaries? #f
697 #:target ,target
698 ;; This package is used as a target input, but it should not have
699 ;; the usual cross-compilation inputs since that would include
700 ;; itself.
701 #:implicit-cross-inputs? #f
702
703 ;; We need SRFI 26.
704 #:modules ((guix build gnu-build-system)
705 (guix build utils)
706 (srfi srfi-26))
707
708 ,@(package-arguments libc))
709 ((#:phases phases)
710 `(modify-phases ,phases
711 (add-before 'configure 'add-cross-binutils-to-PATH
712 (lambda* (#:key native-inputs inputs #:allow-other-keys)
713 ;; Add BINUTILS/TARGET/bin to $PATH so that 'gcc
714 ;; -print-prog-name=objdump' returns the correct name. See
715 ;; <https://inbox.sourceware.org/libc-alpha/[email protected]/t/>.
716 (define cross-objdump
717 (search-input-file
718 (or native-inputs inputs)
719 (string-append ,target "/bin/objdump")))
720
721 (define cross-binutils
722 (dirname cross-objdump))
723
724 (format #t "adding '~a' to the front of 'PATH'~%"
725 cross-binutils)
726 (setenv "PATH" (string-append cross-binutils ":"
727 (getenv "PATH"))))))))))
728
729 ;; Shadow the native "kernel-headers" because glibc's recipe expects the
730 ;; "kernel-headers" input to point to the right thing.
731 (propagated-inputs `(("kernel-headers" ,xheaders)))
732 (inputs (if static-bash
733 `(("static-bash" ,static-bash))
734 '()))
735 (native-inputs `(("cross-gcc" ,xgcc)
736 ("cross-binutils" ,xbinutils)
737 ,@(if (target-hurd? target)
738 `(("cross-mig"
739 ,(cross-mig target
740 #:xgcc xgcc
741 #:xbinutils xbinutils)))
742 '())
743 ,@(if static-bash '() (package-inputs libc))
744 ,@(alist-delete "mig" (package-native-inputs libc))))))
745 ((? target-avr?)
746 (make-avr-libc #:xbinutils xbinutils
747 #:xgcc xgcc))
748 (else #f)))
749
750(define* (static-bash-for-glibc target
751 #:key
752 (xbinutils (cross-binutils target))
753 (xlibc (cross-libc* target
754 #:static-bash #f))
755 (xgcc (cross-gcc target
756 #:xbinutils xbinutils
757 #:libc xlibc)))
758 ;; Return a statically-linked Bash to be used by the cross libc in system(3) & co.
759 ;; Only for targets that use glibc.
760 (and (or (target-linux? target)
761 (target-hurd? target))
762 (package
763 (inherit static-bash)
764 (name (string-append "bash-static-cross-" target))
765 (native-inputs
766 `(("cross-gcc" ,xgcc)
767 ("cross-binutils" ,xbinutils)
768 ,@(if (target-loongarch64? target)
769 `(("config" ,config))
770 '())))
771 (inputs
772 `(("cross-libc" ,xlibc)
773 ("cross-libc:static" ,xlibc "static")))
774 (arguments
775 `(#:target ,target
776
777 ;; This package is used as a target input, but it should not have
778 ;; the usual cross-compilation inputs since that would include
779 ;; itself.
780 #:implicit-cross-inputs? #f
781 ,@arguments)))))
782
783(define* (cross-gcc-toolchain/implementation target
784 #:key
785 (base-gcc %xgcc)
786 (xbinutils (cross-binutils target))
787 (with-winpthreads? #t)
788 (libc (cross-libc
789 target
790 #:xgcc (cross-gcc target #:xgcc base-gcc)
791 #:xbinutils xbinutils
792 #:with-winpthreads? with-winpthreads?))
793 (xgcc (cross-gcc target
794 #:xgcc base-gcc
795 #:libc libc
796 #:xbinutils xbinutils)))
797 "Returns PACKAGE that contains a cross-compilation tool chain for TARGET
798with XBINUTILS, XGCC and LIBC (if exists for TARGET)."
799 (package
800 ;; Using PACKAGE-NAME of XGCC is avoided here as there are platforms that
801 ;; still need a toolchain but don't have a libc (e.g. or1k-elf).
802 (name (string-append "gcc-cross-" target "-toolchain"))
803 (version (package-version xgcc))
804 (source #f)
805 (build-system trivial-build-system)
806 (arguments
807 (list #:modules '((guix build union))
808 #:builder
809 #~(begin
810 (use-modules (ice-9 match)
811 (guix build union))
812
813 (match %build-inputs
814 (((names . directory) ...)
815 (union-build #$output directory))))))
816 (inputs `(,xbinutils ,xgcc ,@(if libc (list libc) '())))
817 (native-search-paths (package-search-paths xgcc))
818 (home-page (package-home-page xgcc))
819 (synopsis
820 (format #f "Complete GCC tool chain for C/C++ development (~a)" target))
821 (description "This package provides a complete GCC cross toolchain for
822C/C++ development to be installed in user profiles. This includes GCC, as
823well as libc (headers and binariesl), and Binutils. GCC is the GNU Compiler
824Collection.")
825 (license (delete-duplicates `(,(package-license xgcc)
826 ,(package-license xbinutils)
827 ,@(if libc
828 (list (package-license libc))
829 '()))))))
830
831(define cross-gcc-toolchain
832 (memoize cross-gcc-toolchain/implementation))
833
834
835;;; Concrete cross tool chains are instantiated like this:
836;;
837;; (define-public xgcc-armhf
838;; (let ((triplet "arm-linux-gnueabihf"))
839;; (cross-gcc triplet
840;; #:xbinutils (cross-binutils triplet)
841;; #:libc (cross-libc triplet))))
842;;
843;;; We don't do that here because we'd be referring to bindings from (gnu
844;;; packages gcc) from the top level, which doesn't play well with circular
845;;; dependencies among modules.