From 67fd642293ebc0d88d6f691c2b6bc5ce55eefe36 Mon Sep 17 00:00:00 2001 From: Jan Nieuwenhuizen Date: Thu, 14 Apr 2016 07:39:37 +0200 Subject: [PATCH 4/9] gnu: cross-build: i686-w64-mingw32: new cross target. * gnu/packages/cross-base.scm (cross-gcc-core): New variable. Minimal core gcc to cross-build a newlib/non-glibc libc, needed to build a full cross-gcc. --- gnu/packages/cross-base.scm | 242 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 222 insertions(+), 20 deletions(-) diff --git a/gnu/packages/cross-base.scm b/gnu/packages/cross-base.scm index f1ac2ea..bb0aae8 100644 --- a/gnu/packages/cross-base.scm +++ b/gnu/packages/cross-base.scm @@ -1,6 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2013, 2014, 2015, 2016 Ludovic Courtès ;;; Copyright © 2014, 2015 Mark H Weaver +;;; Copyright © 2016 Jan Nieuwenhuizen ;;; ;;; This file is part of GNU Guix. ;;; @@ -18,13 +19,18 @@ ;;; 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 linux) + #:use-module (gnu packages compression) #:use-module (gnu packages hurd) + #: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) @@ -35,7 +41,9 @@ #:use-module (ice-9 match) #:export (cross-binutils cross-libc - cross-gcc)) + cross-gcc + cross-gcc-core + cross-newlib?)) (define %xgcc ;; GCC package used as the basis for cross-compilation. It doesn't have to @@ -102,7 +110,7 @@ may be either a libc package or #f.)" `(append (list ,(string-append "--target=" target) ,@(if libc `( ;; Disable libcilkrts because it is not - ;; ported to GNU/Hurd. + ;; ported to GNU/Hurd. "--disable-libcilkrts") `( ;; Disable features not needed at this stage. "--disable-shared" "--enable-static" @@ -129,20 +137,46 @@ may be either a libc package or #f.)" "--disable-libitm" "--disable-libvtv" "--disable-libsanitizer" - ))) + )) + + ;; We need to build gcc+winpthreads with + ;; --enable-threads=win32 first, and only then + ;; (re)build gcc with --enable-threads=posix. + ;; + ;; i686-w64-mingw32/libstdc++-v3/include/i686-w64-mingw32/bits/gthr-default.h:33:62: + ;; error: types may not be defined in casts + ;; #define CONST_CAST2(TOTYPE,FROMTYPE,X) ((__extension__(union {FROMTYPE _q; TOTYPE _nq;})(X))._nq) + + ,@(if (and libc (equal? target "i686-w64-mingw32")) + ;;'("--with-threads=win32") + '() ;; + '()) + + ,@(if (cross-newlib? target) + '("--with-newlib" + "--without-headers") + '())) ,(if libc flags `(remove (cut string-match "--enable-languages.*" <>) ,flags)))) ((#:make-flags flags) - (if libc + (cond + ((equal? target "i686-w64-mingw32") + `(append (let ((runtime (assoc-ref %build-inputs "mingw-w64"))) + (if runtime + (list + (string-append "FLAGS_FOR_TARGET=-B" runtime "/lib")) + '())) + ,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 @@ -171,7 +205,44 @@ may be either a libc package or #f.)" ;; for cross-compilers. (zero? (system* "make" "install-strip"))) ,phases)))) - (if libc + (cond + ((equal? target "i686-w64-mingw32") + `(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 + (setenv "CROSS_CPATH" + (string-append + libc "/include" + ":" libc "/i686-w64-mingw32/include"))) + (if libc + (setenv "CROSS_LIBRARY_PATH" + (string-append + libc "/lib" + ":" libc "/i686-w64-mingw32/lib"))) + (setenv "CPP" (string-append gcc "/bin/cpp")) + (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) ":")) + (for-each unsetenv + '("C_INCLUDE_PATH" "CPLUS_INCLUDE_PATH")) + (setenv "LIBRARY_PATH" + (list->search-path-as-string + (remove cross? libpath) ":")) + #t)))))) + (libc `(alist-cons-before 'configure 'set-cross-path (lambda* (#:key inputs #:allow-other-keys) @@ -220,22 +291,31 @@ may be either a libc package or #f.)" (list->search-path-as-string (remove cross? libpath) ":")) #t))) - ,phases) - phases))))))) + ,phases)) + (else 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"))) + ((equal? "i686-w64-mingw32" 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 ((equal? "i686-w64-mingw32" 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." - + (define (cross-kernel-headers target libc) "Return headers depending on TARGET." (match target @@ -243,7 +323,7 @@ GCC that does not target a libc; otherwise, target that libc." (assoc-ref (package-propagated-inputs libc) "hurd-kernel-headers")) (_ (assoc-ref (package-propagated-inputs libc) "linux-headers")))) - + (package (inherit %xgcc) (name (string-append "gcc-cross-" (if libc "" "sans-libc-") @@ -253,7 +333,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. @@ -275,6 +358,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. @@ -283,12 +367,16 @@ 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 + ((equal? target "i686-w64-mingw32") + `(("mingw-w64" ,mingw-w64) + ,@inputs)) + (libc `(("libc" ,libc) ("xkernel-headers" ;the target headers ,@(cross-kernel-headers target libc)) - ,@inputs) - inputs)))) + ,@inputs)) + (else inputs))))) (inputs '()) @@ -302,6 +390,95 @@ GCC that does not target a libc; otherwise, target that libc." (files '("lib" "lib64"))))) (native-search-paths '()))) +(define* (cross-gcc-core target + #:optional (xbinutils (cross-binutils target))) + "Return a cross-compiler-core to be used to build the c library for TARGET, +where TARGET is a GNU triplet. Use XBINUTILS as the associated +cross-Binutils." + (package (inherit (cross-gcc target xbinutils)) + (name (string-append "gcc-core-cross-" target)) + (inputs `()) + ;; FIXME: no effect? must add inputs to mingw-source + (propagated-inputs + `(("gmp" ,gmp) + ("mpfr" ,mpfr) + ("mpc" ,mpc) + ("zlib" ,zlib))) + (native-inputs + `(("ld-wrapper-cross" ,(make-ld-wrapper + (string-append "ld-wrapper-" target) + #:target target + #:binutils xbinutils)) + ("cross-binutils" ,xbinutils) + ("make" ,gnu-make) + ("tar" ,tar) + ("xz" ,xz) + ("bash" ,bash) + ("glibc" ,glibc) + ("coreutils" ,coreutils) + ("sed" ,sed) + ("gcc" ,gcc) + ("binutils" ,binutils) + ("gawk" ,gawk) + ("grep" ,grep) + ("make" ,gnu-make) + ("bzip2" ,bzip2) + ("diffutils" ,diffutils) + ("gzip" ,gzip) + ,@(if (equal? target "i686-w64-mingw32") + `(("mingw-source" ,(package-source mingw-w64))) + '()))) + (arguments + (let ((args `(,@(package-arguments (cross-gcc target xbinutils))))) + (substitute-keyword-arguments args + ((#:configure-flags flags) + `(append (list + ,(string-append "--target=" target)) + (remove (cut string-match "--enable-languages.*" <>) + (remove (cut string-match "--enable-threads=*" <>) + ,flags)) + '("--with-newlib" + "--without-threads" + "--without-headers"))) + ((#:make-flags flags) + `(append '("all-gcc" "all-target-libgcc") + ,flags)) + ((#:phases phases) + `(modify-phases ,phases + (add-before + 'configure 'setenv + (lambda* (#:key outputs inputs #:allow-other-keys) + (let* ((gmp (assoc-ref inputs "gmp")) + (mpfr (assoc-ref inputs "mpfr")) + (mpc (assoc-ref inputs "mpc")) + (zlib (assoc-ref inputs "zlib"))) + (setenv "LD_LIBRARY_PATH" + (string-append + gmp "/lib" + ":" mpfr "/lib" + ":" mpc "/lib" + ":" zlib "/lib")) + (cond + ((equal? ,target "i686-w64-mingw32") + (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")) + (setenv "CROSS_CPATH" + (string-append + mingw-headers "/include" + ":" mingw-headers "/crt" + ":" mingw-headers "/defaults/include")))))))) + (replace 'install + (lambda _ + (zero? (system* "make" "install-gcc" "install-target-libgcc")))) + (delete 'make-cross-binutils-visible) + (delete 'validate-runpath)))))))) + (define* (cross-libc target #:optional (xgcc (cross-gcc target)) @@ -330,7 +507,7 @@ XBINUTILS and the cross tool chain." ("cross-binutils" ,xbinutils) ,@(package-native-inputs linux-libre-headers))))) - (define xgnumach-headers + (define xgnumach-headers (package (inherit gnumach-headers) (name (string-append (package-name gnumach-headers) "-cross-" target)) @@ -453,6 +630,8 @@ XBINUTILS and the cross tool chain." ("cross-binutils" ,xbinutils) ("cross-mig" ,xmig) ,@(alist-delete "mig"(package-native-inputs glibc/hurd)))))) + ((? cross-newlib?) + (cross-newlib? target)) (_ (package (inherit glibc) (name (string-append "glibc-cross-" target)) @@ -493,6 +672,14 @@ XBINUTILS and the cross tool chain." ,@(package-inputs glibc) ;FIXME: static-bash ,@(package-native-inputs glibc))))))) +(define (native-libc target) + (if (equal? target "i686-w64-mingw32") mingw-w64 + glibc)) + +(define (cross-newlib? target) + (and (not (eq? (native-libc target) glibc)) + (native-libc target))) + ;;; ;;; Concrete cross toolchains. @@ -533,3 +720,18 @@ XBINUTILS and the cross tool chain." ;; (cross-gcc triplet ;; (cross-binutils triplet) ;; (cross-libc triplet)))) + +(define-public xgcc-core-i686-w64-mingw32 + (let ((triplet "i686-w64-mingw32")) + (cross-gcc-core 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)))) -- 2.7.3