guix-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 03/11] gnu: cross-build: i686-w64-mingw32: new cross target.


From: Jan Nieuwenhuizen
Subject: [PATCH 03/11] gnu: cross-build: i686-w64-mingw32: new cross target.
Date: Tue, 9 Aug 2016 08:41:31 +0200

* 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 | 300 +++++++++++++++++++++++++++++++-------------
 guix/utils.scm              |   5 +
 2 files changed, 221 insertions(+), 84 deletions(-)

diff --git a/gnu/packages/cross-base.scm b/gnu/packages/cross-base.scm
index cb53668..294de40 100644
--- a/gnu/packages/cross-base.scm
+++ b/gnu/packages/cross-base.scm
@@ -19,12 +19,12 @@
 ;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
 
 (define-module (gnu packages cross-base)
-  #:use-module (guix licenses)
   #:use-module (gnu packages)
-  #:use-module (gnu packages gcc)
   #:use-module (gnu packages base)
+  #:use-module (gnu packages gcc)
   #:use-module (gnu packages commencement)
   #:use-module (gnu packages linux)
+  #:use-module (gnu packages mingw)
   #:use-module (guix packages)
   #:use-module (guix download)
   #:use-module (guix utils)
@@ -35,7 +35,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
@@ -129,7 +130,12 @@ may be either a libc package or #f.)"
                                "--disable-libitm"
                                "--disable-libvtv"
                                "--disable-libsanitizer"
-                               )))
+                                ))
+
+                       ;; For a newlib (non-glibc) target
+                       ,@(if (cross-newlib? target)
+                             '("--with-newlib")
+                             '()))
 
                  ,(if libc
                       flags
@@ -171,7 +177,85 @@ 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 mingw headers to CROSS_C_*_INCLUDE_PATH,
+                   ;; and remove them from C_*INCLUDE_PATH.
+                   (let ((libc (assoc-ref inputs "libc"))
+                         (gcc (assoc-ref inputs "gcc")))
+                     (define (cross? x)
+                       (and libc (string-prefix? libc x)))
+                     (define (unpacked-mingw-dir)
+                       (match
+                           (scandir
+                            "."
+                            (lambda (name) (string-contains name "mingw-w64")))
+                         ((mingw-dir)
+                          (string-append
+                           (getcwd) "/" mingw-dir "/mingw-w64-headers"))))
+                     (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")))
+                         ;; libc is false, so we are building xgcc-sans-libc
+                         ;; Add essential headers from mingw-w64.
+                         (let ((mingw-source (assoc-ref inputs 
"mingw-source")))
+                           (system* "tar" "xf" mingw-source)
+                           (let ((mingw-headers (unpacked-mingw-dir)))
+                             ;; We need _mingw.h which will gets built from
+                             ;; _mingw.h.in by mingw-w64's configure.  We 
cannot
+                             ;; configure mingw-w64 until we have
+                             ;; xgcc-sans-libc; substitute to the rescue.
+                             (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"))))
+                             (when 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=> (getenv var)
+                               (lambda (value)
+                                 (let* ((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"))
+                     #t)))))
+            (libc
               `(alist-cons-before
                 'configure 'set-cross-path
                 (lambda* (#:key inputs #:allow-other-keys)
@@ -208,16 +292,25 @@ may be either a libc package or #f.)"
                                 "OBJCPLUS_INCLUDE_PATH"
                                 "LIBRARY_PATH"))
                     #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.
          (search-patches "ath9k-htc-firmware-gcc.patch"))
+        ((mingw-target? target)
+         (search-patches "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 #f)))
+
 (define* (cross-gcc target
                     #:optional (xbinutils (cross-binutils target)) libc)
   "Return a cross-compiler for TARGET, where TARGET is a GNU triplet.  Use
@@ -232,7 +325,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.
@@ -242,6 +338,8 @@ GCC that does not target a libc; otherwise, target that 
libc."
      `(#:implicit-inputs? #f
        #:modules ((guix build gnu-build-system)
                   (guix build utils)
+                  (ice-9 ftw)
+                  (ice-9 match)
                   (ice-9 regex)
                   (srfi srfi-1)
                   (srfi srfi-26))
@@ -262,13 +360,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
-               `(("libc" ,libc)
-                 ("xkernel-headers"                ;the target headers
-                  ,@(assoc-ref (package-propagated-inputs libc)
-                               "kernel-headers"))
-                 ,@inputs)
-               inputs))))
+           (cond
+            ((mingw-target? target)
+             (if libc
+                 `(("libc" ,mingw-w64)
+                   ,@inputs)
+                 `(("mingw-source" ,(package-source mingw-w64))
+                   ,@inputs)))
+            (libc
+             `(("libc" ,libc)
+               ("xkernel-headers"                ;the target headers
+                ,@(assoc-ref (package-propagated-inputs libc)
+                             "kernel-headers"))
+               ,@inputs))
+            (else inputs)))))
 
     (inputs '())
 
@@ -298,75 +403,87 @@ 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
-    (package (inherit linux-libre-headers)
-      (name (string-append (package-name linux-libre-headers)
-                           "-cross-" target))
-      (arguments
-       (substitute-keyword-arguments
-           `(#:implicit-cross-inputs? #f
-             ,@(package-arguments linux-libre-headers))
-         ((#:phases phases)
-          `(alist-replace
-            'build
-            (lambda _
-              (setenv "ARCH" ,(system->linux-architecture target))
-              (format #t "`ARCH' set to `~a' (cross compiling)~%" (getenv 
"ARCH"))
-
-              (and (zero? (system* "make" "defconfig"))
-                   (zero? (system* "make" "mrproper" "headers_check"))))
-            ,phases))))
-      (native-inputs `(("cross-gcc" ,xgcc)
-                       ("cross-binutils" ,xbinutils)
-                       ,@(package-native-inputs linux-libre-headers)))))
-
-  (package (inherit glibc)
-    (name (string-append "glibc-cross-" target))
-    (arguments
-     (substitute-keyword-arguments
-         `(;; 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
-
-           ;; We need SRFI 26.
-           #:modules ((guix build gnu-build-system)
-                      (guix build utils)
-                      (srfi srfi-26))
-
-           ,@(package-arguments glibc))
-       ((#:configure-flags flags)
-        `(cons ,(string-append "--host=" target)
-               ,flags))
-       ((#:phases phases)
-        `(alist-cons-before
-          'configure 'set-cross-kernel-headers-path
-          (lambda* (#:key inputs #:allow-other-keys)
-            (let* ((kernel (assoc-ref inputs "kernel-headers"))
-                   (cpath (string-append kernel "/include")))
-              (for-each (cut setenv <> cpath)
-                        '("CROSS_C_INCLUDE_PATH"
-                          "CROSS_CPLUS_INCLUDE_PATH"
-                          "CROSS_OBJC_INCLUDE_PATH"
-                          "CROSS_OBJCPLUS_INCLUDE_PATH"))
-              #t))
-          ,phases))))
-
-    ;; Shadow the native "kernel-headers" because glibc's recipe expects the
-    ;; "kernel-headers" input to point to the right thing.
-    (propagated-inputs `(("kernel-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)))))
+  (cond
+   ((cross-newlib? target)
+    (native-libc target))
+   (else
+    (let ((xlinux-headers
+           (package (inherit linux-libre-headers)
+             (name (string-append (package-name linux-libre-headers)
+                                  "-cross-" target))
+             (arguments
+              (substitute-keyword-arguments
+                  `(#:implicit-cross-inputs? #f
+                    ,@(package-arguments linux-libre-headers))
+                ((#:phases phases)
+                 `(alist-replace
+                   'build
+                   (lambda _
+                     (setenv "ARCH" ,(system->linux-architecture target))
+                     (format #t "`ARCH' set to `~a' (cross compiling)~%"
+                             (getenv "ARCH"))
+
+                     (and (zero? (system* "make" "defconfig"))
+                          (zero? (system* "make" "mrproper" "headers_check"))))
+                   ,phases))))
+             (native-inputs `(("cross-gcc" ,xgcc)
+                              ("cross-binutils" ,xbinutils)
+                              ,@(package-native-inputs 
linux-libre-headers))))))
+      (package (inherit glibc)
+        (name (string-append "glibc-cross-" target))
+        (arguments
+         (substitute-keyword-arguments
+             `(;; 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
+
+               ;; We need SRFI 26.
+               #:modules ((guix build gnu-build-system)
+                          (guix build utils)
+                          (srfi srfi-26))
+
+               ,@(package-arguments glibc))
+           ((#:configure-flags flags)
+            `(cons ,(string-append "--host=" target)
+                   ,flags))
+           ((#:phases phases)
+            `(alist-cons-before
+              'configure 'set-cross-kernel-headers-path
+              (lambda* (#:key inputs #:allow-other-keys)
+                (let* ((kernel (assoc-ref inputs "kernel-headers"))
+                       (cpath (string-append kernel "/include")))
+                  (for-each (cut setenv <> cpath)
+                            '("CROSS_C_INCLUDE_PATH"
+                              "CROSS_CPLUS_INCLUDE_PATH"
+                              "CROSS_OBJC_INCLUDE_PATH"
+                              "CROSS_OBJCPLUS_INCLUDE_PATH"))
+                  #t))
+              ,phases))))
+
+        ;; Shadow the native "kernel-headers" because glibc's recipe expects 
the
+        ;; "kernel-headers" input to point to the right thing.
+        (propagated-inputs `(("kernel-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))))))))
+
+(define (native-libc target)
+  (if (mingw-target? target)
+      mingw-w64
+      glibc))
+
+(define (cross-newlib? target)
+  (not (eq? (native-libc target) glibc)))
 
 
 ;;;
@@ -413,3 +530,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 c68094c..e44504c 100644
--- a/guix/utils.scm
+++ b/guix/utils.scm
@@ -68,6 +68,7 @@
             gnu-triplet->nix-system
             %current-system
             %current-target-system
+            mingw-target?
             package-name->name+version
             version-compare
             version>?
@@ -487,6 +488,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 \"address@hidden", return two values: 
\"foo\"
 and \"0.9.1b\".  When the version part is unavailable, SPEC and #f are
-- 
2.9.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]