;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2013, 2014 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2014, 2015 Mark H Weaver <mhw@netris.org>
;;;
;;; This file is part of GNU Guix.
;;;
#:use-module (gnu packages)
#:use-module (gnu packages gcc)
#:use-module (gnu packages base)
+ #:use-module (gnu packages commencement)
#:use-module (gnu packages linux)
#:use-module (guix packages)
#:use-module (guix download)
(define (cross p target)
(package (inherit p)
- (location (source-properties->location (current-source-location)))
(name (string-append (package-name p) "-cross-" target))
(arguments
(substitute-keyword-arguments (package-arguments p)
`(cons ,(string-append "--target=" target)
,flags))))))
+(define (package-with-patch original patch)
+ "Return package ORIGINAL with PATCH applied."
+ (package (inherit original)
+ (source (origin (inherit (package-source original))
+ (patches (list patch))))))
+
(define (cross-binutils target)
"Return a cross-Binutils for TARGET."
(let ((binutils (package (inherit binutils)
;; practice the RUNPATH of target libs only refers to
;; target libs, not native libs, so this is safe.
`(cons "--with-sysroot=/" ,flags)))))))
- (cross binutils target)))
+
+ ;; For Xtensa, apply Qualcomm's patch.
+ (cross (if (string-prefix? "xtensa-" target)
+ (package-with-patch binutils
+ (search-patch
+ "ath9k-htc-firmware-binutils.patch"))
+ binutils)
+ target)))
+
+(define (cross-gcc-arguments target libc)
+ "Return build system arguments for a cross-gcc for TARGET, using LIBC (which
+may be either a libc package or #f.)"
+ ;; Set the current target system so that 'glibc-dynamic-linker' returns the
+ ;; right name.
+ (parameterize ((%current-target-system target))
+ ;; Disable stripping as this can break binaries, with object files of
+ ;; libgcc.a showing up as having an unknown architecture. See
+ ;; <http://lists.fedoraproject.org/pipermail/arm/2010-August/000663.html>
+ ;; for instance.
+ (let ((args `(#:strip-binaries? #f
+ ,@(package-arguments gcc-4.9))))
+ (substitute-keyword-arguments args
+ ((#:configure-flags flags)
+ `(append (list ,(string-append "--target=" target)
+ ,@(if libc
+ '()
+ `( ;; Disable features not needed at this stage.
+ "--disable-shared" "--enable-static"
+
+ ;; Disable C++ because libstdc++'s configure
+ ;; script otherwise fails with "Link tests are not
+ ;; allowed after GCC_NO_EXECUTABLES."
+ "--enable-languages=c"
+
+ "--disable-threads" ;libgcc, would need libc
+ "--disable-libatomic"
+ "--disable-libmudflap"
+ "--disable-libgomp"
+ "--disable-libssp"
+ "--disable-libquadmath"
+ "--disable-decimal-float" ;would need libc
+ )))
+
+ ,(if libc
+ flags
+ `(remove (cut string-match "--enable-languages.*" <>)
+ ,flags))))
+ ((#:make-flags flags)
+ (if libc
+ `(let ((libc (assoc-ref %build-inputs "libc")))
+ ;; FLAGS_FOR_TARGET are needed for the target libraries to receive
+ ;; the -Bxxx for the startfiles.
+ (cons (string-append "FLAGS_FOR_TARGET=-B" libc "/lib")
+ ,flags))
+ flags))
+ ((#:phases phases)
+ (let ((phases
+ `(alist-cons-after
+ 'install 'make-cross-binutils-visible
+ (lambda* (#:key outputs inputs #:allow-other-keys)
+ (let* ((out (assoc-ref outputs "out"))
+ (libexec (string-append out "/libexec/gcc/"
+ ,target))
+ (binutils (string-append
+ (assoc-ref inputs "binutils-cross")
+ "/bin/" ,target "-"))
+ (wrapper (string-append
+ (assoc-ref inputs "ld-wrapper-cross")
+ "/bin/" ,target "-ld")))
+ (for-each (lambda (file)
+ (symlink (string-append binutils file)
+ (string-append libexec "/"
+ file)))
+ '("as" "nm"))
+ (symlink wrapper (string-append libexec "/ld"))
+ #t))
+ (alist-replace
+ 'install
+ (lambda _
+ ;; Unlike our 'strip' phase, this will do the right thing
+ ;; for cross-compilers.
+ (zero? (system* "make" "install-strip")))
+ ,phases))))
+ (if libc
+ `(alist-cons-before
+ 'configure 'set-cross-path
+ (lambda* (#:key inputs #:allow-other-keys)
+ ;; Add the cross Linux headers to CROSS_CPATH, and remove them
+ ;; from CPATH.
+ (let ((libc (assoc-ref inputs "libc"))
+ (linux (assoc-ref inputs
+ "libc/linux-headers")))
+ (define (cross? x)
+ ;; Return #t if X is a cross-libc or cross Linux.
+ (or (string-prefix? libc x)
+ (string-prefix? linux x)))
+
+ (setenv "CROSS_CPATH"
+ (string-append libc "/include:"
+ linux "/include"))
+ (setenv "CROSS_LIBRARY_PATH"
+ (string-append libc "/lib"))
+
+ (let ((cpath (search-path-as-string->list
+ (getenv "CPATH")))
+ (libpath (search-path-as-string->list
+ (getenv "LIBRARY_PATH"))))
+ (setenv "CPATH"
+ (list->search-path-as-string
+ (remove cross? cpath) ":"))
+ (setenv "LIBRARY_PATH"
+ (list->search-path-as-string
+ (remove cross? libpath) ":"))
+ #t)))
+ ,phases)
+ phases)))))))
+
+(define (cross-gcc-patches target)
+ "Return GCC patches needed for TARGET."
+ (cond ((string-prefix? "xtensa-" target)
+ ;; Patch by Qualcomm needed to build the ath9k-htc firmware.
+ (list (search-patch "ath9k-htc-firmware-gcc.patch")))
+ (else '())))
(define* (cross-gcc target
#:optional (xbinutils (cross-binutils target)) libc)
"Return a cross-compiler for TARGET, where TARGET is a GNU triplet. Use
XBINUTILS as the associated cross-Binutils. If LIBC is false, then build a
GCC that does not target a libc; otherwise, target that libc."
- (package (inherit gcc-4.8)
+ (package (inherit gcc-4.9)
(name (string-append "gcc-cross-"
(if libc "" "sans-libc-")
target))
- (source (origin (inherit (package-source gcc-4.8))
+ (source (origin (inherit (package-source gcc-4.9))
(patches
- (list (search-patch
- "gcc-cross-environment-variables.patch")))))
+ (append
+ (origin-patches (package-source gcc-4.9))
+ (cons (search-patch "gcc-cross-environment-variables.patch")
+ (cross-gcc-patches target))))))
;; For simplicity, use a single output. Otherwise libgcc_s & co. are not
;; found by default, etc.
(srfi srfi-1)
(srfi srfi-26))
- ,@(substitute-keyword-arguments (package-arguments gcc-4.8)
- ((#:configure-flags flags)
- `(append (list ,(string-append "--target=" target)
- ,@(gcc-configure-flags-for-triplet target)
- ,@(if libc
- '()
- `( ;; Disable features not needed at this stage.
- "--disable-shared" "--enable-static"
-
- ;; Disable C++ because libstdc++'s
- ;; configure script otherwise fails with
- ;; "Link tests are not allowed after
- ;; GCC_NO_EXECUTABLES."
- "--enable-languages=c"
-
- "--disable-threads" ; libgcc, would need libc
- "--disable-libatomic"
- "--disable-libmudflap"
- "--disable-libgomp"
- "--disable-libssp"
- "--disable-libquadmath"
- "--disable-decimal-float" ; would need libc
- )))
-
- ,(if libc
- flags
- `(remove (cut string-match "--enable-languages.*" <>)
- ,flags))))
- ((#:make-flags flags)
- (if libc
- `(let ((libc (assoc-ref %build-inputs "libc")))
- ;; FLAGS_FOR_TARGET are needed for the target libraries to
- ;; receive the -Bxxx for the startfiles.
- (cons (string-append "FLAGS_FOR_TARGET=-B" libc "/lib")
- ,flags))
- flags))
- ((#:phases phases)
- (let ((phases
- `(alist-cons-after
- 'install 'make-cross-binutils-visible
- (lambda* (#:key outputs inputs #:allow-other-keys)
- (let* ((out (assoc-ref outputs "out"))
- (libexec (string-append out "/libexec/gcc/"
- ,target))
- (binutils (string-append
- (assoc-ref inputs "binutils-cross")
- "/bin/" ,target "-")))
- (for-each (lambda (file)
- (symlink (string-append binutils file)
- (string-append libexec "/"
- file)))
- '("as" "ld" "nm"))
- #t))
- ,phases)))
- (if libc
- `(alist-cons-before
- 'configure 'set-cross-path
- (lambda* (#:key inputs #:allow-other-keys)
- ;; Add the cross Linux headers to CROSS_CPATH, and remove
- ;; them from CPATH.
- (let ((libc (assoc-ref inputs "libc"))
- (linux (assoc-ref inputs
- "libc/cross-linux-headers")))
- (define (cross? x)
- ;; Return #t if X is a cross-libc or cross Linux.
- (or (string-prefix? libc x)
- (string-prefix? linux x)))
-
- (setenv "CROSS_CPATH"
- (string-append libc "/include:"
- linux "/include"))
- (setenv "CROSS_LIBRARY_PATH"
- (string-append libc "/lib"))
-
- (let ((cpath (search-path-as-string->list
- (getenv "CPATH")))
- (libpath (search-path-as-string->list
- (getenv "LIBRARY_PATH"))))
- (setenv "CPATH"
- (list->search-path-as-string
- (remove cross? cpath) ":"))
- (setenv "LIBRARY_PATH"
- (list->search-path-as-string
- (remove cross? libpath) ":"))
- #t)))
- ,phases)
- phases)))
- ((#:strip-binaries? _)
- ;; Disable stripping as this can break binaries, with object files
- ;; of libgcc.a showing up as having an unknown architecture. See
- ;; <http://lists.fedoraproject.org/pipermail/arm/2010-August/000663.html>
- ;; for instance.
- #f))))
+ ,@(cross-gcc-arguments target libc)))
(native-inputs
- `(("binutils-cross" ,xbinutils)
+ `(("ld-wrapper-cross" ,(make-ld-wrapper
+ (string-append "ld-wrapper-" target)
+ #:target target
+ #:binutils xbinutils))
+ ("binutils-cross" ,xbinutils)
;; Call it differently so that the builder can check whether the "libc"
;; input is #f.
("libc-native" ,@(assoc-ref %final-inputs "libc"))
;; Remaining inputs.
- ,@(let ((inputs (append (package-inputs gcc-4.8)
+ ,@(let ((inputs (append (package-inputs gcc-4.9)
(alist-delete "libc" %final-inputs))))
(if libc
`(("libc" ,libc)
(search-paths
(list (search-path-specification
(variable "CROSS_CPATH")
- (directories '("include")))
+ (files '("include")))
(search-path-specification
(variable "CROSS_LIBRARY_PATH")
- (directories '("lib" "lib64")))))
+ (files '("lib" "lib64")))))
(native-search-paths '())))
(define* (cross-libc target
(name (string-append (package-name linux-libre-headers)
"-cross-" target))
(arguments
- (substitute-keyword-arguments (package-arguments linux-libre-headers)
+ (substitute-keyword-arguments
+ `(#:implicit-cross-inputs? #f
+ ,@(package-arguments linux-libre-headers))
((#:phases phases)
`(alist-replace
'build
(name (string-append "glibc-cross-" target))
(arguments
(substitute-keyword-arguments
- `(#:strip-binaries? #f ; disable stripping (see above)
+ `(;; Disable stripping (see above.)
+ #:strip-binaries? #f
+
+ ;; This package is used as a target input, but it should not have
+ ;; the usual cross-compilation inputs since that would include
+ ;; itself.
+ #:implicit-cross-inputs? #f
+
,@(package-arguments glibc))
((#:configure-flags flags)
`(cons ,(string-append "--host=" target)
`(alist-cons-before
'configure 'set-cross-linux-headers-path
(lambda* (#:key inputs #:allow-other-keys)
- (let ((linux (assoc-ref inputs "cross-linux-headers")))
+ (let ((linux (assoc-ref inputs "linux-headers")))
(setenv "CROSS_CPATH"
(string-append linux "/include"))
#t))
,phases))))
- (propagated-inputs `(("cross-linux-headers" ,xlinux-headers)))
+ ;; Shadow the native "linux-headers" because glibc's recipe expect the
+ ;; "linux-headers" input to point to the right thing.
+ (propagated-inputs `(("linux-headers" ,xlinux-headers)))
+
+ ;; FIXME: 'static-bash' should really be an input, not a native input, but
+ ;; to do that will require building an intermediate cross libc.
+ (inputs '())
+
(native-inputs `(("cross-gcc" ,xgcc)
("cross-binutils" ,xbinutils)
+ ,@(package-inputs glibc) ;FIXME: static-bash
,@(package-native-inputs glibc)))))
\f
;;;
(define-public xgcc-mips64el
- (let ((triplet "mips64el-linux-gnuabi64")) ; N64 ABI
+ (let* ((triplet "mips64el-linux-gnuabi64") ;N64 ABI
+ (xgcc (cross-gcc triplet
+ (cross-binutils triplet)
+ (cross-libc triplet))))
+ ;; Don't attempt to build this cross-compiler on i686;
+ ;; see <http://bugs.gnu.org/19598>.
+ (package (inherit xgcc)
+ (supported-systems (fold delete
+ (package-supported-systems xgcc)
+ '("mips64el-linux" "i686-linux"))))))
+
+(define-public xgcc-avr
+ ;; AVR cross-compiler, used to build AVR-Libc.
+ (let ((triplet "avr"))
(cross-gcc triplet
- (cross-binutils triplet)
- (cross-libc triplet))))
+ (cross-binutils triplet))))
+
+(define-public xgcc-xtensa
+ ;; Bare-bones Xtensa cross-compiler, used to build the Atheros firmware.
+ (cross-gcc "xtensa-elf"))
+
+(define-public xgcc-armhf
+ (let* ((triplet "arm-linux-gnueabihf")
+ (xgcc (cross-gcc triplet
+ (cross-binutils triplet)
+ (cross-libc triplet))))
+ (package (inherit xgcc)
+ (supported-systems (delete "armhf-linux" %supported-systems)))))
;; (define-public xgcc-armel
;; (let ((triplet "armel-linux-gnueabi"))