Commit | Line | Data |
---|---|---|
3593e5d5 LC |
1 | ;;; GNU Guix --- Functional package management for GNU |
2 | ;;; Copyright © 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org> | |
3e629738 | 3 | ;;; Copyright © 2014, 2015, 2018 Mark H Weaver <mhw@netris.org> |
3593e5d5 LC |
4 | ;;; Copyright © 2016 Jan Nieuwenhuizen <janneke@gnu.org> |
5 | ;;; Copyright © 2016 Manolis Fragkiskos Ragkousis <manolis837@gmail.com> | |
01e8263f | 6 | ;;; Copyright © 2019 Marius Bakke <mbakke@fastmail.com> |
67dac6b8 | 7 | ;;; Copyright © 2019 Carl Dong <contact@carldong.me> |
3593e5d5 LC |
8 | ;;; |
9 | ;;; This file is part of GNU Guix. | |
10 | ;;; | |
11 | ;;; GNU Guix is free software; you can redistribute it and/or modify it | |
12 | ;;; under the terms of the GNU General Public License as published by | |
13 | ;;; the Free Software Foundation; either version 3 of the License, or (at | |
14 | ;;; your option) any later version. | |
15 | ;;; | |
16 | ;;; GNU Guix is distributed in the hope that it will be useful, but | |
17 | ;;; WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 | ;;; GNU General Public License for more details. | |
20 | ;;; | |
21 | ;;; You should have received a copy of the GNU General Public License | |
22 | ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. | |
23 | ||
24 | (define-module (gnu build cross-toolchain) | |
25 | #:use-module (guix build utils) | |
26 | #:use-module (guix build gnu-build-system) | |
27 | #:use-module (srfi srfi-1) | |
28 | #:use-module (srfi srfi-26) | |
29 | #:use-module (ice-9 match) | |
30 | #:use-module (ice-9 ftw) | |
31 | #:export (cross-gcc-build-phases)) | |
32 | ||
33 | ;;; Commentary: | |
34 | ;;; | |
35 | ;;; This module provides tools to build a cross-compiler. | |
36 | ;;; | |
37 | ;;; Code: | |
38 | ||
39 | (define %gcc-include-paths | |
40 | ;; Environment variables for header search paths. | |
01e8263f MB |
41 | ;; Note: See <http://bugs.gnu.org/30756> for why not 'C_INCLUDE_PATH' & co. |
42 | '("CPATH")) | |
3593e5d5 LC |
43 | |
44 | (define %gcc-cross-include-paths | |
45 | ;; Search path for target headers when cross-compiling. | |
46 | (map (cut string-append "CROSS_" <>) %gcc-include-paths)) | |
47 | ||
48 | (define* (make-cross-binutils-visible #:key outputs inputs target | |
49 | #:allow-other-keys) | |
50 | "Create symlinks for 'as', 'nm', and 'ld' in the \"out\" output, under | |
51 | libexec/gcc, so that the cross-GCC can find them." | |
52 | (let* ((out (assoc-ref outputs "out")) | |
53 | (libexec (string-append out "/libexec/gcc/" target)) | |
54 | (binutils (string-append (assoc-ref inputs "binutils-cross") | |
55 | "/bin/" target "-")) | |
56 | (wrapper (string-append (assoc-ref inputs "ld-wrapper-cross") | |
57 | "/bin/" target "-ld"))) | |
58 | (for-each (lambda (file) | |
59 | (symlink (string-append binutils file) | |
60 | (string-append libexec "/" file))) | |
61 | '("as" "nm")) | |
62 | (symlink wrapper (string-append libexec "/ld")) | |
63 | #t)) | |
64 | ||
65 | (define* (set-cross-path #:key inputs #:allow-other-keys) | |
66 | "Add the cross kernel headers to CROSS_CPATH, and remove them from | |
67 | C_INCLUDE_PATH et al." | |
68 | (match (assoc-ref inputs "libc") | |
69 | ((? string? libc) | |
70 | (let ((kernel (assoc-ref inputs "xkernel-headers"))) | |
71 | (define (cross? x) | |
72 | ;; Return #t if X is a cross-libc or cross Linux. | |
73 | (or (string-prefix? libc x) | |
74 | (string-prefix? kernel x))) | |
75 | ||
76 | (let ((cpath (string-append libc "/include" | |
77 | ":" kernel "/include"))) | |
78 | (for-each (cut setenv <> cpath) | |
79 | %gcc-cross-include-paths)) | |
80 | ||
81 | (setenv "CROSS_LIBRARY_PATH" | |
82 | (string-append libc "/lib:" kernel "/lib")) ;for Hurd's libihash | |
83 | ||
84 | (for-each (lambda (var) | |
85 | (and=> (getenv var) | |
86 | (lambda (value) | |
87 | (let* ((path (search-path-as-string->list value)) | |
88 | (native-path (list->search-path-as-string | |
89 | (remove cross? path) ":"))) | |
90 | (setenv var native-path))))) | |
91 | (cons "LIBRARY_PATH" %gcc-include-paths)) | |
92 | #t)) | |
93 | (#f | |
94 | ;; We're building the sans-libc cross-compiler, so nothing to do. | |
95 | #t))) | |
96 | ||
67dac6b8 | 97 | (define* (set-cross-path/mingw #:key inputs target #:allow-other-keys) |
3593e5d5 LC |
98 | "Add the cross MinGW headers to CROSS_C_*_INCLUDE_PATH, and remove them from |
99 | C_*INCLUDE_PATH." | |
100 | (let ((libc (assoc-ref inputs "libc")) | |
101 | (gcc (assoc-ref inputs "gcc"))) | |
102 | (define (cross? x) | |
103 | (and libc (string-prefix? libc x))) | |
104 | ||
105 | (define (unpacked-mingw-dir) | |
106 | (match (scandir "." (lambda (name) | |
107 | (string-contains name "mingw-w64"))) | |
108 | ((mingw-dir) | |
109 | (string-append | |
110 | (getcwd) "/" mingw-dir "/mingw-w64-headers")))) | |
111 | ||
112 | (if libc | |
113 | (let ((cpath (string-append libc "/include" | |
67dac6b8 | 114 | ":" libc "/" target "/include"))) |
3593e5d5 LC |
115 | (for-each (cut setenv <> cpath) |
116 | %gcc-cross-include-paths)) | |
117 | ||
118 | ;; libc is false, so we are building xgcc-sans-libc. | |
119 | ;; Add essential headers from mingw-w64. | |
120 | (let ((mingw-source (assoc-ref inputs "mingw-source"))) | |
3e629738 | 121 | (invoke "tar" "xvf" mingw-source) |
3593e5d5 LC |
122 | (let ((mingw-headers (unpacked-mingw-dir))) |
123 | ;; We need _mingw.h which will gets built from _mingw.h.in by | |
124 | ;; mingw-w64's configure. We cannot configure mingw-w64 until we | |
125 | ;; have xgcc-sans-libc; substitute to the rescue. | |
126 | (copy-file (string-append mingw-headers "/crt/_mingw.h.in") | |
127 | (string-append mingw-headers "/crt/_mingw.h")) | |
128 | ||
129 | (substitute* (string-append mingw-headers "/crt/_mingw.h") | |
130 | (("@MINGW_HAS_SECURE_API@") | |
07d71754 DT |
131 | "#define MINGW_HAS_SECURE_API 1") |
132 | (("@DEFAULT_WIN32_WINNT@") | |
133 | "0x502") | |
134 | (("@DEFAULT_MSVCRT_VERSION@") | |
135 | "0x700")) | |
3593e5d5 LC |
136 | |
137 | (let ((cpath (string-append mingw-headers "/include" | |
138 | ":" mingw-headers "/crt" | |
139 | ":" mingw-headers | |
140 | "/defaults/include"))) | |
141 | (for-each (cut setenv <> cpath) | |
142 | (cons "CROSS_LIBRARY_PATH" | |
143 | %gcc-cross-include-paths)))))) | |
144 | ||
145 | (when libc | |
146 | (setenv "CROSS_LIBRARY_PATH" | |
147 | (string-append libc "/lib" | |
67dac6b8 | 148 | ":" libc "/" target "/lib"))) |
3593e5d5 LC |
149 | |
150 | (setenv "CPP" (string-append gcc "/bin/cpp")) | |
151 | (for-each (lambda (var) | |
152 | (and=> (getenv var) | |
153 | (lambda (value) | |
154 | (let* ((path (search-path-as-string->list | |
155 | value)) | |
156 | (native-path (list->search-path-as-string | |
157 | (remove cross? path) ":"))) | |
158 | (setenv var native-path))))) | |
159 | (cons "LIBRARY_PATH" %gcc-include-paths)) | |
160 | #t)) | |
161 | ||
162 | (define (install-strip . _) | |
163 | "Install a stripped GCC." | |
164 | ;; Unlike our 'strip' phase, this will do the right thing for | |
165 | ;; cross-compilers. | |
3e629738 | 166 | (invoke "make" "install-strip")) |
3593e5d5 LC |
167 | |
168 | (define* (cross-gcc-build-phases target | |
169 | #:optional (phases %standard-phases)) | |
170 | "Modify PHASES to include everything needed to build a cross-GCC for TARGET, | |
171 | a target triplet." | |
172 | (modify-phases phases | |
173 | (add-before 'configure 'set-cross-path | |
67dac6b8 CD |
174 | ;; This mingw32 target checking logic should match that of target-mingw? |
175 | ;; in (guix utils), but (guix utils) is too large too copy over to the | |
176 | ;; build side entirely and for now we have no way to select variables to | |
177 | ;; copy over. See (gnu packages cross-base) for more details. | |
178 | (if (string-suffix? "-mingw32" target) | |
179 | (cut set-cross-path/mingw #:target target <...>) | |
3593e5d5 LC |
180 | set-cross-path)) |
181 | (add-after 'install 'make-cross-binutils-visible | |
182 | (cut make-cross-binutils-visible #:target target <...>)) | |
183 | (replace 'install install-strip))) | |
184 | ||
185 | ;;; cross-toolchain.scm ends here |