1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
3 ;;; Copyright © 2014, 2015 Mark H Weaver <mhw@netris.org>
4 ;;; Copyright © 2016 Jan Nieuwenhuizen <janneke@gnu.org>
5 ;;; Copyright © 2016 Manolis Fragkiskos Ragkousis <manolis837@gmail.com>
7 ;;; This file is part of GNU Guix.
9 ;;; GNU Guix is free software; you can redistribute it and/or modify it
10 ;;; under the terms of the GNU General Public License as published by
11 ;;; the Free Software Foundation; either version 3 of the License, or (at
12 ;;; your option) any later version.
14 ;;; GNU Guix is distributed in the hope that it will be useful, but
15 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;;; GNU General Public License for more details.
19 ;;; You should have received a copy of the GNU General Public License
20 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
22 (define-module (gnu packages cross-base)
23 #:use-module (guix licenses)
24 #:use-module (gnu packages)
25 #:use-module (gnu packages gcc)
26 #:use-module (gnu packages base)
27 #:use-module (gnu packages commencement)
28 #:use-module (gnu packages linux)
29 #:use-module (gnu packages hurd)
30 #:use-module (guix packages)
31 #:use-module (guix download)
32 #:use-module (guix utils)
33 #:use-module (guix build-system gnu)
34 #:use-module (guix build-system trivial)
35 #:use-module (srfi srfi-1)
36 #:use-module (srfi srfi-26)
37 #:use-module (ice-9 match)
38 #:use-module (ice-9 regex)
39 #:export (cross-binutils
44 ;; GCC package used as the basis for cross-compilation. It doesn't have to
45 ;; be 'gcc' and can be a specific variant such as 'gcc-4.8'.
48 (define (cross p target)
50 (name (string-append (package-name p) "-cross-" target))
52 (substitute-keyword-arguments (package-arguments p)
53 ((#:configure-flags flags)
54 `(cons ,(string-append "--target=" target)
57 (define (package-with-patch original patch)
58 "Return package ORIGINAL with PATCH applied."
59 (package (inherit original)
60 (source (origin (inherit (package-source original))
61 (patches (list patch))))))
63 (define (cross-binutils target)
64 "Return a cross-Binutils for TARGET."
65 (let ((binutils (package (inherit binutils)
67 (substitute-keyword-arguments (package-arguments
69 ((#:configure-flags flags)
70 ;; Build with `--with-sysroot' so that ld honors
71 ;; DT_RUNPATH entries when searching for a needed
72 ;; library. This works because as a side effect
73 ;; `genscripts.sh' sets `USE_LIBPATH=yes', which tells
74 ;; elf32.em to use DT_RUNPATH in its search list.
75 ;; See <http://sourceware.org/ml/binutils/2013-05/msg00312.html>.
77 ;; In theory choosing / as the sysroot could lead ld
78 ;; to pick up native libs instead of target ones. In
79 ;; practice the RUNPATH of target libs only refers to
80 ;; target libs, not native libs, so this is safe.
81 `(cons "--with-sysroot=/" ,flags)))))))
83 ;; For Xtensa, apply Qualcomm's patch.
84 (cross (if (string-prefix? "xtensa-" target)
85 (package-with-patch binutils
87 "ath9k-htc-firmware-binutils.patch"))
91 (define (cross-gcc-arguments target libc)
92 "Return build system arguments for a cross-gcc for TARGET, using LIBC (which
93 may be either a libc package or #f.)"
94 ;; Set the current target system so that 'glibc-dynamic-linker' returns the
96 (parameterize ((%current-target-system target))
97 ;; Disable stripping as this can break binaries, with object files of
98 ;; libgcc.a showing up as having an unknown architecture. See
99 ;; <http://lists.fedoraproject.org/pipermail/arm/2010-August/000663.html>
101 (let ((args `(#:strip-binaries? #f
102 ,@(package-arguments %xgcc))))
103 (substitute-keyword-arguments args
104 ((#:configure-flags flags)
105 `(append (list ,(string-append "--target=" target)
107 `( ;; Disable libcilkrts because it is not
108 ;; ported to GNU/Hurd.
109 "--disable-libcilkrts")
110 `( ;; Disable features not needed at this stage.
111 "--disable-shared" "--enable-static"
112 "--enable-languages=c,c++"
114 ;; libstdc++ cannot be built at this stage
115 ;; ("Link tests are not allowed after
116 ;; GCC_NO_EXECUTABLES.").
117 "--disable-libstdc++-v3"
119 "--disable-threads" ;libgcc, would need libc
120 "--disable-libatomic"
121 "--disable-libmudflap"
124 "--disable-libquadmath"
125 "--disable-decimal-float" ;would need libc
126 "--disable-libcilkrts"
128 ;; When target is any OS other than 'none' these
129 ;; libraries will fail if there is no libc
131 ;; <https://lists.gnu.org/archive/html/guix-devel/2016-02/msg01311.html>
134 "--disable-libsanitizer"
139 `(remove (cut string-match "--enable-languages.*" <>)
141 ((#:make-flags flags)
143 `(let ((libc (assoc-ref %build-inputs "libc")))
144 ;; FLAGS_FOR_TARGET are needed for the target libraries to receive
145 ;; the -Bxxx for the startfiles.
146 (cons (string-append "FLAGS_FOR_TARGET=-B" libc "/lib")
152 'install 'make-cross-binutils-visible
153 (lambda* (#:key outputs inputs #:allow-other-keys)
154 (let* ((out (assoc-ref outputs "out"))
155 (libexec (string-append out "/libexec/gcc/"
157 (binutils (string-append
158 (assoc-ref inputs "binutils-cross")
159 "/bin/" ,target "-"))
160 (wrapper (string-append
161 (assoc-ref inputs "ld-wrapper-cross")
162 "/bin/" ,target "-ld")))
163 (for-each (lambda (file)
164 (symlink (string-append binutils file)
165 (string-append libexec "/"
168 (symlink wrapper (string-append libexec "/ld"))
173 ;; Unlike our 'strip' phase, this will do the right thing
174 ;; for cross-compilers.
175 (zero? (system* "make" "install-strip")))
179 'configure 'set-cross-path
180 (lambda* (#:key inputs #:allow-other-keys)
181 ;; Add the cross kernel headers to CROSS_CPATH, and remove them
183 (let ((libc (assoc-ref inputs "libc"))
184 (kernel (assoc-ref inputs "xkernel-headers")))
186 ;; Return #t if X is a cross-libc or cross Linux.
187 (or (string-prefix? libc x)
188 (string-prefix? kernel x)))
189 (let ((cpath (string-append
191 ":" kernel "/include")))
192 (for-each (cut setenv <> cpath)
193 '("CROSS_C_INCLUDE_PATH"
194 "CROSS_CPLUS_INCLUDE_PATH"
195 "CROSS_OBJC_INCLUDE_PATH"
196 "CROSS_OBJCPLUS_INCLUDE_PATH")))
197 (setenv "CROSS_LIBRARY_PATH"
198 (string-append libc "/lib:"
199 kernel "/lib")) ;for Hurd's libihash
204 (let* ((path (search-path-as-string->list value))
205 (native-path (list->search-path-as-string
206 (remove cross? path) ":")))
207 (setenv var native-path)))))
211 "OBJCPLUS_INCLUDE_PATH"
217 (define (cross-gcc-patches target)
218 "Return GCC patches needed for TARGET."
219 (cond ((string-prefix? "xtensa-" target)
220 ;; Patch by Qualcomm needed to build the ath9k-htc firmware.
221 (search-patches "ath9k-htc-firmware-gcc.patch"))
224 (define* (cross-gcc target
225 #:optional (xbinutils (cross-binutils target)) libc)
226 "Return a cross-compiler for TARGET, where TARGET is a GNU triplet. Use
227 XBINUTILS as the associated cross-Binutils. If LIBC is false, then build a
228 GCC that does not target a libc; otherwise, target that libc."
229 (package (inherit %xgcc)
230 (name (string-append "gcc-cross-"
231 (if libc "" "sans-libc-")
233 (source (origin (inherit (package-source %xgcc))
236 (origin-patches (package-source %xgcc))
237 (cons (search-patch "gcc-cross-environment-variables.patch")
238 (cross-gcc-patches target))))))
240 ;; For simplicity, use a single output. Otherwise libgcc_s & co. are not
241 ;; found by default, etc.
245 `(#:implicit-inputs? #f
246 #:modules ((guix build gnu-build-system)
252 ,@(cross-gcc-arguments target libc)))
255 `(("ld-wrapper-cross" ,(make-ld-wrapper
256 (string-append "ld-wrapper-" target)
258 #:binutils xbinutils))
259 ("binutils-cross" ,xbinutils)
261 ;; Call it differently so that the builder can check whether the "libc"
263 ("libc-native" ,@(assoc-ref %final-inputs "libc"))
266 ,@(let ((inputs (append (package-inputs %xgcc)
267 (alist-delete "libc" %final-inputs))))
270 ("xkernel-headers" ;the target headers
271 ,@(assoc-ref (package-propagated-inputs libc)
278 ;; Only search target inputs, not host inputs.
279 ;; Note: See <http://bugs.gnu.org/22186> for why not 'CPATH'.
281 (list (search-path-specification
282 (variable "CROSS_C_INCLUDE_PATH")
283 (files '("include")))
284 (search-path-specification
285 (variable "CROSS_CPLUS_INCLUDE_PATH")
286 (files '("include")))
287 (search-path-specification
288 (variable "CROSS_OBJC_INCLUDE_PATH")
289 (files '("include")))
290 (search-path-specification
291 (variable "CROSS_OBJCPLUS_INCLUDE_PATH")
292 (files '("include")))
293 (search-path-specification
294 (variable "CROSS_LIBRARY_PATH")
295 (files '("lib" "lib64")))))
296 (native-search-paths '())))
298 (define* (cross-kernel-headers target
300 (xgcc (cross-gcc target))
301 (xbinutils (cross-binutils target)))
302 "Return headers depending on TARGET."
304 (define xlinux-headers
305 (package (inherit linux-libre-headers)
306 (name (string-append (package-name linux-libre-headers)
309 (substitute-keyword-arguments
310 `(#:implicit-cross-inputs? #f
311 ,@(package-arguments linux-libre-headers))
316 (setenv "ARCH" ,(system->linux-architecture target))
317 (format #t "`ARCH' set to `~a' (cross compiling)~%" (getenv "ARCH"))
319 (and (zero? (system* "make" "defconfig"))
320 (zero? (system* "make" "mrproper" "headers_check"))))
322 (native-inputs `(("cross-gcc" ,xgcc)
323 ("cross-binutils" ,xbinutils)
324 ,@(package-native-inputs linux-libre-headers)))))
326 (define xgnumach-headers
327 (package (inherit gnumach-headers)
328 (name (string-append (package-name gnumach-headers)
331 (native-inputs `(("cross-gcc" ,xgcc)
332 ("cross-binutils" ,xbinutils)
333 ,@(package-native-inputs gnumach-headers)))))
336 (package (inherit mig)
337 (name (string-append "mig-cross"))
339 `(#:modules ((guix build gnu-build-system)
342 #:phases (alist-cons-before
343 'configure 'set-cross-headers-path
344 (lambda* (#:key inputs #:allow-other-keys)
345 (let* ((mach (assoc-ref inputs "cross-gnumach-headers"))
346 (cpath (string-append mach "/include")))
347 (for-each (cut setenv <> cpath)
348 '("CROSS_C_INCLUDE_PATH"
349 "CROSS_CPLUS_INCLUDE_PATH"
350 "CROSS_OBJC_INCLUDE_PATH"
351 "CROSS_OBJCPLUS_INCLUDE_PATH"))))
353 #:configure-flags (list ,(string-append "--target=" target))
354 ,@(package-arguments mig)))
356 (propagated-inputs `(("cross-gnumach-headers" ,xgnumach-headers)))
357 (native-inputs `(("cross-gcc" ,xgcc)
358 ("cross-binutils" ,xbinutils)
359 ,@(package-native-inputs mig)))))
361 (define xhurd-headers
362 (package (inherit hurd-headers)
363 (name (string-append (package-name hurd-headers)
366 (propagated-inputs `(("cross-mig" ,xmig)))
367 (native-inputs `(("cross-gcc" ,xgcc)
368 ("cross-binutils" ,xbinutils)
370 ,@(alist-delete "mig"(package-native-inputs hurd-headers))))))
372 (define xglibc/hurd-headers
373 (package (inherit glibc/hurd-headers)
374 (name (string-append (package-name glibc/hurd-headers)
378 (substitute-keyword-arguments
379 `(#:modules ((guix build gnu-build-system)
382 ,@(package-arguments glibc/hurd-headers))
385 'pre-configure 'set-cross-headers-path
386 (lambda* (#:key inputs #:allow-other-keys)
387 (let* ((mach (assoc-ref inputs "gnumach-headers"))
388 (hurd (assoc-ref inputs "hurd-headers"))
389 (cpath (string-append mach "/include:"
391 (for-each (cut setenv <> cpath)
392 '("CROSS_C_INCLUDE_PATH"
393 "CROSS_CPLUS_INCLUDE_PATH"
394 "CROSS_OBJC_INCLUDE_PATH"
395 "CROSS_OBJCPLUS_INCLUDE_PATH"))))
398 (propagated-inputs `(("gnumach-headers" ,xgnumach-headers)
399 ("hurd-headers" ,xhurd-headers)))
401 (native-inputs `(("cross-gcc" ,xgcc)
402 ("cross-binutils" ,xbinutils)
404 ,@(alist-delete "mig"(package-native-inputs glibc/hurd-headers))))))
406 (define xhurd-minimal
407 (package (inherit hurd-minimal)
408 (name (string-append (package-name hurd-minimal)
411 (substitute-keyword-arguments
412 `(#:modules ((guix build gnu-build-system)
415 ,@(package-arguments hurd-minimal))
418 'configure 'set-cross-headers-path
419 (lambda* (#:key inputs #:allow-other-keys)
420 (let* ((glibc-headers (assoc-ref inputs "cross-glibc-hurd-headers"))
421 (cpath (string-append glibc-headers "/include")))
422 (for-each (cut setenv <> cpath)
423 '("CROSS_C_INCLUDE_PATH"
424 "CROSS_CPLUS_INCLUDE_PATH"
425 "CROSS_OBJC_INCLUDE_PATH"
426 "CROSS_OBJCPLUS_INCLUDE_PATH"))))
429 (inputs `(("cross-glibc-hurd-headers" ,xglibc/hurd-headers)))
431 (native-inputs `(("cross-gcc" ,xgcc)
432 ("cross-binutils" ,xbinutils)
434 ,@(alist-delete "mig"(package-native-inputs hurd-minimal))))))
436 (define xhurd-core-headers
437 (package (inherit hurd-core-headers)
438 (name (string-append (package-name hurd-core-headers)
441 (inputs `(("gnumach-headers" ,xgnumach-headers)
442 ("hurd-headers" ,xhurd-headers)
443 ("hurd-minimal" ,xhurd-minimal)))
445 (native-inputs `(("cross-gcc" ,xgcc)
446 ("cross-binutils" ,xbinutils)
448 ,@(package-native-inputs hurd-core-headers)))))
451 ((or "i586-pc-gnu" "i586-gnu") xhurd-core-headers)
454 (define* (cross-libc target
456 (xgcc (cross-gcc target))
457 (xbinutils (cross-binutils target))
458 (xheaders (cross-kernel-headers target)))
459 "Return a libc cross-built for TARGET, a GNU triplet. Use XGCC and
460 XBINUTILS and the cross tool chain."
461 (define (cross-libc-for-target target)
462 "Return libc depending on TARGET."
464 ((or "i586-pc-gnu" "i586-gnu") glibc/hurd)
467 (package (inherit glibc)
468 (name (string-append "glibc-cross-" target))
470 (substitute-keyword-arguments
471 `(;; Disable stripping (see above.)
474 ;; This package is used as a target input, but it should not have
475 ;; the usual cross-compilation inputs since that would include
477 #:implicit-cross-inputs? #f
480 #:modules ((guix build gnu-build-system)
484 ;; Package-arguments does not use the correct libc, so we use
485 ;; (cross-libc-for-target ...) to determine the correct one.
486 ,@(package-arguments (cross-libc-for-target target)))
487 ((#:configure-flags flags)
488 `(cons ,(string-append "--host=" target)
492 'configure 'set-cross-kernel-headers-path
493 (lambda* (#:key inputs #:allow-other-keys)
494 (let* ((kernel (assoc-ref inputs "kernel-headers"))
495 (cpath (string-append kernel "/include")))
496 (for-each (cut setenv <> cpath)
497 '("CROSS_C_INCLUDE_PATH"
498 "CROSS_CPLUS_INCLUDE_PATH"
499 "CROSS_OBJC_INCLUDE_PATH"
500 "CROSS_OBJCPLUS_INCLUDE_PATH"))
501 (setenv "CROSS_LIBRARY_PATH"
502 (string-append kernel "/lib")) ;for Hurd's libihash
506 ;; Shadow the native "kernel-headers" because glibc's recipe expects the
507 ;; "kernel-headers" input to point to the right thing.
508 (propagated-inputs `(("kernel-headers" ,xheaders)))
510 ;; FIXME: 'static-bash' should really be an input, not a native input, but
511 ;; to do that will require building an intermediate cross libc.
514 (native-inputs `(("cross-gcc" ,xgcc)
515 ("cross-binutils" ,xbinutils)
516 ,@(if (string-match (or "i586-pc-gnu" "i586-gnu") target)
518 ,@(assoc-ref (package-native-inputs xheaders)
521 ,@(package-inputs glibc) ;FIXME: static-bash
522 ,@(package-native-inputs glibc)))))
526 ;;; Concrete cross toolchains.
529 (define-public xgcc-mips64el
530 (let* ((triplet "mips64el-linux-gnuabi64") ;N64 ABI
531 (xgcc (cross-gcc triplet
532 (cross-binutils triplet)
533 (cross-libc triplet))))
534 ;; Don't attempt to build this cross-compiler on i686;
535 ;; see <http://bugs.gnu.org/19598>.
536 (package (inherit xgcc)
537 (supported-systems (fold delete
538 (package-supported-systems xgcc)
539 '("mips64el-linux" "i686-linux"))))))
541 (define-public xgcc-xtensa
542 ;; Bare-bones Xtensa cross-compiler, used to build the Atheros firmware.
543 (cross-gcc "xtensa-elf"))
545 (define-public xgcc-armhf
546 (let* ((triplet "arm-linux-gnueabihf")
547 (xgcc (cross-gcc triplet
548 (cross-binutils triplet)
549 (cross-libc triplet))))
550 (package (inherit xgcc)
551 (supported-systems (delete "armhf-linux" %supported-systems)))))
553 ;; (define-public xgcc-armel
554 ;; (let ((triplet "armel-linux-gnueabi"))
555 ;; (cross-gcc triplet
556 ;; (cross-binutils triplet)
557 ;; (cross-libc triplet))))