gexp.scm 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
  3. ;;;
  4. ;;; This file is part of GNU Guix.
  5. ;;;
  6. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  7. ;;; under the terms of the GNU General Public License as published by
  8. ;;; the Free Software Foundation; either version 3 of the License, or (at
  9. ;;; your option) any later version.
  10. ;;;
  11. ;;; GNU Guix is distributed in the hope that it will be useful, but
  12. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ;;; GNU General Public License for more details.
  15. ;;;
  16. ;;; You should have received a copy of the GNU General Public License
  17. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  18. (define-module (guix gexp)
  19. #:use-module (guix store)
  20. #:use-module (guix monads)
  21. #:use-module (guix derivations)
  22. #:use-module (guix grafts)
  23. #:use-module (guix utils)
  24. #:use-module (srfi srfi-1)
  25. #:use-module (srfi srfi-9)
  26. #:use-module (srfi srfi-9 gnu)
  27. #:use-module (srfi srfi-26)
  28. #:use-module (srfi srfi-34)
  29. #:use-module (srfi srfi-35)
  30. #:use-module (ice-9 match)
  31. #:export (gexp
  32. gexp?
  33. with-imported-modules
  34. gexp-input
  35. gexp-input?
  36. local-file
  37. local-file?
  38. local-file-file
  39. local-file-absolute-file-name
  40. local-file-name
  41. local-file-recursive?
  42. plain-file
  43. plain-file?
  44. plain-file-name
  45. plain-file-content
  46. computed-file
  47. computed-file?
  48. computed-file-name
  49. computed-file-gexp
  50. computed-file-options
  51. program-file
  52. program-file?
  53. program-file-name
  54. program-file-gexp
  55. program-file-guile
  56. scheme-file
  57. scheme-file?
  58. scheme-file-name
  59. scheme-file-gexp
  60. file-append
  61. file-append?
  62. file-append-base
  63. file-append-suffix
  64. load-path-expression
  65. gexp-modules
  66. gexp->derivation
  67. gexp->file
  68. gexp->script
  69. text-file*
  70. mixed-text-file
  71. file-union
  72. directory-union
  73. imported-files
  74. imported-modules
  75. compiled-modules
  76. define-gexp-compiler
  77. gexp-compiler?
  78. lower-object
  79. lower-inputs
  80. &gexp-error
  81. gexp-error?
  82. &gexp-input-error
  83. gexp-input-error?
  84. gexp-error-invalid-input))
  85. ;;; Commentary:
  86. ;;;
  87. ;;; This module implements "G-expressions", or "gexps". Gexps are like
  88. ;;; S-expressions (sexps), with two differences:
  89. ;;;
  90. ;;; 1. References (un-quotations) to derivations or packages in a gexp are
  91. ;;; replaced by the corresponding output file name; in addition, the
  92. ;;; 'ungexp-native' unquote-like form allows code to explicitly refer to
  93. ;;; the native code of a given package, in case of cross-compilation;
  94. ;;;
  95. ;;; 2. Gexps embed information about the derivations they refer to.
  96. ;;;
  97. ;;; Gexps make it easy to write to files Scheme code that refers to store
  98. ;;; items, or to write Scheme code to build derivations.
  99. ;;;
  100. ;;; Code:
  101. ;; "G expressions".
  102. (define-record-type <gexp>
  103. (make-gexp references modules proc)
  104. gexp?
  105. (references gexp-references) ;list of <gexp-input>
  106. (modules gexp-self-modules) ;list of module names
  107. (proc gexp-proc)) ;procedure
  108. (define (write-gexp gexp port)
  109. "Write GEXP on PORT."
  110. (display "#<gexp " port)
  111. ;; Try to write the underlying sexp. Now, this trick doesn't work when
  112. ;; doing things like (ungexp-splicing (gexp ())) because GEXP's procedure
  113. ;; tries to use 'append' on that, which fails with wrong-type-arg.
  114. (false-if-exception
  115. (write (apply (gexp-proc gexp)
  116. (gexp-references gexp))
  117. port))
  118. (format port " ~a>"
  119. (number->string (object-address gexp) 16)))
  120. (set-record-type-printer! <gexp> write-gexp)
  121. ;;;
  122. ;;; Methods.
  123. ;;;
  124. ;; Compiler for a type of objects that may be introduced in a gexp.
  125. (define-record-type <gexp-compiler>
  126. (gexp-compiler type lower expand)
  127. gexp-compiler?
  128. (type gexp-compiler-type) ;record type descriptor
  129. (lower gexp-compiler-lower)
  130. (expand gexp-compiler-expand)) ;#f | DRV -> sexp
  131. (define-condition-type &gexp-error &error
  132. gexp-error?)
  133. (define-condition-type &gexp-input-error &gexp-error
  134. gexp-input-error?
  135. (input gexp-error-invalid-input))
  136. (define %gexp-compilers
  137. ;; 'eq?' mapping of record type descriptor to <gexp-compiler>.
  138. (make-hash-table 20))
  139. (define (default-expander thing obj output)
  140. "This is the default expander for \"things\" that appear in gexps. It
  141. returns its output file name of OBJ's OUTPUT."
  142. (match obj
  143. ((? derivation? drv)
  144. (derivation->output-path drv output))
  145. ((? string? file)
  146. file)))
  147. (define (register-compiler! compiler)
  148. "Register COMPILER as a gexp compiler."
  149. (hashq-set! %gexp-compilers
  150. (gexp-compiler-type compiler) compiler))
  151. (define (lookup-compiler object)
  152. "Search for a compiler for OBJECT. Upon success, return the three argument
  153. procedure to lower it; otherwise return #f."
  154. (and=> (hashq-ref %gexp-compilers (struct-vtable object))
  155. gexp-compiler-lower))
  156. (define (lookup-expander object)
  157. "Search for an expander for OBJECT. Upon success, return the three argument
  158. procedure to expand it; otherwise return #f."
  159. (and=> (hashq-ref %gexp-compilers (struct-vtable object))
  160. gexp-compiler-expand))
  161. (define* (lower-object obj
  162. #:optional (system (%current-system))
  163. #:key target)
  164. "Return as a value in %STORE-MONAD the derivation or store item
  165. corresponding to OBJ for SYSTEM, cross-compiling for TARGET if TARGET is true.
  166. OBJ must be an object that has an associated gexp compiler, such as a
  167. <package>."
  168. (match (lookup-compiler obj)
  169. (#f
  170. (raise (condition (&gexp-input-error (input obj)))))
  171. (lower
  172. (lower obj system target))))
  173. (define-syntax define-gexp-compiler
  174. (syntax-rules (=> compiler expander)
  175. "Define NAME as a compiler for objects matching PREDICATE encountered in
  176. gexps.
  177. In the simplest form of the macro, BODY must return a derivation for PARAM, an
  178. object that matches PREDICATE, for SYSTEM and TARGET (the latter of which is
  179. #f except when cross-compiling.)
  180. The more elaborate form allows you to specify an expander:
  181. (define-gexp-compiler something something?
  182. compiler => (lambda (param system target) ...)
  183. expander => (lambda (param drv output) ...))
  184. The expander specifies how an object is converted to its sexp representation."
  185. ((_ (name (param record-type) system target) body ...)
  186. (define-gexp-compiler name record-type
  187. compiler => (lambda (param system target) body ...)
  188. expander => default-expander))
  189. ((_ name record-type
  190. compiler => compile
  191. expander => expand)
  192. (begin
  193. (define name
  194. (gexp-compiler record-type compile expand))
  195. (register-compiler! name)))))
  196. (define-gexp-compiler (derivation-compiler (drv <derivation>) system target)
  197. ;; Derivations are the lowest-level representation, so this is the identity
  198. ;; compiler.
  199. (with-monad %store-monad
  200. (return drv)))
  201. ;;;
  202. ;;; File declarations.
  203. ;;;
  204. ;; A local file name. FILE is the file name the user entered, which can be a
  205. ;; relative file name, and ABSOLUTE is a promise that computes its canonical
  206. ;; absolute file name. We keep it in a promise to compute it lazily and avoid
  207. ;; repeated 'stat' calls.
  208. (define-record-type <local-file>
  209. (%%local-file file absolute name recursive? select?)
  210. local-file?
  211. (file local-file-file) ;string
  212. (absolute %local-file-absolute-file-name) ;promise string
  213. (name local-file-name) ;string
  214. (recursive? local-file-recursive?) ;Boolean
  215. (select? local-file-select?)) ;string stat -> Boolean
  216. (define (true file stat) #t)
  217. (define* (%local-file file promise #:optional (name (basename file))
  218. #:key recursive? (select? true))
  219. ;; This intermediate procedure is part of our ABI, but the underlying
  220. ;; %%LOCAL-FILE is not.
  221. (%%local-file file promise name recursive? select?))
  222. (define (absolute-file-name file directory)
  223. "Return the canonical absolute file name for FILE, which lives in the
  224. vicinity of DIRECTORY."
  225. (canonicalize-path
  226. (cond ((string-prefix? "/" file) file)
  227. ((not directory) file)
  228. ((string-prefix? "/" directory)
  229. (string-append directory "/" file))
  230. (else file))))
  231. (define-syntax local-file
  232. (lambda (s)
  233. "Return an object representing local file FILE to add to the store; this
  234. object can be used in a gexp. If FILE is a relative file name, it is looked
  235. up relative to the source file where this form appears. FILE will be added to
  236. the store under NAME--by default the base name of FILE.
  237. When RECURSIVE? is true, the contents of FILE are added recursively; if FILE
  238. designates a flat file and RECURSIVE? is true, its contents are added, and its
  239. permission bits are kept.
  240. When RECURSIVE? is true, call (SELECT? FILE STAT) for each directory entry,
  241. where FILE is the entry's absolute file name and STAT is the result of
  242. 'lstat'; exclude entries for which SELECT? does not return true.
  243. This is the declarative counterpart of the 'interned-file' monadic procedure.
  244. It is implemented as a macro to capture the current source directory where it
  245. appears."
  246. (syntax-case s ()
  247. ((_ file rest ...)
  248. #'(%local-file file
  249. (delay (absolute-file-name file (current-source-directory)))
  250. rest ...))
  251. ((_)
  252. #'(syntax-error "missing file name"))
  253. (id
  254. (identifier? #'id)
  255. ;; XXX: We could return #'(lambda (file . rest) ...). However,
  256. ;; (syntax-source #'id) is #f so (current-source-directory) would not
  257. ;; work. Thus, simply forbid this form.
  258. #'(syntax-error
  259. "'local-file' is a macro and cannot be used like this")))))
  260. (define (local-file-absolute-file-name file)
  261. "Return the absolute file name for FILE, a <local-file> instance. A
  262. 'system-error' exception is raised if FILE could not be found."
  263. (force (%local-file-absolute-file-name file)))
  264. (define-gexp-compiler (local-file-compiler (file <local-file>) system target)
  265. ;; "Compile" FILE by adding it to the store.
  266. (match file
  267. (($ <local-file> file (= force absolute) name recursive? select?)
  268. ;; Canonicalize FILE so that if it's a symlink, it is resolved. Failing
  269. ;; to do that, when RECURSIVE? is #t, we could end up creating a dangling
  270. ;; symlink in the store, and when RECURSIVE? is #f 'add-to-store' would
  271. ;; just throw an error, both of which are inconvenient.
  272. (interned-file absolute name
  273. #:recursive? recursive? #:select? select?))))
  274. (define-record-type <plain-file>
  275. (%plain-file name content references)
  276. plain-file?
  277. (name plain-file-name) ;string
  278. (content plain-file-content) ;string
  279. (references plain-file-references)) ;list (currently unused)
  280. (define (plain-file name content)
  281. "Return an object representing a text file called NAME with the given
  282. CONTENT (a string) to be added to the store.
  283. This is the declarative counterpart of 'text-file'."
  284. ;; XXX: For now just ignore 'references' because it's not clear how to use
  285. ;; them in a declarative context.
  286. (%plain-file name content '()))
  287. (define-gexp-compiler (plain-file-compiler (file <plain-file>) system target)
  288. ;; "Compile" FILE by adding it to the store.
  289. (match file
  290. (($ <plain-file> name content references)
  291. (text-file name content references))))
  292. (define-record-type <computed-file>
  293. (%computed-file name gexp guile options)
  294. computed-file?
  295. (name computed-file-name) ;string
  296. (gexp computed-file-gexp) ;gexp
  297. (guile computed-file-guile) ;<package>
  298. (options computed-file-options)) ;list of arguments
  299. (define* (computed-file name gexp
  300. #:key guile (options '(#:local-build? #t)))
  301. "Return an object representing the store item NAME, a file or directory
  302. computed by GEXP. OPTIONS is a list of additional arguments to pass
  303. to 'gexp->derivation'.
  304. This is the declarative counterpart of 'gexp->derivation'."
  305. (%computed-file name gexp guile options))
  306. (define-gexp-compiler (computed-file-compiler (file <computed-file>)
  307. system target)
  308. ;; Compile FILE by returning a derivation whose build expression is its
  309. ;; gexp.
  310. (match file
  311. (($ <computed-file> name gexp guile options)
  312. (if guile
  313. (mlet %store-monad ((guile (lower-object guile system
  314. #:target target)))
  315. (apply gexp->derivation name gexp #:guile-for-build guile
  316. options))
  317. (apply gexp->derivation name gexp options)))))
  318. (define-record-type <program-file>
  319. (%program-file name gexp guile)
  320. program-file?
  321. (name program-file-name) ;string
  322. (gexp program-file-gexp) ;gexp
  323. (guile program-file-guile)) ;package
  324. (define* (program-file name gexp #:key (guile #f))
  325. "Return an object representing the executable store item NAME that runs
  326. GEXP. GUILE is the Guile package used to execute that script.
  327. This is the declarative counterpart of 'gexp->script'."
  328. (%program-file name gexp guile))
  329. (define-gexp-compiler (program-file-compiler (file <program-file>)
  330. system target)
  331. ;; Compile FILE by returning a derivation that builds the script.
  332. (match file
  333. (($ <program-file> name gexp guile)
  334. (gexp->script name gexp
  335. #:guile (or guile (default-guile))))))
  336. (define-record-type <scheme-file>
  337. (%scheme-file name gexp)
  338. scheme-file?
  339. (name scheme-file-name) ;string
  340. (gexp scheme-file-gexp)) ;gexp
  341. (define* (scheme-file name gexp)
  342. "Return an object representing the Scheme file NAME that contains GEXP.
  343. This is the declarative counterpart of 'gexp->file'."
  344. (%scheme-file name gexp))
  345. (define-gexp-compiler (scheme-file-compiler (file <scheme-file>)
  346. system target)
  347. ;; Compile FILE by returning a derivation that builds the file.
  348. (match file
  349. (($ <scheme-file> name gexp)
  350. (gexp->file name gexp))))
  351. ;; Appending SUFFIX to BASE's output file name.
  352. (define-record-type <file-append>
  353. (%file-append base suffix)
  354. file-append?
  355. (base file-append-base) ;<package> | <derivation> | ...
  356. (suffix file-append-suffix)) ;list of strings
  357. (define (file-append base . suffix)
  358. "Return a <file-append> object that expands to the concatenation of BASE and
  359. SUFFIX."
  360. (%file-append base suffix))
  361. (define-gexp-compiler file-append-compiler <file-append>
  362. compiler => (lambda (obj system target)
  363. (match obj
  364. (($ <file-append> base _)
  365. (lower-object base system #:target target))))
  366. expander => (lambda (obj lowered output)
  367. (match obj
  368. (($ <file-append> base suffix)
  369. (let* ((expand (lookup-expander base))
  370. (base (expand base lowered output)))
  371. (string-append base (string-concatenate suffix)))))))
  372. ;;;
  373. ;;; Inputs & outputs.
  374. ;;;
  375. ;; The input of a gexp.
  376. (define-record-type <gexp-input>
  377. (%gexp-input thing output native?)
  378. gexp-input?
  379. (thing gexp-input-thing) ;<package> | <origin> | <derivation> | ...
  380. (output gexp-input-output) ;string
  381. (native? gexp-input-native?)) ;Boolean
  382. (define (write-gexp-input input port)
  383. (match input
  384. (($ <gexp-input> thing output #f)
  385. (format port "#<gexp-input ~s:~a>" thing output))
  386. (($ <gexp-input> thing output #t)
  387. (format port "#<gexp-input native ~s:~a>" thing output))))
  388. (set-record-type-printer! <gexp-input> write-gexp-input)
  389. (define* (gexp-input thing ;convenience procedure
  390. #:optional (output "out")
  391. #:key native?)
  392. "Return a new <gexp-input> for the OUTPUT of THING; NATIVE? determines
  393. whether this should be considered a \"native\" input or not."
  394. (%gexp-input thing output native?))
  395. ;; Reference to one of the derivation's outputs, for gexps used in
  396. ;; derivations.
  397. (define-record-type <gexp-output>
  398. (gexp-output name)
  399. gexp-output?
  400. (name gexp-output-name))
  401. (define (write-gexp-output output port)
  402. (match output
  403. (($ <gexp-output> name)
  404. (format port "#<gexp-output ~a>" name))))
  405. (set-record-type-printer! <gexp-output> write-gexp-output)
  406. (define (gexp-modules gexp)
  407. "Return the list of Guile module names GEXP relies on. If (gexp? GEXP) is
  408. false, meaning that GEXP is a plain Scheme object, return the empty list."
  409. (if (gexp? gexp)
  410. (delete-duplicates
  411. (append (gexp-self-modules gexp)
  412. (append-map (match-lambda
  413. (($ <gexp-input> (? gexp? exp))
  414. (gexp-modules exp))
  415. (($ <gexp-input> (lst ...))
  416. (append-map (lambda (item)
  417. (if (gexp? item)
  418. (gexp-modules item)
  419. '()))
  420. lst))
  421. (_
  422. '()))
  423. (gexp-references gexp))))
  424. '())) ;plain Scheme data type
  425. (define* (lower-inputs inputs
  426. #:key system target)
  427. "Turn any package from INPUTS into a derivation for SYSTEM; return the
  428. corresponding input list as a monadic value. When TARGET is true, use it as
  429. the cross-compilation target triplet."
  430. (with-monad %store-monad
  431. (sequence %store-monad
  432. (map (match-lambda
  433. (((? struct? thing) sub-drv ...)
  434. (mlet %store-monad ((drv (lower-object
  435. thing system #:target target)))
  436. (return `(,drv ,@sub-drv))))
  437. (input
  438. (return input)))
  439. inputs))))
  440. (define* (lower-reference-graphs graphs #:key system target)
  441. "Given GRAPHS, a list of (FILE-NAME INPUT ...) lists for use as a
  442. #:reference-graphs argument, lower it such that each INPUT is replaced by the
  443. corresponding derivation."
  444. (match graphs
  445. (((file-names . inputs) ...)
  446. (mlet %store-monad ((inputs (lower-inputs inputs
  447. #:system system
  448. #:target target)))
  449. (return (map cons file-names inputs))))))
  450. (define* (lower-references lst #:key system target)
  451. "Based on LST, a list of output names and packages, return a list of output
  452. names and file names suitable for the #:allowed-references argument to
  453. 'derivation'."
  454. (with-monad %store-monad
  455. (define lower
  456. (match-lambda
  457. ((? string? output)
  458. (return output))
  459. (($ <gexp-input> thing output native?)
  460. (mlet %store-monad ((drv (lower-object thing system
  461. #:target (if native?
  462. #f target))))
  463. (return (derivation->output-path drv output))))
  464. (thing
  465. (mlet %store-monad ((drv (lower-object thing system
  466. #:target target)))
  467. (return (derivation->output-path drv))))))
  468. (sequence %store-monad (map lower lst))))
  469. (define default-guile-derivation
  470. ;; Here we break the abstraction by talking to the higher-level layer.
  471. ;; Thus, do the resolution lazily to hide the circular dependency.
  472. (let ((proc (delay
  473. (let ((iface (resolve-interface '(guix packages))))
  474. (module-ref iface 'default-guile-derivation)))))
  475. (lambda (system)
  476. ((force proc) system))))
  477. (define* (gexp->derivation name exp
  478. #:key
  479. system (target 'current)
  480. hash hash-algo recursive?
  481. (env-vars '())
  482. (modules '())
  483. (module-path %load-path)
  484. (guile-for-build (%guile-for-build))
  485. (graft? (%graft?))
  486. references-graphs
  487. allowed-references disallowed-references
  488. leaked-env-vars
  489. local-build? (substitutable? #t)
  490. deprecation-warnings
  491. (script-name (string-append name "-builder")))
  492. "Return a derivation NAME that runs EXP (a gexp) with GUILE-FOR-BUILD (a
  493. derivation) on SYSTEM; EXP is stored in a file called SCRIPT-NAME. When
  494. TARGET is true, it is used as the cross-compilation target triplet for
  495. packages referred to by EXP.
  496. MODULES is deprecated in favor of 'with-imported-modules'. Its meaning is to
  497. make MODULES available in the evaluation context of EXP; MODULES is a list of
  498. names of Guile modules searched in MODULE-PATH to be copied in the store,
  499. compiled, and made available in the load path during the execution of
  500. EXP---e.g., '((guix build utils) (guix build gnu-build-system)).
  501. GRAFT? determines whether packages referred to by EXP should be grafted when
  502. applicable.
  503. When REFERENCES-GRAPHS is true, it must be a list of tuples of one of the
  504. following forms:
  505. (FILE-NAME PACKAGE)
  506. (FILE-NAME PACKAGE OUTPUT)
  507. (FILE-NAME DERIVATION)
  508. (FILE-NAME DERIVATION OUTPUT)
  509. (FILE-NAME STORE-ITEM)
  510. The right-hand-side of each element of REFERENCES-GRAPHS is automatically made
  511. an input of the build process of EXP. In the build environment, each
  512. FILE-NAME contains the reference graph of the corresponding item, in a simple
  513. text format.
  514. ALLOWED-REFERENCES must be either #f or a list of output names and packages.
  515. In the latter case, the list denotes store items that the result is allowed to
  516. refer to. Any reference to another store item will lead to a build error.
  517. Similarly for DISALLOWED-REFERENCES, which can list items that must not be
  518. referenced by the outputs.
  519. DEPRECATION-WARNINGS determines whether to show deprecation warnings while
  520. compiling modules. It can be #f, #t, or 'detailed.
  521. The other arguments are as for 'derivation'."
  522. (define %modules
  523. (delete-duplicates
  524. (append modules (gexp-modules exp))))
  525. (define outputs (gexp-outputs exp))
  526. (define (graphs-file-names graphs)
  527. ;; Return a list of (FILE-NAME . STORE-PATH) pairs made from GRAPHS.
  528. (map (match-lambda
  529. ;; TODO: Remove 'derivation?' special cases.
  530. ((file-name (? derivation? drv))
  531. (cons file-name (derivation->output-path drv)))
  532. ((file-name (? derivation? drv) sub-drv)
  533. (cons file-name (derivation->output-path drv sub-drv)))
  534. ((file-name thing)
  535. (cons file-name thing)))
  536. graphs))
  537. (mlet* %store-monad (;; The following binding forces '%current-system' and
  538. ;; '%current-target-system' to be looked up at >>=
  539. ;; time.
  540. (graft? (set-grafting graft?))
  541. (system -> (or system (%current-system)))
  542. (target -> (if (eq? target 'current)
  543. (%current-target-system)
  544. target))
  545. (normals (lower-inputs (gexp-inputs exp)
  546. #:system system
  547. #:target target))
  548. (natives (lower-inputs (gexp-native-inputs exp)
  549. #:system system
  550. #:target #f))
  551. (inputs -> (append normals natives))
  552. (sexp (gexp->sexp exp
  553. #:system system
  554. #:target target))
  555. (builder (text-file script-name
  556. (object->string sexp)))
  557. (modules (if (pair? %modules)
  558. (imported-modules %modules
  559. #:system system
  560. #:module-path module-path
  561. #:guile guile-for-build)
  562. (return #f)))
  563. (compiled (if (pair? %modules)
  564. (compiled-modules %modules
  565. #:system system
  566. #:module-path module-path
  567. #:guile guile-for-build
  568. #:deprecation-warnings
  569. deprecation-warnings)
  570. (return #f)))
  571. (graphs (if references-graphs
  572. (lower-reference-graphs references-graphs
  573. #:system system
  574. #:target target)
  575. (return #f)))
  576. (allowed (if allowed-references
  577. (lower-references allowed-references
  578. #:system system
  579. #:target target)
  580. (return #f)))
  581. (disallowed (if disallowed-references
  582. (lower-references disallowed-references
  583. #:system system
  584. #:target target)
  585. (return #f)))
  586. (guile (if guile-for-build
  587. (return guile-for-build)
  588. (default-guile-derivation system))))
  589. (mbegin %store-monad
  590. (set-grafting graft?) ;restore the initial setting
  591. (raw-derivation name
  592. (string-append (derivation->output-path guile)
  593. "/bin/guile")
  594. `("--no-auto-compile"
  595. ,@(if (pair? %modules)
  596. `("-L" ,(derivation->output-path modules)
  597. "-C" ,(derivation->output-path compiled))
  598. '())
  599. ,builder)
  600. #:outputs outputs
  601. #:env-vars env-vars
  602. #:system system
  603. #:inputs `((,guile)
  604. (,builder)
  605. ,@(if modules
  606. `((,modules) (,compiled) ,@inputs)
  607. inputs)
  608. ,@(match graphs
  609. (((_ . inputs) ...) inputs)
  610. (_ '())))
  611. #:hash hash #:hash-algo hash-algo #:recursive? recursive?
  612. #:references-graphs (and=> graphs graphs-file-names)
  613. #:allowed-references allowed
  614. #:disallowed-references disallowed
  615. #:leaked-env-vars leaked-env-vars
  616. #:local-build? local-build?
  617. #:substitutable? substitutable?))))
  618. (define* (gexp-inputs exp #:key native?)
  619. "Return the input list for EXP. When NATIVE? is true, return only native
  620. references; otherwise, return only non-native references."
  621. (define (add-reference-inputs ref result)
  622. (match ref
  623. (($ <gexp-input> (? gexp? exp) _ #t)
  624. (if native?
  625. (append (gexp-inputs exp)
  626. (gexp-inputs exp #:native? #t)
  627. result)
  628. result))
  629. (($ <gexp-input> (? gexp? exp) _ #f)
  630. (append (gexp-inputs exp #:native? native?)
  631. result))
  632. (($ <gexp-input> (? string? str))
  633. (if (direct-store-path? str)
  634. (cons `(,str) result)
  635. result))
  636. (($ <gexp-input> (? struct? thing) output n?)
  637. (if (and (eqv? n? native?) (lookup-compiler thing))
  638. ;; THING is a derivation, or a package, or an origin, etc.
  639. (cons `(,thing ,output) result)
  640. result))
  641. (($ <gexp-input> (lst ...) output n?)
  642. (fold-right add-reference-inputs result
  643. ;; XXX: For now, automatically convert LST to a list of
  644. ;; gexp-inputs. Inherit N?.
  645. (map (match-lambda
  646. ((? gexp-input? x)
  647. (%gexp-input (gexp-input-thing x)
  648. (gexp-input-output x)
  649. n?))
  650. (x
  651. (%gexp-input x "out" n?)))
  652. lst)))
  653. (_
  654. ;; Ignore references to other kinds of objects.
  655. result)))
  656. (fold-right add-reference-inputs
  657. '()
  658. (gexp-references exp)))
  659. (define gexp-native-inputs
  660. (cut gexp-inputs <> #:native? #t))
  661. (define (gexp-outputs exp)
  662. "Return the outputs referred to by EXP as a list of strings."
  663. (define (add-reference-output ref result)
  664. (match ref
  665. (($ <gexp-output> name)
  666. (cons name result))
  667. (($ <gexp-input> (? gexp? exp))
  668. (append (gexp-outputs exp) result))
  669. (($ <gexp-input> (lst ...) output native?)
  670. ;; XXX: Automatically convert LST.
  671. (add-reference-output (map (match-lambda
  672. ((? gexp-input? x) x)
  673. (x (%gexp-input x "out" native?)))
  674. lst)
  675. result))
  676. ((lst ...)
  677. (fold-right add-reference-output result lst))
  678. (_
  679. result)))
  680. (delete-duplicates
  681. (add-reference-output (gexp-references exp) '())))
  682. (define* (gexp->sexp exp #:key
  683. (system (%current-system))
  684. (target (%current-target-system)))
  685. "Return (monadically) the sexp corresponding to EXP for the given OUTPUT,
  686. and in the current monad setting (system type, etc.)"
  687. (define* (reference->sexp ref #:optional native?)
  688. (with-monad %store-monad
  689. (match ref
  690. (($ <gexp-output> output)
  691. ;; Output file names are not known in advance but the daemon defines
  692. ;; an environment variable for each of them at build time, so use
  693. ;; that trick.
  694. (return `((@ (guile) getenv) ,output)))
  695. (($ <gexp-input> (? gexp? exp) output n?)
  696. (gexp->sexp exp
  697. #:system system
  698. #:target (if (or n? native?) #f target)))
  699. (($ <gexp-input> (refs ...) output n?)
  700. (sequence %store-monad
  701. (map (lambda (ref)
  702. ;; XXX: Automatically convert REF to an gexp-input.
  703. (reference->sexp
  704. (if (gexp-input? ref)
  705. ref
  706. (%gexp-input ref "out" n?))
  707. (or n? native?)))
  708. refs)))
  709. (($ <gexp-input> (? struct? thing) output n?)
  710. (let ((target (if (or n? native?) #f target))
  711. (expand (lookup-expander thing)))
  712. (mlet %store-monad ((obj (lower-object thing system
  713. #:target target)))
  714. ;; OBJ must be either a derivation or a store file name.
  715. (return (expand thing obj output)))))
  716. (($ <gexp-input> x)
  717. (return x))
  718. (x
  719. (return x)))))
  720. (mlet %store-monad
  721. ((args (sequence %store-monad
  722. (map reference->sexp (gexp-references exp)))))
  723. (return (apply (gexp-proc exp) args))))
  724. (define (syntax-location-string s)
  725. "Return a string representing the source code location of S."
  726. (let ((props (syntax-source s)))
  727. (if props
  728. (let ((file (assoc-ref props 'filename))
  729. (line (and=> (assoc-ref props 'line) 1+))
  730. (column (assoc-ref props 'column)))
  731. (if file
  732. (simple-format #f "~a:~a:~a"
  733. file line column)
  734. (simple-format #f "~a:~a" line column)))
  735. "<unknown location>")))
  736. (define-syntax-parameter current-imported-modules
  737. ;; Current list of imported modules.
  738. (identifier-syntax '()))
  739. (define-syntax-rule (with-imported-modules modules body ...)
  740. "Mark the gexps defined in BODY... as requiring MODULES in their execution
  741. environment."
  742. (syntax-parameterize ((current-imported-modules
  743. (identifier-syntax modules)))
  744. body ...))
  745. (define-syntax gexp
  746. (lambda (s)
  747. (define (collect-escapes exp)
  748. ;; Return all the 'ungexp' present in EXP.
  749. (let loop ((exp exp)
  750. (result '()))
  751. (syntax-case exp (ungexp
  752. ungexp-splicing
  753. ungexp-native
  754. ungexp-native-splicing)
  755. ((ungexp _)
  756. (cons exp result))
  757. ((ungexp _ _)
  758. (cons exp result))
  759. ((ungexp-splicing _ ...)
  760. (cons exp result))
  761. ((ungexp-native _ ...)
  762. (cons exp result))
  763. ((ungexp-native-splicing _ ...)
  764. (cons exp result))
  765. ((exp0 . exp)
  766. (let ((result (loop #'exp0 result)))
  767. (loop #'exp result)))
  768. (_
  769. result))))
  770. (define (escape->ref exp)
  771. ;; Turn 'ungexp' form EXP into a "reference".
  772. (syntax-case exp (ungexp ungexp-splicing
  773. ungexp-native ungexp-native-splicing
  774. output)
  775. ((ungexp output)
  776. #'(gexp-output "out"))
  777. ((ungexp output name)
  778. #'(gexp-output name))
  779. ((ungexp thing)
  780. #'(%gexp-input thing "out" #f))
  781. ((ungexp drv-or-pkg out)
  782. #'(%gexp-input drv-or-pkg out #f))
  783. ((ungexp-splicing lst)
  784. #'(%gexp-input lst "out" #f))
  785. ((ungexp-native thing)
  786. #'(%gexp-input thing "out" #t))
  787. ((ungexp-native drv-or-pkg out)
  788. #'(%gexp-input drv-or-pkg out #t))
  789. ((ungexp-native-splicing lst)
  790. #'(%gexp-input lst "out" #t))))
  791. (define (substitute-ungexp exp substs)
  792. ;; Given EXP, an 'ungexp' or 'ungexp-native' form, substitute it with
  793. ;; the corresponding form in SUBSTS.
  794. (match (assoc exp substs)
  795. ((_ id)
  796. id)
  797. (_ ;internal error
  798. (with-syntax ((exp exp))
  799. #'(syntax-error "error: no 'ungexp' substitution" exp)))))
  800. (define (substitute-ungexp-splicing exp substs)
  801. (syntax-case exp ()
  802. ((exp rest ...)
  803. (match (assoc #'exp substs)
  804. ((_ id)
  805. (with-syntax ((id id))
  806. #`(append id
  807. #,(substitute-references #'(rest ...) substs))))
  808. (_
  809. #'(syntax-error "error: no 'ungexp-splicing' substitution"
  810. exp))))))
  811. (define (substitute-references exp substs)
  812. ;; Return a variant of EXP where all the cars of SUBSTS have been
  813. ;; replaced by the corresponding cdr.
  814. (syntax-case exp (ungexp ungexp-native
  815. ungexp-splicing ungexp-native-splicing)
  816. ((ungexp _ ...)
  817. (substitute-ungexp exp substs))
  818. ((ungexp-native _ ...)
  819. (substitute-ungexp exp substs))
  820. (((ungexp-splicing _ ...) rest ...)
  821. (substitute-ungexp-splicing exp substs))
  822. (((ungexp-native-splicing _ ...) rest ...)
  823. (substitute-ungexp-splicing exp substs))
  824. ((exp0 . exp)
  825. #`(cons #,(substitute-references #'exp0 substs)
  826. #,(substitute-references #'exp substs)))
  827. (x #''x)))
  828. (syntax-case s (ungexp output)
  829. ((_ exp)
  830. (let* ((escapes (delete-duplicates (collect-escapes #'exp)))
  831. (formals (generate-temporaries escapes))
  832. (sexp (substitute-references #'exp (zip escapes formals)))
  833. (refs (map escape->ref escapes)))
  834. #`(make-gexp (list #,@refs)
  835. current-imported-modules
  836. (lambda #,formals
  837. #,sexp)))))))
  838. ;;;
  839. ;;; Module handling.
  840. ;;;
  841. (define %utils-module
  842. ;; This file provides 'mkdir-p', needed to implement 'imported-files' and
  843. ;; other primitives below. Note: We give the file name relative to this
  844. ;; file you are currently reading; 'search-path' could return a file name
  845. ;; relative to the current working directory.
  846. (local-file "build/utils.scm"
  847. "build-utils.scm"))
  848. (define* (imported-files files
  849. #:key (name "file-import")
  850. (system (%current-system))
  851. (guile (%guile-for-build)))
  852. "Return a derivation that imports FILES into STORE. FILES must be a list
  853. of (FINAL-PATH . FILE) pairs. Each FILE is mapped to FINAL-PATH in the
  854. resulting store path. FILE can be either a file name, or a file-like object,
  855. as returned by 'local-file' for example."
  856. (define file-pair
  857. (match-lambda
  858. ((final-path . (? string? file-name))
  859. (mlet %store-monad ((file (interned-file file-name
  860. (basename final-path))))
  861. (return (list final-path file))))
  862. ((final-path . file-like)
  863. (mlet %store-monad ((file (lower-object file-like system)))
  864. (return (list final-path file))))))
  865. (mlet %store-monad ((files (sequence %store-monad
  866. (map file-pair files))))
  867. (define build
  868. (gexp
  869. (begin
  870. (primitive-load (ungexp %utils-module)) ;for 'mkdir-p'
  871. (use-modules (ice-9 match))
  872. (mkdir (ungexp output)) (chdir (ungexp output))
  873. (for-each (match-lambda
  874. ((final-path store-path)
  875. (mkdir-p (dirname final-path))
  876. (symlink store-path final-path)))
  877. '(ungexp files)))))
  878. ;; TODO: Pass FILES as an environment variable so that BUILD remains
  879. ;; exactly the same regardless of FILES: less disk space, and fewer
  880. ;; 'add-to-store' RPCs.
  881. (gexp->derivation name build
  882. #:system system
  883. #:guile-for-build guile
  884. #:local-build? #t)))
  885. (define* (imported-modules modules
  886. #:key (name "module-import")
  887. (system (%current-system))
  888. (guile (%guile-for-build))
  889. (module-path %load-path))
  890. "Return a derivation that contains the source files of MODULES, a list of
  891. module names such as `(ice-9 q)'. All of MODULES must be either names of
  892. modules to be found in the MODULE-PATH search path, or a module name followed
  893. by an arrow followed by a file-like object. For example:
  894. (imported-modules `((guix build utils)
  895. (guix gcrypt)
  896. ((guix config) => ,(scheme-file …))))
  897. In this example, the first two modules are taken from MODULE-PATH, and the
  898. last one is created from the given <scheme-file> object."
  899. (mlet %store-monad ((files
  900. (mapm %store-monad
  901. (match-lambda
  902. (((module ...) '=> file)
  903. (return
  904. (cons (module->source-file-name module)
  905. file)))
  906. ((module ...)
  907. (let ((f (module->source-file-name module)))
  908. (return
  909. (cons f (search-path* module-path f))))))
  910. modules)))
  911. (imported-files files #:name name #:system system
  912. #:guile guile)))
  913. (define* (compiled-modules modules
  914. #:key (name "module-import-compiled")
  915. (system (%current-system))
  916. (guile (%guile-for-build))
  917. (module-path %load-path)
  918. (deprecation-warnings #f))
  919. "Return a derivation that builds a tree containing the `.go' files
  920. corresponding to MODULES. All the MODULES are built in a context where
  921. they can refer to each other."
  922. (mlet %store-monad ((modules (imported-modules modules
  923. #:system system
  924. #:guile guile
  925. #:module-path
  926. module-path)))
  927. (define build
  928. (gexp
  929. (begin
  930. (primitive-load (ungexp %utils-module)) ;for 'mkdir-p'
  931. (use-modules (ice-9 ftw)
  932. (srfi srfi-26)
  933. (system base compile))
  934. (define (regular? file)
  935. (not (member file '("." ".."))))
  936. (define (process-directory directory output)
  937. (let ((entries (map (cut string-append directory "/" <>)
  938. (scandir directory regular?))))
  939. (for-each (lambda (entry)
  940. (if (file-is-directory? entry)
  941. (let ((output (string-append output "/"
  942. (basename entry))))
  943. (mkdir-p output)
  944. (process-directory entry output))
  945. (let* ((base (string-drop-right
  946. (basename entry)
  947. 4)) ;.scm
  948. (output (string-append output "/" base
  949. ".go")))
  950. (compile-file entry
  951. #:output-file output
  952. #:opts
  953. %auto-compilation-options))))
  954. entries)))
  955. (set! %load-path (cons (ungexp modules) %load-path))
  956. (mkdir (ungexp output))
  957. (chdir (ungexp modules))
  958. (process-directory "." (ungexp output)))))
  959. ;; TODO: Pass MODULES as an environment variable.
  960. (gexp->derivation name build
  961. #:system system
  962. #:guile-for-build guile
  963. #:local-build? #t
  964. #:env-vars
  965. (case deprecation-warnings
  966. ((#f)
  967. '(("GUILE_WARN_DEPRECATED" . "no")))
  968. ((detailed)
  969. '(("GUILE_WARN_DEPRECATED" . "detailed")))
  970. (else
  971. '())))))
  972. ;;;
  973. ;;; Convenience procedures.
  974. ;;;
  975. (define (default-guile)
  976. ;; Lazily resolve 'guile-2.2' (not 'guile-final' because this is for
  977. ;; programs returned by 'program-file' and we don't want to keep references
  978. ;; to several Guile packages). This module must not refer to (gnu …)
  979. ;; modules directly, to avoid circular dependencies, hence this hack.
  980. (module-ref (resolve-interface '(gnu packages guile))
  981. 'guile-2.2))
  982. (define (load-path-expression modules)
  983. "Return as a monadic value a gexp that sets '%load-path' and
  984. '%load-compiled-path' to point to MODULES, a list of module names."
  985. (mlet %store-monad ((modules (imported-modules modules))
  986. (compiled (compiled-modules modules)))
  987. (return (gexp (eval-when (expand load eval)
  988. (set! %load-path
  989. (cons (ungexp modules) %load-path))
  990. (set! %load-compiled-path
  991. (cons (ungexp compiled)
  992. %load-compiled-path)))))))
  993. (define* (gexp->script name exp
  994. #:key (guile (default-guile)))
  995. "Return an executable script NAME that runs EXP using GUILE, with EXP's
  996. imported modules in its search path."
  997. (mlet %store-monad ((set-load-path
  998. (load-path-expression (gexp-modules exp))))
  999. (gexp->derivation name
  1000. (gexp
  1001. (call-with-output-file (ungexp output)
  1002. (lambda (port)
  1003. ;; Note: that makes a long shebang. When the store
  1004. ;; is /gnu/store, that fits within the 128-byte
  1005. ;; limit imposed by Linux, but that may go beyond
  1006. ;; when running tests.
  1007. (format port
  1008. "#!~a/bin/guile --no-auto-compile~%!#~%"
  1009. (ungexp guile))
  1010. (write '(ungexp set-load-path) port)
  1011. (write '(ungexp exp) port)
  1012. (chmod port #o555)))))))
  1013. (define* (gexp->file name exp #:key (set-load-path? #t))
  1014. "Return a derivation that builds a file NAME containing EXP. When
  1015. SET-LOAD-PATH? is true, emit code in the resulting file to set '%load-path'
  1016. and '%load-compiled-path' to honor EXP's imported modules."
  1017. (match (if set-load-path? (gexp-modules exp) '())
  1018. (() ;zero modules
  1019. (gexp->derivation name
  1020. (gexp
  1021. (call-with-output-file (ungexp output)
  1022. (lambda (port)
  1023. (write '(ungexp exp) port))))
  1024. #:local-build? #t
  1025. #:substitutable? #f))
  1026. ((modules ...)
  1027. (mlet %store-monad ((set-load-path (load-path-expression modules)))
  1028. (gexp->derivation name
  1029. (gexp
  1030. (call-with-output-file (ungexp output)
  1031. (lambda (port)
  1032. (write '(ungexp set-load-path) port)
  1033. (write '(ungexp exp) port))))
  1034. #:local-build? #t
  1035. #:substitutable? #f)))))
  1036. (define* (text-file* name #:rest text)
  1037. "Return as a monadic value a derivation that builds a text file containing
  1038. all of TEXT. TEXT may list, in addition to strings, objects of any type that
  1039. can be used in a gexp: packages, derivations, local file objects, etc. The
  1040. resulting store file holds references to all these."
  1041. (define builder
  1042. (gexp (call-with-output-file (ungexp output "out")
  1043. (lambda (port)
  1044. (display (string-append (ungexp-splicing text)) port)))))
  1045. (gexp->derivation name builder
  1046. #:local-build? #t
  1047. #:substitutable? #f))
  1048. (define* (mixed-text-file name #:rest text)
  1049. "Return an object representing store file NAME containing TEXT. TEXT is a
  1050. sequence of strings and file-like objects, as in:
  1051. (mixed-text-file \"profile\"
  1052. \"export PATH=\" coreutils \"/bin:\" grep \"/bin\")
  1053. This is the declarative counterpart of 'text-file*'."
  1054. (define build
  1055. (gexp (call-with-output-file (ungexp output "out")
  1056. (lambda (port)
  1057. (display (string-append (ungexp-splicing text)) port)))))
  1058. (computed-file name build))
  1059. (define (file-union name files)
  1060. "Return a <computed-file> that builds a directory containing all of FILES.
  1061. Each item in FILES must be a two-element list where the first element is the
  1062. file name to use in the new directory, and the second element is a gexp
  1063. denoting the target file. Here's an example:
  1064. (file-union \"etc\"
  1065. `((\"hosts\" ,(plain-file \"hosts\"
  1066. \"127.0.0.1 localhost\"))
  1067. (\"bashrc\" ,(plain-file \"bashrc\"
  1068. \"alias ls='ls --color'\"))))
  1069. This yields an 'etc' directory containing these two files."
  1070. (computed-file name
  1071. (gexp
  1072. (begin
  1073. (mkdir (ungexp output))
  1074. (chdir (ungexp output))
  1075. (ungexp-splicing
  1076. (map (match-lambda
  1077. ((target source)
  1078. (gexp
  1079. (begin
  1080. ;; Stat the source to abort early if it does
  1081. ;; not exist.
  1082. (stat (ungexp source))
  1083. (symlink (ungexp source)
  1084. (ungexp target))))))
  1085. files))))))
  1086. (define* (directory-union name things
  1087. #:key (copy? #f) (quiet? #f))
  1088. "Return a directory that is the union of THINGS, where THINGS is a list of
  1089. file-like objects denoting directories. For example:
  1090. (directory-union \"guile+emacs\" (list guile emacs))
  1091. yields a directory that is the union of the 'guile' and 'emacs' packages.
  1092. When HARD-LINKS? is true, create hard links instead of symlinks. When QUIET?
  1093. is true, the derivation will not print anything."
  1094. (define symlink
  1095. (if copy?
  1096. (gexp (lambda (old new)
  1097. (if (file-is-directory? old)
  1098. (symlink old new)
  1099. (copy-file old new))))
  1100. (gexp symlink)))
  1101. (define log-port
  1102. (if quiet?
  1103. (gexp (%make-void-port "w"))
  1104. (gexp (current-error-port))))
  1105. (match things
  1106. ((one)
  1107. ;; Only one thing; return it.
  1108. one)
  1109. (_
  1110. (computed-file name
  1111. (with-imported-modules '((guix build union))
  1112. (gexp (begin
  1113. (use-modules (guix build union))
  1114. (union-build (ungexp output)
  1115. '(ungexp things)
  1116. #:log-port (ungexp log-port)
  1117. #:symlink (ungexp symlink)))))))))
  1118. ;;;
  1119. ;;; Syntactic sugar.
  1120. ;;;
  1121. (eval-when (expand load eval)
  1122. (define* (read-ungexp chr port #:optional native?)
  1123. "Read an 'ungexp' or 'ungexp-splicing' form from PORT. When NATIVE? is
  1124. true, use 'ungexp-native' and 'ungexp-native-splicing' instead."
  1125. (define unquote-symbol
  1126. (match (peek-char port)
  1127. (#\@
  1128. (read-char port)
  1129. (if native?
  1130. 'ungexp-native-splicing
  1131. 'ungexp-splicing))
  1132. (_
  1133. (if native?
  1134. 'ungexp-native
  1135. 'ungexp))))
  1136. (match (read port)
  1137. ((? symbol? symbol)
  1138. (let ((str (symbol->string symbol)))
  1139. (match (string-index-right str #\:)
  1140. (#f
  1141. `(,unquote-symbol ,symbol))
  1142. (colon
  1143. (let ((name (string->symbol (substring str 0 colon)))
  1144. (output (substring str (+ colon 1))))
  1145. `(,unquote-symbol ,name ,output))))))
  1146. (x
  1147. `(,unquote-symbol ,x))))
  1148. (define (read-gexp chr port)
  1149. "Read a 'gexp' form from PORT."
  1150. `(gexp ,(read port)))
  1151. ;; Extend the reader
  1152. (read-hash-extend #\~ read-gexp)
  1153. (read-hash-extend #\$ read-ungexp)
  1154. (read-hash-extend #\+ (cut read-ungexp <> <> #t)))
  1155. ;;; gexp.scm ends here