meson.scm 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  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. ;;;
  7. ;;; This file is part of GNU Guix.
  8. ;;;
  9. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  10. ;;; under the terms of the GNU General Public License as published by
  11. ;;; the Free Software Foundation; either version 3 of the License, or (at
  12. ;;; your option) any later version.
  13. ;;;
  14. ;;; GNU Guix is distributed in the hope that it will be useful, but
  15. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  16. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. ;;; GNU General Public License for more details.
  18. ;;;
  19. ;;; You should have received a copy of the GNU General Public License
  20. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  21. (define-module (guix build-system meson)
  22. #:use-module (guix gexp)
  23. #:use-module (guix utils)
  24. #:use-module (guix store)
  25. #:use-module (guix monads)
  26. #:use-module (guix search-paths)
  27. #:use-module (guix build-system)
  28. #:use-module (guix build-system gnu)
  29. #:use-module (guix build-system glib-or-gtk)
  30. #:use-module (guix packages)
  31. #:use-module (ice-9 match)
  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 (target-hurd? triplet)
  43. (and (string-suffix? "-gnu" triplet)
  44. (not (string-contains triplet "linux"))))
  45. (define (make-machine-alist triplet)
  46. "Make an association list describing what should go into
  47. the ‘host_machine’ section of the cross file when cross-compiling
  48. for TRIPLET."
  49. `((system . ,(cond ((target-hurd? triplet) "gnu")
  50. ((target-linux? triplet) "linux")
  51. ((target-mingw? triplet) "windows")
  52. (#t (error "meson: unknown operating system"))))
  53. (cpu_family . ,(cond ((target-x86-32? triplet) "x86")
  54. ((target-x86-64? triplet) "x86_64")
  55. ((target-arm32? triplet) "arm")
  56. ((target-aarch64? triplet) "aarch64")
  57. ((target-powerpc? triplet)
  58. (if (target-64bit? triplet)
  59. "ppc64"
  60. "ppc"))
  61. (#t (error "meson: unknown architecture"))))
  62. (cpu . ,(cond ((target-x86-32? triplet) ; i386, ..., i686
  63. (substring triplet 0 4))
  64. ((target-x86-64? triplet) "x86_64")
  65. (#t (error "meson: unknown CPU"))))
  66. (endian . ,(cond ((string-prefix? "powerpc64le-" triplet) "little")
  67. ((string-prefix? "mips64el-" triplet) "little")
  68. ((target-x86-32? triplet) "little")
  69. ((target-x86-64? triplet) "little")
  70. (#t (error "meson: unknown architecture"))))))
  71. (define (make-binaries-alist triplet)
  72. "Make an associatoin list describing what should go into
  73. the ‘binaries’ section of the cross file when cross-compiling for
  74. TRIPLET."
  75. `((c . ,(cc-for-target triplet))
  76. (cpp . ,(cxx-for-target triplet))
  77. (pkgconfig . ,(pkg-config-for-target triplet))
  78. (objcopy . ,(string-append triplet "-objcopy"))
  79. (ar . ,(string-append triplet "-ar"))
  80. (ld . ,(string-append triplet "-ld"))
  81. (strip . ,(string-append triplet "-strip"))))
  82. (define (make-cross-file triplet)
  83. (computed-file "cross-file"
  84. (with-imported-modules '((guix build meson-configuration))
  85. #~(begin
  86. (use-modules (guix build meson-configuration))
  87. (call-with-output-file #$output
  88. (lambda (f)
  89. (parameterize ((configuration-port f))
  90. (write-section-header "host_machine")
  91. (write-assignments '#$(make-machine-alist triplet))
  92. (write-section-header "binaries")
  93. (write-assignments '#$(make-binaries-alist triplet)))))))))
  94. (define %meson-build-system-modules
  95. ;; Build-side modules imported by default.
  96. `((guix build meson-build-system)
  97. ;; The modules from glib-or-gtk contains the modules from gnu-build-system,
  98. ;; so there is no need to import that too.
  99. ,@%glib-or-gtk-build-system-modules))
  100. (define (default-ninja)
  101. "Return the default ninja package."
  102. ;; Lazily resolve the binding to avoid a circular dependency.
  103. (let ((module (resolve-interface '(gnu packages ninja))))
  104. (module-ref module 'ninja)))
  105. (define (default-meson)
  106. "Return the default meson package."
  107. ;; Lazily resolve the binding to avoid a circular dependency.
  108. (let ((module (resolve-interface '(gnu packages build-tools))))
  109. (module-ref module 'meson)))
  110. (define* (lower name
  111. #:key source inputs native-inputs outputs system target
  112. (meson (default-meson))
  113. (ninja (default-ninja))
  114. (glib-or-gtk? #f)
  115. #:allow-other-keys
  116. #:rest arguments)
  117. "Return a bag for NAME."
  118. (define private-keywords
  119. `(#:meson #:ninja #:inputs #:native-inputs #:outputs
  120. ,@(if target
  121. '()
  122. '(#:target))))
  123. (bag
  124. (name name)
  125. (system system) (target target)
  126. (build-inputs `(("meson" ,meson)
  127. ("ninja" ,ninja)
  128. ,@native-inputs
  129. ,@(if target '() inputs)
  130. ;; Keep the standard inputs of 'gnu-build-system'.
  131. ,@(if target
  132. (standard-cross-packages target 'host)
  133. '())
  134. ,@(standard-packages)))
  135. (host-inputs `(,@(if source
  136. `(("source" ,source))
  137. '())
  138. ,@(if target inputs '())))
  139. ;; Keep the standard inputs of 'gnu-buid-system'.
  140. (target-inputs (if target
  141. (standard-cross-packages target 'target)
  142. '()))
  143. (outputs outputs)
  144. (build (if target meson-cross-build meson-build))
  145. (arguments (strip-keyword-arguments private-keywords arguments))))
  146. (define* (meson-build name inputs
  147. #:key
  148. guile source
  149. (outputs '("out"))
  150. (configure-flags ''())
  151. (search-paths '())
  152. (build-type "debugoptimized")
  153. (tests? #t)
  154. (test-target "test")
  155. (glib-or-gtk? #f)
  156. (parallel-build? #t)
  157. (parallel-tests? #f)
  158. (validate-runpath? #t)
  159. (patch-shebangs? #t)
  160. (strip-binaries? #t)
  161. (strip-flags ''("--strip-debug"))
  162. (strip-directories ''("lib" "lib64" "libexec"
  163. "bin" "sbin"))
  164. (elf-directories ''("lib" "lib64" "libexec"
  165. "bin" "sbin"))
  166. (phases '%standard-phases)
  167. (system (%current-system))
  168. (imported-modules %meson-build-system-modules)
  169. (modules '((guix build meson-build-system)
  170. (guix build utils)))
  171. allowed-references
  172. disallowed-references)
  173. "Build SOURCE using MESON, and with INPUTS, assuming that SOURCE
  174. has a 'meson.build' file."
  175. (define builder
  176. (with-imported-modules imported-modules
  177. #~(begin
  178. (use-modules #$@(sexp->gexp modules))
  179. (define build-phases
  180. #$(let ((phases (if (pair? phases) (sexp->gexp phases) phases)))
  181. (if glib-or-gtk?
  182. phases
  183. #~(modify-phases #$phases
  184. (delete 'glib-or-gtk-compile-schemas)
  185. (delete 'glib-or-gtk-wrap)))))
  186. #$(with-build-variables inputs outputs
  187. #~(meson-build #:source #+source
  188. #:system #$system
  189. #:outputs %outputs
  190. #:inputs %build-inputs
  191. #:search-paths '#$(sexp->gexp
  192. (map search-path-specification->sexp
  193. search-paths))
  194. #:phases build-phases
  195. #:configure-flags #$(sexp->gexp configure-flags)
  196. #:build-type #$build-type
  197. #:tests? #$tests?
  198. #:test-target #$test-target
  199. #:parallel-build? #$parallel-build?
  200. #:parallel-tests? #$parallel-tests?
  201. #:validate-runpath? #$validate-runpath?
  202. #:patch-shebangs? #$patch-shebangs?
  203. #:strip-binaries? #$strip-binaries?
  204. #:strip-flags #$(sexp->gexp strip-flags)
  205. #:strip-directories #$(sexp->gexp strip-directories)
  206. #:elf-directories #$(sexp->gexp elf-directories))))))
  207. (mlet %store-monad ((guile (package->derivation (or guile (default-guile))
  208. system #:graft? #f)))
  209. (gexp->derivation name builder
  210. #:system system
  211. #:target #f
  212. #:substitutable? substitutable?
  213. #:allowed-references allowed-references
  214. #:disallowed-references disallowed-references
  215. #:guile-for-build guile)))
  216. (define* (meson-cross-build name
  217. #:key
  218. target
  219. build-inputs host-inputs target-inputs
  220. guile source
  221. (outputs '("out"))
  222. (configure-flags ''())
  223. (search-paths '())
  224. (native-search-paths '())
  225. (build-type "debugoptimized")
  226. (tests? #f)
  227. (test-target "test")
  228. (glib-or-gtk? #f)
  229. (parallel-build? #t)
  230. (parallel-tests? #f)
  231. (validate-runpath? #t)
  232. (patch-shebangs? #t)
  233. (strip-binaries? #t)
  234. (strip-flags ''("--strip-debug"))
  235. (strip-directories ''("lib" "lib64" "libexec"
  236. "bin" "sbin"))
  237. (elf-directories ''("lib" "lib64" "libexec"
  238. "bin" "sbin"))
  239. (phases '%standard-phases)
  240. (system (%current-system))
  241. (imported-modules %meson-build-system-modules)
  242. (modules '((guix build meson-build-system)
  243. (guix build utils)))
  244. allowed-references
  245. disallowed-references)
  246. "Cross-build SOURCE for TARGET using MESON, and with INPUTS, assuming that
  247. SOURCE has a 'meson.build' file."
  248. (define cross-file
  249. (make-cross-file target))
  250. (define inputs
  251. (if (null? target-inputs)
  252. (input-tuples->gexp host-inputs)
  253. #~(append #$(input-tuples->gexp host-inputs)
  254. #+(input-tuples->gexp target-inputs))))
  255. (define builder
  256. (with-imported-modules imported-modules
  257. #~(begin
  258. (use-modules #$@(sexp->gexp modules))
  259. (define build-phases
  260. #$(let ((phases (if (pair? phases) (sexp->gexp phases) phases)))
  261. (if glib-or-gtk?
  262. phases
  263. #~(modify-phases #$phases
  264. (delete 'glib-or-gtk-compile-schemas)
  265. (delete 'glib-or-gtk-wrap)))))
  266. ;; Do not use 'with-build-variables', as there should be
  267. ;; no reason to use %build-inputs and friends.
  268. (meson-build #:source #+source
  269. #:system #$system
  270. #:outputs #$(outputs->gexp outputs)
  271. #:inputs #$inputs
  272. #:native-inputs #+(input-tuples->gexp build-inputs)
  273. #:search-paths '#$(sexp->gexp
  274. (map search-path-specification->sexp
  275. search-paths))
  276. #:native-search-paths '#$(sexp->gexp
  277. (map search-path-specification->sexp
  278. native-search-paths))
  279. #:phases build-phases
  280. #:configure-flags `("--cross-file" #+cross-file
  281. ,@#$(sexp->gexp configure-flags))
  282. #:build-type #$build-type
  283. #:tests? #$tests?
  284. #:test-target #$test-target
  285. #:parallel-build? #$parallel-build?
  286. #:parallel-tests? #$parallel-tests?
  287. #:validate-runpath? #$validate-runpath?
  288. #:patch-shebangs? #$patch-shebangs?
  289. #:strip-binaries? #$strip-binaries?
  290. #:strip-flags #$(sexp->gexp strip-flags)
  291. #:strip-directories #$(sexp->gexp strip-directories)
  292. #:elf-directories #$(sexp->gexp elf-directories)))))
  293. (mlet %store-monad ((guile (package->derivation (or guile (default-guile))
  294. system #:graft? #f)))
  295. (gexp->derivation name builder
  296. #:system system
  297. #:target target
  298. #:substitutable? substitutable?
  299. #:allowed-references allowed-references
  300. #:disallowed-references disallowed-references
  301. #:guile-for-build guile)))
  302. (define meson-build-system
  303. (build-system
  304. (name 'meson)
  305. (description "The standard Meson build system")
  306. (lower lower)))
  307. ;;; meson.scm ends here