cross-base.scm 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018 Ludovic Courtès <ludo@gnu.org>
  3. ;;; Copyright © 2014, 2015, 2018 Mark H Weaver <mhw@netris.org>
  4. ;;; Copyright © 2016 Jan Nieuwenhuizen <janneke@gnu.org>
  5. ;;; Copyright © 2016 Manolis Fragkiskos Ragkousis <manolis837@gmail.com>
  6. ;;; Copyright © 2018 Tobias Geerinckx-Rice <me@tobias.gr>
  7. ;;;
  8. ;;; This file is part of GNU Guix.
  9. ;;;
  10. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  11. ;;; under the terms of the GNU General Public License as published by
  12. ;;; the Free Software Foundation; either version 3 of the License, or (at
  13. ;;; your option) any later version.
  14. ;;;
  15. ;;; GNU Guix is distributed in the hope that it will be useful, but
  16. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  17. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. ;;; GNU General Public License for more details.
  19. ;;;
  20. ;;; You should have received a copy of the GNU General Public License
  21. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  22. (define-module (gnu packages cross-base)
  23. #:use-module (gnu packages)
  24. #:use-module (gnu packages gcc)
  25. #:use-module (gnu packages base)
  26. #:use-module (gnu packages linux)
  27. #:use-module (gnu packages hurd)
  28. #:use-module (gnu packages mingw)
  29. #:use-module (guix packages)
  30. #:use-module (guix download)
  31. #:use-module (guix utils)
  32. #:use-module (guix build-system gnu)
  33. #:use-module (guix build-system trivial)
  34. #:use-module (srfi srfi-1)
  35. #:use-module (srfi srfi-26)
  36. #:use-module (ice-9 match)
  37. #:use-module (ice-9 regex)
  38. #:export (cross-binutils
  39. cross-libc
  40. cross-gcc
  41. cross-newlib?))
  42. (define-syntax %xgcc
  43. ;; GCC package used as the basis for cross-compilation. It doesn't have to
  44. ;; be 'gcc' and can be a specific variant such as 'gcc-4.8'.
  45. ;;
  46. ;; Note: This is a macro so that we do not refer to 'gcc' from the top
  47. ;; level, which would lead to circular-dependency issues.
  48. (identifier-syntax gcc))
  49. (define %gcc-include-paths
  50. ;; Environment variables for header search paths.
  51. ;; Note: See <http://bugs.gnu.org/22186> for why not 'CPATH'.
  52. '("C_INCLUDE_PATH"
  53. "CPLUS_INCLUDE_PATH"
  54. "OBJC_INCLUDE_PATH"
  55. "OBJCPLUS_INCLUDE_PATH"))
  56. (define %gcc-cross-include-paths
  57. ;; Search path for target headers when cross-compiling.
  58. (map (cut string-append "CROSS_" <>) %gcc-include-paths))
  59. (define (cross p target)
  60. (package (inherit p)
  61. (name (string-append (package-name p) "-cross-" target))
  62. (arguments
  63. (substitute-keyword-arguments (package-arguments p)
  64. ((#:configure-flags flags)
  65. `(cons ,(string-append "--target=" target)
  66. ,flags))))))
  67. (define (package-with-patch original patch)
  68. "Return package ORIGINAL with PATCH applied."
  69. (package (inherit original)
  70. (source (origin (inherit (package-source original))
  71. (patches (list patch))))))
  72. (define (cross-binutils target)
  73. "Return a cross-Binutils for TARGET."
  74. (let ((binutils (package (inherit binutils)
  75. (arguments
  76. (substitute-keyword-arguments (package-arguments
  77. binutils)
  78. ((#:configure-flags flags)
  79. ;; Build with `--with-sysroot' so that ld honors
  80. ;; DT_RUNPATH entries when searching for a needed
  81. ;; library. This works because as a side effect
  82. ;; `genscripts.sh' sets `USE_LIBPATH=yes', which tells
  83. ;; elf32.em to use DT_RUNPATH in its search list.
  84. ;; See <http://sourceware.org/ml/binutils/2013-05/msg00312.html>.
  85. ;;
  86. ;; In theory choosing / as the sysroot could lead ld
  87. ;; to pick up native libs instead of target ones. In
  88. ;; practice the RUNPATH of target libs only refers to
  89. ;; target libs, not native libs, so this is safe.
  90. `(cons "--with-sysroot=/" ,flags)))))))
  91. ;; For Xtensa, apply Qualcomm's patch.
  92. (cross (if (string-prefix? "xtensa-" target)
  93. (package-with-patch binutils
  94. (search-patch
  95. "ath9k-htc-firmware-binutils.patch"))
  96. binutils)
  97. target)))
  98. (define (cross-gcc-arguments target xgcc libc)
  99. "Return build system arguments for a cross-gcc for TARGET, using XGCC as the
  100. base compiler and using LIBC (which may be either a libc package or #f.)"
  101. ;; Set the current target system so that 'glibc-dynamic-linker' returns the
  102. ;; right name.
  103. (parameterize ((%current-target-system target))
  104. ;; Disable stripping as this can break binaries, with object files of
  105. ;; libgcc.a showing up as having an unknown architecture. See
  106. ;; <http://lists.fedoraproject.org/pipermail/arm/2010-August/000663.html>
  107. ;; for instance.
  108. (let ((args `(#:strip-binaries? #f
  109. ,@(package-arguments xgcc))))
  110. (substitute-keyword-arguments args
  111. ((#:configure-flags flags)
  112. `(append (list ,(string-append "--target=" target)
  113. ,@(if libc
  114. `( ;; Disable libcilkrts because it is not
  115. ;; ported to GNU/Hurd.
  116. "--disable-libcilkrts")
  117. `( ;; Disable features not needed at this stage.
  118. "--disable-shared" "--enable-static"
  119. "--enable-languages=c,c++"
  120. ;; libstdc++ cannot be built at this stage
  121. ;; ("Link tests are not allowed after
  122. ;; GCC_NO_EXECUTABLES.").
  123. "--disable-libstdc++-v3"
  124. "--disable-threads" ;libgcc, would need libc
  125. "--disable-libatomic"
  126. "--disable-libmudflap"
  127. "--disable-libgomp"
  128. "--disable-libssp"
  129. "--disable-libquadmath"
  130. "--disable-decimal-float" ;would need libc
  131. "--disable-libcilkrts"
  132. ;; When target is any OS other than 'none' these
  133. ;; libraries will fail if there is no libc
  134. ;; present. See
  135. ;; <https://lists.gnu.org/archive/html/guix-devel/2016-02/msg01311.html>
  136. "--disable-libitm"
  137. "--disable-libvtv"
  138. "--disable-libsanitizer"
  139. ))
  140. ;; For a newlib (non-glibc) target
  141. ,@(if (cross-newlib? target)
  142. '("--with-newlib")
  143. '()))
  144. ,(if libc
  145. flags
  146. `(remove (cut string-match "--enable-languages.*" <>)
  147. ,flags))))
  148. ((#:make-flags flags)
  149. (if libc
  150. `(let ((libc (assoc-ref %build-inputs "libc")))
  151. ;; FLAGS_FOR_TARGET are needed for the target libraries to receive
  152. ;; the -Bxxx for the startfiles.
  153. (cons (string-append "FLAGS_FOR_TARGET=-B" libc "/lib")
  154. ,flags))
  155. flags))
  156. ((#:phases phases)
  157. `(cross-gcc-build-phases ,target ,phases))))))
  158. (define (cross-gcc-patches target)
  159. "Return GCC patches needed for TARGET."
  160. (cond ((string-prefix? "xtensa-" target)
  161. ;; Patch by Qualcomm needed to build the ath9k-htc firmware.
  162. (search-patches "ath9k-htc-firmware-gcc.patch"))
  163. ((target-mingw? target)
  164. (search-patches "gcc-4.9.3-mingw-gthr-default.patch"))
  165. (else '())))
  166. (define (cross-gcc-snippet target)
  167. "Return GCC snippet needed for TARGET."
  168. (cond ((target-mingw? target)
  169. '(begin
  170. (copy-recursively "libstdc++-v3/config/os/mingw32-w64"
  171. "libstdc++-v3/config/os/newlib")
  172. #t))
  173. (else #f)))
  174. (define* (cross-gcc target
  175. #:key
  176. (xgcc %xgcc)
  177. (xbinutils (cross-binutils target))
  178. (libc #f))
  179. "Return a cross-compiler for TARGET, where TARGET is a GNU triplet. Use
  180. XGCC as the base compiler. Use XBINUTILS as the associated cross-Binutils.
  181. If LIBC is false, then build a GCC that does not target a libc; otherwise,
  182. target that libc."
  183. (package (inherit xgcc)
  184. (name (string-append "gcc-cross-"
  185. (if libc "" "sans-libc-")
  186. target))
  187. (source (origin (inherit (package-source xgcc))
  188. (patches
  189. (append
  190. (origin-patches (package-source xgcc))
  191. (cons (if (version>=? (package-version xgcc) "6.0")
  192. (search-patch "gcc-6-cross-environment-variables.patch")
  193. (search-patch "gcc-cross-environment-variables.patch"))
  194. (cross-gcc-patches target))))
  195. (modules '((guix build utils)))
  196. (snippet
  197. (cross-gcc-snippet target))))
  198. ;; For simplicity, use a single output. Otherwise libgcc_s & co. are not
  199. ;; found by default, etc.
  200. (outputs '("out"))
  201. (arguments
  202. `(#:implicit-inputs? #f
  203. #:imported-modules ((gnu build cross-toolchain)
  204. ,@%gnu-build-system-modules)
  205. #:modules ((guix build gnu-build-system)
  206. (guix build utils)
  207. (gnu build cross-toolchain)
  208. (srfi srfi-1)
  209. (srfi srfi-26)
  210. (ice-9 regex))
  211. ,@(cross-gcc-arguments target xgcc libc)))
  212. (native-inputs
  213. `(("ld-wrapper-cross" ,(make-ld-wrapper
  214. (string-append "ld-wrapper-" target)
  215. #:target (const target)
  216. #:binutils xbinutils))
  217. ("binutils-cross" ,xbinutils)
  218. ;; Call it differently so that the builder can check whether the "libc"
  219. ;; input is #f.
  220. ("libc-native" ,@(assoc-ref (%final-inputs) "libc"))
  221. ;; Remaining inputs.
  222. ,@(let ((inputs (append (package-inputs xgcc)
  223. (alist-delete "libc" (%final-inputs)))))
  224. (cond
  225. ((target-mingw? target)
  226. (if libc
  227. `(("libc" ,mingw-w64)
  228. ,@inputs)
  229. `(("mingw-source" ,(package-source mingw-w64))
  230. ,@inputs)))
  231. (libc
  232. `(("libc" ,libc)
  233. ("libc:static" ,libc "static")
  234. ("xkernel-headers" ;the target headers
  235. ,@(assoc-ref (package-propagated-inputs libc)
  236. "kernel-headers"))
  237. ,@inputs))
  238. (else inputs)))))
  239. (inputs '())
  240. ;; Only search target inputs, not host inputs.
  241. (search-paths (cons (search-path-specification
  242. (variable "CROSS_LIBRARY_PATH")
  243. (files '("lib" "lib64")))
  244. (map (lambda (variable)
  245. (search-path-specification
  246. (variable variable)
  247. (files '("include"))))
  248. %gcc-cross-include-paths)))
  249. (native-search-paths '())))
  250. (define* (cross-kernel-headers target
  251. #:optional
  252. (xgcc (cross-gcc target))
  253. (xbinutils (cross-binutils target)))
  254. "Return headers depending on TARGET."
  255. (define xlinux-headers
  256. (package (inherit linux-libre-headers)
  257. (name (string-append (package-name linux-libre-headers)
  258. "-cross-" target))
  259. (arguments
  260. (substitute-keyword-arguments
  261. `(#:implicit-cross-inputs? #f
  262. ,@(package-arguments linux-libre-headers))
  263. ((#:phases phases)
  264. `(alist-replace
  265. 'build
  266. (lambda _
  267. (setenv "ARCH" ,(system->linux-architecture target))
  268. (format #t "`ARCH' set to `~a' (cross compiling)~%" (getenv "ARCH"))
  269. (invoke "make" ,(system->defconfig target))
  270. (invoke "make" "mrproper" "headers_check"))
  271. ,phases))))
  272. (native-inputs `(("cross-gcc" ,xgcc)
  273. ("cross-binutils" ,xbinutils)
  274. ,@(package-native-inputs linux-libre-headers)))))
  275. (define xgnumach-headers
  276. (package (inherit gnumach-headers)
  277. (name (string-append (package-name gnumach-headers)
  278. "-cross-" target))
  279. (native-inputs `(("cross-gcc" ,xgcc)
  280. ("cross-binutils" ,xbinutils)
  281. ,@(package-native-inputs gnumach-headers)))))
  282. (define xmig
  283. (package (inherit mig)
  284. (name (string-append "mig-cross"))
  285. (arguments
  286. `(#:modules ((guix build gnu-build-system)
  287. (guix build utils)
  288. (srfi srfi-26))
  289. #:phases (modify-phases %standard-phases
  290. (add-before 'configure 'set-cross-headers-path
  291. (lambda* (#:key inputs #:allow-other-keys)
  292. (let* ((mach (assoc-ref inputs "cross-gnumach-headers"))
  293. (cpath (string-append mach "/include")))
  294. (for-each (cut setenv <> cpath)
  295. ',%gcc-cross-include-paths)
  296. #t))))
  297. #:configure-flags (list ,(string-append "--target=" target))
  298. ,@(package-arguments mig)))
  299. (propagated-inputs `(("cross-gnumach-headers" ,xgnumach-headers)))
  300. (native-inputs `(("cross-gcc" ,xgcc)
  301. ("cross-binutils" ,xbinutils)
  302. ,@(package-native-inputs mig)))))
  303. (define xhurd-headers
  304. (package (inherit hurd-headers)
  305. (name (string-append (package-name hurd-headers)
  306. "-cross-" target))
  307. (native-inputs `(("cross-gcc" ,xgcc)
  308. ("cross-binutils" ,xbinutils)
  309. ("cross-mig" ,xmig)
  310. ,@(alist-delete "mig"(package-native-inputs hurd-headers))))))
  311. (define xglibc/hurd-headers
  312. (package (inherit glibc/hurd-headers)
  313. (name (string-append (package-name glibc/hurd-headers)
  314. "-cross-" target))
  315. (arguments
  316. (substitute-keyword-arguments
  317. `(#:modules ((guix build gnu-build-system)
  318. (guix build utils)
  319. (srfi srfi-26))
  320. ,@(package-arguments glibc/hurd-headers))
  321. ((#:phases phases)
  322. `(modify-phases ,phases
  323. (add-after 'unpack 'set-cross-headers-path
  324. (lambda* (#:key inputs #:allow-other-keys)
  325. (let* ((mach (assoc-ref inputs "gnumach-headers"))
  326. (hurd (assoc-ref inputs "hurd-headers"))
  327. (cpath (string-append mach "/include:"
  328. hurd "/include")))
  329. (for-each (cut setenv <> cpath)
  330. ',%gcc-cross-include-paths)
  331. #t)))))))
  332. (propagated-inputs `(("gnumach-headers" ,xgnumach-headers)
  333. ("hurd-headers" ,xhurd-headers)))
  334. (native-inputs `(("cross-gcc" ,xgcc)
  335. ("cross-binutils" ,xbinutils)
  336. ("cross-mig" ,xmig)
  337. ,@(alist-delete "mig"(package-native-inputs glibc/hurd-headers))))))
  338. (define xhurd-minimal
  339. (package (inherit hurd-minimal)
  340. (name (string-append (package-name hurd-minimal)
  341. "-cross-" target))
  342. (arguments
  343. (substitute-keyword-arguments
  344. `(#:modules ((guix build gnu-build-system)
  345. (guix build utils)
  346. (srfi srfi-26))
  347. ,@(package-arguments hurd-minimal))
  348. ((#:phases phases)
  349. `(modify-phases ,phases
  350. (add-before 'configure 'set-cross-headers-path
  351. (lambda* (#:key inputs #:allow-other-keys)
  352. (let* ((glibc-headers (assoc-ref inputs "cross-glibc-hurd-headers"))
  353. (cpath (string-append glibc-headers "/include")))
  354. (for-each (cut setenv <> cpath)
  355. ',%gcc-cross-include-paths)
  356. #t)))))))
  357. (inputs `(("cross-glibc-hurd-headers" ,xglibc/hurd-headers)))
  358. (native-inputs `(("cross-gcc" ,xgcc)
  359. ("cross-binutils" ,xbinutils)
  360. ("cross-mig" ,xmig)
  361. ,@(alist-delete "mig"(package-native-inputs hurd-minimal))))))
  362. (define xhurd-core-headers
  363. (package (inherit hurd-core-headers)
  364. (name (string-append (package-name hurd-core-headers)
  365. "-cross-" target))
  366. (inputs `(("gnumach-headers" ,xgnumach-headers)
  367. ("hurd-headers" ,xhurd-headers)
  368. ("hurd-minimal" ,xhurd-minimal)))
  369. (native-inputs `(("cross-gcc" ,xgcc)
  370. ("cross-binutils" ,xbinutils)
  371. ("cross-mig" ,xmig)
  372. ,@(package-native-inputs hurd-core-headers)))))
  373. (match target
  374. ((or "i586-pc-gnu" "i586-gnu") xhurd-core-headers)
  375. (_ xlinux-headers)))
  376. (define* (cross-libc target
  377. #:optional
  378. (xgcc (cross-gcc target))
  379. (xbinutils (cross-binutils target))
  380. (xheaders (cross-kernel-headers target)))
  381. "Return a libc cross-built for TARGET, a GNU triplet. Use XGCC and
  382. XBINUTILS and the cross tool chain."
  383. (if (cross-newlib? target)
  384. (native-libc target)
  385. (let ((libc glibc))
  386. (package (inherit libc)
  387. (name (string-append "glibc-cross-" target))
  388. (arguments
  389. (substitute-keyword-arguments
  390. `(;; Disable stripping (see above.)
  391. #:strip-binaries? #f
  392. ;; This package is used as a target input, but it should not have
  393. ;; the usual cross-compilation inputs since that would include
  394. ;; itself.
  395. #:implicit-cross-inputs? #f
  396. ;; We need SRFI 26.
  397. #:modules ((guix build gnu-build-system)
  398. (guix build utils)
  399. (srfi srfi-26))
  400. ,@(package-arguments libc))
  401. ((#:configure-flags flags)
  402. `(cons ,(string-append "--host=" target)
  403. ,(if (hurd-triplet? target)
  404. `(cons "--disable-werror" ,flags)
  405. flags)))
  406. ((#:phases phases)
  407. `(modify-phases ,phases
  408. ;; XXX: The hack below allows us to make sure the
  409. ;; 'apply-hurd-patch' phase gets added in the first
  410. ;; cross-libc, but does *not* get added twice subsequently
  411. ;; when cross-building another libc.
  412. ,@(if (and (hurd-triplet? target)
  413. (not (hurd-target?)))
  414. `((add-after 'unpack 'apply-hurd-patch
  415. (lambda* (#:key inputs native-inputs
  416. #:allow-other-keys)
  417. ;; TODO: Move this to 'patches' field.
  418. (let ((patch (or (assoc-ref native-inputs
  419. "hurd-magic-pid-patch")
  420. (assoc-ref inputs
  421. "hurd-magic-pid-patch"))))
  422. (invoke "patch" "-p1" "--force" "--input"
  423. patch)))))
  424. '())
  425. (add-before 'configure 'set-cross-kernel-headers-path
  426. (lambda* (#:key inputs #:allow-other-keys)
  427. (let* ((kernel (assoc-ref inputs "kernel-headers"))
  428. (cpath (string-append kernel "/include")))
  429. (for-each (cut setenv <> cpath)
  430. ',%gcc-cross-include-paths)
  431. (setenv "CROSS_LIBRARY_PATH"
  432. (string-append kernel "/lib")) ; for Hurd's libihash
  433. #t)))))))
  434. ;; Shadow the native "kernel-headers" because glibc's recipe expects the
  435. ;; "kernel-headers" input to point to the right thing.
  436. (propagated-inputs `(("kernel-headers" ,xheaders)))
  437. ;; FIXME: 'static-bash' should really be an input, not a native input, but
  438. ;; to do that will require building an intermediate cross libc.
  439. (inputs '())
  440. (native-inputs `(("cross-gcc" ,xgcc)
  441. ("cross-binutils" ,xbinutils)
  442. ,@(if (hurd-triplet? target)
  443. `(("cross-mig"
  444. ,@(assoc-ref (package-native-inputs xheaders)
  445. "cross-mig"))
  446. ("hurd-magic-pid-patch"
  447. ,(search-patch "glibc-hurd-magic-pid.patch")))
  448. '())
  449. ,@(package-inputs libc) ;FIXME: static-bash
  450. ,@(package-native-inputs libc)))))))
  451. (define (native-libc target)
  452. (if (target-mingw? target)
  453. mingw-w64
  454. glibc))
  455. (define (cross-newlib? target)
  456. (not (eq? (native-libc target) glibc)))
  457. ;;; Concrete cross tool chains are instantiated like this:
  458. ;;
  459. ;; (define-public xgcc-armhf
  460. ;; (let ((triplet "arm-linux-gnueabihf"))
  461. ;; (cross-gcc triplet
  462. ;; #:xbinutils (cross-binutils triplet)
  463. ;; #:libc (cross-libc triplet))))
  464. ;;
  465. ;;; We don't do that here because we'd be referring to bindings from (gnu
  466. ;;; packages gcc) from the top level, which doesn't play well with circular
  467. ;;; dependencies among modules.