From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp2 ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms11 with LMTPS id kKLfKSJMm18tZwAA0tVLHw (envelope-from ) for ; Thu, 29 Oct 2020 23:11:30 +0000 Received: from aspmx1.migadu.com ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp2 with LMTPS id CRmfJSJMm19hXQAAB5/wlQ (envelope-from ) for ; Thu, 29 Oct 2020 23:11:30 +0000 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 4D41B9400D3 for ; Thu, 29 Oct 2020 23:11:30 +0000 (UTC) Received: from localhost ([::1]:44954 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kYH4r-0007Xr-4T for larch@yhetil.org; Thu, 29 Oct 2020 19:11:29 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:54750) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kYH4S-0007RD-Ai for guix-patches@gnu.org; Thu, 29 Oct 2020 19:11:04 -0400 Received: from debbugs.gnu.org ([209.51.188.43]:43756) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kYH4S-0006RX-1F for guix-patches@gnu.org; Thu, 29 Oct 2020 19:11:04 -0400 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1kYH4R-0000PZ-Sg for guix-patches@gnu.org; Thu, 29 Oct 2020 19:11:03 -0400 X-Loop: help-debbugs@gnu.org Subject: [bug#44321] [PATCH 6/6] doc: Add "Defining Package Variants" section. Resent-From: Ludovic =?UTF-8?Q?Court=C3=A8s?= Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Thu, 29 Oct 2020 23:11:03 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 44321 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 44321@debbugs.gnu.org Cc: Ludovic =?UTF-8?Q?Court=C3=A8s?= Received: via spool by 44321-submit@debbugs.gnu.org id=B44321.16040130281498 (code B ref 44321); Thu, 29 Oct 2020 23:11:03 +0000 Received: (at 44321) by debbugs.gnu.org; 29 Oct 2020 23:10:28 +0000 Received: from localhost ([127.0.0.1]:55297 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kYH3r-0000O0-NB for submit@debbugs.gnu.org; Thu, 29 Oct 2020 19:10:28 -0400 Received: from eggs.gnu.org ([209.51.188.92]:54500) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kYH3g-0000Mg-Rm for 44321@debbugs.gnu.org; Thu, 29 Oct 2020 19:10:17 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]:49477) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kYH3b-0006Aa-Lb; Thu, 29 Oct 2020 19:10:11 -0400 Received: from [2a01:e0a:1d:7270:af76:b9b:ca24:c465] (port=50412 helo=gnu.org) by fencepost.gnu.org with esmtpsa (TLS1.2:DHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.82) (envelope-from ) id 1kYH3b-0007CN-21; Thu, 29 Oct 2020 19:10:11 -0400 From: Ludovic =?UTF-8?Q?Court=C3=A8s?= Date: Fri, 30 Oct 2020 00:10:00 +0100 Message-Id: <20201029231000.14568-6-ludo@gnu.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201029231000.14568-1-ludo@gnu.org> References: <20201029231000.14568-1-ludo@gnu.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-Spam-Score: -3.3 (---) X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+larch=yhetil.org@gnu.org Sender: "Guix-patches" X-Scanner: scn0 Authentication-Results: aspmx1.migadu.com; dkim=none; dmarc=pass (policy=none) header.from=gnu.org; spf=pass (aspmx1.migadu.com: domain of guix-patches-bounces@gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=guix-patches-bounces@gnu.org X-Spam-Score: 3.49 X-TUID: Bc12Ns/zvd29 * doc/guix.texi (Defining Packages): Move documentation of 'package-input-rewriting' & co. to... (Defining Package Variants): ... here. New node. Also document 'inherit' and 'options->transformation'. --- doc/guix.texi | 278 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 204 insertions(+), 74 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index 22bddf10e3..831ee3f881 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -253,6 +253,7 @@ Programming Interface * Package Modules:: Packages from the programmer's viewpoint. * Defining Packages:: Defining new packages. +* Defining Package Variants:: Customizing packages. * Build Systems:: Specifying how packages are built. * Build Phases:: Phases of the build process of a package. * Build Utilities:: Helpers for your package definitions and more. @@ -260,7 +261,7 @@ Programming Interface * Derivations:: Low-level interface to package derivations. * The Store Monad:: Purely functional interface to the store. * G-Expressions:: Manipulating build expressions. -* Invoking guix repl:: Programming Guix in Guile. +* Invoking guix repl:: Programming Guix in Guile Defining Packages @@ -6204,6 +6205,7 @@ package definitions. @menu * Package Modules:: Packages from the programmer's viewpoint. * Defining Packages:: Defining new packages. +* Defining Package Variants:: Customizing packages. * Build Systems:: Specifying how packages are built. * Build Phases:: Phases of the build process of a package. * Build Utilities:: Helpers for your package definitions and more. @@ -6473,79 +6475,8 @@ and operating system, such as @code{"aarch64-linux-gnu"} (@pxref{Specifying Target Triplets,,, autoconf, Autoconf}). @end deffn -@cindex package transformations -@cindex input rewriting -@cindex dependency tree rewriting -Packages can be manipulated in arbitrary ways. An example of a useful -transformation is @dfn{input rewriting}, whereby the dependency tree of -a package is rewritten by replacing specific inputs by others: - -@deffn {Scheme Procedure} package-input-rewriting @var{replacements} @ - [@var{rewrite-name}] [#:deep? #t] -Return a procedure that, when passed a package, replaces its direct and -indirect dependencies, including implicit inputs when @var{deep?} is -true, according to @var{replacements}. @var{replacements} is a list of -package pairs; the first element of each pair is the package to replace, -and the second one is the replacement. - -Optionally, @var{rewrite-name} is a one-argument procedure that takes -the name of a package and returns its new name after rewrite. -@end deffn - -@noindent -Consider this example: - -@lisp -(define libressl-instead-of-openssl - ;; This is a procedure to replace OPENSSL by LIBRESSL, - ;; recursively. - (package-input-rewriting `((,openssl . ,libressl)))) - -(define git-with-libressl - (libressl-instead-of-openssl git)) -@end lisp - -@noindent -Here we first define a rewriting procedure that replaces @var{openssl} -with @var{libressl}. Then we use it to define a @dfn{variant} of the -@var{git} package that uses @var{libressl} instead of @var{openssl}. -This is exactly what the @option{--with-input} command-line option does -(@pxref{Package Transformation Options, @option{--with-input}}). - -The following variant of @code{package-input-rewriting} can match packages to -be replaced by name rather than by identity. - -@deffn {Scheme Procedure} package-input-rewriting/spec @var{replacements} [#:deep? #t] -Return a procedure that, given a package, applies the given -@var{replacements} to all the package graph, including implicit inputs -unless @var{deep?} is false. @var{replacements} is a list of -spec/procedures pair; each spec is a package specification such as -@code{"gcc"} or @code{"guile@@2"}, and each procedure takes a matching -package and returns a replacement for that package. -@end deffn - -The example above could be rewritten this way: - -@lisp -(define libressl-instead-of-openssl - ;; Replace all the packages called "openssl" with LibreSSL. - (package-input-rewriting/spec `(("openssl" . ,(const libressl))))) -@end lisp - -The key difference here is that, this time, packages are matched by spec and -not by identity. In other words, any package in the graph that is called -@code{openssl} will be replaced. - -A more generic procedure to rewrite a package dependency graph is -@code{package-mapping}: it supports arbitrary changes to nodes in the -graph. - -@deffn {Scheme Procedure} package-mapping @var{proc} [@var{cut?}] [#:deep? #f] -Return a procedure that, given a package, applies @var{proc} to all the packages -depended on and returns the resulting package. The procedure stops recursion -when @var{cut?} returns true for a given package. When @var{deep?} is true, @var{proc} is -applied to implicit inputs as well. -@end deffn +Once you have package definitions, you can easily define @emph{variants} +of those packages. @xref{Defining Package Variants}, for more on that. @menu * package Reference:: The package data type. @@ -6903,6 +6834,200 @@ commit: @end lisp @end deftp +@node Defining Package Variants +@section Defining Package Variants + +@cindex customizing packages +@cindex variants, of packages +One of the nice things with Guix is that, given a package definition, +you can easily @emph{derive} variants of that package---for a different +upstream version, with different dependencies, different compilation +options, and so on. Some of these custom packages can be defined +straight from the command line (@pxref{Package Transformation Options}). +This section describes how to define package variants in code. This can +be useful in ``manifests'' (@pxref{profile-manifest, +@option{--manifest}}) and in your own package collection +(@pxref{Creating a Channel}), among others! + +@cindex inherit, for package definitions +As discussed earlier, packages are first-class objects in the Scheme +language. The @code{(guix packages)} module provides the @code{package} +construct to define new package objects (@pxref{package Reference}). +The easiest way to define a package variant is using the @code{inherit} +keyword together with @code{package}. This allows you to inherit from a +package definition while overriding the fields you want. + +For example, given the @code{hello} variable, which contains a +definition for the current version of GNU@tie{}Hello, here's how you +would define a variant for version 2.2 (released in 2006, it's +vintage!): + +@lisp +(use-modules (gnu packages base)) ;for 'hello' + +(define hello-2.2 + (package + (inherit hello) + (version "2.2") + (source (origin + (method url-fetch) + (uri (string-append "mirror://gnu/hello/hello-" version + ".tar.gz")) + (sha256 + (base32 + "0lappv4slgb5spyqbh6yl5r013zv72yqg2pcl30mginf3wdqd8k9")))))) +@end lisp + +The example above corresponds to what the @option{--with-source} package +transformation option does. Essentially @code{hello-2.2} preserves all +the fields of @code{hello}, except @code{version} and @code{source}, +which it overrides. Note that the original @code{hello} variable is +still there, in the @code{(gnu packages base)} module, unchanged. When +you define a custom package like this, you are really @emph{adding} a +new package definition; the original one remains available. + +You can just as well define variants with a different set of +dependencies than the original package. For example, the default +@code{gdb} package depends on @code{guile}, but since that is an +optional dependency, you can define a variant that removes that +dependency like so: + +@lisp +(use-modules (gnu packages gdb) ;for 'gdb' + (srfi srfi-1)) ;for 'alist-delete' + +(define gdb-sans-guile + (package + (inherit gdb) + (inputs (alist-delete "guile" + (package-inputs gdb))))) +@end lisp + +@cindex package transformations +These are pretty simple package variants. As a convenience, the +@code{(guix transformations)} module provides a high-level interface +that directly maps to package transformation options (@pxref{Package +Transformation Options}): + +@deffn {Scheme Procedure} options->transformation @var{opts} +Return a procedure that, when passed an object to build (package, +derivation, etc.), applies the transformations specified by @var{opts} and returns +the resulting objects. @var{opts} must be a list of symbol/string pairs such as: + +@example +((with-branch . "guile-gcrypt=master") + (without-tests . "libgcrypt")) +@end example + +Each symbol names a transformation and the corresponding string is an argument +to that transformation. +@end deffn + +For instance, a manifest equivalent to this command: + +@example +guix build guix \ + --with-branch=guile-gcrypt=master \ + --with-debug-info=zlib +@end example + +@noindent +... would look like this: + +@lisp +(use-modules (guix transformations)) + +(define transform + ;; The package transformation procedure. + (options->transformation + '((with-branch . "guile-gcrypt=master") + (with-debug-info . "zlib")))) + +(packages->manifest + (list (transform (specification->package "guix")))) +@end lisp + +@cindex input rewriting +@cindex dependency graph rewriting +The @code{options->transformation} procedure is convenient, but it's +perhaps also not as flexible as you may like. How is it implemented? +The astute reader probably noticed that most package transformation +options go beyond the superficial changes shown in the first examples of +this section: they involve @dfn{input rewriting}, whereby the dependency +graph of a package is rewritten by replacing specific inputs by others. + +Dependency graph rewriting, for the purposes of swapping packages in the +graph, is what the @code{package-input-rewriting} procedure in +@code{(guix packages)} implements. + +@deffn {Scheme Procedure} package-input-rewriting @var{replacements} @ + [@var{rewrite-name}] [#:deep? #t] +Return a procedure that, when passed a package, replaces its direct and +indirect dependencies, including implicit inputs when @var{deep?} is +true, according to @var{replacements}. @var{replacements} is a list of +package pairs; the first element of each pair is the package to replace, +and the second one is the replacement. + +Optionally, @var{rewrite-name} is a one-argument procedure that takes +the name of a package and returns its new name after rewrite. +@end deffn + +@noindent +Consider this example: + +@lisp +(define libressl-instead-of-openssl + ;; This is a procedure to replace OPENSSL by LIBRESSL, + ;; recursively. + (package-input-rewriting `((,openssl . ,libressl)))) + +(define git-with-libressl + (libressl-instead-of-openssl git)) +@end lisp + +@noindent +Here we first define a rewriting procedure that replaces @var{openssl} +with @var{libressl}. Then we use it to define a @dfn{variant} of the +@var{git} package that uses @var{libressl} instead of @var{openssl}. +This is exactly what the @option{--with-input} command-line option does +(@pxref{Package Transformation Options, @option{--with-input}}). + +The following variant of @code{package-input-rewriting} can match packages to +be replaced by name rather than by identity. + +@deffn {Scheme Procedure} package-input-rewriting/spec @var{replacements} [#:deep? #t] +Return a procedure that, given a package, applies the given +@var{replacements} to all the package graph, including implicit inputs +unless @var{deep?} is false. @var{replacements} is a list of +spec/procedures pair; each spec is a package specification such as +@code{"gcc"} or @code{"guile@@2"}, and each procedure takes a matching +package and returns a replacement for that package. +@end deffn + +The example above could be rewritten this way: + +@lisp +(define libressl-instead-of-openssl + ;; Replace all the packages called "openssl" with LibreSSL. + (package-input-rewriting/spec `(("openssl" . ,(const libressl))))) +@end lisp + +The key difference here is that, this time, packages are matched by spec and +not by identity. In other words, any package in the graph that is called +@code{openssl} will be replaced. + +A more generic procedure to rewrite a package dependency graph is +@code{package-mapping}: it supports arbitrary changes to nodes in the +graph. + +@deffn {Scheme Procedure} package-mapping @var{proc} [@var{cut?}] [#:deep? #f] +Return a procedure that, given a package, applies @var{proc} to all the packages +depended on and returns the resulting package. The procedure stops recursion +when @var{cut?} returns true for a given package. When @var{deep?} is true, @var{proc} is +applied to implicit inputs as well. +@end deffn + + @node Build Systems @section Build Systems @@ -10155,6 +10280,11 @@ that does not respect a @code{#:tests? #f} setting. Therefore, @end table +Wondering how to achieve the same effect using Scheme code, for example +in your manifest, or how to write your own package transformation? +@xref{Defining Package Variants}, for an overview of the programming +interfaces available. + @node Additional Build Options @subsection Additional Build Options -- 2.28.0