qt-build-system.scm 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2014 Federico Beffa <beffa@fbengineering.ch>
  3. ;;; Copyright © 2014, 2015, 2021 Ludovic Courtès <ludo@gnu.org>
  4. ;;; Copyright © 2018 Mark H Weaver <mhw@netris.org>
  5. ;;; Copyright © 2019, 2020 Hartmut Goebel <h.goebel@crazy-compilers.com>
  6. ;;; Copyright © 2021 Maxime Devos <maximedevos@telenet.be>
  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 qt-build-system)
  23. #:use-module ((guix build cmake-build-system) #:prefix cmake:)
  24. #:use-module (guix build utils)
  25. #:use-module (ice-9 match)
  26. #:use-module (ice-9 regex)
  27. #:use-module (ice-9 ftw)
  28. #:use-module (srfi srfi-1)
  29. #:use-module (srfi srfi-26)
  30. #:export (%standard-phases
  31. qt-build))
  32. ;; Commentary:
  33. ;;
  34. ;; Builder-side code of the standard Qt build procedure.
  35. ;;
  36. ;; Code:
  37. (define* (check-setup #:rest args)
  38. ;; Make Qt render "offscreen". In many cases this allows to run tests
  39. ;; without starting a X11 server.
  40. (setenv "QT_QPA_PLATFORM" "offscreen")
  41. ;; Qt/KDE tests often need dbus (`dbus-launch …`) which is not fully
  42. ;; set-up the the build container.
  43. (setenv "DBUS_FATAL_WARNINGS" "0")
  44. ;; Set here to ease overwriting 'check (even if set there, too)
  45. (setenv "CTEST_OUTPUT_ON_FAILURE" "1")
  46. #t)
  47. (define (variables-for-wrapping base-directories)
  48. (define (collect-sub-dirs base-directories file-type subdirectory
  49. selectors)
  50. ;; Append SUBDIRECTORY and each of BASE-DIRECTORIES, and return the subset
  51. ;; that exists and has at least one of the SELECTORS sub-directories,
  52. ;; unless SELECTORS is the empty list. FILE-TYPE should by 'directory or
  53. ;; 'regular file. For the later, it allows searching for plain files
  54. ;; rather than directories.
  55. (define exists? (match file-type
  56. ('directory directory-exists?)
  57. ('regular file-exists?)))
  58. (filter-map (lambda (dir)
  59. (let ((directory (string-append dir subdirectory)))
  60. (and (exists? directory)
  61. (or (null? selectors)
  62. (any (lambda (selector)
  63. (exists?
  64. (string-append directory selector)))
  65. selectors))
  66. directory)))
  67. base-directories))
  68. (filter-map
  69. (match-lambda
  70. ((variable file-type directory selectors ...)
  71. (match (collect-sub-dirs base-directories file-type directory
  72. selectors)
  73. (()
  74. #f)
  75. (directories
  76. `(,variable = ,directories)))))
  77. ;; These shall match the search-path-specification for Qt and KDE
  78. ;; libraries.
  79. (list '("XDG_DATA_DIRS" directory "/share"
  80. ;; These are "selectors": consider /share if and only if at least
  81. ;; one of these sub-directories exist. This avoids adding
  82. ;; irrelevant packages to XDG_DATA_DIRS just because they have a
  83. ;; /share sub-directory.
  84. "/glib-2.0/schemas" "/sounds" "/themes"
  85. "/cursors" "/wallpapers" "/icons" "/mime")
  86. '("XDG_CONFIG_DIRS" directory "/etc/xdg")
  87. '("QT_PLUGIN_PATH" directory "/lib/qt5/plugins")
  88. '("QML2_IMPORT_PATH" directory "/lib/qt5/qml")
  89. '("QTWEBENGINEPROCESS_PATH" regular
  90. "/lib/qt5/libexec/QtWebEngineProcess"))))
  91. (define* (wrap-all-programs #:key inputs outputs
  92. (qt-wrap-excluded-outputs '())
  93. #:allow-other-keys)
  94. "Implement phase \"qt-wrap\": look for GSettings schemas and
  95. gtk+-v.0 libraries and create wrappers with suitably set environment variables
  96. if found.
  97. Wrapping is not applied to outputs whose name is listed in
  98. QT-WRAP-EXCLUDED-OUTPUTS. This is useful when an output is known not
  99. to contain any Qt binaries, and where wrapping would gratuitously
  100. add a dependency of that output on Qt."
  101. (define (find-files-to-wrap directory)
  102. (append-map
  103. (lambda (dir)
  104. (if (directory-exists? dir)
  105. (find-files dir (lambda (file stat)
  106. (not (wrapped-program? file))))
  107. '()))
  108. (list (string-append directory "/bin")
  109. (string-append directory "/sbin")
  110. (string-append directory "/libexec")
  111. (string-append directory "/lib/libexec"))))
  112. (define input-directories
  113. ;; FIXME: Filter out unwanted inputs, e.g. cmake
  114. (match inputs
  115. (((_ . dir) ...)
  116. dir)))
  117. ;; Do not require bash to be present in the package inputs
  118. ;; even when there is nothing to wrap.
  119. ;; Also, calculate (sh) only once to prevent some I/O.
  120. (define %sh (delay (search-input-file inputs "bin/bash")))
  121. (define (sh) (force %sh))
  122. (define handle-output
  123. (match-lambda
  124. ((output . directory)
  125. (unless (member output qt-wrap-excluded-outputs)
  126. (let ((bin-list (find-files-to-wrap directory))
  127. (vars-to-wrap (variables-for-wrapping
  128. (append (list directory)
  129. input-directories))))
  130. (when (not (null? vars-to-wrap))
  131. (for-each (cut apply wrap-program <> #:sh (sh) vars-to-wrap)
  132. bin-list)))))))
  133. (for-each handle-output outputs)
  134. #t)
  135. (define %standard-phases
  136. (modify-phases cmake:%standard-phases
  137. (add-before 'check 'check-setup check-setup)
  138. (add-after 'install 'qt-wrap wrap-all-programs)))
  139. (define* (qt-build #:key inputs (phases %standard-phases)
  140. #:allow-other-keys #:rest args)
  141. "Build the given package, applying all of PHASES in order."
  142. (apply cmake:cmake-build #:inputs inputs #:phases phases args))