derivations.scm 59 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2012-2021, 2023 Ludovic Courtès <ludo@gnu.org>
  3. ;;; Copyright © 2016, 2017 Mathieu Lirzin <mthl@gnu.org>
  4. ;;;
  5. ;;; This file is part of GNU Guix.
  6. ;;;
  7. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  8. ;;; under the terms of the GNU General Public License as published by
  9. ;;; the Free Software Foundation; either version 3 of the License, or (at
  10. ;;; your option) any later version.
  11. ;;;
  12. ;;; GNU Guix is distributed in the hope that it will be useful, but
  13. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. ;;; GNU General Public License for more details.
  16. ;;;
  17. ;;; You should have received a copy of the GNU General Public License
  18. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  19. (define-module (guix derivations)
  20. #:use-module (srfi srfi-1)
  21. #:use-module (srfi srfi-9)
  22. #:use-module (srfi srfi-9 gnu)
  23. #:use-module (srfi srfi-11)
  24. #:use-module (srfi srfi-26)
  25. #:use-module (srfi srfi-34)
  26. #:use-module (srfi srfi-35)
  27. #:use-module (ice-9 binary-ports)
  28. #:use-module ((ice-9 textual-ports) #:select (put-char put-string))
  29. #:use-module (rnrs bytevectors)
  30. #:use-module (ice-9 match)
  31. #:use-module (ice-9 rdelim)
  32. #:use-module (ice-9 vlist)
  33. #:use-module (guix store)
  34. #:use-module (guix utils)
  35. #:use-module (guix base16)
  36. #:use-module (guix memoization)
  37. #:use-module (guix combinators)
  38. #:use-module (guix deprecation)
  39. #:use-module (guix diagnostics)
  40. #:use-module (guix i18n)
  41. #:use-module (guix monads)
  42. #:use-module (gcrypt hash)
  43. #:use-module (guix sets)
  44. #:export (<derivation>
  45. derivation?
  46. derivation-outputs
  47. derivation-inputs
  48. derivation-sources
  49. derivation-system
  50. derivation-builder
  51. derivation-builder-arguments
  52. derivation-builder-environment-vars
  53. derivation-file-name
  54. derivation-prerequisites
  55. derivation-build-plan
  56. derivation-prerequisites-to-build ;deprecated
  57. <derivation-output>
  58. derivation-output?
  59. derivation-output-path
  60. derivation-output-hash-algo
  61. derivation-output-hash
  62. derivation-output-recursive?
  63. <derivation-input>
  64. derivation-input?
  65. derivation-input
  66. derivation-input-path
  67. derivation-input-derivation
  68. derivation-input-sub-derivations
  69. derivation-input-output-paths
  70. derivation-input-output-path
  71. valid-derivation-input?
  72. &derivation-error
  73. derivation-error?
  74. derivation-error-derivation
  75. &derivation-missing-output-error
  76. derivation-missing-output-error?
  77. derivation-missing-output
  78. derivation-name
  79. derivation-output-names
  80. fixed-output-derivation?
  81. offloadable-derivation?
  82. substitutable-derivation?
  83. derivation-input-fold
  84. substitution-oracle
  85. derivation-hash
  86. derivation-properties
  87. read-derivation
  88. read-derivation-from-file
  89. write-derivation
  90. derivation->output-path
  91. derivation->output-paths
  92. derivation-path->output-path
  93. derivation-path->output-paths
  94. derivation
  95. raw-derivation
  96. invalidate-derivation-caches!
  97. map-derivation
  98. build-derivations
  99. built-derivations
  100. file-search-error?
  101. file-search-error-file-name
  102. file-search-error-search-path
  103. search-path*
  104. module->source-file-name
  105. build-expression->derivation)
  106. ;; Re-export it from here for backward compatibility.
  107. #:re-export (%guile-for-build))
  108. ;;;
  109. ;;; Error conditions.
  110. ;;;
  111. (define-condition-type &derivation-error &store-error
  112. derivation-error?
  113. (derivation derivation-error-derivation))
  114. (define-condition-type &derivation-missing-output-error &derivation-error
  115. derivation-missing-output-error?
  116. (output derivation-missing-output))
  117. ;;;
  118. ;;; Nix derivations, as implemented in Nix's `derivations.cc'.
  119. ;;;
  120. (define-immutable-record-type <derivation>
  121. (make-derivation outputs inputs sources system builder args env-vars
  122. file-name)
  123. derivation?
  124. (outputs derivation-outputs) ; list of name/<derivation-output> pairs
  125. (inputs derivation-inputs) ; list of <derivation-input>
  126. (sources derivation-sources) ; list of store paths
  127. (system derivation-system) ; string
  128. (builder derivation-builder) ; store path
  129. (args derivation-builder-arguments) ; list of strings
  130. (env-vars derivation-builder-environment-vars) ; list of name/value pairs
  131. (file-name derivation-file-name)) ; the .drv file name
  132. (define-immutable-record-type <derivation-output>
  133. (make-derivation-output path hash-algo hash recursive?)
  134. derivation-output?
  135. (path derivation-output-path) ; store path
  136. (hash-algo derivation-output-hash-algo) ; symbol | #f
  137. (hash derivation-output-hash) ; bytevector | #f
  138. (recursive? derivation-output-recursive?)) ; Boolean
  139. (define-immutable-record-type <derivation-input>
  140. (make-derivation-input drv sub-derivations)
  141. derivation-input?
  142. (drv derivation-input-derivation) ; <derivation>
  143. (sub-derivations derivation-input-sub-derivations)) ; list of strings
  144. (define (derivation-input-path input)
  145. "Return the file name of the derivation INPUT refers to."
  146. (derivation-file-name (derivation-input-derivation input)))
  147. (define* (derivation-input drv #:optional
  148. (outputs (derivation-output-names drv)))
  149. "Return a <derivation-input> for the OUTPUTS of DRV."
  150. ;; This is a public interface meant to be more convenient than
  151. ;; 'make-derivation-input' and giving us more control.
  152. (make-derivation-input drv outputs))
  153. (define (derivation-input-key input)
  154. "Return an object for which 'equal?' and 'hash' are constant-time, and which
  155. can thus be used as a key for INPUT in lookup tables."
  156. (cons (derivation-input-path input)
  157. (derivation-input-sub-derivations input)))
  158. (set-record-type-printer! <derivation>
  159. (lambda (drv port)
  160. (format port "#<derivation ~a => ~a ~a>"
  161. (derivation-file-name drv)
  162. (string-join
  163. (map (match-lambda
  164. ((_ . output)
  165. (derivation-output-path output)))
  166. (derivation-outputs drv)))
  167. (number->string (object-address drv) 16))))
  168. (define (derivation-name drv)
  169. "Return the base name of DRV."
  170. (let ((base (store-path-package-name (derivation-file-name drv))))
  171. (string-drop-right base 4)))
  172. (define (derivation-output-names drv)
  173. "Return the names of the outputs of DRV."
  174. (match (derivation-outputs drv)
  175. (((names . _) ...)
  176. names)))
  177. (define (fixed-output-derivation? drv)
  178. "Return #t if DRV is a fixed-output derivation, such as the result of a
  179. download with a fixed hash (aka. `fetchurl')."
  180. (match drv
  181. (($ <derivation>
  182. (("out" . ($ <derivation-output> _ (? symbol?) (? bytevector?)))))
  183. #t)
  184. (_ #f)))
  185. (define (derivation-input<? input1 input2)
  186. "Compare INPUT1 and INPUT2, two <derivation-input>."
  187. (string<? (derivation-input-path input1)
  188. (derivation-input-path input2)))
  189. (define (derivation-input-output-paths input)
  190. "Return the list of output paths corresponding to INPUT, a
  191. <derivation-input>."
  192. (match input
  193. (($ <derivation-input> drv sub-drvs)
  194. (map (cut derivation->output-path drv <>)
  195. sub-drvs))))
  196. (define (derivation-input-output-path input)
  197. "Return the output file name of INPUT. If INPUT has more than one outputs,
  198. an error is raised."
  199. (match input
  200. (($ <derivation-input> drv (output))
  201. (derivation->output-path drv output))))
  202. (define (valid-derivation-input? store input)
  203. "Return true if INPUT is valid--i.e., if all the outputs it requests are in
  204. the store."
  205. (every (cut valid-path? store <>)
  206. (derivation-input-output-paths input)))
  207. (define (coalesce-duplicate-inputs inputs)
  208. "Return a list of inputs, such that when INPUTS contains the same DRV twice,
  209. they are coalesced, with their sub-derivations merged. This is needed because
  210. Nix itself keeps only one of them."
  211. (define table
  212. (make-hash-table 25))
  213. (for-each (lambda (input)
  214. ;; If DRV1 and DRV2 are fixed-output derivations with the same
  215. ;; output path, they must be coalesced. Thus, TABLE is keyed by
  216. ;; output paths.
  217. (let* ((drv (derivation-input-derivation input))
  218. (key (string-join
  219. (map (match-lambda
  220. ((_ . output)
  221. (derivation-output-path output)))
  222. (derivation-outputs drv))))
  223. (sub-drvs (derivation-input-sub-derivations input)))
  224. (match (hash-get-handle table key)
  225. (#f
  226. (hash-set! table key input))
  227. ((and handle (key . ($ <derivation-input> drv sub-drvs2)))
  228. ;; Merge DUP with INPUT.
  229. (let* ((sub-drvs (delete-duplicates
  230. (append sub-drvs sub-drvs2)))
  231. (input
  232. (make-derivation-input drv
  233. (sort sub-drvs string<?))))
  234. (set-cdr! handle input))))))
  235. inputs)
  236. (hash-fold (lambda (key input lst)
  237. (cons input lst))
  238. '()
  239. table))
  240. (define* (derivation-prerequisites drv #:optional (cut? (const #f)))
  241. "Return the list of derivation-inputs required to build DRV, recursively.
  242. CUT? is a predicate that is passed a derivation-input and returns true to
  243. eliminate the given input and its dependencies from the search. An example of
  244. such a predicate is 'valid-derivation-input?'; when it is used as CUT?, the
  245. result is the set of prerequisites of DRV not already in valid."
  246. (let loop ((drv drv)
  247. (result '())
  248. (input-set (set)))
  249. (let ((inputs (remove (lambda (input)
  250. (or (set-contains? input-set
  251. (derivation-input-key input))
  252. (cut? input)))
  253. (derivation-inputs drv))))
  254. (fold2 loop
  255. (append inputs result)
  256. (fold set-insert input-set
  257. (map derivation-input-key inputs))
  258. (map derivation-input-derivation inputs)))))
  259. (define (offloadable-derivation? drv)
  260. "Return true if DRV can be offloaded, false otherwise."
  261. (match (assoc "preferLocalBuild"
  262. (derivation-builder-environment-vars drv))
  263. (("preferLocalBuild" . "1") #f)
  264. (_ #t)))
  265. (define (substitutable-derivation? drv)
  266. "Return #t if DRV can be substituted."
  267. (match (assoc "allowSubstitutes"
  268. (derivation-builder-environment-vars drv))
  269. (("allowSubstitutes" . value)
  270. (string=? value "1"))
  271. (_ #t)))
  272. (define (derivation-output-paths drv sub-drvs)
  273. "Return the output paths of outputs SUB-DRVS of DRV."
  274. (match drv
  275. (($ <derivation> outputs)
  276. (map (lambda (sub-drv)
  277. (derivation-output-path (assoc-ref outputs sub-drv)))
  278. sub-drvs))))
  279. (define* (derivation-input-fold proc seed inputs
  280. #:key (cut? (const #f)))
  281. "Perform a breadth-first traversal of INPUTS, calling PROC on each input
  282. with the current result, starting from SEED. Skip recursion on inputs that
  283. match CUT?."
  284. (let loop ((inputs inputs)
  285. (result seed)
  286. (visited (set)))
  287. (match inputs
  288. (()
  289. result)
  290. ((input rest ...)
  291. (let ((key (derivation-input-key input)))
  292. (cond ((set-contains? visited key)
  293. (loop rest result visited))
  294. ((cut? input)
  295. (loop rest result (set-insert key visited)))
  296. (else
  297. (let ((drv (derivation-input-derivation input)))
  298. (loop (append (derivation-inputs drv) rest)
  299. (proc input result)
  300. (set-insert key visited))))))))))
  301. (define* (substitution-oracle store inputs-or-drv
  302. #:key (mode (build-mode normal)))
  303. "Return a one-argument procedure that, when passed a store file name,
  304. returns a 'substitutable?' if it's substitutable and #f otherwise.
  305. The returned procedure knows about all substitutes for all the derivation
  306. inputs or derivations listed in INPUTS-OR-DRV, *except* those that are already
  307. valid (that is, it won't bother checking whether an item is substitutable if
  308. it's already on disk); it also knows about their prerequisites, unless they
  309. are themselves substitutable.
  310. Creating a single oracle (thus making a single 'substitutable-path-info' call) and
  311. reusing it is much more efficient than calling 'has-substitutes?' or similar
  312. repeatedly, because it avoids the costs associated with launching the
  313. substituter many times."
  314. (define valid-input?
  315. (cut valid-derivation-input? store <>))
  316. (define (closure inputs)
  317. (reverse
  318. (derivation-input-fold (lambda (input closure)
  319. (let ((drv (derivation-input-derivation input)))
  320. (if (substitutable-derivation? drv)
  321. (cons input closure)
  322. closure)))
  323. '()
  324. inputs
  325. #:cut? valid-input?)))
  326. (let* ((inputs (closure (map (match-lambda
  327. ((? derivation-input? input)
  328. input)
  329. ((? derivation? drv)
  330. (derivation-input drv)))
  331. inputs-or-drv)))
  332. (items (append-map derivation-input-output-paths inputs))
  333. (subst (fold (lambda (subst vhash)
  334. (vhash-cons (substitutable-path subst) subst
  335. vhash))
  336. vlist-null
  337. (substitutable-path-info store items))))
  338. (lambda (item)
  339. (match (vhash-assoc item subst)
  340. (#f #f)
  341. ((key . value) value)))))
  342. (define (dependencies-of-substitutables substitutables inputs)
  343. "Return the subset of INPUTS whose output file names is among the references
  344. of SUBSTITUTABLES."
  345. (let ((items (fold set-insert (set)
  346. (append-map substitutable-references substitutables))))
  347. (filter (lambda (input)
  348. (any (cut set-contains? items <>)
  349. (derivation-input-output-paths input)))
  350. inputs)))
  351. (define* (derivation-build-plan store inputs
  352. #:key
  353. (mode (build-mode normal))
  354. (substitutable-info
  355. (substitution-oracle
  356. store inputs #:mode mode)))
  357. "Given INPUTS, a list of derivation-inputs, return two values: the list of
  358. derivations to build, and the list of substitutable items that, together,
  359. allow INPUTS to be realized.
  360. SUBSTITUTABLE-INFO must be a one-argument procedure similar to that returned
  361. by 'substitution-oracle'."
  362. (define (built? item)
  363. (valid-path? store item))
  364. (define (input-built? input)
  365. ;; In 'check' mode, assume that DRV is not built.
  366. (and (not (and (eqv? mode (build-mode check))
  367. (member input inputs)))
  368. (every built? (derivation-input-output-paths input))))
  369. (define (input-substitutable-info input)
  370. (and (substitutable-derivation? (derivation-input-derivation input))
  371. (let* ((items (derivation-input-output-paths input))
  372. (info (filter-map substitutable-info items)))
  373. (and (= (length info) (length items))
  374. info))))
  375. (let loop ((inputs inputs) ;list of <derivation-input>
  376. (build '()) ;list of <derivation>
  377. (substitute '()) ;list of <substitutable>
  378. (visited (set))) ;set of <derivation-input>
  379. (match inputs
  380. (()
  381. (values build substitute))
  382. ((input rest ...)
  383. (let ((key (derivation-input-key input))
  384. (deps (derivation-inputs
  385. (derivation-input-derivation input))))
  386. (cond ((set-contains? visited key)
  387. (loop rest build substitute visited))
  388. ((input-built? input)
  389. (loop rest build substitute
  390. (set-insert key visited)))
  391. ((input-substitutable-info input)
  392. =>
  393. (lambda (substitutables)
  394. (loop (append (dependencies-of-substitutables substitutables
  395. deps)
  396. rest)
  397. build
  398. (append substitutables substitute)
  399. (set-insert key visited))))
  400. (else
  401. (loop (append deps rest)
  402. (cons (derivation-input-derivation input) build)
  403. substitute
  404. (set-insert key visited)))))))))
  405. (define-deprecated (derivation-prerequisites-to-build store drv #:rest rest)
  406. derivation-build-plan
  407. (let-values (((build download)
  408. (apply derivation-build-plan store
  409. (list (derivation-input drv)) rest)))
  410. (values (map derivation-input build) download)))
  411. (define* (read-derivation drv-port
  412. #:optional (read-derivation-from-file
  413. read-derivation-from-file))
  414. "Read the derivation from DRV-PORT and return the corresponding <derivation>
  415. object. Call READ-DERIVATION-FROM-FILE to read derivations declared as inputs
  416. of the derivation being parsed.
  417. Most of the time you'll want to use 'read-derivation-from-file', which caches
  418. things as appropriate and is thus more efficient."
  419. (define comma (string->symbol ","))
  420. (define (ununquote x)
  421. (match x
  422. (('unquote x) (ununquote x))
  423. ((x ...) (map ununquote x))
  424. (_ x)))
  425. (define (outputs->alist x)
  426. (fold-right (lambda (output result)
  427. (match output
  428. ((name path "" "")
  429. ;; Regular derivation.
  430. (alist-cons name
  431. (make-derivation-output path #f #f #f)
  432. result))
  433. ((name path hash-algo hash)
  434. ;; Fixed-output, unless HASH is the empty string (in that
  435. ;; case, HASH-ALGO must be preserved despite being
  436. ;; unused).
  437. (let* ((rec? (string-prefix? "r:" hash-algo))
  438. (algo (string->symbol
  439. (if rec?
  440. (string-drop hash-algo 2)
  441. hash-algo)))
  442. (hash (and (not (string-null? hash))
  443. (base16-string->bytevector hash))))
  444. (alist-cons name
  445. (make-derivation-output path algo
  446. hash rec?)
  447. result)))))
  448. '()
  449. x))
  450. (define (make-input-drvs x)
  451. (fold-right (lambda (input result)
  452. (match input
  453. ((path (sub-drvs ...))
  454. (let ((drv (read-derivation-from-file path)))
  455. (cons (make-derivation-input drv sub-drvs)
  456. result)))))
  457. '()
  458. x))
  459. ;; The contents of a derivation are typically ASCII, but choosing
  460. ;; UTF-8 allows us to take the fast path for Guile's `scm_getc'.
  461. (set-port-encoding! drv-port "UTF-8")
  462. (let loop ((exp (read drv-port))
  463. (result '()))
  464. (match exp
  465. ((? eof-object?)
  466. (let ((result (reverse result)))
  467. (match result
  468. (('Derive ((outputs ...) (input-drvs ...)
  469. (input-srcs ...)
  470. (? string? system)
  471. (? string? builder)
  472. ((? string? args) ...)
  473. ((var value) ...)))
  474. (make-derivation (outputs->alist outputs)
  475. (make-input-drvs input-drvs)
  476. input-srcs
  477. system builder args
  478. (fold-right alist-cons '() var value)
  479. (port-filename drv-port)))
  480. (_
  481. (error "failed to parse derivation" drv-port result)))))
  482. ((? (cut eq? <> comma))
  483. (loop (read drv-port) result))
  484. (_
  485. (loop (read drv-port)
  486. (cons (ununquote exp) result))))))
  487. (define %derivation-cache
  488. ;; Maps derivation file names to <derivation> objects.
  489. ;; XXX: This is redundant with 'atts-cache' in the store.
  490. (make-weak-value-hash-table 200))
  491. (define (read-derivation-from-file file)
  492. "Read the derivation in FILE, a '.drv' file, and return the corresponding
  493. <derivation> object."
  494. ;; Memoize that operation because 'read-derivation' is quite expensive,
  495. ;; and because the same argument is read more than 15 times on average
  496. ;; during something like (package-derivation s gdb).
  497. (or (and file (hash-ref %derivation-cache file))
  498. (let ((drv (call-with-input-file file read-derivation)))
  499. (hash-set! %derivation-cache file drv)
  500. drv)))
  501. (define-inlinable (write-sequence lst write-item port)
  502. ;; Write each element of LST with WRITE-ITEM to PORT, separating them with a
  503. ;; comma.
  504. (match lst
  505. (()
  506. #t)
  507. ((prefix (... ...) last)
  508. (for-each (lambda (item)
  509. (write-item item port)
  510. (put-char port #\,))
  511. prefix)
  512. (write-item last port))))
  513. (define-inlinable (write-list lst write-item port)
  514. ;; Write LST as a derivation list to PORT, using WRITE-ITEM to write each
  515. ;; element.
  516. (put-char port #\[)
  517. (write-sequence lst write-item port)
  518. (put-char port #\]))
  519. (define-inlinable (write-tuple lst write-item port)
  520. ;; Same, but write LST as a tuple.
  521. (put-char port #\()
  522. (write-sequence lst write-item port)
  523. (put-char port #\)))
  524. (define %escape-char-set
  525. ;; Characters that need to be escaped.
  526. (char-set #\" #\\ #\newline #\return #\tab))
  527. (define (escaped-string str)
  528. "Escape double quote characters found in STR, if any."
  529. (define escape
  530. (match-lambda
  531. (#\" "\\\"")
  532. (#\\ "\\\\")
  533. (#\newline "\\n")
  534. (#\return "\\r")
  535. (#\tab "\\t")))
  536. (let loop ((str str)
  537. (result '()))
  538. (let ((index (string-index str %escape-char-set)))
  539. (if index
  540. (let ((rest (string-drop str (+ 1 index))))
  541. (loop rest
  542. (cons* (escape (string-ref str index))
  543. (string-take str index)
  544. result)))
  545. (if (null? result)
  546. str
  547. (string-concatenate-reverse (cons str result)))))))
  548. (define (write-derivation drv port)
  549. "Write the ATerm-like serialization of DRV to PORT. See Section 2.4 of
  550. Eelco Dolstra's PhD dissertation for an overview of a previous version of
  551. that form."
  552. ;; Use 'put-string', which does less work and is faster than 'display'.
  553. ;; Likewise, 'write-escaped-string' is faster than 'write'.
  554. (define (write-escaped-string str port)
  555. (put-char port #\")
  556. (put-string port (escaped-string str))
  557. (put-char port #\"))
  558. (define (write-string-list lst)
  559. (write-list lst write-escaped-string port))
  560. (define (write-output output port)
  561. (match output
  562. ((name . ($ <derivation-output> path hash-algo hash recursive?))
  563. (write-tuple (list name path
  564. (if hash-algo
  565. (string-append (if recursive? "r:" "")
  566. (symbol->string hash-algo))
  567. "")
  568. (or (and=> hash bytevector->base16-string)
  569. ""))
  570. write-escaped-string
  571. port))))
  572. (define (write-input input port)
  573. (match input
  574. (($ <derivation-input> obj sub-drvs)
  575. (put-string port "(\"")
  576. ;; 'derivation/masked-inputs' produces objects that contain a string
  577. ;; instead of a <derivation>, so we need to account for that.
  578. (put-string port (if (derivation? obj)
  579. (derivation-file-name obj)
  580. obj))
  581. (put-string port "\",")
  582. (write-string-list sub-drvs)
  583. (put-char port #\)))))
  584. (define (write-env-var env-var port)
  585. (match env-var
  586. ((name . value)
  587. (put-char port #\()
  588. (write-escaped-string name port)
  589. (put-char port #\,)
  590. (write-escaped-string value port)
  591. (put-char port #\)))))
  592. ;; Assume all the lists we are writing are already sorted.
  593. (match drv
  594. (($ <derivation> outputs inputs sources
  595. system builder args env-vars)
  596. (put-string port "Derive(")
  597. (write-list outputs write-output port)
  598. (put-char port #\,)
  599. (write-list inputs write-input port)
  600. (put-char port #\,)
  601. (write-string-list sources)
  602. (simple-format port ",\"~a\",\"~a\"," system builder)
  603. (write-string-list args)
  604. (put-char port #\,)
  605. (write-list env-vars write-env-var port)
  606. (put-char port #\)))))
  607. (define derivation->bytevector
  608. (lambda (drv)
  609. "Return the external representation of DRV as a UTF-8-encoded string."
  610. (with-fluids ((%default-port-encoding "UTF-8"))
  611. (call-with-values open-bytevector-output-port
  612. (lambda (port get-bytevector)
  613. (write-derivation drv port)
  614. (get-bytevector))))))
  615. (define* (derivation->output-path drv #:optional (output "out"))
  616. "Return the store path of its output OUTPUT. Raise a
  617. '&derivation-missing-output-error' condition if OUTPUT is not an output of
  618. DRV."
  619. (let ((output* (assoc-ref (derivation-outputs drv) output)))
  620. (if output*
  621. (derivation-output-path output*)
  622. (raise (condition (&derivation-missing-output-error
  623. (derivation drv)
  624. (output output)))))))
  625. (define (derivation->output-paths drv)
  626. "Return the list of name/path pairs of the outputs of DRV."
  627. (map (match-lambda
  628. ((name . output)
  629. (cons name (derivation-output-path output))))
  630. (derivation-outputs drv)))
  631. (define derivation-path->output-path
  632. ;; This procedure is called frequently, so memoize it.
  633. (let ((memoized (mlambda (path output)
  634. (derivation->output-path (read-derivation-from-file path)
  635. output))))
  636. (lambda* (path #:optional (output "out"))
  637. "Read the derivation from PATH (`/gnu/store/xxx.drv'), and return the store
  638. path of its output OUTPUT."
  639. (memoized path output))))
  640. (define (derivation-path->output-paths path)
  641. "Read the derivation from PATH (`/gnu/store/xxx.drv'), and return the
  642. list of name/path pairs of its outputs."
  643. (derivation->output-paths (read-derivation-from-file path)))
  644. ;;;
  645. ;;; Derivation primitive.
  646. ;;;
  647. (define derivation-base16-hash
  648. (mlambdaq (drv)
  649. "Return a string containing the base16 representation of the hash of DRV."
  650. (bytevector->base16-string (derivation-hash drv))))
  651. (define (derivation/masked-inputs drv)
  652. "Assuming DRV is a regular derivation (not fixed-output), replace the file
  653. name of each input with that input's hash."
  654. (match drv
  655. (($ <derivation> outputs inputs sources
  656. system builder args env-vars)
  657. (let ((inputs (map (match-lambda
  658. (($ <derivation-input> drv sub-drvs)
  659. (let ((hash (derivation-base16-hash drv)))
  660. (make-derivation-input hash sub-drvs))))
  661. inputs)))
  662. (make-derivation outputs
  663. (sort (delete-duplicates inputs)
  664. (lambda (drv1 drv2)
  665. (string<? (derivation-input-derivation drv1)
  666. (derivation-input-derivation drv2))))
  667. sources
  668. system builder args env-vars
  669. #f)))))
  670. (define derivation-hash ; `hashDerivationModulo' in derivations.cc
  671. (lambda (drv)
  672. "Return the hash of DRV, modulo its fixed-output inputs, as a bytevector."
  673. (match drv
  674. (($ <derivation> ((_ . ($ <derivation-output> path
  675. (? symbol? hash-algo) (? bytevector? hash)
  676. (? boolean? recursive?)))))
  677. ;; A fixed-output derivation.
  678. (sha256
  679. (string->utf8
  680. (string-append "fixed:out:"
  681. (if recursive? "r:" "")
  682. (symbol->string hash-algo)
  683. ":" (bytevector->base16-string hash)
  684. ":" path))))
  685. (_
  686. ;; XXX: At this point this remains faster than `port-sha256', because
  687. ;; the SHA256 port's `write' method gets called for every single
  688. ;; character.
  689. (sha256 (derivation->bytevector (derivation/masked-inputs drv)))))))
  690. (define (warn-about-derivation-deprecation name)
  691. ;; TRANSLATORS: 'derivation' must not be translated; it refers to the
  692. ;; 'derivation' procedure.
  693. (warning (G_ "in '~a': deprecated 'derivation' calling convention used~%")
  694. name))
  695. (define* (derivation store name builder args
  696. #:key
  697. (system (%current-system)) (env-vars '())
  698. (inputs '()) (sources '())
  699. (outputs '("out"))
  700. hash hash-algo recursive?
  701. references-graphs
  702. allowed-references disallowed-references
  703. leaked-env-vars local-build?
  704. (substitutable? #t)
  705. (properties '())
  706. (%deprecation-warning? #t))
  707. "Build a derivation with the given arguments, and return the resulting
  708. <derivation> object. When HASH and HASH-ALGO are given, a
  709. fixed-output derivation is created---i.e., one whose result is known in
  710. advance, such as a file download. If, in addition, RECURSIVE? is true, then
  711. that fixed output may be an executable file or a directory and HASH must be
  712. the hash of an archive containing this output.
  713. When REFERENCES-GRAPHS is true, it must be a list of file name/store path
  714. pairs. In that case, the reference graph of each store path is exported in
  715. the build environment in the corresponding file, in a simple text format.
  716. When ALLOWED-REFERENCES is true, it must be a list of store items or outputs
  717. that the derivation's outputs may refer to. Likewise, DISALLOWED-REFERENCES,
  718. if true, must be a list of things the outputs may not refer to.
  719. When LEAKED-ENV-VARS is true, it must be a list of strings denoting
  720. environment variables that are allowed to \"leak\" from the daemon's
  721. environment to the build environment. This is only applicable to fixed-output
  722. derivations--i.e., when HASH is true. The main use is to allow variables such
  723. as \"http_proxy\" to be passed to derivations that download files.
  724. When LOCAL-BUILD? is true, declare that the derivation is not a good candidate
  725. for offloading and should rather be built locally. This is the case for small
  726. derivations where the costs of data transfers would outweigh the benefits.
  727. When SUBSTITUTABLE? is false, declare that substitutes of the derivation's
  728. output should not be used.
  729. PROPERTIES must be an association list describing \"properties\" of the
  730. derivation. It is kept as-is, uninterpreted, in the derivation."
  731. (define (add-output-paths drv)
  732. ;; Return DRV with an actual store path for each of its output and the
  733. ;; corresponding environment variable.
  734. (match drv
  735. (($ <derivation> outputs inputs sources
  736. system builder args env-vars)
  737. (let* ((drv-hash (derivation-hash drv))
  738. (outputs (map (match-lambda
  739. ((output-name . ($ <derivation-output>
  740. _ algo hash rec?))
  741. (let ((path
  742. (if hash
  743. (fixed-output-path name hash
  744. #:hash-algo algo
  745. #:output output-name
  746. #:recursive? rec?)
  747. (output-path output-name
  748. drv-hash name))))
  749. (cons output-name
  750. (make-derivation-output path algo
  751. hash rec?)))))
  752. outputs)))
  753. (make-derivation outputs inputs sources system builder args
  754. (map (match-lambda
  755. ((name . value)
  756. (cons name
  757. (or (and=> (assoc-ref outputs name)
  758. derivation-output-path)
  759. value))))
  760. env-vars)
  761. #f)))))
  762. (define (user+system-env-vars)
  763. ;; Some options are passed to the build daemon via the env. vars of
  764. ;; derivations (urgh!). We hide that from our API, but here is the place
  765. ;; where we kludgify those options.
  766. (let ((env-vars `(,@(if local-build?
  767. `(("preferLocalBuild" . "1"))
  768. '())
  769. ,@(if (not substitutable?)
  770. `(("allowSubstitutes" . "0"))
  771. '())
  772. ,@(if allowed-references
  773. `(("allowedReferences"
  774. . ,(string-join allowed-references)))
  775. '())
  776. ,@(if disallowed-references
  777. `(("disallowedReferences"
  778. . ,(string-join disallowed-references)))
  779. '())
  780. ,@(if leaked-env-vars
  781. `(("impureEnvVars"
  782. . ,(string-join leaked-env-vars)))
  783. '())
  784. ,@(match properties
  785. (() '())
  786. (lst `(("guix properties"
  787. . ,(object->string properties)))))
  788. ,@env-vars)))
  789. (match references-graphs
  790. (((file . path) ...)
  791. (let ((value (map (cut string-append <> " " <>)
  792. file path)))
  793. ;; XXX: This all breaks down if an element of FILE or PATH contains
  794. ;; white space.
  795. `(("exportReferencesGraph" . ,(string-join value " "))
  796. ,@env-vars)))
  797. (#f
  798. env-vars))))
  799. (define (env-vars-with-empty-outputs env-vars)
  800. ;; Return a variant of ENV-VARS where each OUTPUTS is associated with an
  801. ;; empty string, even outputs that do not appear in ENV-VARS.
  802. (let ((e (map (match-lambda
  803. ((name . val)
  804. (if (member name outputs)
  805. (cons name "")
  806. (cons name val))))
  807. env-vars)))
  808. (fold (lambda (output-name env-vars)
  809. (if (assoc output-name env-vars)
  810. env-vars
  811. (append env-vars `((,output-name . "")))))
  812. e
  813. outputs)))
  814. (define-syntax-rule (warn-deprecation name)
  815. (when %deprecation-warning?
  816. (warn-about-derivation-deprecation name)))
  817. (define input->derivation-input
  818. (match-lambda
  819. ((? derivation-input? input)
  820. input)
  821. (((? derivation? drv))
  822. (warn-deprecation name)
  823. (make-derivation-input drv '("out")))
  824. (((? derivation? drv) sub-drvs ...)
  825. (warn-deprecation name)
  826. (make-derivation-input drv sub-drvs))
  827. (_
  828. (warn-deprecation name)
  829. #f)))
  830. (define input->source
  831. (match-lambda
  832. (((? string? input) . _)
  833. (warn-deprecation name)
  834. (if (direct-store-path? input)
  835. input
  836. (add-to-store store (basename input)
  837. #t "sha256" input)))
  838. (_ #f)))
  839. ;; Note: lists are sorted alphabetically, to conform with the behavior of
  840. ;; C++ `std::map' in Nix itself.
  841. (let* ((outputs (map (lambda (name)
  842. ;; Return outputs with an empty path.
  843. (cons name
  844. (make-derivation-output "" hash-algo
  845. hash recursive?)))
  846. (sort outputs string<?)))
  847. (sources (sort (delete-duplicates
  848. (append (filter-map input->source inputs)
  849. sources))
  850. string<?))
  851. (inputs (sort (coalesce-duplicate-inputs
  852. (filter-map input->derivation-input inputs))
  853. derivation-input<?))
  854. (env-vars (sort (env-vars-with-empty-outputs
  855. (user+system-env-vars))
  856. (lambda (e1 e2)
  857. (string<? (car e1) (car e2)))))
  858. (drv-masked (make-derivation outputs inputs sources
  859. system builder args env-vars #f))
  860. (drv (add-output-paths drv-masked)))
  861. (let* ((file (add-data-to-store store (string-append name ".drv")
  862. (derivation->bytevector drv)
  863. (append (map derivation-input-path inputs)
  864. sources)))
  865. (drv* (set-field drv (derivation-file-name) file)))
  866. ;; Preserve pointer equality. This improves the performance of
  867. ;; 'eq?'-memoization on derivations.
  868. (or (hash-ref %derivation-cache file)
  869. (begin
  870. (hash-set! %derivation-cache file drv*)
  871. drv*)))))
  872. (define (invalidate-derivation-caches!)
  873. "Invalidate internal derivation caches. This is mostly useful for
  874. long-running processes that know what they're doing. Use with care!"
  875. ;; Typically this is meant to be used by Cuirass and Hydra, which can clear
  876. ;; caches when they start evaluating packages for another architecture.
  877. (invalidate-memoization! derivation-base16-hash)
  878. ;; FIXME: Comment out to work around <https://bugs.gnu.org/36487>.
  879. ;; (hash-clear! %derivation-cache)
  880. )
  881. (define derivation-properties
  882. (mlambdaq (drv)
  883. "Return the property alist associated with DRV."
  884. (match (assoc "guix properties"
  885. (derivation-builder-environment-vars drv))
  886. ((_ . str) (call-with-input-string str read))
  887. (#f '()))))
  888. (define* (map-derivation store drv mapping
  889. #:key (system (%current-system)))
  890. "Given MAPPING, a list of pairs of derivations, return a derivation based on
  891. DRV where all the 'car's of MAPPING have been replaced by its 'cdr's,
  892. recursively."
  893. (define (substitute str initial replacements)
  894. (fold (lambda (path replacement result)
  895. (string-replace-substring result path
  896. replacement))
  897. str
  898. initial replacements))
  899. (define (substitute-file file initial replacements)
  900. (define contents
  901. (with-fluids ((%default-port-encoding #f))
  902. (call-with-input-file file read-string)))
  903. (let ((updated (substitute contents initial replacements)))
  904. (if (string=? updated contents)
  905. file
  906. ;; XXX: permissions aren't preserved.
  907. (add-text-to-store store (store-path-package-name file)
  908. updated))))
  909. (define input->output-paths
  910. (match-lambda
  911. ((? derivation-input? input)
  912. (derivation-input-output-paths input))
  913. ((? string? file)
  914. (list file))))
  915. (let ((mapping (fold (lambda (pair result)
  916. (match pair
  917. (((? derivation? orig) . replacement)
  918. (vhash-cons (derivation-file-name orig)
  919. replacement result))
  920. ((file . replacement)
  921. (vhash-cons file replacement result))))
  922. vlist-null
  923. mapping)))
  924. (define rewritten-input
  925. ;; Rewrite the given input according to MAPPING, and return an input
  926. ;; in the format used in 'derivation' calls.
  927. (mlambda (input loop)
  928. (match input
  929. (($ <derivation-input> drv (sub-drvs ...))
  930. (match (vhash-assoc (derivation-file-name drv) mapping)
  931. ((_ . (? derivation? replacement))
  932. (derivation-input replacement sub-drvs))
  933. ((_ . (? string? source))
  934. source)
  935. (#f
  936. (derivation-input (loop drv) sub-drvs)))))))
  937. (let loop ((drv drv))
  938. (let* ((inputs (map (cut rewritten-input <> loop)
  939. (derivation-inputs drv)))
  940. (initial (append-map derivation-input-output-paths
  941. (derivation-inputs drv)))
  942. (replacements (append-map input->output-paths inputs))
  943. ;; Sources typically refer to the output directories of the
  944. ;; original inputs, INITIAL. Rewrite them by substituting
  945. ;; REPLACEMENTS.
  946. (sources (map (lambda (source)
  947. (match (vhash-assoc source mapping)
  948. ((_ . replacement)
  949. replacement)
  950. (#f
  951. (substitute-file source
  952. initial replacements))))
  953. (derivation-sources drv)))
  954. ;; Now augment the lists of initials and replacements.
  955. (initial (append (derivation-sources drv) initial))
  956. (replacements (append sources replacements))
  957. (name (store-path-package-name
  958. (string-drop-right (derivation-file-name drv)
  959. 4))))
  960. (derivation store name
  961. (substitute (derivation-builder drv)
  962. initial replacements)
  963. (map (cut substitute <> initial replacements)
  964. (derivation-builder-arguments drv))
  965. #:system system
  966. #:env-vars (map (match-lambda
  967. ((var . value)
  968. `(,var
  969. . ,(substitute value initial
  970. replacements))))
  971. (derivation-builder-environment-vars drv))
  972. #:inputs (filter derivation-input? inputs)
  973. #:sources (append sources (filter string? inputs))
  974. #:outputs (derivation-output-names drv)
  975. #:hash (match (derivation-outputs drv)
  976. ((($ <derivation-output> _ algo hash))
  977. hash)
  978. (_ #f))
  979. #:hash-algo (match (derivation-outputs drv)
  980. ((($ <derivation-output> _ algo hash))
  981. algo)
  982. (_ #f)))))))
  983. ;;;
  984. ;;; Store compatibility layer.
  985. ;;;
  986. (define* (build-derivations store derivations
  987. #:optional (mode (build-mode normal)))
  988. "Build DERIVATIONS, a list of <derivation> or <derivation-input> objects,
  989. .drv file names, or derivation/output pairs, using the specified MODE."
  990. (build-things store (map (match-lambda
  991. ((? derivation? drv)
  992. (derivation-file-name drv))
  993. ((? derivation-input? input)
  994. (cons (derivation-input-path input)
  995. (string-join
  996. (derivation-input-sub-derivations input)
  997. ",")))
  998. ((? string? file) file)
  999. (((? derivation? drv) . output)
  1000. (cons (derivation-file-name drv)
  1001. output))
  1002. (((? string? file) . output)
  1003. (cons file output)))
  1004. derivations)
  1005. mode))
  1006. ;;;
  1007. ;;; Guile-based builders.
  1008. ;;;
  1009. (define (parent-directories file-name)
  1010. "Return the list of parent dirs of FILE-NAME, in the order in which an
  1011. `mkdir -p' implementation would make them."
  1012. (let ((not-slash (char-set-complement (char-set #\/))))
  1013. (reverse
  1014. (fold (lambda (dir result)
  1015. (match result
  1016. (()
  1017. (list dir))
  1018. ((prev _ ...)
  1019. (cons (string-append prev "/" dir)
  1020. result))))
  1021. '()
  1022. (remove (cut string=? <> ".")
  1023. (string-tokenize (dirname file-name) not-slash))))))
  1024. (define* (imported-files store files ;deprecated
  1025. #:key (name "file-import"))
  1026. "Return a store item that contains FILES. FILES must be a list
  1027. of (FINAL-PATH . FILE-NAME) pairs; each FILE-NAME is read from the file
  1028. system, imported, and appears under FINAL-PATH in the resulting store path."
  1029. (add-file-tree-to-store store
  1030. `(,name directory
  1031. ,@(file-mapping->tree files))))
  1032. ;; The "file not found" error condition.
  1033. (define-condition-type &file-search-error &error
  1034. file-search-error?
  1035. (file file-search-error-file-name)
  1036. (path file-search-error-search-path))
  1037. (define search-path*
  1038. ;; A memoizing version of 'search-path' so 'imported-modules' does not end
  1039. ;; up looking for the same files over and over again.
  1040. (mlambda (path file)
  1041. "Search for FILE in PATH and memoize the result. Raise a
  1042. '&file-search-error' condition if it could not be found."
  1043. (or (search-path path file)
  1044. (raise (condition
  1045. (&file-search-error (file file)
  1046. (path path)))))))
  1047. (define (module->source-file-name module)
  1048. "Return the file name corresponding to MODULE, a Guile module name (a list
  1049. of symbols.)"
  1050. (string-append (string-join (map symbol->string module) "/")
  1051. ".scm"))
  1052. (define* (%imported-modules store modules ;deprecated
  1053. #:key (name "module-import")
  1054. (module-path %load-path))
  1055. "Return a store item that contains the source files of MODULES, a list of
  1056. module names such as `(ice-9 q)'. All of MODULES must be in the MODULE-PATH
  1057. search path."
  1058. ;; TODO: Determine the closure of MODULES, build the `.go' files,
  1059. ;; canonicalize the source files through read/write, etc.
  1060. (let ((files (map (lambda (m)
  1061. (let ((f (module->source-file-name m)))
  1062. (cons f (search-path* module-path f))))
  1063. modules)))
  1064. (imported-files store files #:name name)))
  1065. (define* (%compiled-modules store modules ;deprecated
  1066. #:key (name "module-import-compiled")
  1067. (system (%current-system))
  1068. (guile (%guile-for-build))
  1069. (module-path %load-path))
  1070. "Return a derivation that builds a tree containing the `.go' files
  1071. corresponding to MODULES. All the MODULES are built in a context where
  1072. they can refer to each other."
  1073. (let* ((module-dir (%imported-modules store modules
  1074. #:module-path module-path))
  1075. (files (map (lambda (m)
  1076. (let ((f (string-join (map symbol->string m)
  1077. "/")))
  1078. (cons (string-append f ".go")
  1079. (string-append module-dir "/" f ".scm"))))
  1080. modules)))
  1081. (define builder
  1082. `(begin
  1083. (use-modules (system base compile))
  1084. (let ((out (assoc-ref %outputs "out")))
  1085. (mkdir out)
  1086. (chdir out))
  1087. (set! %load-path
  1088. (cons ,module-dir %load-path))
  1089. ,@(map (match-lambda
  1090. ((output . input)
  1091. (let ((make-parent-dirs (map (lambda (dir)
  1092. `(unless (file-exists? ,dir)
  1093. (mkdir ,dir)))
  1094. (parent-directories output))))
  1095. `(begin
  1096. ,@make-parent-dirs
  1097. (compile-file ,input
  1098. #:output-file ,output
  1099. #:opts %auto-compilation-options)))))
  1100. files)))
  1101. (build-expression->derivation store name builder
  1102. #:inputs `(("modules" ,module-dir))
  1103. #:system system
  1104. #:guile-for-build guile
  1105. #:local-build? #t)))
  1106. (define %module-cache
  1107. ;; Map a list of modules to its 'imported+compiled-modules' result.
  1108. (make-hash-table))
  1109. (define* (imported+compiled-modules store modules #:key
  1110. (system (%current-system))
  1111. (guile (%guile-for-build)))
  1112. "Return a pair containing the derivation to import MODULES and that where
  1113. MODULES are compiled."
  1114. (define key
  1115. (list modules (derivation-file-name guile) system))
  1116. (or (hash-ref %module-cache key)
  1117. (let ((result (cons (%imported-modules store modules)
  1118. (%compiled-modules store modules
  1119. #:system system #:guile guile))))
  1120. (hash-set! %module-cache key result)
  1121. result)))
  1122. (define-deprecated (build-expression->derivation store name exp
  1123. #:key
  1124. (system (%current-system))
  1125. (inputs '())
  1126. (outputs '("out"))
  1127. hash hash-algo recursive?
  1128. (env-vars '())
  1129. (modules '())
  1130. guile-for-build
  1131. references-graphs
  1132. allowed-references
  1133. disallowed-references
  1134. local-build? (substitutable? #t)
  1135. (properties '()))
  1136. gexp->derivation ;unbound, but that's okay
  1137. "Return a derivation that executes Scheme expression EXP as a builder
  1138. for derivation NAME. INPUTS must be a list of (NAME DRV-PATH SUB-DRV)
  1139. tuples; when SUB-DRV is omitted, \"out\" is assumed. MODULES is a list
  1140. of names of Guile modules from the current search path to be copied in
  1141. the store, compiled, and made available in the load path during the
  1142. execution of EXP.
  1143. EXP is evaluated in an environment where %OUTPUT is bound to the main
  1144. output path, %OUTPUTS is bound to a list of output/path pairs, and where
  1145. %BUILD-INPUTS is bound to an alist of string/output-path pairs made from
  1146. INPUTS. Optionally, ENV-VARS is a list of string pairs specifying the
  1147. name and value of environment variables visible to the builder. The
  1148. builder terminates by passing the result of EXP to `exit'; thus, when
  1149. EXP returns #f, the build is considered to have failed.
  1150. EXP is built using GUILE-FOR-BUILD (a derivation). When GUILE-FOR-BUILD is
  1151. omitted or is #f, the value of the `%guile-for-build' fluid is used instead.
  1152. See the `derivation' procedure for the meaning of REFERENCES-GRAPHS,
  1153. ALLOWED-REFERENCES, DISALLOWED-REFERENCES, LOCAL-BUILD?, SUBSTITUTABLE?,
  1154. and PROPERTIES."
  1155. (define guile-drv
  1156. (or guile-for-build (%guile-for-build)))
  1157. (define guile
  1158. (string-append (derivation->output-path guile-drv)
  1159. "/bin/guile"))
  1160. (define module-form?
  1161. (match-lambda
  1162. (((or 'define-module 'use-modules) _ ...) #t)
  1163. (_ #f)))
  1164. (define source-path
  1165. ;; When passed an input that is a source, return its path; otherwise
  1166. ;; return #f.
  1167. (match-lambda
  1168. ((_ (? derivation?) _ ...)
  1169. #f)
  1170. ((_ path _ ...)
  1171. (and (not (derivation-path? path))
  1172. path))))
  1173. (let* ((prologue `(begin
  1174. ,@(match exp
  1175. ((_ ...)
  1176. ;; Module forms must appear at the top-level so
  1177. ;; that any macros they export can be expanded.
  1178. (filter module-form? exp))
  1179. (_ `(,exp)))
  1180. (define %output (getenv "out"))
  1181. (define %outputs
  1182. (map (lambda (o)
  1183. (cons o (getenv o)))
  1184. ',outputs))
  1185. (define %build-inputs
  1186. ',(map (match-lambda
  1187. ((name drv . rest)
  1188. (let ((sub (match rest
  1189. (() "out")
  1190. ((x) x))))
  1191. (cons name
  1192. (cond
  1193. ((derivation? drv)
  1194. (derivation->output-path drv sub))
  1195. ((derivation-path? drv)
  1196. (derivation-path->output-path drv
  1197. sub))
  1198. (else drv))))))
  1199. inputs))
  1200. ,@(if (null? modules)
  1201. '()
  1202. ;; Remove our own settings.
  1203. '((unsetenv "GUILE_LOAD_COMPILED_PATH")))
  1204. ;; Guile sets it, but remove it to avoid conflicts when
  1205. ;; building Guile-using packages.
  1206. (unsetenv "LD_LIBRARY_PATH")))
  1207. (builder (add-text-to-store store
  1208. (string-append name "-guile-builder")
  1209. ;; Explicitly use UTF-8 for determinism,
  1210. ;; and also because UTF-8 output is faster.
  1211. (with-fluids ((%default-port-encoding
  1212. "UTF-8"))
  1213. (call-with-output-string
  1214. (lambda (port)
  1215. (write prologue port)
  1216. (write
  1217. `(exit
  1218. ,(match exp
  1219. ((_ ...)
  1220. (remove module-form? exp))
  1221. (_ `(,exp))))
  1222. port))))
  1223. ;; The references don't really matter
  1224. ;; since the builder is always used in
  1225. ;; conjunction with the drv that needs
  1226. ;; it. For clarity, we add references
  1227. ;; to the subset of INPUTS that are
  1228. ;; sources, avoiding references to other
  1229. ;; .drv; otherwise, BUILDER's hash would
  1230. ;; depend on those, even if they are
  1231. ;; fixed-output.
  1232. (filter-map source-path inputs)))
  1233. (mod+go-drv (if (pair? modules)
  1234. (imported+compiled-modules store modules
  1235. #:guile guile-drv
  1236. #:system system)
  1237. '(#f . #f)))
  1238. (mod-dir (car mod+go-drv))
  1239. (go-drv (cdr mod+go-drv))
  1240. (go-dir (and go-drv
  1241. (derivation->output-path go-drv))))
  1242. (derivation store name guile
  1243. `("--no-auto-compile"
  1244. ,@(if mod-dir `("-L" ,mod-dir) '())
  1245. ,builder)
  1246. ;; 'build-expression->derivation' is somewhat deprecated so
  1247. ;; don't bother warning here.
  1248. #:%deprecation-warning? #f
  1249. #:system system
  1250. #:inputs `((,(or guile-for-build (%guile-for-build)))
  1251. (,builder)
  1252. ,@(map cdr inputs)
  1253. ,@(if mod-dir `((,mod-dir) (,go-drv)) '()))
  1254. ;; When MODULES is non-empty, shamelessly clobber
  1255. ;; $GUILE_LOAD_COMPILED_PATH.
  1256. #:env-vars (if go-dir
  1257. `(("GUILE_LOAD_COMPILED_PATH" . ,go-dir)
  1258. ,@(alist-delete "GUILE_LOAD_COMPILED_PATH"
  1259. env-vars))
  1260. env-vars)
  1261. #:hash hash #:hash-algo hash-algo
  1262. #:recursive? recursive?
  1263. #:outputs outputs
  1264. #:references-graphs references-graphs
  1265. #:allowed-references allowed-references
  1266. #:disallowed-references disallowed-references
  1267. #:local-build? local-build?
  1268. #:substitutable? substitutable?
  1269. #:properties properties)))
  1270. ;;;
  1271. ;;; Monadic interface.
  1272. ;;;
  1273. (define built-derivations
  1274. (store-lift build-derivations))
  1275. (define raw-derivation
  1276. (store-lift derivation))