From c36dc0d45b90aa5f957d79ed5cb4b2db50ec0a5e Mon Sep 17 00:00:00 2001 From: Jan Nieuwenhuizen Date: Sun, 17 Apr 2016 18:42:43 +0200 Subject: [PATCH 04/10] gnu: cross-build: i686-w64-mingw32: new cross target. * guix/utils.scm (mingw-target?): New function. * gnu/packages/cross-base.scm (cross-gcc-snippet): New function for mingw. (cross-gcc): Use it. (cross-gcc-arguments, cross-gcc-patches, cross-gcc): Support mingw. (native-libc, cross-newlib?): New functions. (cross-libc): Use cross-newlib? to support mingw. (xbinutils-i686-w64-mingw32, xgcc-sans-libc-i686-w64-mingw32, xgcc-i686-w64-mingw32): New variables. --- gnu/packages/cross-base.scm | 163 +++++++++++++++++++++++++++++++++++++++----- guix/utils.scm | 5 ++ 2 files changed, 151 insertions(+), 17 deletions(-) diff --git a/gnu/packages/cross-base.scm b/gnu/packages/cross-base.scm index c5bf66f..5d2d0fe 100644 --- a/gnu/packages/cross-base.scm +++ b/gnu/packages/cross-base.scm @@ -19,12 +19,17 @@ ;;; along with GNU Guix. If not, see . (define-module (gnu packages cross-base) - #:use-module (guix licenses) + #:use-module ((guix licenses) #:prefix license:) #:use-module (gnu packages) - #:use-module (gnu packages gcc) #:use-module (gnu packages base) + #:use-module (gnu packages bash) + #:use-module (gnu packages gawk) + #:use-module (gnu packages gcc) #:use-module (gnu packages commencement) + #:use-module (gnu packages compression) #:use-module (gnu packages linux) + #:use-module (gnu packages mingw) + #:use-module (gnu packages multiprecision) #:use-module (guix packages) #:use-module (guix download) #:use-module (guix utils) @@ -36,7 +41,8 @@ #:use-module (ice-9 match) #:export (cross-binutils cross-libc - cross-gcc)) + cross-gcc + cross-newlib?)) (define %xgcc ;; GCC package used as the basis for cross-compilation. It doesn't have to @@ -122,20 +128,34 @@ may be either a libc package or #f.)" "--disable-libquadmath" "--disable-decimal-float" ;would need libc "--disable-libcilkrts" - ))) + )) + + ,@(if (cross-newlib? target) + '("--with-newlib" + "--without-threads" + "--without-headers") + '())) ,(if libc flags `(remove (cut string-match "--enable-languages.*" <>) ,flags)))) ((#:make-flags flags) - (if libc + (cond + ((mingw-target? target) + `(append (let ((runtime (assoc-ref %build-inputs "mingw-w64"))) + (if runtime + (list + (string-append "FLAGS_FOR_TARGET=-B" runtime "/lib")) + '("all-gcc" "all-target-libgcc"))) + ,flags)) + (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)) + ,flags))) + (else flags))) ((#:phases phases) (let ((phases `(alist-cons-after @@ -164,7 +184,70 @@ may be either a libc package or #f.)" ;; for cross-compilers. (zero? (system* "make" "install-strip"))) ,phases)))) - (if libc + (cond + ((mingw-target? target) + `(modify-phases ,phases + (add-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 "mingw-w64")) + (gcc (assoc-ref inputs "gcc"))) + (define (cross? x) + (format (current-error-port) "cross? remove ~a => ~a\n" x (and libc (string-prefix? libc x))) + (and libc (string-prefix? libc x))) + (if libc + (let ((cpath (string-append + libc "/include" + ":" libc "/i686-w64-mingw32/include"))) + (for-each (cut setenv <> cpath) + '("CROSS_C_INCLUDE_PATH" + "CROSS_CPLUS_INCLUDE_PATH" + "CROSS_OBJC_INCLUDE_PATH" + "CROSS_OBJCPLUS_INCLUDE_PATH"))) + (let ((mingw-source (assoc-ref inputs "mingw-source")) + (mingw-headers + (string-append (getcwd) "/mingw-w64-v5.0-rc2/mingw-w64-headers"))) + (system* "tar" "xf" mingw-source) + (copy-file (string-append mingw-headers "/crt/_mingw.h.in") + (string-append mingw-headers "/crt/_mingw.h")) + (substitute* (string-append mingw-headers "/crt/_mingw.h") + (("@MINGW_HAS_SECURE_API@") "#define MINGW_HAS_SECURE_API 1")) + (let ((cpath (string-append + mingw-headers "/include" + ":" mingw-headers "/crt" + ":" mingw-headers "/defaults/include"))) + (for-each (cut setenv <> cpath) + '("CROSS_C_INCLUDE_PATH" + "CROSS_CPLUS_INCLUDE_PATH" + "CROSS_OBJC_INCLUDE_PATH" + "CROSS_OBJCPLUS_INCLUDE_PATH" + "CROSS_LIBRARY_PATH"))))) + (if libc + (setenv "CROSS_LIBRARY_PATH" + (string-append + libc "/lib" + ":" libc "/i686-w64-mingw32/lib"))) + (setenv "CPP" (string-append gcc "/bin/cpp")) + (for-each (lambda (var) + (and-let* ((value (getenv var)) + (path (search-path-as-string->list + value)) + (native-path + (list->search-path-as-string + (remove cross? path) ":"))) + (setenv var native-path))) + '("C_INCLUDE_PATH" + "CPLUS_INCLUDE_PATH" + "OBJC_INCLUDE_PATH" + "OBJCPLUS_INCLUDE_PATH" + "LIBRARY_PATH"))))) + ,@(if libc '() + '((replace 'install + (lambda _ + (zero? (system* "make" "install-gcc" "install-target-libgcc")))))))) + (libc `(alist-cons-before 'configure 'set-cross-path (lambda* (#:key inputs #:allow-other-keys) @@ -208,10 +291,19 @@ may be either a libc package or #f.)" (cond ((string-prefix? "xtensa-" target) ;; Patch by Qualcomm needed to build the ath9k-htc firmware. (list (search-patch "ath9k-htc-firmware-gcc.patch"))) + ((mingw-target? target) + (list (search-patch "gcc-4.9.3-mingw-gthr-default.patch"))) + (else '()))) + +(define (cross-gcc-snippet target) + "Return GCC snippet needed for TARGET." + (cond ((mingw-target? target) + '(copy-recursively "libstdc++-v3/config/os/mingw32-w64" + "libstdc++-v3/config/os/newlib")) (else '()))) (define* (cross-gcc target - #:optional (xbinutils (cross-binutils target)) libc) + #:optional (xbinutils (cross-binutils target)) (libc #f)) "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." @@ -224,7 +316,10 @@ GCC that does not target a libc; otherwise, target that libc." (append (origin-patches (package-source %xgcc)) (cons (search-patch "gcc-cross-environment-variables.patch") - (cross-gcc-patches target)))))) + (cross-gcc-patches target)))) + (modules '((guix build utils))) + (snippet + (cross-gcc-snippet target)))) ;; For simplicity, use a single output. Otherwise libgcc_s & co. are not ;; found by default, etc. @@ -247,6 +342,7 @@ GCC that does not target a libc; otherwise, target that libc." #:target target #:binutils xbinutils)) ("binutils-cross" ,xbinutils) + ("gcc" ,gcc) ;; Call it differently so that the builder can check whether the "libc" ;; input is #f. @@ -255,13 +351,20 @@ GCC that does not target a libc; otherwise, target that libc." ;; Remaining inputs. ,@(let ((inputs (append (package-inputs %xgcc) (alist-delete "libc" %final-inputs)))) - (if libc + (cond + ((mingw-target? target) + (if libc + `(("mingw-w64" ,mingw-w64) + ,@inputs) + `(("mingw-source" ,(package-source mingw-w64)) + ,@inputs))) + (libc `(("libc" ,libc) ("xlinux-headers" ;the target headers ,@(assoc-ref (package-propagated-inputs libc) "linux-headers")) - ,@inputs) - inputs)))) + ,@inputs)) + (else inputs))))) (inputs '()) @@ -290,7 +393,11 @@ GCC that does not target a libc; otherwise, target that libc." (xbinutils (cross-binutils target))) "Return a libc cross-built for TARGET, a GNU triplet. Use XGCC and XBINUTILS and the cross tool chain." - (define xlinux-headers + (cond + ((cross-newlib? target) + (cross-newlib? target)) + (else + (let ((xlinux-headers (package (inherit linux-libre-headers) (name (string-append (package-name linux-libre-headers) "-cross-" target)) @@ -310,8 +417,7 @@ XBINUTILS and the cross tool chain." ,phases)))) (native-inputs `(("cross-gcc" ,xgcc) ("cross-binutils" ,xbinutils) - ,@(package-native-inputs linux-libre-headers))))) - + ,@(package-native-inputs linux-libre-headers)))))) (package (inherit glibc) (name (string-append "glibc-cross-" target)) (arguments @@ -353,7 +459,15 @@ XBINUTILS and the cross tool chain." (native-inputs `(("cross-gcc" ,xgcc) ("cross-binutils" ,xbinutils) ,@(package-inputs glibc) ;FIXME: static-bash - ,@(package-native-inputs glibc))))) + ,@(package-native-inputs glibc)))))))) + +(define (native-libc target) + (if (mingw-target? target) mingw-w64 + glibc)) + +(define (cross-newlib? target) + (and (not (eq? (native-libc target) glibc)) + (native-libc target))) ;;; @@ -395,3 +509,18 @@ XBINUTILS and the cross tool chain." ;; (cross-gcc triplet ;; (cross-binutils triplet) ;; (cross-libc triplet)))) + +(define-public xgcc-sans-libc-i686-w64-mingw32 + (let ((triplet "i686-w64-mingw32")) + (cross-gcc triplet + (cross-binutils triplet)))) + +(define-public xbinutils-i686-w64-mingw32 + (let ((triplet "i686-w64-mingw32")) + (cross-binutils triplet))) + +(define-public xgcc-i686-w64-mingw32 + (let ((triplet "i686-w64-mingw32")) + (cross-gcc triplet + (cross-binutils triplet) + (cross-newlib? triplet)))) diff --git a/guix/utils.scm b/guix/utils.scm index de54179..b796bde 100644 --- a/guix/utils.scm +++ b/guix/utils.scm @@ -65,6 +65,7 @@ gnu-triplet->nix-system %current-system %current-target-system + mingw-target? package-name->name+version version-compare version>? @@ -544,6 +545,10 @@ returned by `config.guess'." ;; cross-building to. (make-parameter #f)) +(define* (mingw-target? #:optional (target (%current-target-system))) + (and target + (string-suffix? "-mingw32" target))) + (define (package-name->name+version spec) "Given SPEC, a package name like \"foo@0.9.1b\", return two values: \"foo\" and \"0.9.1b\". When the version part is unavailable, SPEC and #f are -- 2.7.3