meson.scm 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2017 Peter Mikkelsen <petermikkelsen10@gmail.com>
  3. ;;; Copyright © 2018, 2019 Marius Bakke <mbakke@fastmail.com>
  4. ;;; Copyright © 2021 Ludovic Courtès <ludo@gnu.org>
  5. ;;; Copyright © 2021 Maxime Devos <maximedevos@telenet.be>
  6. ;;; Copyright © 2022 Efraim Flashner <efraim@flashner.co.il>
  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 (guix build-system meson)
  23. #:use-module (guix gexp)
  24. #:use-module (guix utils)
  25. #:use-module (guix store)
  26. #:use-module (guix monads)
  27. #:use-module (guix search-paths)
  28. #:use-module (guix build-system)
  29. #:use-module (guix build-system gnu)
  30. #:use-module (guix build-system glib-or-gtk)
  31. #:use-module (guix packages)
  32. #:use-module (ice-9 match)
  33. #:export (%meson-build-system-modules
  34. meson-build-system
  35. make-cross-file))
  36. ;; Commentary:
  37. ;;
  38. ;; Standard build procedure for packages using Meson. This is implemented as an
  39. ;; extension of `gnu-build-system', with the option to turn on the glib/gtk
  40. ;; phases from `glib-or-gtk-build-system'.
  41. ;;
  42. ;; Code:
  43. (define (make-machine-alist triplet)
  44. "Make an association list describing what should go into
  45. the ‘host_machine’ section of the cross file when cross-compiling
  46. for TRIPLET."
  47. `((system . ,(cond ((target-hurd? triplet) "gnu")
  48. ((target-linux? triplet) "linux")
  49. ((target-mingw? triplet) "windows")
  50. (#t (error "meson: unknown operating system"))))
  51. (cpu_family . ,(cond ((target-x86-32? triplet) "x86")
  52. ((target-x86-64? triplet) "x86_64")
  53. ((target-arm32? triplet) "arm")
  54. ((target-aarch64? triplet) "aarch64")
  55. ((target-powerpc? triplet)
  56. (if (target-64bit? triplet)
  57. "ppc64"
  58. "ppc"))
  59. ((target-riscv64? triplet) "riscv64")
  60. (#t (error "meson: unknown architecture"))))
  61. (cpu . ,(cond ((target-x86-32? triplet) ; i386, ..., i686
  62. (substring triplet 0 4))
  63. ((target-x86-64? triplet) "x86_64")
  64. ((target-aarch64? triplet) "armv8-a")
  65. ((target-arm32? triplet) "armv7")
  66. ;; According to #mesonbuild on OFTC, there does not appear
  67. ;; to be an official-ish list of CPU types recognised by
  68. ;; Meson, the "cpu" field is not used by Meson itself and
  69. ;; most software doesn't look at this field, except perhaps
  70. ;; for selecting optimisations, so set it to something
  71. ;; arbitrary.
  72. (#t "strawberries")))
  73. (endian . ,(cond ((string-prefix? "powerpc64le-" triplet) "little")
  74. ((string-prefix? "mips64el-" triplet) "little")
  75. ((target-x86-32? triplet) "little")
  76. ((target-x86-64? triplet) "little")
  77. ;; At least in Guix. Aarch64 and 32-bit arm
  78. ;; have a big-endian mode as well.
  79. ((target-arm? triplet) "little")
  80. ((target-ppc32? triplet) "big")
  81. ((target-riscv64? triplet) "little")
  82. (#t (error "meson: unknown architecture"))))))
  83. (define (make-binaries-alist triplet)
  84. "Make an associatoin list describing what should go into
  85. the ‘binaries’ section of the cross file when cross-compiling for
  86. TRIPLET."
  87. `((c . ,(cc-for-target triplet))
  88. (cpp . ,(cxx-for-target triplet))
  89. (pkgconfig . ,(pkg-config-for-target triplet))
  90. (objcopy . ,(string-append triplet "-objcopy"))
  91. (ar . ,(string-append triplet "-ar"))
  92. (ld . ,(string-append triplet "-ld"))
  93. (strip . ,(string-append triplet "-strip"))))
  94. (define (make-cross-file triplet)
  95. (computed-file "cross-file"
  96. (with-imported-modules '((guix build meson-configuration))
  97. #~(begin
  98. (use-modules (guix build meson-configuration))
  99. (call-with-output-file #$output
  100. (lambda (port)
  101. (write-section-header port "host_machine")
  102. (write-assignments port '#$(make-machine-alist triplet))
  103. (write-section-header port "binaries")
  104. (write-assignments port '#$(make-binaries-alist triplet))))))))
  105. (define %meson-build-system-modules
  106. ;; Build-side modules imported by default.
  107. `((guix build meson-build-system)
  108. ;; The modules from glib-or-gtk contains the modules from gnu-build-system,
  109. ;; so there is no need to import that too.
  110. ,@%glib-or-gtk-build-system-modules))
  111. (define (default-ninja)
  112. "Return the default ninja package."
  113. ;; Lazily resolve the binding to avoid a circular dependency.
  114. (let ((module (resolve-interface '(gnu packages ninja))))
  115. (module-ref module 'ninja)))
  116. (define (default-meson)
  117. "Return the default meson package."
  118. ;; Lazily resolve the binding to avoid a circular dependency.
  119. (let ((module (resolve-interface '(gnu packages build-tools))))
  120. (module-ref module 'meson)))
  121. (define* (lower name
  122. #:key source inputs native-inputs outputs system target
  123. (meson (default-meson))
  124. (ninja (default-ninja))
  125. (glib-or-gtk? #f)
  126. #:allow-other-keys
  127. #:rest arguments)
  128. "Return a bag for NAME."
  129. (define private-keywords
  130. `(#:meson #:ninja #:inputs #:native-inputs #:outputs
  131. ,@(if target
  132. '()
  133. '(#:target))))
  134. (bag
  135. (name name)
  136. (system system) (target target)
  137. (build-inputs `(("meson" ,meson)
  138. ("ninja" ,ninja)
  139. ,@native-inputs
  140. ,@(if target '() inputs)
  141. ;; Keep the standard inputs of 'gnu-build-system'.
  142. ,@(if target
  143. (standard-cross-packages target 'host)
  144. '())
  145. ,@(standard-packages)))
  146. (host-inputs `(,@(if source
  147. `(("source" ,source))
  148. '())
  149. ,@(if target inputs '())))
  150. ;; Keep the standard inputs of 'gnu-buid-system'.
  151. (target-inputs (if target
  152. (standard-cross-packages target 'target)
  153. '()))
  154. (outputs outputs)
  155. (build (if target meson-cross-build meson-build))
  156. (arguments (strip-keyword-arguments private-keywords arguments))))
  157. (define* (meson-build name inputs
  158. #:key
  159. guile source
  160. (outputs '("out"))
  161. (configure-flags ''())
  162. (search-paths '())
  163. (build-type "debugoptimized")
  164. (tests? #t)
  165. (test-options ''())
  166. (glib-or-gtk? #f)
  167. (parallel-build? #t)
  168. (parallel-tests? #f)
  169. (validate-runpath? #t)
  170. (patch-shebangs? #t)
  171. (strip-binaries? #t)
  172. (strip-flags ''("--strip-debug"))
  173. (strip-directories ''("lib" "lib64" "libexec"
  174. "bin" "sbin"))
  175. (elf-directories ''("lib" "lib64" "libexec"
  176. "bin" "sbin"))
  177. (phases '%standard-phases)
  178. (system (%current-system))
  179. (imported-modules %meson-build-system-modules)
  180. (modules '((guix build meson-build-system)
  181. (guix build utils)))
  182. allowed-references
  183. disallowed-references)
  184. "Build SOURCE using MESON, and with INPUTS, assuming that SOURCE
  185. has a 'meson.build' file."
  186. (define builder
  187. (with-imported-modules imported-modules
  188. #~(begin
  189. (use-modules #$@(sexp->gexp modules))
  190. (define build-phases
  191. #$(let ((phases (if (pair? phases) (sexp->gexp phases) phases)))
  192. (if glib-or-gtk?
  193. phases
  194. #~(modify-phases #$phases
  195. (delete 'glib-or-gtk-compile-schemas)
  196. (delete 'glib-or-gtk-wrap)))))
  197. #$(with-build-variables inputs outputs
  198. #~(meson-build #:source #+source
  199. #:system #$system
  200. #:outputs %outputs
  201. #:inputs %build-inputs
  202. #:search-paths '#$(sexp->gexp
  203. (map search-path-specification->sexp
  204. search-paths))
  205. #:phases build-phases
  206. #:configure-flags
  207. #$(if (pair? configure-flags)
  208. (sexp->gexp configure-flags)
  209. configure-flags)
  210. #:build-type #$build-type
  211. #:tests? #$tests?
  212. #:test-options #$(sexp->gexp test-options)
  213. #:parallel-build? #$parallel-build?
  214. #:parallel-tests? #$parallel-tests?
  215. #:validate-runpath? #$validate-runpath?
  216. #:patch-shebangs? #$patch-shebangs?
  217. #:strip-binaries? #$strip-binaries?
  218. #:strip-flags #$(sexp->gexp strip-flags)
  219. #:strip-directories #$(sexp->gexp strip-directories)
  220. #:elf-directories #$(sexp->gexp elf-directories))))))
  221. (mlet %store-monad ((guile (package->derivation (or guile (default-guile))
  222. system #:graft? #f)))
  223. (gexp->derivation name builder
  224. #:system system
  225. #:target #f
  226. #:graft? #f
  227. #:substitutable? substitutable?
  228. #:allowed-references allowed-references
  229. #:disallowed-references disallowed-references
  230. #:guile-for-build guile)))
  231. (define* (meson-cross-build name
  232. #:key
  233. target
  234. build-inputs host-inputs target-inputs
  235. guile source
  236. (outputs '("out"))
  237. (configure-flags ''())
  238. (search-paths '())
  239. (native-search-paths '())
  240. (build-type "debugoptimized")
  241. (tests? #f)
  242. (test-options ''())
  243. (glib-or-gtk? #f)
  244. (parallel-build? #t)
  245. (parallel-tests? #f)
  246. (validate-runpath? #t)
  247. (patch-shebangs? #t)
  248. (strip-binaries? #t)
  249. (strip-flags ''("--strip-debug"))
  250. (strip-directories ''("lib" "lib64" "libexec"
  251. "bin" "sbin"))
  252. (elf-directories ''("lib" "lib64" "libexec"
  253. "bin" "sbin"))
  254. ;; See 'gnu-cross-build' for why this needs to be
  255. ;; disabled when cross-compiling.
  256. (make-dynamic-linker-cache? #f)
  257. (phases '%standard-phases)
  258. (system (%current-system))
  259. (imported-modules %meson-build-system-modules)
  260. (modules '((guix build meson-build-system)
  261. (guix build utils)))
  262. allowed-references
  263. disallowed-references)
  264. "Cross-build SOURCE for TARGET using MESON, and with INPUTS, assuming that
  265. SOURCE has a 'meson.build' file."
  266. (define cross-file
  267. (make-cross-file target))
  268. (define inputs
  269. (if (null? target-inputs)
  270. (input-tuples->gexp host-inputs)
  271. #~(append #$(input-tuples->gexp host-inputs)
  272. #+(input-tuples->gexp target-inputs))))
  273. (define builder
  274. (with-imported-modules imported-modules
  275. #~(begin
  276. (use-modules #$@(sexp->gexp modules))
  277. (define %build-host-inputs
  278. #+(input-tuples->gexp build-inputs))
  279. (define %build-target-inputs
  280. (append #$(input-tuples->gexp host-inputs)
  281. #+(input-tuples->gexp target-inputs)))
  282. (define %build-inputs
  283. (append %build-host-inputs %build-target-inputs))
  284. (define %outputs
  285. #$(outputs->gexp outputs))
  286. (define build-phases
  287. #$(let ((phases (if (pair? phases) (sexp->gexp phases) phases)))
  288. (if glib-or-gtk?
  289. phases
  290. #~(modify-phases #$phases
  291. (delete 'glib-or-gtk-compile-schemas)
  292. (delete 'glib-or-gtk-wrap)))))
  293. ;; Do not use 'with-build-variables', as there should be
  294. ;; no reason to use %build-inputs and friends.
  295. (meson-build #:source #+source
  296. #:system #$system
  297. #:build #$(nix-system->gnu-triplet system)
  298. #:target #$target
  299. #:outputs #$(outputs->gexp outputs)
  300. #:inputs #$inputs
  301. #:native-inputs #+(input-tuples->gexp build-inputs)
  302. #:search-paths '#$(sexp->gexp
  303. (map search-path-specification->sexp
  304. search-paths))
  305. #:native-search-paths '#$(sexp->gexp
  306. (map search-path-specification->sexp
  307. native-search-paths))
  308. #:phases build-phases
  309. #:make-dynamic-linker-cache? #$make-dynamic-linker-cache?
  310. #:configure-flags `("--cross-file" #+cross-file
  311. ,@#$(if (pair? configure-flags)
  312. (sexp->gexp configure-flags)
  313. configure-flags))
  314. #:build-type #$build-type
  315. #:tests? #$tests?
  316. #:test-options #$(sexp->gexp test-options)
  317. #:parallel-build? #$parallel-build?
  318. #:parallel-tests? #$parallel-tests?
  319. #:validate-runpath? #$validate-runpath?
  320. #:patch-shebangs? #$patch-shebangs?
  321. #:strip-binaries? #$strip-binaries?
  322. #:strip-flags #$(sexp->gexp strip-flags)
  323. #:strip-directories #$(sexp->gexp strip-directories)
  324. #:elf-directories #$(sexp->gexp elf-directories)))))
  325. (mlet %store-monad ((guile (package->derivation (or guile (default-guile))
  326. system #:graft? #f)))
  327. (gexp->derivation name builder
  328. #:system system
  329. #:target target
  330. #:graft? #f
  331. #:substitutable? substitutable?
  332. #:allowed-references allowed-references
  333. #:disallowed-references disallowed-references
  334. #:guile-for-build guile)))
  335. (define meson-build-system
  336. (build-system
  337. (name 'meson)
  338. (description "The standard Meson build system")
  339. (lower lower)))
  340. ;;; meson.scm ends here