gexp.scm 74 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2014, 2015, 2016, 2017, 2018, 2019 Ludovic Courtès <ludo@gnu.org>
  3. ;;; Copyright © 2018 Clément Lassieur <clement@lassieur.org>
  4. ;;; Copyright © 2018 Jan Nieuwenhuizen <janneke@gnu.org>
  5. ;;; Copyright © 2019 Mathieu Othacehe <m.othacehe@gmail.com>
  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 gexp)
  22. #:use-module (guix store)
  23. #:use-module (guix monads)
  24. #:use-module (guix derivations)
  25. #:use-module (guix grafts)
  26. #:use-module (guix utils)
  27. #:use-module (rnrs bytevectors)
  28. #:use-module (srfi srfi-1)
  29. #:use-module (srfi srfi-9)
  30. #:use-module (srfi srfi-9 gnu)
  31. #:use-module (srfi srfi-26)
  32. #:use-module (srfi srfi-34)
  33. #:use-module (srfi srfi-35)
  34. #:use-module (ice-9 match)
  35. #:export (gexp
  36. gexp?
  37. with-imported-modules
  38. with-extensions
  39. gexp-input
  40. gexp-input?
  41. gexp-input-thing
  42. gexp-input-output
  43. gexp-input-native?
  44. local-file
  45. local-file?
  46. local-file-file
  47. local-file-absolute-file-name
  48. local-file-name
  49. local-file-recursive?
  50. plain-file
  51. plain-file?
  52. plain-file-name
  53. plain-file-content
  54. computed-file
  55. computed-file?
  56. computed-file-name
  57. computed-file-gexp
  58. computed-file-options
  59. program-file
  60. program-file?
  61. program-file-name
  62. program-file-gexp
  63. program-file-guile
  64. program-file-module-path
  65. scheme-file
  66. scheme-file?
  67. scheme-file-name
  68. scheme-file-gexp
  69. file-append
  70. file-append?
  71. file-append-base
  72. file-append-suffix
  73. load-path-expression
  74. gexp-modules
  75. lower-gexp
  76. lowered-gexp?
  77. lowered-gexp-sexp
  78. lowered-gexp-inputs
  79. lowered-gexp-sources
  80. lowered-gexp-guile
  81. lowered-gexp-load-path
  82. lowered-gexp-load-compiled-path
  83. gexp->derivation
  84. gexp->file
  85. gexp->script
  86. text-file*
  87. mixed-text-file
  88. file-union
  89. directory-union
  90. imported-files
  91. imported-modules
  92. compiled-modules
  93. define-gexp-compiler
  94. gexp-compiler?
  95. file-like?
  96. lower-object
  97. lower-inputs
  98. &gexp-error
  99. gexp-error?
  100. &gexp-input-error
  101. gexp-input-error?
  102. gexp-error-invalid-input))
  103. ;;; Commentary:
  104. ;;;
  105. ;;; This module implements "G-expressions", or "gexps". Gexps are like
  106. ;;; S-expressions (sexps), with two differences:
  107. ;;;
  108. ;;; 1. References (un-quotations) to derivations or packages in a gexp are
  109. ;;; replaced by the corresponding output file name; in addition, the
  110. ;;; 'ungexp-native' unquote-like form allows code to explicitly refer to
  111. ;;; the native code of a given package, in case of cross-compilation;
  112. ;;;
  113. ;;; 2. Gexps embed information about the derivations they refer to.
  114. ;;;
  115. ;;; Gexps make it easy to write to files Scheme code that refers to store
  116. ;;; items, or to write Scheme code to build derivations.
  117. ;;;
  118. ;;; Code:
  119. ;; "G expressions".
  120. (define-record-type <gexp>
  121. (make-gexp references modules extensions proc)
  122. gexp?
  123. (references gexp-references) ;list of <gexp-input>
  124. (modules gexp-self-modules) ;list of module names
  125. (extensions gexp-self-extensions) ;list of lowerable things
  126. (proc gexp-proc)) ;procedure
  127. (define (write-gexp gexp port)
  128. "Write GEXP on PORT."
  129. (display "#<gexp " port)
  130. ;; Try to write the underlying sexp. Now, this trick doesn't work when
  131. ;; doing things like (ungexp-splicing (gexp ())) because GEXP's procedure
  132. ;; tries to use 'append' on that, which fails with wrong-type-arg.
  133. (false-if-exception
  134. (write (apply (gexp-proc gexp)
  135. (gexp-references gexp))
  136. port))
  137. (format port " ~a>"
  138. (number->string (object-address gexp) 16)))
  139. (set-record-type-printer! <gexp> write-gexp)
  140. ;;;
  141. ;;; Methods.
  142. ;;;
  143. ;; Compiler for a type of objects that may be introduced in a gexp.
  144. (define-record-type <gexp-compiler>
  145. (gexp-compiler type lower expand)
  146. gexp-compiler?
  147. (type gexp-compiler-type) ;record type descriptor
  148. (lower gexp-compiler-lower)
  149. (expand gexp-compiler-expand)) ;#f | DRV -> sexp
  150. (define-condition-type &gexp-error &error
  151. gexp-error?)
  152. (define-condition-type &gexp-input-error &gexp-error
  153. gexp-input-error?
  154. (input gexp-error-invalid-input))
  155. (define %gexp-compilers
  156. ;; 'eq?' mapping of record type descriptor to <gexp-compiler>.
  157. (make-hash-table 20))
  158. (define (default-expander thing obj output)
  159. "This is the default expander for \"things\" that appear in gexps. It
  160. returns its output file name of OBJ's OUTPUT."
  161. (match obj
  162. ((? derivation? drv)
  163. (derivation->output-path drv output))
  164. ((? string? file)
  165. file)))
  166. (define (register-compiler! compiler)
  167. "Register COMPILER as a gexp compiler."
  168. (hashq-set! %gexp-compilers
  169. (gexp-compiler-type compiler) compiler))
  170. (define (lookup-compiler object)
  171. "Search for a compiler for OBJECT. Upon success, return the three argument
  172. procedure to lower it; otherwise return #f."
  173. (and=> (hashq-ref %gexp-compilers (struct-vtable object))
  174. gexp-compiler-lower))
  175. (define (file-like? object)
  176. "Return #t if OBJECT leads to a file in the store once unquoted in a
  177. G-expression; otherwise return #f."
  178. (and (struct? object) (->bool (lookup-compiler object))))
  179. (define (lookup-expander object)
  180. "Search for an expander for OBJECT. Upon success, return the three argument
  181. procedure to expand it; otherwise return #f."
  182. (and=> (hashq-ref %gexp-compilers (struct-vtable object))
  183. gexp-compiler-expand))
  184. (define* (lower-object obj
  185. #:optional (system (%current-system))
  186. #:key target)
  187. "Return as a value in %STORE-MONAD the derivation or store item
  188. corresponding to OBJ for SYSTEM, cross-compiling for TARGET if TARGET is true.
  189. OBJ must be an object that has an associated gexp compiler, such as a
  190. <package>."
  191. (match (lookup-compiler obj)
  192. (#f
  193. (raise (condition (&gexp-input-error (input obj)))))
  194. (lower
  195. ;; Cache in STORE the result of lowering OBJ.
  196. (mlet %store-monad ((graft? (grafting?)))
  197. (mcached (let ((lower (lookup-compiler obj)))
  198. (lower obj system target))
  199. obj
  200. system target graft?)))))
  201. (define-syntax define-gexp-compiler
  202. (syntax-rules (=> compiler expander)
  203. "Define NAME as a compiler for objects matching PREDICATE encountered in
  204. gexps.
  205. In the simplest form of the macro, BODY must return a derivation for PARAM, an
  206. object that matches PREDICATE, for SYSTEM and TARGET (the latter of which is
  207. #f except when cross-compiling.)
  208. The more elaborate form allows you to specify an expander:
  209. (define-gexp-compiler something something?
  210. compiler => (lambda (param system target) ...)
  211. expander => (lambda (param drv output) ...))
  212. The expander specifies how an object is converted to its sexp representation."
  213. ((_ (name (param record-type) system target) body ...)
  214. (define-gexp-compiler name record-type
  215. compiler => (lambda (param system target) body ...)
  216. expander => default-expander))
  217. ((_ name record-type
  218. compiler => compile
  219. expander => expand)
  220. (begin
  221. (define name
  222. (gexp-compiler record-type compile expand))
  223. (register-compiler! name)))))
  224. (define-gexp-compiler (derivation-compiler (drv <derivation>) system target)
  225. ;; Derivations are the lowest-level representation, so this is the identity
  226. ;; compiler.
  227. (with-monad %store-monad
  228. (return drv)))
  229. ;;;
  230. ;;; File declarations.
  231. ;;;
  232. ;; A local file name. FILE is the file name the user entered, which can be a
  233. ;; relative file name, and ABSOLUTE is a promise that computes its canonical
  234. ;; absolute file name. We keep it in a promise to compute it lazily and avoid
  235. ;; repeated 'stat' calls.
  236. (define-record-type <local-file>
  237. (%%local-file file absolute name recursive? select?)
  238. local-file?
  239. (file local-file-file) ;string
  240. (absolute %local-file-absolute-file-name) ;promise string
  241. (name local-file-name) ;string
  242. (recursive? local-file-recursive?) ;Boolean
  243. (select? local-file-select?)) ;string stat -> Boolean
  244. (define (true file stat) #t)
  245. (define* (%local-file file promise #:optional (name (basename file))
  246. #:key recursive? (select? true))
  247. ;; This intermediate procedure is part of our ABI, but the underlying
  248. ;; %%LOCAL-FILE is not.
  249. (%%local-file file promise name recursive? select?))
  250. (define (absolute-file-name file directory)
  251. "Return the canonical absolute file name for FILE, which lives in the
  252. vicinity of DIRECTORY."
  253. (canonicalize-path
  254. (cond ((string-prefix? "/" file) file)
  255. ((not directory) file)
  256. ((string-prefix? "/" directory)
  257. (string-append directory "/" file))
  258. (else file))))
  259. (define-syntax local-file
  260. (lambda (s)
  261. "Return an object representing local file FILE to add to the store; this
  262. object can be used in a gexp. If FILE is a relative file name, it is looked
  263. up relative to the source file where this form appears. FILE will be added to
  264. the store under NAME--by default the base name of FILE.
  265. When RECURSIVE? is true, the contents of FILE are added recursively; if FILE
  266. designates a flat file and RECURSIVE? is true, its contents are added, and its
  267. permission bits are kept.
  268. When RECURSIVE? is true, call (SELECT? FILE STAT) for each directory entry,
  269. where FILE is the entry's absolute file name and STAT is the result of
  270. 'lstat'; exclude entries for which SELECT? does not return true.
  271. This is the declarative counterpart of the 'interned-file' monadic procedure.
  272. It is implemented as a macro to capture the current source directory where it
  273. appears."
  274. (syntax-case s ()
  275. ((_ file rest ...)
  276. (string? (syntax->datum #'file))
  277. ;; FILE is a literal, so resolve it relative to the source directory.
  278. #'(%local-file file
  279. (delay (absolute-file-name file (current-source-directory)))
  280. rest ...))
  281. ((_ file rest ...)
  282. ;; Resolve FILE relative to the current directory.
  283. #'(%local-file file
  284. (delay (absolute-file-name file (getcwd)))
  285. rest ...))
  286. ((_)
  287. #'(syntax-error "missing file name"))
  288. (id
  289. (identifier? #'id)
  290. ;; XXX: We could return #'(lambda (file . rest) ...). However,
  291. ;; (syntax-source #'id) is #f so (current-source-directory) would not
  292. ;; work. Thus, simply forbid this form.
  293. #'(syntax-error
  294. "'local-file' is a macro and cannot be used like this")))))
  295. (define (local-file-absolute-file-name file)
  296. "Return the absolute file name for FILE, a <local-file> instance. A
  297. 'system-error' exception is raised if FILE could not be found."
  298. (force (%local-file-absolute-file-name file)))
  299. (define-gexp-compiler (local-file-compiler (file <local-file>) system target)
  300. ;; "Compile" FILE by adding it to the store.
  301. (match file
  302. (($ <local-file> file (= force absolute) name recursive? select?)
  303. ;; Canonicalize FILE so that if it's a symlink, it is resolved. Failing
  304. ;; to do that, when RECURSIVE? is #t, we could end up creating a dangling
  305. ;; symlink in the store, and when RECURSIVE? is #f 'add-to-store' would
  306. ;; just throw an error, both of which are inconvenient.
  307. (interned-file absolute name
  308. #:recursive? recursive? #:select? select?))))
  309. (define-record-type <plain-file>
  310. (%plain-file name content references)
  311. plain-file?
  312. (name plain-file-name) ;string
  313. (content plain-file-content) ;string or bytevector
  314. (references plain-file-references)) ;list (currently unused)
  315. (define (plain-file name content)
  316. "Return an object representing a text file called NAME with the given
  317. CONTENT (a string) to be added to the store.
  318. This is the declarative counterpart of 'text-file'."
  319. ;; XXX: For now just ignore 'references' because it's not clear how to use
  320. ;; them in a declarative context.
  321. (%plain-file name content '()))
  322. (define-gexp-compiler (plain-file-compiler (file <plain-file>) system target)
  323. ;; "Compile" FILE by adding it to the store.
  324. (match file
  325. (($ <plain-file> name (and (? string?) content) references)
  326. (text-file name content references))
  327. (($ <plain-file> name (and (? bytevector?) content) references)
  328. (binary-file name content references))))
  329. (define-record-type <computed-file>
  330. (%computed-file name gexp guile options)
  331. computed-file?
  332. (name computed-file-name) ;string
  333. (gexp computed-file-gexp) ;gexp
  334. (guile computed-file-guile) ;<package>
  335. (options computed-file-options)) ;list of arguments
  336. (define* (computed-file name gexp
  337. #:key guile (options '(#:local-build? #t)))
  338. "Return an object representing the store item NAME, a file or directory
  339. computed by GEXP. OPTIONS is a list of additional arguments to pass
  340. to 'gexp->derivation'.
  341. This is the declarative counterpart of 'gexp->derivation'."
  342. (%computed-file name gexp guile options))
  343. (define-gexp-compiler (computed-file-compiler (file <computed-file>)
  344. system target)
  345. ;; Compile FILE by returning a derivation whose build expression is its
  346. ;; gexp.
  347. (match file
  348. (($ <computed-file> name gexp guile options)
  349. (if guile
  350. (mlet %store-monad ((guile (lower-object guile system
  351. #:target target)))
  352. (apply gexp->derivation name gexp #:guile-for-build guile
  353. #:system system #:target target options))
  354. (apply gexp->derivation name gexp
  355. #:system system #:target target options)))))
  356. (define-record-type <program-file>
  357. (%program-file name gexp guile path)
  358. program-file?
  359. (name program-file-name) ;string
  360. (gexp program-file-gexp) ;gexp
  361. (guile program-file-guile) ;package
  362. (path program-file-module-path)) ;list of strings
  363. (define* (program-file name gexp #:key (guile #f) (module-path %load-path))
  364. "Return an object representing the executable store item NAME that runs
  365. GEXP. GUILE is the Guile package used to execute that script. Imported
  366. modules of GEXP are looked up in MODULE-PATH.
  367. This is the declarative counterpart of 'gexp->script'."
  368. (%program-file name gexp guile module-path))
  369. (define-gexp-compiler (program-file-compiler (file <program-file>)
  370. system target)
  371. ;; Compile FILE by returning a derivation that builds the script.
  372. (match file
  373. (($ <program-file> name gexp guile module-path)
  374. (gexp->script name gexp
  375. #:module-path module-path
  376. #:guile (or guile (default-guile))
  377. #:system system
  378. #:target target))))
  379. (define-record-type <scheme-file>
  380. (%scheme-file name gexp splice?)
  381. scheme-file?
  382. (name scheme-file-name) ;string
  383. (gexp scheme-file-gexp) ;gexp
  384. (splice? scheme-file-splice?)) ;Boolean
  385. (define* (scheme-file name gexp #:key splice?)
  386. "Return an object representing the Scheme file NAME that contains GEXP.
  387. This is the declarative counterpart of 'gexp->file'."
  388. (%scheme-file name gexp splice?))
  389. (define-gexp-compiler (scheme-file-compiler (file <scheme-file>)
  390. system target)
  391. ;; Compile FILE by returning a derivation that builds the file.
  392. (match file
  393. (($ <scheme-file> name gexp splice?)
  394. (gexp->file name gexp
  395. #:splice? splice?
  396. #:system system
  397. #:target target))))
  398. ;; Appending SUFFIX to BASE's output file name.
  399. (define-record-type <file-append>
  400. (%file-append base suffix)
  401. file-append?
  402. (base file-append-base) ;<package> | <derivation> | ...
  403. (suffix file-append-suffix)) ;list of strings
  404. (define (write-file-append file port)
  405. (match file
  406. (($ <file-append> base suffix)
  407. (format port "#<file-append ~s ~s>" base
  408. (string-join suffix)))))
  409. (set-record-type-printer! <file-append> write-file-append)
  410. (define (file-append base . suffix)
  411. "Return a <file-append> object that expands to the concatenation of BASE and
  412. SUFFIX."
  413. (%file-append base suffix))
  414. (define-gexp-compiler file-append-compiler <file-append>
  415. compiler => (lambda (obj system target)
  416. (match obj
  417. (($ <file-append> base _)
  418. (lower-object base system #:target target))))
  419. expander => (lambda (obj lowered output)
  420. (match obj
  421. (($ <file-append> base suffix)
  422. (let* ((expand (lookup-expander base))
  423. (base (expand base lowered output)))
  424. (string-append base (string-concatenate suffix)))))))
  425. ;;;
  426. ;;; Inputs & outputs.
  427. ;;;
  428. ;; The input of a gexp.
  429. (define-record-type <gexp-input>
  430. (%gexp-input thing output native?)
  431. gexp-input?
  432. (thing gexp-input-thing) ;<package> | <origin> | <derivation> | ...
  433. (output gexp-input-output) ;string
  434. (native? gexp-input-native?)) ;Boolean
  435. (define (write-gexp-input input port)
  436. (match input
  437. (($ <gexp-input> thing output #f)
  438. (format port "#<gexp-input ~s:~a>" thing output))
  439. (($ <gexp-input> thing output #t)
  440. (format port "#<gexp-input native ~s:~a>" thing output))))
  441. (set-record-type-printer! <gexp-input> write-gexp-input)
  442. (define* (gexp-input thing ;convenience procedure
  443. #:optional (output "out")
  444. #:key native?)
  445. "Return a new <gexp-input> for the OUTPUT of THING; NATIVE? determines
  446. whether this should be considered a \"native\" input or not."
  447. (%gexp-input thing output native?))
  448. ;; Reference to one of the derivation's outputs, for gexps used in
  449. ;; derivations.
  450. (define-record-type <gexp-output>
  451. (gexp-output name)
  452. gexp-output?
  453. (name gexp-output-name))
  454. (define (write-gexp-output output port)
  455. (match output
  456. (($ <gexp-output> name)
  457. (format port "#<gexp-output ~a>" name))))
  458. (set-record-type-printer! <gexp-output> write-gexp-output)
  459. (define* (gexp-attribute gexp self-attribute #:optional (equal? equal?))
  460. "Recurse on GEXP and the expressions it refers to, summing the items
  461. returned by SELF-ATTRIBUTE, a procedure that takes a gexp. Use EQUAL? as the
  462. second argument to 'delete-duplicates'."
  463. (if (gexp? gexp)
  464. (delete-duplicates
  465. (append (self-attribute gexp)
  466. (append-map (match-lambda
  467. (($ <gexp-input> (? gexp? exp))
  468. (gexp-attribute exp self-attribute))
  469. (($ <gexp-input> (lst ...))
  470. (append-map (lambda (item)
  471. (if (gexp? item)
  472. (gexp-attribute item
  473. self-attribute)
  474. '()))
  475. lst))
  476. (_
  477. '()))
  478. (gexp-references gexp)))
  479. equal?)
  480. '())) ;plain Scheme data type
  481. (define (gexp-modules gexp)
  482. "Return the list of Guile module names GEXP relies on. If (gexp? GEXP) is
  483. false, meaning that GEXP is a plain Scheme object, return the empty list."
  484. (define (module=? m1 m2)
  485. ;; Return #t when M1 equals M2. Special-case '=>' specs because their
  486. ;; right-hand side may not be comparable with 'equal?': it's typically a
  487. ;; file-like object that embeds a gexp, which in turn embeds closure;
  488. ;; those closures may be 'eq?' when running compiled code but are unlikely
  489. ;; to be 'eq?' when running on 'eval'. Ignore the right-hand side to
  490. ;; avoid this discrepancy.
  491. (match m1
  492. (((name1 ...) '=> _)
  493. (match m2
  494. (((name2 ...) '=> _) (equal? name1 name2))
  495. (_ #f)))
  496. (_
  497. (equal? m1 m2))))
  498. (gexp-attribute gexp gexp-self-modules module=?))
  499. (define (gexp-extensions gexp)
  500. "Return the list of Guile extensions (packages) GEXP relies on. If (gexp?
  501. GEXP) is false, meaning that GEXP is a plain Scheme object, return the empty
  502. list."
  503. (gexp-attribute gexp gexp-self-extensions))
  504. (define* (lower-inputs inputs
  505. #:key system target)
  506. "Turn any object from INPUTS into a derivation input for SYSTEM or a store
  507. item (a \"source\"); return the corresponding input list as a monadic value.
  508. When TARGET is true, use it as the cross-compilation target triplet."
  509. (define (store-item? obj)
  510. (and (string? obj) (store-path? obj)))
  511. (with-monad %store-monad
  512. (mapm %store-monad
  513. (match-lambda
  514. (((? struct? thing) sub-drv ...)
  515. (mlet %store-monad ((obj (lower-object
  516. thing system #:target target)))
  517. (return (match obj
  518. ((? derivation? drv)
  519. (let ((outputs (if (null? sub-drv)
  520. '("out")
  521. sub-drv)))
  522. (derivation-input drv outputs)))
  523. ((? store-item? item)
  524. item)))))
  525. (((? store-item? item))
  526. (return item)))
  527. inputs)))
  528. (define* (lower-reference-graphs graphs #:key system target)
  529. "Given GRAPHS, a list of (FILE-NAME INPUT ...) lists for use as a
  530. #:reference-graphs argument, lower it such that each INPUT is replaced by the
  531. corresponding <derivation-input> or store item."
  532. (match graphs
  533. (((file-names . inputs) ...)
  534. (mlet %store-monad ((inputs (lower-inputs inputs
  535. #:system system
  536. #:target target)))
  537. (return (map cons file-names inputs))))))
  538. (define* (lower-references lst #:key system target)
  539. "Based on LST, a list of output names and packages, return a list of output
  540. names and file names suitable for the #:allowed-references argument to
  541. 'derivation'."
  542. (with-monad %store-monad
  543. (define lower
  544. (match-lambda
  545. ((? string? output)
  546. (return output))
  547. (($ <gexp-input> thing output native?)
  548. (mlet %store-monad ((drv (lower-object thing system
  549. #:target (if native?
  550. #f target))))
  551. (return (derivation->output-path drv output))))
  552. (thing
  553. (mlet %store-monad ((drv (lower-object thing system
  554. #:target target)))
  555. (return (derivation->output-path drv))))))
  556. (mapm %store-monad lower lst)))
  557. (define default-guile-derivation
  558. ;; Here we break the abstraction by talking to the higher-level layer.
  559. ;; Thus, do the resolution lazily to hide the circular dependency.
  560. (let ((proc (delay
  561. (let ((iface (resolve-interface '(guix packages))))
  562. (module-ref iface 'default-guile-derivation)))))
  563. (lambda (system)
  564. ((force proc) system))))
  565. ;; Representation of a gexp instantiated for a given target and system.
  566. ;; It's an intermediate representation between <gexp> and <derivation>.
  567. (define-record-type <lowered-gexp>
  568. (lowered-gexp sexp inputs sources guile load-path load-compiled-path)
  569. lowered-gexp?
  570. (sexp lowered-gexp-sexp) ;sexp
  571. (inputs lowered-gexp-inputs) ;list of <derivation-input>
  572. (sources lowered-gexp-sources) ;list of store items
  573. (guile lowered-gexp-guile) ;<derivation-input> | #f
  574. (load-path lowered-gexp-load-path) ;list of store items
  575. (load-compiled-path lowered-gexp-load-compiled-path)) ;list of store items
  576. (define* (imported+compiled-modules modules system
  577. #:key (extensions '())
  578. deprecation-warnings guile
  579. (module-path %load-path))
  580. "Return a pair where the first element is the imported MODULES and the
  581. second element is the derivation to compile them."
  582. (mcached equal?
  583. (mlet %store-monad ((modules (if (pair? modules)
  584. (imported-modules modules
  585. #:system system
  586. #:module-path module-path)
  587. (return #f)))
  588. (compiled (if (pair? modules)
  589. (compiled-modules modules
  590. #:system system
  591. #:module-path module-path
  592. #:extensions extensions
  593. #:guile guile
  594. #:deprecation-warnings
  595. deprecation-warnings)
  596. (return #f))))
  597. (return (cons modules compiled)))
  598. modules
  599. system extensions guile deprecation-warnings module-path))
  600. (define* (lower-gexp exp
  601. #:key
  602. (module-path %load-path)
  603. (system (%current-system))
  604. (target 'current)
  605. (graft? (%graft?))
  606. (guile-for-build (%guile-for-build))
  607. (effective-version "2.2")
  608. deprecation-warnings)
  609. "*Note: This API is subject to change; use at your own risk!*
  610. Lower EXP, a gexp, instantiating it for SYSTEM and TARGET. Return a
  611. <lowered-gexp> ready to be used.
  612. Lowered gexps are an intermediate representation that's useful for
  613. applications that deal with gexps outside in a way that is disconnected from
  614. derivations--e.g., code evaluated for its side effects."
  615. (define %modules
  616. (delete-duplicates (gexp-modules exp)))
  617. (define (search-path modules extensions suffix)
  618. (append (match modules
  619. ((? derivation? drv)
  620. (list (derivation->output-path drv)))
  621. (#f
  622. '())
  623. ((? store-path? item)
  624. (list item)))
  625. (map (lambda (extension)
  626. (string-append (match extension
  627. ((? derivation? drv)
  628. (derivation->output-path drv))
  629. ((? store-path? item)
  630. item))
  631. suffix))
  632. extensions)))
  633. (mlet* %store-monad ( ;; The following binding forces '%current-system' and
  634. ;; '%current-target-system' to be looked up at >>=
  635. ;; time.
  636. (graft? (set-grafting graft?))
  637. (system -> (or system (%current-system)))
  638. (target -> (if (eq? target 'current)
  639. (%current-target-system)
  640. target))
  641. (guile (if guile-for-build
  642. (return guile-for-build)
  643. (default-guile-derivation system)))
  644. (normals (lower-inputs (gexp-inputs exp)
  645. #:system system
  646. #:target target))
  647. (natives (lower-inputs (gexp-native-inputs exp)
  648. #:system system
  649. #:target #f))
  650. (inputs -> (append normals natives))
  651. (sexp (gexp->sexp exp
  652. #:system system
  653. #:target target))
  654. (extensions -> (gexp-extensions exp))
  655. (exts (mapm %store-monad
  656. (lambda (obj)
  657. (lower-object obj system))
  658. extensions))
  659. (modules+compiled (imported+compiled-modules
  660. %modules system
  661. #:extensions extensions
  662. #:deprecation-warnings
  663. deprecation-warnings
  664. #:guile guile
  665. #:module-path module-path))
  666. (modules -> (car modules+compiled))
  667. (compiled -> (cdr modules+compiled)))
  668. (define load-path
  669. (search-path modules exts
  670. (string-append "/share/guile/site/" effective-version)))
  671. (define load-compiled-path
  672. (search-path compiled exts
  673. (string-append "/lib/guile/" effective-version
  674. "/site-ccache")))
  675. (mbegin %store-monad
  676. (set-grafting graft?) ;restore the initial setting
  677. (return (lowered-gexp sexp
  678. `(,@(if (derivation? modules)
  679. (list (derivation-input modules))
  680. '())
  681. ,@(if compiled
  682. (list (derivation-input compiled))
  683. '())
  684. ,@(map derivation-input exts)
  685. ,@(filter derivation-input? inputs))
  686. (filter string? (cons modules inputs))
  687. (derivation-input guile '("out"))
  688. load-path
  689. load-compiled-path)))))
  690. (define* (gexp->derivation name exp
  691. #:key
  692. system (target 'current)
  693. hash hash-algo recursive?
  694. (env-vars '())
  695. (modules '())
  696. (module-path %load-path)
  697. (guile-for-build (%guile-for-build))
  698. (effective-version "2.2")
  699. (graft? (%graft?))
  700. references-graphs
  701. allowed-references disallowed-references
  702. leaked-env-vars
  703. local-build? (substitutable? #t)
  704. (properties '())
  705. deprecation-warnings
  706. (script-name (string-append name "-builder")))
  707. "Return a derivation NAME that runs EXP (a gexp) with GUILE-FOR-BUILD (a
  708. derivation) on SYSTEM; EXP is stored in a file called SCRIPT-NAME. When
  709. TARGET is true, it is used as the cross-compilation target triplet for
  710. packages referred to by EXP.
  711. MODULES is deprecated in favor of 'with-imported-modules'. Its meaning is to
  712. make MODULES available in the evaluation context of EXP; MODULES is a list of
  713. names of Guile modules searched in MODULE-PATH to be copied in the store,
  714. compiled, and made available in the load path during the execution of
  715. EXP---e.g., '((guix build utils) (guix build gnu-build-system)).
  716. EFFECTIVE-VERSION determines the string to use when adding extensions of
  717. EXP (see 'with-extensions') to the search path---e.g., \"2.2\".
  718. GRAFT? determines whether packages referred to by EXP should be grafted when
  719. applicable.
  720. When REFERENCES-GRAPHS is true, it must be a list of tuples of one of the
  721. following forms:
  722. (FILE-NAME PACKAGE)
  723. (FILE-NAME PACKAGE OUTPUT)
  724. (FILE-NAME DERIVATION)
  725. (FILE-NAME DERIVATION OUTPUT)
  726. (FILE-NAME STORE-ITEM)
  727. The right-hand-side of each element of REFERENCES-GRAPHS is automatically made
  728. an input of the build process of EXP. In the build environment, each
  729. FILE-NAME contains the reference graph of the corresponding item, in a simple
  730. text format.
  731. ALLOWED-REFERENCES must be either #f or a list of output names and packages.
  732. In the latter case, the list denotes store items that the result is allowed to
  733. refer to. Any reference to another store item will lead to a build error.
  734. Similarly for DISALLOWED-REFERENCES, which can list items that must not be
  735. referenced by the outputs.
  736. DEPRECATION-WARNINGS determines whether to show deprecation warnings while
  737. compiling modules. It can be #f, #t, or 'detailed.
  738. The other arguments are as for 'derivation'."
  739. (define outputs (gexp-outputs exp))
  740. (define requested-graft? graft?)
  741. (define (graphs-file-names graphs)
  742. ;; Return a list of (FILE-NAME . STORE-PATH) pairs made from GRAPHS.
  743. (map (match-lambda
  744. ((file-name . (? derivation-input? input))
  745. (cons file-name (first (derivation-input-output-paths input))))
  746. ((file-name . (? string? item))
  747. (cons file-name item)))
  748. graphs))
  749. (define (add-modules exp modules)
  750. (if (null? modules)
  751. exp
  752. (make-gexp (gexp-references exp)
  753. (append modules (gexp-self-modules exp))
  754. (gexp-self-extensions exp)
  755. (gexp-proc exp))))
  756. (mlet* %store-monad ( ;; The following binding forces '%current-system' and
  757. ;; '%current-target-system' to be looked up at >>=
  758. ;; time.
  759. (graft? (set-grafting graft?))
  760. (system -> (or system (%current-system)))
  761. (target -> (if (eq? target 'current)
  762. (%current-target-system)
  763. target))
  764. (exp -> (add-modules exp modules))
  765. (lowered (lower-gexp exp
  766. #:module-path module-path
  767. #:system system
  768. #:target target
  769. #:graft? requested-graft?
  770. #:guile-for-build
  771. guile-for-build
  772. #:effective-version
  773. effective-version
  774. #:deprecation-warnings
  775. deprecation-warnings))
  776. (graphs (if references-graphs
  777. (lower-reference-graphs references-graphs
  778. #:system system
  779. #:target target)
  780. (return #f)))
  781. (allowed (if allowed-references
  782. (lower-references allowed-references
  783. #:system system
  784. #:target target)
  785. (return #f)))
  786. (disallowed (if disallowed-references
  787. (lower-references disallowed-references
  788. #:system system
  789. #:target target)
  790. (return #f)))
  791. (guile -> (lowered-gexp-guile lowered))
  792. (builder (text-file script-name
  793. (object->string
  794. (lowered-gexp-sexp lowered)))))
  795. (mbegin %store-monad
  796. (set-grafting graft?) ;restore the initial setting
  797. (raw-derivation name
  798. (string-append (derivation-input-output-path guile)
  799. "/bin/guile")
  800. `("--no-auto-compile"
  801. ,@(append-map (lambda (directory)
  802. `("-L" ,directory))
  803. (lowered-gexp-load-path lowered))
  804. ,@(append-map (lambda (directory)
  805. `("-C" ,directory))
  806. (lowered-gexp-load-compiled-path lowered))
  807. ,builder)
  808. #:outputs outputs
  809. #:env-vars env-vars
  810. #:system system
  811. #:inputs `(,guile
  812. ,@(lowered-gexp-inputs lowered)
  813. ,@(match graphs
  814. (((_ . inputs) ...)
  815. (filter derivation-input? inputs))
  816. (#f '())))
  817. #:sources `(,builder
  818. ,@(if (and (string? modules)
  819. (store-path? modules))
  820. (list modules)
  821. '())
  822. ,@(lowered-gexp-sources lowered)
  823. ,@(match graphs
  824. (((_ . inputs) ...)
  825. (filter string? inputs))
  826. (#f '())))
  827. #:hash hash #:hash-algo hash-algo #:recursive? recursive?
  828. #:references-graphs (and=> graphs graphs-file-names)
  829. #:allowed-references allowed
  830. #:disallowed-references disallowed
  831. #:leaked-env-vars leaked-env-vars
  832. #:local-build? local-build?
  833. #:substitutable? substitutable?
  834. #:properties properties))))
  835. (define* (gexp-inputs exp #:key native?)
  836. "Return the input list for EXP. When NATIVE? is true, return only native
  837. references; otherwise, return only non-native references."
  838. ;; TODO: Return <gexp-input> records instead of tuples.
  839. (define (add-reference-inputs ref result)
  840. (match ref
  841. (($ <gexp-input> (? gexp? exp) _ #t)
  842. (if native?
  843. (append (gexp-inputs exp)
  844. (gexp-inputs exp #:native? #t)
  845. result)
  846. result))
  847. (($ <gexp-input> (? gexp? exp) _ #f)
  848. (append (gexp-inputs exp #:native? native?)
  849. result))
  850. (($ <gexp-input> (? string? str))
  851. (if (direct-store-path? str)
  852. (cons `(,str) result)
  853. result))
  854. (($ <gexp-input> (? struct? thing) output n?)
  855. (if (and (eqv? n? native?) (lookup-compiler thing))
  856. ;; THING is a derivation, or a package, or an origin, etc.
  857. (cons `(,thing ,output) result)
  858. result))
  859. (($ <gexp-input> (lst ...) output n?)
  860. (fold-right add-reference-inputs result
  861. ;; XXX: For now, automatically convert LST to a list of
  862. ;; gexp-inputs. Inherit N?.
  863. (map (match-lambda
  864. ((? gexp-input? x)
  865. (%gexp-input (gexp-input-thing x)
  866. (gexp-input-output x)
  867. n?))
  868. (x
  869. (%gexp-input x "out" n?)))
  870. lst)))
  871. (_
  872. ;; Ignore references to other kinds of objects.
  873. result)))
  874. (fold-right add-reference-inputs
  875. '()
  876. (gexp-references exp)))
  877. (define gexp-native-inputs
  878. (cut gexp-inputs <> #:native? #t))
  879. (define (gexp-outputs exp)
  880. "Return the outputs referred to by EXP as a list of strings."
  881. (define (add-reference-output ref result)
  882. (match ref
  883. (($ <gexp-output> name)
  884. (cons name result))
  885. (($ <gexp-input> (? gexp? exp))
  886. (append (gexp-outputs exp) result))
  887. (($ <gexp-input> (lst ...) output native?)
  888. ;; XXX: Automatically convert LST.
  889. (add-reference-output (map (match-lambda
  890. ((? gexp-input? x) x)
  891. (x (%gexp-input x "out" native?)))
  892. lst)
  893. result))
  894. ((lst ...)
  895. (fold-right add-reference-output result lst))
  896. (_
  897. result)))
  898. (delete-duplicates
  899. (add-reference-output (gexp-references exp) '())))
  900. (define* (gexp->sexp exp #:key
  901. (system (%current-system))
  902. (target (%current-target-system)))
  903. "Return (monadically) the sexp corresponding to EXP for the given OUTPUT,
  904. and in the current monad setting (system type, etc.)"
  905. (define (self-quoting? x)
  906. (letrec-syntax ((one-of (syntax-rules ()
  907. ((_) #f)
  908. ((_ pred rest ...)
  909. (or (pred x)
  910. (one-of rest ...))))))
  911. (one-of symbol? string? keyword? pair? null? array?
  912. number? boolean? char?)))
  913. (define* (reference->sexp ref #:optional native?)
  914. (with-monad %store-monad
  915. (match ref
  916. (($ <gexp-output> output)
  917. ;; Output file names are not known in advance but the daemon defines
  918. ;; an environment variable for each of them at build time, so use
  919. ;; that trick.
  920. (return `((@ (guile) getenv) ,output)))
  921. (($ <gexp-input> (? gexp? exp) output n?)
  922. (gexp->sexp exp
  923. #:system system
  924. #:target (if (or n? native?) #f target)))
  925. (($ <gexp-input> (refs ...) output n?)
  926. (mapm %store-monad
  927. (lambda (ref)
  928. ;; XXX: Automatically convert REF to an gexp-input.
  929. (reference->sexp
  930. (if (gexp-input? ref)
  931. ref
  932. (%gexp-input ref "out" n?))
  933. (or n? native?)))
  934. refs))
  935. (($ <gexp-input> (? struct? thing) output n?)
  936. (let ((target (if (or n? native?) #f target))
  937. (expand (lookup-expander thing)))
  938. (mlet %store-monad ((obj (lower-object thing system
  939. #:target target)))
  940. ;; OBJ must be either a derivation or a store file name.
  941. (return (expand thing obj output)))))
  942. (($ <gexp-input> (? self-quoting? x))
  943. (return x))
  944. (($ <gexp-input> x)
  945. (raise (condition (&gexp-input-error (input x)))))
  946. (x
  947. (return x)))))
  948. (mlet %store-monad
  949. ((args (mapm %store-monad
  950. reference->sexp (gexp-references exp))))
  951. (return (apply (gexp-proc exp) args))))
  952. (define-syntax-rule (define-syntax-parameter-once name proc)
  953. ;; Like 'define-syntax-parameter' but ensure the top-level binding for NAME
  954. ;; does not get redefined. This works around a race condition in a
  955. ;; multi-threaded context with Guile <= 2.2.4: <https://bugs.gnu.org/27476>.
  956. (eval-when (load eval expand compile)
  957. (define name
  958. (if (module-locally-bound? (current-module) 'name)
  959. (module-ref (current-module) 'name)
  960. (make-syntax-transformer 'name 'syntax-parameter
  961. (list proc))))))
  962. (define-syntax-parameter-once current-imported-modules
  963. ;; Current list of imported modules.
  964. (identifier-syntax '()))
  965. (define-syntax-rule (with-imported-modules modules body ...)
  966. "Mark the gexps defined in BODY... as requiring MODULES in their execution
  967. environment."
  968. (syntax-parameterize ((current-imported-modules
  969. (identifier-syntax modules)))
  970. body ...))
  971. (define-syntax-parameter-once current-imported-extensions
  972. ;; Current list of extensions.
  973. (identifier-syntax '()))
  974. (define-syntax-rule (with-extensions extensions body ...)
  975. "Mark the gexps defined in BODY... as requiring EXTENSIONS in their
  976. execution environment."
  977. (syntax-parameterize ((current-imported-extensions
  978. (identifier-syntax extensions)))
  979. body ...))
  980. (define-syntax gexp
  981. (lambda (s)
  982. (define (collect-escapes exp)
  983. ;; Return all the 'ungexp' present in EXP.
  984. (let loop ((exp exp)
  985. (result '()))
  986. (syntax-case exp (ungexp
  987. ungexp-splicing
  988. ungexp-native
  989. ungexp-native-splicing)
  990. ((ungexp _)
  991. (cons exp result))
  992. ((ungexp _ _)
  993. (cons exp result))
  994. ((ungexp-splicing _ ...)
  995. (cons exp result))
  996. ((ungexp-native _ ...)
  997. (cons exp result))
  998. ((ungexp-native-splicing _ ...)
  999. (cons exp result))
  1000. ((exp0 . exp)
  1001. (let ((result (loop #'exp0 result)))
  1002. (loop #'exp result)))
  1003. (_
  1004. result))))
  1005. (define (escape->ref exp)
  1006. ;; Turn 'ungexp' form EXP into a "reference".
  1007. (syntax-case exp (ungexp ungexp-splicing
  1008. ungexp-native ungexp-native-splicing
  1009. output)
  1010. ((ungexp output)
  1011. #'(gexp-output "out"))
  1012. ((ungexp output name)
  1013. #'(gexp-output name))
  1014. ((ungexp thing)
  1015. #'(%gexp-input thing "out" #f))
  1016. ((ungexp drv-or-pkg out)
  1017. #'(%gexp-input drv-or-pkg out #f))
  1018. ((ungexp-splicing lst)
  1019. #'(%gexp-input lst "out" #f))
  1020. ((ungexp-native thing)
  1021. #'(%gexp-input thing "out" #t))
  1022. ((ungexp-native drv-or-pkg out)
  1023. #'(%gexp-input drv-or-pkg out #t))
  1024. ((ungexp-native-splicing lst)
  1025. #'(%gexp-input lst "out" #t))))
  1026. (define (substitute-ungexp exp substs)
  1027. ;; Given EXP, an 'ungexp' or 'ungexp-native' form, substitute it with
  1028. ;; the corresponding form in SUBSTS.
  1029. (match (assoc exp substs)
  1030. ((_ id)
  1031. id)
  1032. (_ ;internal error
  1033. (with-syntax ((exp exp))
  1034. #'(syntax-error "error: no 'ungexp' substitution" exp)))))
  1035. (define (substitute-ungexp-splicing exp substs)
  1036. (syntax-case exp ()
  1037. ((exp rest ...)
  1038. (match (assoc #'exp substs)
  1039. ((_ id)
  1040. (with-syntax ((id id))
  1041. #`(append id
  1042. #,(substitute-references #'(rest ...) substs))))
  1043. (_
  1044. #'(syntax-error "error: no 'ungexp-splicing' substitution"
  1045. exp))))))
  1046. (define (substitute-references exp substs)
  1047. ;; Return a variant of EXP where all the cars of SUBSTS have been
  1048. ;; replaced by the corresponding cdr.
  1049. (syntax-case exp (ungexp ungexp-native
  1050. ungexp-splicing ungexp-native-splicing)
  1051. ((ungexp _ ...)
  1052. (substitute-ungexp exp substs))
  1053. ((ungexp-native _ ...)
  1054. (substitute-ungexp exp substs))
  1055. (((ungexp-splicing _ ...) rest ...)
  1056. (substitute-ungexp-splicing exp substs))
  1057. (((ungexp-native-splicing _ ...) rest ...)
  1058. (substitute-ungexp-splicing exp substs))
  1059. ((exp0 . exp)
  1060. #`(cons #,(substitute-references #'exp0 substs)
  1061. #,(substitute-references #'exp substs)))
  1062. (x #''x)))
  1063. (syntax-case s (ungexp output)
  1064. ((_ exp)
  1065. (let* ((escapes (delete-duplicates (collect-escapes #'exp)))
  1066. (formals (generate-temporaries escapes))
  1067. (sexp (substitute-references #'exp (zip escapes formals)))
  1068. (refs (map escape->ref escapes)))
  1069. #`(make-gexp (list #,@refs)
  1070. current-imported-modules
  1071. current-imported-extensions
  1072. (lambda #,formals
  1073. #,sexp)))))))
  1074. ;;;
  1075. ;;; Module handling.
  1076. ;;;
  1077. (define %not-slash
  1078. (char-set-complement (char-set #\/)))
  1079. (define (file-mapping->tree mapping)
  1080. "Convert MAPPING, an alist like:
  1081. ((\"guix/build/utils.scm\" . \"…/utils.scm\"))
  1082. to a tree suitable for 'interned-file-tree'."
  1083. (let ((mapping (map (match-lambda
  1084. ((destination . source)
  1085. (cons (string-tokenize destination
  1086. %not-slash)
  1087. source)))
  1088. mapping)))
  1089. (fold (lambda (pair result)
  1090. (match pair
  1091. ((destination . source)
  1092. (let loop ((destination destination)
  1093. (result result))
  1094. (match destination
  1095. ((file)
  1096. (let* ((mode (stat:mode (stat source)))
  1097. (type (if (zero? (logand mode #o100))
  1098. 'regular
  1099. 'executable)))
  1100. (alist-cons file
  1101. `(,type (file ,source))
  1102. result)))
  1103. ((file rest ...)
  1104. (let ((directory (assoc-ref result file)))
  1105. (alist-cons file
  1106. `(directory
  1107. ,@(loop rest
  1108. (match directory
  1109. (('directory . entries) entries)
  1110. (#f '()))))
  1111. (if directory
  1112. (alist-delete file result)
  1113. result)))))))))
  1114. '()
  1115. mapping)))
  1116. (define %utils-module
  1117. ;; This file provides 'mkdir-p', needed to implement 'imported-files' and
  1118. ;; other primitives below. Note: We give the file name relative to this
  1119. ;; file you are currently reading; 'search-path' could return a file name
  1120. ;; relative to the current working directory.
  1121. (local-file "build/utils.scm"
  1122. "build-utils.scm"))
  1123. (define* (imported-files/derivation files
  1124. #:key (name "file-import")
  1125. (symlink? #f)
  1126. (system (%current-system))
  1127. (guile (%guile-for-build)))
  1128. "Return a derivation that imports FILES into STORE. FILES must be a list
  1129. of (FINAL-PATH . FILE) pairs. Each FILE is mapped to FINAL-PATH in the
  1130. resulting store path. FILE can be either a file name, or a file-like object,
  1131. as returned by 'local-file' for example. If SYMLINK? is true, create symlinks
  1132. to the source files instead of copying them."
  1133. (define file-pair
  1134. (match-lambda
  1135. ((final-path . (? string? file-name))
  1136. (mlet %store-monad ((file (interned-file file-name
  1137. (basename final-path))))
  1138. (return (list final-path file))))
  1139. ((final-path . file-like)
  1140. (mlet %store-monad ((file (lower-object file-like system)))
  1141. (return (list final-path file))))))
  1142. (mlet %store-monad ((files (mapm %store-monad file-pair files)))
  1143. (define build
  1144. (gexp
  1145. (begin
  1146. (primitive-load (ungexp %utils-module)) ;for 'mkdir-p'
  1147. (use-modules (ice-9 match))
  1148. (mkdir (ungexp output)) (chdir (ungexp output))
  1149. (for-each (match-lambda
  1150. ((final-path store-path)
  1151. (mkdir-p (dirname final-path))
  1152. ((ungexp (if symlink? 'symlink 'copy-file))
  1153. store-path final-path)))
  1154. '(ungexp files)))))
  1155. ;; TODO: Pass FILES as an environment variable so that BUILD remains
  1156. ;; exactly the same regardless of FILES: less disk space, and fewer
  1157. ;; 'add-to-store' RPCs.
  1158. (gexp->derivation name build
  1159. #:system system
  1160. #:guile-for-build guile
  1161. #:local-build? #t
  1162. ;; Avoid deprecation warnings about the use of the _IO*
  1163. ;; constants in (guix build utils).
  1164. #:env-vars
  1165. '(("GUILE_WARN_DEPRECATED" . "no")))))
  1166. (define* (imported-files files
  1167. #:key (name "file-import")
  1168. ;; The following parameters make sense when creating
  1169. ;; an actual derivation.
  1170. (system (%current-system))
  1171. (guile (%guile-for-build)))
  1172. "Import FILES into the store and return the resulting derivation or store
  1173. file name (a derivation is created if and only if some elements of FILES are
  1174. file-like objects and not local file names.) FILES must be a list
  1175. of (FINAL-PATH . FILE) pairs. Each FILE is mapped to FINAL-PATH in the
  1176. resulting store path. FILE can be either a file name, or a file-like object,
  1177. as returned by 'local-file' for example."
  1178. (if (any (match-lambda
  1179. ((_ . (? struct? source)) #t)
  1180. (_ #f))
  1181. files)
  1182. (imported-files/derivation files #:name name
  1183. #:symlink? derivation?
  1184. #:system system #:guile guile)
  1185. (interned-file-tree `(,name directory
  1186. ,@(file-mapping->tree files)))))
  1187. (define* (imported-modules modules
  1188. #:key (name "module-import")
  1189. (system (%current-system))
  1190. (guile (%guile-for-build))
  1191. (module-path %load-path))
  1192. "Return a derivation that contains the source files of MODULES, a list of
  1193. module names such as `(ice-9 q)'. All of MODULES must be either names of
  1194. modules to be found in the MODULE-PATH search path, or a module name followed
  1195. by an arrow followed by a file-like object. For example:
  1196. (imported-modules `((guix build utils)
  1197. (guix gcrypt)
  1198. ((guix config) => ,(scheme-file …))))
  1199. In this example, the first two modules are taken from MODULE-PATH, and the
  1200. last one is created from the given <scheme-file> object."
  1201. (let ((files (map (match-lambda
  1202. (((module ...) '=> file)
  1203. (cons (module->source-file-name module)
  1204. file))
  1205. ((module ...)
  1206. (let ((f (module->source-file-name module)))
  1207. (cons f (search-path* module-path f)))))
  1208. modules)))
  1209. (imported-files files #:name name
  1210. #:system system
  1211. #:guile guile)))
  1212. (define* (compiled-modules modules
  1213. #:key (name "module-import-compiled")
  1214. (system (%current-system))
  1215. target
  1216. (guile (%guile-for-build))
  1217. (module-path %load-path)
  1218. (extensions '())
  1219. (deprecation-warnings #f))
  1220. "Return a derivation that builds a tree containing the `.go' files
  1221. corresponding to MODULES. All the MODULES are built in a context where
  1222. they can refer to each other. When TARGET is true, cross-compile MODULES for
  1223. TARGET, a GNU triplet."
  1224. (define total (length modules))
  1225. (mlet %store-monad ((modules (imported-modules modules
  1226. #:system system
  1227. #:guile guile
  1228. #:module-path
  1229. module-path)))
  1230. (define build
  1231. (gexp
  1232. (begin
  1233. (primitive-load (ungexp %utils-module)) ;for 'mkdir-p'
  1234. (use-modules (ice-9 ftw)
  1235. (ice-9 format)
  1236. (srfi srfi-1)
  1237. (srfi srfi-26)
  1238. (system base compile))
  1239. ;; TODO: Inline this on the next rebuild cycle.
  1240. (ungexp-splicing
  1241. (if target
  1242. (gexp ((use-modules (system base target))))
  1243. (gexp ())))
  1244. (define (regular? file)
  1245. (not (member file '("." ".."))))
  1246. (define (process-entry entry output processed)
  1247. (if (file-is-directory? entry)
  1248. (let ((output (string-append output "/" (basename entry))))
  1249. (mkdir-p output)
  1250. (process-directory entry output processed))
  1251. (let* ((base (basename entry ".scm"))
  1252. (output (string-append output "/" base ".go")))
  1253. (format #t "[~2@a/~2@a] Compiling '~a'...~%"
  1254. (+ 1 processed (ungexp total))
  1255. (ungexp (* total 2))
  1256. entry)
  1257. (ungexp-splicing
  1258. (if target
  1259. (gexp ((with-target (ungexp target)
  1260. (lambda ()
  1261. (compile-file entry
  1262. #:output-file output
  1263. #:opts
  1264. %auto-compilation-options)))))
  1265. (gexp ((compile-file entry
  1266. #:output-file output
  1267. #:opts %auto-compilation-options)))))
  1268. (+ 1 processed))))
  1269. (define (process-directory directory output processed)
  1270. (let ((entries (map (cut string-append directory "/" <>)
  1271. (scandir directory regular?))))
  1272. (fold (cut process-entry <> output <>)
  1273. processed
  1274. entries)))
  1275. (define* (load-from-directory directory
  1276. #:optional (loaded 0))
  1277. "Load all the source files found in DIRECTORY."
  1278. ;; XXX: This works around <https://bugs.gnu.org/15602>.
  1279. (let ((entries (map (cut string-append directory "/" <>)
  1280. (scandir directory regular?))))
  1281. (fold (lambda (file loaded)
  1282. (if (file-is-directory? file)
  1283. (load-from-directory file loaded)
  1284. (begin
  1285. (format #t "[~2@a/~2@a] Loading '~a'...~%"
  1286. (+ 1 loaded) (ungexp (* 2 total))
  1287. file)
  1288. (save-module-excursion
  1289. (lambda ()
  1290. (primitive-load file)))
  1291. (+ 1 loaded))))
  1292. loaded
  1293. entries)))
  1294. (setvbuf (current-output-port)
  1295. (cond-expand (guile-2.2 'line) (else _IOLBF)))
  1296. (define mkdir-p
  1297. ;; Capture 'mkdir-p'.
  1298. (@ (guix build utils) mkdir-p))
  1299. ;; Add EXTENSIONS to the search path.
  1300. (set! %load-path
  1301. (append (map (lambda (extension)
  1302. (string-append extension
  1303. "/share/guile/site/"
  1304. (effective-version)))
  1305. '((ungexp-native-splicing extensions)))
  1306. %load-path))
  1307. (set! %load-compiled-path
  1308. (append (map (lambda (extension)
  1309. (string-append extension "/lib/guile/"
  1310. (effective-version)
  1311. "/site-ccache"))
  1312. '((ungexp-native-splicing extensions)))
  1313. %load-compiled-path))
  1314. (set! %load-path (cons (ungexp modules) %load-path))
  1315. ;; Above we loaded our own (guix build utils) but now we may need to
  1316. ;; load a compile a different one. Thus, force a reload.
  1317. (let ((utils (string-append (ungexp modules)
  1318. "/guix/build/utils.scm")))
  1319. (when (file-exists? utils)
  1320. (load utils)))
  1321. (mkdir (ungexp output))
  1322. (chdir (ungexp modules))
  1323. (load-from-directory ".")
  1324. (process-directory "." (ungexp output) 0))))
  1325. ;; TODO: Pass MODULES as an environment variable.
  1326. (gexp->derivation name build
  1327. #:system system
  1328. #:guile-for-build guile
  1329. #:local-build? #t
  1330. #:env-vars
  1331. (case deprecation-warnings
  1332. ((#f)
  1333. '(("GUILE_WARN_DEPRECATED" . "no")))
  1334. ((detailed)
  1335. '(("GUILE_WARN_DEPRECATED" . "detailed")))
  1336. (else
  1337. '())))))
  1338. ;;;
  1339. ;;; Convenience procedures.
  1340. ;;;
  1341. (define (default-guile)
  1342. ;; Lazily resolve 'guile-2.2' (not 'guile-final' because this is for
  1343. ;; programs returned by 'program-file' and we don't want to keep references
  1344. ;; to several Guile packages). This module must not refer to (gnu …)
  1345. ;; modules directly, to avoid circular dependencies, hence this hack.
  1346. (module-ref (resolve-interface '(gnu packages guile))
  1347. 'guile-2.2))
  1348. (define* (load-path-expression modules #:optional (path %load-path)
  1349. #:key (extensions '()) system target)
  1350. "Return as a monadic value a gexp that sets '%load-path' and
  1351. '%load-compiled-path' to point to MODULES, a list of module names. MODULES
  1352. are searched for in PATH. Return #f when MODULES and EXTENSIONS are empty."
  1353. (if (and (null? modules) (null? extensions))
  1354. (with-monad %store-monad
  1355. (return #f))
  1356. (mlet %store-monad ((modules (imported-modules modules
  1357. #:module-path path
  1358. #:system system))
  1359. (compiled (compiled-modules modules
  1360. #:extensions extensions
  1361. #:module-path path
  1362. #:system system
  1363. #:target target)))
  1364. (return
  1365. (gexp (eval-when (expand load eval)
  1366. ;; Augment the load paths and delete duplicates. Do that
  1367. ;; without loading (srfi srfi-1) or anything.
  1368. (let ((extensions '((ungexp-splicing extensions)))
  1369. (prepend (lambda (items lst)
  1370. ;; This is O(N²) but N is typically small.
  1371. (let loop ((items items)
  1372. (lst lst))
  1373. (if (null? items)
  1374. lst
  1375. (loop (cdr items)
  1376. (cons (car items)
  1377. (delete (car items) lst))))))))
  1378. (set! %load-path
  1379. (prepend (cons (ungexp modules)
  1380. (map (lambda (extension)
  1381. (string-append extension
  1382. "/share/guile/site/"
  1383. (effective-version)))
  1384. extensions))
  1385. %load-path))
  1386. (set! %load-compiled-path
  1387. (prepend (cons (ungexp compiled)
  1388. (map (lambda (extension)
  1389. (string-append extension
  1390. "/lib/guile/"
  1391. (effective-version)
  1392. "/site-ccache"))
  1393. extensions))
  1394. %load-compiled-path)))))))))
  1395. (define* (gexp->script name exp
  1396. #:key (guile (default-guile))
  1397. (module-path %load-path)
  1398. (system (%current-system))
  1399. target)
  1400. "Return an executable script NAME that runs EXP using GUILE, with EXP's
  1401. imported modules in its search path. Look up EXP's modules in MODULE-PATH."
  1402. (mlet %store-monad ((set-load-path
  1403. (load-path-expression (gexp-modules exp)
  1404. module-path
  1405. #:extensions
  1406. (gexp-extensions exp)
  1407. #:system system
  1408. #:target target)))
  1409. (gexp->derivation name
  1410. (gexp
  1411. (call-with-output-file (ungexp output)
  1412. (lambda (port)
  1413. ;; Note: that makes a long shebang. When the store
  1414. ;; is /gnu/store, that fits within the 128-byte
  1415. ;; limit imposed by Linux, but that may go beyond
  1416. ;; when running tests.
  1417. (format port
  1418. "#!~a/bin/guile --no-auto-compile~%!#~%"
  1419. (ungexp guile))
  1420. (ungexp-splicing
  1421. (if set-load-path
  1422. (gexp ((write '(ungexp set-load-path) port)))
  1423. (gexp ())))
  1424. (write '(ungexp exp) port)
  1425. (chmod port #o555))))
  1426. #:system system
  1427. #:target target
  1428. #:module-path module-path)))
  1429. (define* (gexp->file name exp #:key
  1430. (set-load-path? #t)
  1431. (module-path %load-path)
  1432. (splice? #f)
  1433. (system (%current-system))
  1434. target)
  1435. "Return a derivation that builds a file NAME containing EXP. When SPLICE?
  1436. is true, EXP is considered to be a list of expressions that will be spliced in
  1437. the resulting file.
  1438. When SET-LOAD-PATH? is true, emit code in the resulting file to set
  1439. '%load-path' and '%load-compiled-path' to honor EXP's imported modules.
  1440. Lookup EXP's modules in MODULE-PATH."
  1441. (define modules (gexp-modules exp))
  1442. (define extensions (gexp-extensions exp))
  1443. (if (or (not set-load-path?)
  1444. (and (null? modules) (null? extensions)))
  1445. (gexp->derivation name
  1446. (gexp
  1447. (call-with-output-file (ungexp output)
  1448. (lambda (port)
  1449. (for-each (lambda (exp)
  1450. (write exp port))
  1451. '(ungexp (if splice?
  1452. exp
  1453. (gexp ((ungexp exp)))))))))
  1454. #:local-build? #t
  1455. #:substitutable? #f
  1456. #:system system
  1457. #:target target)
  1458. (mlet %store-monad ((set-load-path
  1459. (load-path-expression modules module-path
  1460. #:extensions extensions
  1461. #:system system
  1462. #:target target)))
  1463. (gexp->derivation name
  1464. (gexp
  1465. (call-with-output-file (ungexp output)
  1466. (lambda (port)
  1467. (write '(ungexp set-load-path) port)
  1468. (for-each (lambda (exp)
  1469. (write exp port))
  1470. '(ungexp (if splice?
  1471. exp
  1472. (gexp ((ungexp exp)))))))))
  1473. #:module-path module-path
  1474. #:local-build? #t
  1475. #:substitutable? #f
  1476. #:system system
  1477. #:target target))))
  1478. (define* (text-file* name #:rest text)
  1479. "Return as a monadic value a derivation that builds a text file containing
  1480. all of TEXT. TEXT may list, in addition to strings, objects of any type that
  1481. can be used in a gexp: packages, derivations, local file objects, etc. The
  1482. resulting store file holds references to all these."
  1483. (define builder
  1484. (gexp (call-with-output-file (ungexp output "out")
  1485. (lambda (port)
  1486. (display (string-append (ungexp-splicing text)) port)))))
  1487. (gexp->derivation name builder
  1488. #:local-build? #t
  1489. #:substitutable? #f))
  1490. (define* (mixed-text-file name #:rest text)
  1491. "Return an object representing store file NAME containing TEXT. TEXT is a
  1492. sequence of strings and file-like objects, as in:
  1493. (mixed-text-file \"profile\"
  1494. \"export PATH=\" coreutils \"/bin:\" grep \"/bin\")
  1495. This is the declarative counterpart of 'text-file*'."
  1496. (define build
  1497. (gexp (call-with-output-file (ungexp output "out")
  1498. (lambda (port)
  1499. (display (string-append (ungexp-splicing text)) port)))))
  1500. (computed-file name build))
  1501. (define (file-union name files)
  1502. "Return a <computed-file> that builds a directory containing all of FILES.
  1503. Each item in FILES must be a two-element list where the first element is the
  1504. file name to use in the new directory, and the second element is a gexp
  1505. denoting the target file. Here's an example:
  1506. (file-union \"etc\"
  1507. `((\"hosts\" ,(plain-file \"hosts\"
  1508. \"127.0.0.1 localhost\"))
  1509. (\"bashrc\" ,(plain-file \"bashrc\"
  1510. \"alias ls='ls --color'\"))
  1511. (\"libvirt/qemu.conf\" ,(plain-file \"qemu.conf\" \"\"))))
  1512. This yields an 'etc' directory containing these two files."
  1513. (computed-file name
  1514. (with-imported-modules '((guix build utils))
  1515. (gexp
  1516. (begin
  1517. (use-modules (guix build utils))
  1518. (mkdir (ungexp output))
  1519. (chdir (ungexp output))
  1520. (ungexp-splicing
  1521. (map (match-lambda
  1522. ((target source)
  1523. (gexp
  1524. (begin
  1525. ;; Stat the source to abort early if it does
  1526. ;; not exist.
  1527. (stat (ungexp source))
  1528. (mkdir-p (dirname (ungexp target)))
  1529. (symlink (ungexp source)
  1530. (ungexp target))))))
  1531. files)))))))
  1532. (define* (directory-union name things
  1533. #:key (copy? #f) (quiet? #f)
  1534. (resolve-collision 'warn-about-collision))
  1535. "Return a directory that is the union of THINGS, where THINGS is a list of
  1536. file-like objects denoting directories. For example:
  1537. (directory-union \"guile+emacs\" (list guile emacs))
  1538. yields a directory that is the union of the 'guile' and 'emacs' packages.
  1539. Call RESOLVE-COLLISION when several files collide, passing it the list of
  1540. colliding files. RESOLVE-COLLISION must return the chosen file or #f, in
  1541. which case the colliding entry is skipped altogether.
  1542. When HARD-LINKS? is true, create hard links instead of symlinks. When QUIET?
  1543. is true, the derivation will not print anything."
  1544. (define symlink
  1545. (if copy?
  1546. (gexp (lambda (old new)
  1547. (if (file-is-directory? old)
  1548. (symlink old new)
  1549. (copy-file old new))))
  1550. (gexp symlink)))
  1551. (define log-port
  1552. (if quiet?
  1553. (gexp (%make-void-port "w"))
  1554. (gexp (current-error-port))))
  1555. (match things
  1556. ((one)
  1557. ;; Only one thing; return it.
  1558. one)
  1559. (_
  1560. (computed-file name
  1561. (with-imported-modules '((guix build union))
  1562. (gexp (begin
  1563. (use-modules (guix build union)
  1564. (srfi srfi-1)) ;for 'first' and 'last'
  1565. (union-build (ungexp output)
  1566. '(ungexp things)
  1567. #:log-port (ungexp log-port)
  1568. #:symlink (ungexp symlink)
  1569. #:resolve-collision
  1570. (ungexp resolve-collision)))))))))
  1571. ;;;
  1572. ;;; Syntactic sugar.
  1573. ;;;
  1574. (eval-when (expand load eval)
  1575. (define* (read-ungexp chr port #:optional native?)
  1576. "Read an 'ungexp' or 'ungexp-splicing' form from PORT. When NATIVE? is
  1577. true, use 'ungexp-native' and 'ungexp-native-splicing' instead."
  1578. (define unquote-symbol
  1579. (match (peek-char port)
  1580. (#\@
  1581. (read-char port)
  1582. (if native?
  1583. 'ungexp-native-splicing
  1584. 'ungexp-splicing))
  1585. (_
  1586. (if native?
  1587. 'ungexp-native
  1588. 'ungexp))))
  1589. (match (read port)
  1590. ((? symbol? symbol)
  1591. (let ((str (symbol->string symbol)))
  1592. (match (string-index-right str #\:)
  1593. (#f
  1594. `(,unquote-symbol ,symbol))
  1595. (colon
  1596. (let ((name (string->symbol (substring str 0 colon)))
  1597. (output (substring str (+ colon 1))))
  1598. `(,unquote-symbol ,name ,output))))))
  1599. (x
  1600. `(,unquote-symbol ,x))))
  1601. (define (read-gexp chr port)
  1602. "Read a 'gexp' form from PORT."
  1603. `(gexp ,(read port)))
  1604. ;; Extend the reader
  1605. (read-hash-extend #\~ read-gexp)
  1606. (read-hash-extend #\$ read-ungexp)
  1607. (read-hash-extend #\+ (cut read-ungexp <> <> #t)))
  1608. ;;; gexp.scm ends here