From mboxrd@z Thu Jan 1 00:00:00 1970 From: ludo@gnu.org (Ludovic =?utf-8?Q?Court=C3=A8s?=) Subject: Re: G expressions Date: Mon, 28 Apr 2014 23:45:10 +0200 Message-ID: <87lhup2knt.fsf@gnu.org> References: <871twneldl.fsf@gnu.org> <87fvkxew6j.fsf@gnu.org> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:58963) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WetMe-0007oy-RC for guix-devel@gnu.org; Mon, 28 Apr 2014 17:45:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WetMP-00033m-QF for guix-devel@gnu.org; Mon, 28 Apr 2014 17:45:28 -0400 Received: from hera.aquilenet.fr ([2a01:474::1]:49056) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WetMP-00033P-C0 for guix-devel@gnu.org; Mon, 28 Apr 2014 17:45:13 -0400 Received: from localhost (localhost [127.0.0.1]) by hera.aquilenet.fr (Postfix) with ESMTP id C0A8E570 for ; Mon, 28 Apr 2014 23:45:11 +0200 (CEST) Received: from hera.aquilenet.fr ([127.0.0.1]) by localhost (hera.aquilenet.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id TAMYmorT6HVS for ; Mon, 28 Apr 2014 23:45:11 +0200 (CEST) Received: from pluto (reverse-83.fdn.fr [80.67.176.83]) by hera.aquilenet.fr (Postfix) with ESMTPSA id 42AE2504 for ; Mon, 28 Apr 2014 23:45:11 +0200 (CEST) In-Reply-To: <87fvkxew6j.fsf@gnu.org> ("Ludovic \=\?utf-8\?Q\?Court\=C3\=A8s\=22'\?\= \=\?utf-8\?Q\?s\?\= message of "Mon, 28 Apr 2014 09:43:16 +0200") List-Id: "Development of GNU Guix and the GNU System distribution." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-devel-bounces+gcggd-guix-devel=m.gmane.org@gnu.org Sender: guix-devel-bounces+gcggd-guix-devel=m.gmane.org@gnu.org To: guix-devel@gnu.org Merged! Here=E2=80=99s the documentation. Comments and bug reports welcome! Ludo=E2=80=99. 4.6 G-Expressions =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D So we have =E2=80=9Cderivations=E2=80=9D, which represent a sequence of bui= ld actions to be performed to produce an item in the store (*note Derivations::). Those build actions are performed when asking the daemon to actually build the derivations; they are run by the daemon in a container (*note Invoking guix-daemon::). It should come as no surprise that we like to write those build actions in Scheme. When we do that, we end up with two "strata" of Scheme code(1): the =E2=80=9Chost code=E2=80=9D=E2=80=94code that defines p= ackages, talks to the daemon, etc.=E2=80=94and the =E2=80=9Cbuild code=E2=80=9D=E2=80=94code that= actually performs build actions, such as making directories, invoking =E2=80=98make=E2=80=99, etc. To describe a derivation and its build actions, one typically needs to embed build code inside host code. It boils down to manipulating build code as data, and Scheme=E2=80=99s homoiconicity=E2=80=94code has a d= irect representation as data=E2=80=94comes in handy for that. But we need more t= han Scheme=E2=80=99s normal =E2=80=98quasiquote=E2=80=99 mechanism to construct= build expressions. The =E2=80=98(guix gexp)=E2=80=99 module implements "G-expressions", a f= orm of S-expressions adapted to build expressions. G-expressions, or "gexps", consist essentially in three syntactic forms: =E2=80=98gexp=E2=80=99, =E2= =80=98ungexp=E2=80=99, and =E2=80=98ungexp-splicing=E2=80=99 (or simply: =E2=80=98#~=E2=80=99, =E2=80= =98#$=E2=80=99, and =E2=80=98#$@=E2=80=99), which are comparable respectively to =E2=80=98quasiquote=E2=80=99, =E2=80=98unquote= =E2=80=99, and =E2=80=98unquote-splicing=E2=80=99 (*note =E2=80=98quasiquote=E2=80=99: (gu= ile)Expression Syntax.). However, there are major differences: =E2=80=A2 Gexps are meant to be written to a file and run or manipulated= by other processes. =E2=80=A2 When a package or derivation is unquoted inside a gexp, the re= sult is as if its output file name had been introduced. =E2=80=A2 Gexps carry information about the packages or derivations they refer to, and these dependencies are automatically added as inputs to the build processes that use them. To illustrate the idea, here is an example of a gexp: (define build-exp #~(begin (mkdir #$output) (chdir #$output) (symlink (string-append #$coreutils "/bin/ls") "list-files"))) This gexp can be passed to =E2=80=98gexp->derivation=E2=80=99; we obtain= a derivation that builds a directory containing exactly one symlink to =E2=80=98/gnu/store/=E2=80=A6-coreutils-8.22/bin/ls=E2=80=99: (gexp->derivation "the-thing" build-exp) As one would expect, the =E2=80=98"/gnu/store/=E2=80=A6-coreutils"=E2=80= =99 string is substituted to the reference to the COREUTILS package in the actual build code, and COREUTILS is automatically made an input to the derivation. Likewise, =E2=80=98#$output=E2=80=99 (equivalent to =E2=80=98(= ungexp output)=E2=80=99) is replaced by a string containing the derivation=E2=80=99s output directory n= ame. The syntactic form to construct gexps is summarized below. -- Scheme Syntax: #~ EXP -- Scheme Syntax: (gexp EXP) Return a G-expression containing EXP. EXP may contain one or more of the following forms: =E2=80=98#$OBJ=E2=80=99 =E2=80=98(ungexp OBJ)=E2=80=99 Introduce a reference to OBJ. OBJ may be a package or a derivation, in which case the =E2=80=98ungexp=E2=80=99 form is re= placed by its output file name=E2=80=94e.g., =E2=80=98"/gnu/store/=E2=80=A6-cor= eutils-8.22=E2=80=99. If OBJ is a list, it is traversed and any package or derivation references are substituted similarly. If OBJ is another gexp, its contents are inserted and its dependencies are added to those of the containing gexp. If OBJ is another kind of object, it is inserted as is. =E2=80=98#$PACKAGE-OR-DERIVATION:OUTPUT=E2=80=99 =E2=80=98(ungexp PACKAGE-OR-DERIVATION OUTPUT)=E2=80=99 This is like the form above, but referring explicitly to the OUTPUT of PACKAGE-OR-DERIVATION=E2=80=94this is useful when PACKAGE-OR-DERIVATION produces multiple outputs (*note Packages with Multiple Outputs::). =E2=80=98#$output[:OUTPUT]=E2=80=99 =E2=80=98(ungexp output [OUTPUT])=E2=80=99 Insert a reference to derivation output OUTPUT, or to the main output when OUTPUT is omitted. This only makes sense for gexps passed to =E2=80=98gexp->derivati= on=E2=80=99. =E2=80=98#$@LST=E2=80=99 =E2=80=98(ungexp-splicing LST)=E2=80=99 Like the above, but splices the contents of LST inside the containing list. G-expressions created by =E2=80=98gexp=E2=80=99 or =E2=80=98#~=E2=80= =99 are run-time objects of the =E2=80=98gexp?=E2=80=99 type (see below.) -- Scheme Procedure: gexp? OBJ Return =E2=80=98#t=E2=80=99 if OBJ is a G-expression. G-expressions are meant to be written to disk, either as code building some derivation, or as plain files in the store. The monadic procedures below allow you to do that (*note The Store Monad::, for more information about monads.) -- Monadic Procedure: gexp->derivation NAME EXP [#:system (%current-system)] [#:inputs '()] [#:hash #f] [#:hash-algo #f] [#:recursive? #f] [#:env-vars '()] [#:modules '()] [#:references-graphs #f] [#:local-build? #f] [#:guile-for-build #f] Return a derivation NAME that runs EXP (a gexp) with GUILE-FOR-BUILD (a derivation) on SYSTEM. Make MODULES available in the evaluation context of EXP; MODULES is a list of names of Guile modules from the current search path to be copied in the store, compiled, and made available in the load path during the execution of EXP=E2=80=94e.g., =E2=80=98((guix build utils)= (guix build gnu-build-system))=E2=80=99. The other arguments are as for =E2=80=98derivation=E2=80=99. -- Monadic Procedure: gexp->script NAME EXP Return an executable script NAME that runs EXP using GUILE with MODULES in its search path. The example below builds a script that simply invokes the =E2=80=98ls= =E2=80=99 command: (use-modules (guix gexp) (gnu packages base)) (gexp->script "list-files" #~(execl (string-append #$coreutils "/bin/ls") "ls")) When =E2=80=9Crunning=E2=80=9D it through the store (*note =E2=80=98ru= n-with-store=E2=80=99: The Store Monad.), we obtain a derivation that procedures an executable file =E2=80=98/gnu/store/=E2=80=A6-list-files=E2=80=99 along these lin= es: #!/gnu/store/=E2=80=A6-guile-2.0.11/bin/guile -ds !# (execl (string-append "/gnu/store/=E2=80=A6-coreutils-8.22"/bin/l= s") "ls") -- Monadic Procedure: gexp->file NAME EXP Return a derivation that builds a file NAME containing EXP. The resulting file holds references to all the dependencies of EXP or a subset thereof. Of course, in addition to gexps embedded in =E2=80=9Chost=E2=80=9D code,= there are also modules containing build tools. To make it clear that they are meant to be used in the build stratum, these modules are kept in the =E2=80=98(guix build =E2=80=A6)=E2=80=99 name space. ---------- Footnotes ---------- (1) The term "stratum" in this context was coined by Manuel Serrano et al. in the context of their work on Hop.