meson.scm 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  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, 2022 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. #:export (%meson-build-system-modules
  33. meson-build-system
  34. make-cross-file))
  35. ;; Commentary:
  36. ;;
  37. ;; Standard build procedure for packages using Meson. This is implemented as an
  38. ;; extension of `gnu-build-system', with the option to turn on the glib/gtk
  39. ;; phases from `glib-or-gtk-build-system'.
  40. ;;
  41. ;; Code:
  42. (define (make-machine-alist triplet)
  43. "Make an association list describing what should go into
  44. the ‘host_machine’ section of the cross file when cross-compiling
  45. for TRIPLET."
  46. `((system . ,(cond ((target-hurd? triplet) "gnu")
  47. ((target-linux? triplet) "linux")
  48. ((target-mingw? triplet) "windows")
  49. (#t (error "meson: unknown operating system"))))
  50. (cpu_family . ,(cond ((target-x86-32? triplet) "x86")
  51. ((target-x86-64? triplet) "x86_64")
  52. ((target-arm32? triplet) "arm")
  53. ((target-aarch64? triplet) "aarch64")
  54. ((target-mips64el? triplet) "mips64")
  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 . ,(if (target-little-endian? triplet)
  74. "little"
  75. "big"))))
  76. (define (make-binaries-alist triplet)
  77. "Make an associatoin list describing what should go into
  78. the ‘binaries’ section of the cross file when cross-compiling for
  79. TRIPLET."
  80. `((c . ,(cc-for-target triplet))
  81. (cpp . ,(cxx-for-target triplet))
  82. (pkgconfig . ,(pkg-config-for-target triplet))
  83. (objcopy . ,(string-append triplet "-objcopy"))
  84. (ar . ,(string-append triplet "-ar"))
  85. (ld . ,(string-append triplet "-ld"))
  86. (strip . ,(string-append triplet "-strip"))))
  87. (define (make-cross-file triplet)
  88. (computed-file "cross-file"
  89. (with-imported-modules '((guix build meson-configuration))
  90. #~(begin
  91. (use-modules (guix build meson-configuration))
  92. (call-with-output-file #$output
  93. (lambda (port)
  94. (write-section-header port "host_machine")
  95. (write-assignments port '#$(make-machine-alist triplet))
  96. (write-section-header port "binaries")
  97. (write-assignments port '#$(make-binaries-alist triplet))))))))
  98. (define %meson-build-system-modules
  99. ;; Build-side modules imported by default.
  100. `((guix build meson-build-system)
  101. ;; The modules from glib-or-gtk contains the modules from gnu-build-system,
  102. ;; so there is no need to import that too.
  103. ,@%glib-or-gtk-build-system-modules))
  104. (define (default-ninja)
  105. "Return the default ninja package."
  106. ;; Lazily resolve the binding to avoid a circular dependency.
  107. (let ((module (resolve-interface '(gnu packages ninja))))
  108. (module-ref module 'ninja)))
  109. (define (default-meson)
  110. "Return the default meson package."
  111. ;; Lazily resolve the binding to avoid a circular dependency.
  112. (let ((module (resolve-interface '(gnu packages build-tools))))
  113. (module-ref module 'meson)))
  114. (define* (lower name
  115. #:key source inputs native-inputs outputs system target
  116. (meson (default-meson))
  117. (ninja (default-ninja))
  118. (glib-or-gtk? #f)
  119. #:allow-other-keys
  120. #:rest arguments)
  121. "Return a bag for NAME."
  122. (define private-keywords
  123. `(#:meson #:ninja #:inputs #:native-inputs #:outputs
  124. ,@(if target
  125. '()
  126. '(#:target))))
  127. (bag
  128. (name name)
  129. (system system) (target target)
  130. (build-inputs `(("meson" ,meson)
  131. ("ninja" ,ninja)
  132. ,@native-inputs
  133. ,@(if target '() inputs)
  134. ;; Keep the standard inputs of 'gnu-build-system'.
  135. ,@(if target
  136. (standard-cross-packages target 'host)
  137. '())
  138. ,@(standard-packages)))
  139. (host-inputs `(,@(if source
  140. `(("source" ,source))
  141. '())
  142. ,@(if target inputs '())))
  143. ;; Keep the standard inputs of 'gnu-buid-system'.
  144. (target-inputs (if target
  145. (standard-cross-packages target 'target)
  146. '()))
  147. (outputs outputs)
  148. (build (if target meson-cross-build meson-build))
  149. (arguments (strip-keyword-arguments private-keywords arguments))))
  150. (define* (meson-build name inputs
  151. #:key
  152. guile source
  153. (outputs '("out"))
  154. (configure-flags ''())
  155. (search-paths '())
  156. (build-type "debugoptimized")
  157. (tests? #t)
  158. (test-options ''())
  159. (glib-or-gtk? #f)
  160. (parallel-build? #t)
  161. (parallel-tests? #f)
  162. (validate-runpath? #t)
  163. (patch-shebangs? #t)
  164. (strip-binaries? #t)
  165. (strip-flags %strip-flags)
  166. (strip-directories %strip-directories)
  167. (elf-directories ''("lib" "lib64" "libexec"
  168. "bin" "sbin"))
  169. (phases '%standard-phases)
  170. (system (%current-system))
  171. (imported-modules %meson-build-system-modules)
  172. (modules '((guix build meson-build-system)
  173. (guix build utils)))
  174. allowed-references
  175. disallowed-references)
  176. "Build SOURCE using MESON, and with INPUTS, assuming that SOURCE
  177. has a 'meson.build' file."
  178. (define builder
  179. (with-imported-modules imported-modules
  180. #~(begin
  181. (use-modules #$@(sexp->gexp modules))
  182. (define build-phases
  183. #$(let ((phases (if (pair? phases) (sexp->gexp phases) phases)))
  184. (if glib-or-gtk?
  185. phases
  186. #~(modify-phases #$phases
  187. (delete 'glib-or-gtk-compile-schemas)
  188. (delete 'glib-or-gtk-wrap)))))
  189. #$(with-build-variables inputs outputs
  190. #~(meson-build #:source #+source
  191. #:system #$system
  192. #:outputs %outputs
  193. #:inputs %build-inputs
  194. #:search-paths '#$(sexp->gexp
  195. (map search-path-specification->sexp
  196. search-paths))
  197. #:phases build-phases
  198. #:configure-flags
  199. #$(if (pair? configure-flags)
  200. (sexp->gexp configure-flags)
  201. configure-flags)
  202. #:build-type #$build-type
  203. #:tests? #$tests?
  204. #:test-options #$(sexp->gexp test-options)
  205. #:parallel-build? #$parallel-build?
  206. #:parallel-tests? #$parallel-tests?
  207. #:validate-runpath? #$validate-runpath?
  208. #:patch-shebangs? #$patch-shebangs?
  209. #:strip-binaries? #$strip-binaries?
  210. #:strip-flags #$strip-flags
  211. #:strip-directories #$strip-directories
  212. #:elf-directories #$(sexp->gexp elf-directories))))))
  213. (mlet %store-monad ((guile (package->derivation (or guile (default-guile))
  214. system #:graft? #f)))
  215. (gexp->derivation name builder
  216. #:system system
  217. #:target #f
  218. #:graft? #f
  219. #:substitutable? substitutable?
  220. #:allowed-references allowed-references
  221. #:disallowed-references disallowed-references
  222. #:guile-for-build guile)))
  223. (define* (meson-cross-build name
  224. #:key
  225. target
  226. build-inputs host-inputs target-inputs
  227. guile source
  228. (outputs '("out"))
  229. (configure-flags ''())
  230. (search-paths '())
  231. (native-search-paths '())
  232. (build-type "debugoptimized")
  233. (tests? #f)
  234. (test-options ''())
  235. (glib-or-gtk? #f)
  236. (parallel-build? #t)
  237. (parallel-tests? #f)
  238. (validate-runpath? #t)
  239. (patch-shebangs? #t)
  240. (strip-binaries? #t)
  241. (strip-flags %strip-flags)
  242. (strip-directories %strip-directories)
  243. (elf-directories ''("lib" "lib64" "libexec"
  244. "bin" "sbin"))
  245. ;; See 'gnu-cross-build' for why this needs to be
  246. ;; disabled when cross-compiling.
  247. (make-dynamic-linker-cache? #f)
  248. (phases '%standard-phases)
  249. (system (%current-system))
  250. (imported-modules %meson-build-system-modules)
  251. (modules '((guix build meson-build-system)
  252. (guix build utils)))
  253. allowed-references
  254. disallowed-references)
  255. "Cross-build SOURCE for TARGET using MESON, and with INPUTS, assuming that
  256. SOURCE has a 'meson.build' file."
  257. (define cross-file
  258. (make-cross-file target))
  259. (define inputs
  260. (if (null? target-inputs)
  261. (input-tuples->gexp host-inputs)
  262. #~(append #$(input-tuples->gexp host-inputs)
  263. #+(input-tuples->gexp target-inputs))))
  264. (define builder
  265. (with-imported-modules imported-modules
  266. #~(begin
  267. (use-modules #$@(sexp->gexp modules))
  268. (define %build-host-inputs
  269. #+(input-tuples->gexp build-inputs))
  270. (define %build-target-inputs
  271. (append #$(input-tuples->gexp host-inputs)
  272. #+(input-tuples->gexp target-inputs)))
  273. (define %build-inputs
  274. (append %build-host-inputs %build-target-inputs))
  275. (define %outputs
  276. #$(outputs->gexp outputs))
  277. (define build-phases
  278. #$(let ((phases (if (pair? phases) (sexp->gexp phases) phases)))
  279. (if glib-or-gtk?
  280. phases
  281. #~(modify-phases #$phases
  282. (delete 'glib-or-gtk-compile-schemas)
  283. (delete 'glib-or-gtk-wrap)))))
  284. ;; Do not use 'with-build-variables', as there should be
  285. ;; no reason to use %build-inputs and friends.
  286. (meson-build #:source #+source
  287. #:system #$system
  288. #:build #$(nix-system->gnu-triplet system)
  289. #:target #$target
  290. #:outputs #$(outputs->gexp outputs)
  291. #:inputs #$inputs
  292. #:native-inputs #+(input-tuples->gexp build-inputs)
  293. #:search-paths '#$(sexp->gexp
  294. (map search-path-specification->sexp
  295. search-paths))
  296. #:native-search-paths '#$(sexp->gexp
  297. (map search-path-specification->sexp
  298. native-search-paths))
  299. #:phases build-phases
  300. #:make-dynamic-linker-cache? #$make-dynamic-linker-cache?
  301. #:configure-flags `("--cross-file" #+cross-file
  302. ,@#$(if (pair? configure-flags)
  303. (sexp->gexp configure-flags)
  304. configure-flags))
  305. #:build-type #$build-type
  306. #:tests? #$tests?
  307. #:test-options #$(sexp->gexp test-options)
  308. #:parallel-build? #$parallel-build?
  309. #:parallel-tests? #$parallel-tests?
  310. #:validate-runpath? #$validate-runpath?
  311. #:patch-shebangs? #$patch-shebangs?
  312. #:strip-binaries? #$strip-binaries?
  313. #:strip-flags #$strip-flags
  314. #:strip-directories #$strip-directories
  315. #:elf-directories #$(sexp->gexp elf-directories)))))
  316. (mlet %store-monad ((guile (package->derivation (or guile (default-guile))
  317. system #:graft? #f)))
  318. (gexp->derivation name builder
  319. #:system system
  320. #:target target
  321. #:graft? #f
  322. #:substitutable? substitutable?
  323. #:allowed-references allowed-references
  324. #:disallowed-references disallowed-references
  325. #:guile-for-build guile)))
  326. (define meson-build-system
  327. (build-system
  328. (name 'meson)
  329. (description "The standard Meson build system")
  330. (lower lower)))
  331. ;;; meson.scm ends here