Functional Package Management with Guix Ludovic Courtès
Total Page:16
File Type:pdf, Size:1020Kb
Functional Package Management with Guix Ludovic Courtès To cite this version: Ludovic Courtès. Functional Package Management with Guix. European Lisp Symposium, Jun 2013, Madrid, Spain. hal-00824004 HAL Id: hal-00824004 https://hal.inria.fr/hal-00824004 Submitted on 20 May 2013 HAL is a multi-disciplinary open access L’archive ouverte pluridisciplinaire HAL, est archive for the deposit and dissemination of sci- destinée au dépôt et à la diffusion de documents entific research documents, whether they are pub- scientifiques de niveau recherche, publiés ou non, lished or not. The documents may come from émanant des établissements d’enseignement et de teaching and research institutions in France or recherche français ou étrangers, des laboratoires abroad, or from public or private research centers. publics ou privés. Functional Package Management with Guix Ludovic Courtès Bordeaux, France [email protected] ABSTRACT 1. INTRODUCTION We describe the design and implementation of GNU Guix, a GNU Guix1 is a purely functional package manager for the purely functional package manager designed to support a com- GNU system [20], and in particular GNU/Linux. Pack- plete GNU/Linux distribution. Guix supports transactional age management consists in all the activities that relate upgrades and roll-backs, unprivileged package management, to building packages from source, honoring the build-time per-user profiles, and garbage collection. It builds upon the and run-time dependencies on packages, installing, removing, low-level build and deployment layer of the Nix package man- and upgrading packages in user environments. In addition ager. Guix uses Scheme as its programming interface. In to these standard features, Guix supports transactional up- particular, we devise an embedded domain-specific language grades and roll-backs, unprivileged package management, (EDSL) to describe and compose packages. We demonstrate per-user profiles, and garbage collection. Guix comes with a how it allows us to benefit from the host general-purpose distribution of user-land free software packages. programming language while not compromising on expres- siveness. Second, we show the use of Scheme to write build Guix seeks to empower users in several ways: by offering the programs, leading to a \two-tier" programming system. uncommon features listed above, by providing the tools that allow users to formally correlate a binary package and the Categories and Subject Descriptors \recipes" and source code that led to it|furthering the spirit D.4.5 [Operating Systems]: Reliability; D.4.5 [Operating of the GNU General Public License|, by allowing them to Systems]: System Programs and Utilities; D.1.1 [Software]: customize the distribution, and by lowering the barrier to Applicative (Functional) Programming entry in distribution development. The keys toward these goals are the implementation of a General Terms purely functional package management paradigm, and the use Languages, Management, Reliability of both declarative and lower-level programming interfaces (APIs) embedded in Scheme. To that end, Guix reuses Keywords the package storage and deployment model implemented by Functional package management, Scheme, Embedded domain- the Nix functional package manager [8]. On top of that, it specific language provides Scheme APIs, and in particular embedded domain- specific languages (EDSLs) to describe software packages and their build system. Guix also uses Scheme for programs and libraries that implement the actual package build processes, leading to a \two-tier" system. This paper focuses on the programming techniques imple- mented by Guix. Our contribution is twofold: we demon- strate that use of Scheme and EDSLs achieves expressiveness comparable to that of Nix's DSL while providing a richer and extensible programming environment; we further show that Scheme is a profitable alternative to shell tools when it comes to package build programs. Section 2 first gives some background on functional package management and Copyright c 2013 Ludovic Courtès its implementation in Nix. Section 3 describes the design Permission is granted to copy, distribute and/or modify this document un- and implementation of Guix's programming and packaging der the terms of the GNU Free Documentation License, Version 1.3 or any interfaces. Section 4 provides an evaluation and discussion of later version published by the Free Software Foundation; with no Invariant the current status of Guix. Section 5 presents related work, Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the li- and Section 6 concludes. cense is available at http://www.gnu.org/licenses/gfdl.html. The source of this document is available from http://git.sv.gnu. org/cgit/guix/maintenance.git. European Lisp Symposium 2013, Madrid, Spain 1http://www.gnu.org/software/guix/ 2. BACKGROUND not transactional; interrupting them may leave the system in This section describes the functional package management an undefined, or even unusable state, where some of the files paradigm and its implementation in Nix. It then shows how have been altered. Third, rolling back to a previous system Guix differs, and what the rationale is. configuration is practically impossible, due to the absence of a mechanism to formally describe the system's configuration. 2.1 Functional Package Management Functional package management is a paradigm whereby the Nix attempts to address these shortcomings through the build and installation process of a package is considered as a functional software deployment paradigm: installed packages pure function, without any side effects. This is in contrast are immutable, and build processes are regarded as pure with widespread approaches to package build and installation functions, as explained before. Thanks to this property, where the build process usually has access to all the software it implements transparent source/binary deployment: the installed on the machine, regardless of what its declared directory name of a build result encodes all the inputs of its inputs are, and where installation modifies files in place. build process, so if a trusted server provides that directory, then it can be directly downloaded from there, avoiding the Functional package management was pioneered by the Nix need for a local build. package manager [8], which has since matured to the point of managing a complete GNU/Linux distribution [9]. To allow Each user has their own profile, which contains symbolic links build processes to be faithfully regarded as pure functions, to the /nix/store directories of installed packages. Thus, Nix can run them in a chroot environment that only contains users can install packages independently, and the actual the inputs it explicitly declared; thus, it becomes impossible storage is shared when several users install the very same for a build process to use, say, Perl, if that package was package in their profile. Nix comes with a garbage collector, not explicitly declared as an input of the build process. In which has two main functions: with conservative scanning, addition, Nix maps the list of inputs of a build process to a it can determine what packages a build output refers to; and statistically unique file system name; that file name is used to upon user request, it can delete any packages not referenced identify the output of the build process. For instance, a par- via any user profile. ticular build of GNU Emacs may be installed in /nix/store/- v9zic07iar8w90zcy398r745w78a7lqs-emacs-24.2, based on To describe and compose build processes, Nix implements a cryptographic hash of all the inputs to that build process; its own domain-specific language (DSL), which provides a changing the compiler, configuration options, build scripts, convenient interface to the build and storage mechanisms or any other inputs to the build process of Emacs yields described above. The Nix language is purely functional, a different name. This is a form of on-disk memoization, lazy, and dynamically typed; it is similar to that of the Vesta with the /nix/store directory acting as a cache of \function software configuration system [11]. It comes with a handful of results"|i.e., a cache of installed packages. Directories under built-in data types, and around 50 primitives. The primitive /nix/store are immutable. to describe a build process is derivation. This direct mapping from build inputs to the result's directory 1: derivation { name is basis of the most important properties of a functional 2: name = "example-1.0"; package manager. It means that build processes are regarded 3: builder = "${./static-bash}"; as referentially transparent. To put it differently, instead 4: args = [ "-c" "echo hello > $out" ]; of merely providing pre-built binaries and/or build recipes, 5: system = "x86_64-linux"; functional package managers provide binaries, build recipes, 6: } and in effect a guarantee that a given binary matches a given build recipe. Figure 1: Call to the derivation primitive in the Nix language. 2.2 Nix The idea of purely functional package started by making an Figure 1 shows code that calls the derivation function with analogy between programming language paradigms and soft- one argument, which is a dictionary. It expects at least ware deployment techniques [8]. The authors observed that, the four key/value pairs shown above; together, they define in essence, package management tools typically used on free the build process and its inputs. The result is a derivation, operating systems, such as RPM and Debian's APT, imple- which is essentially the promise of a build. The derivation ment an imperative software deployment paradigm. Package has a low-level on-disk representation independent of the Nix installation, removal, and upgrade are all done in-place, by language|in other words, derivations are to the Nix language mutating the operating system's state. Likewise, changes what assembly is to higher-level programming languages. to the operating system's configuration are done in-place by When this derivation is instantiated|i.e., built|, it runs changing configuration files. the command static-bash -c "echo hello > $out" in a chroot that contains nothing but the static-bash file; in This imperative approach has several drawbacks.