gnu guix: the functional gnu/linux distro that's a scheme

58
GNU Guix: the functional GNU/Linux distro that’s a Scheme library Ludovic Court ` es Scheme Workshop 18 September 2016, Nara, Japan

Upload: others

Post on 09-Jan-2022

4 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: GNU Guix: the functional GNU/Linux distro that's a Scheme

GNU Guix:the functional

GNU/Linux distrothat’s a Scheme library

Ludovic Courtes

Scheme Workshop18 September 2016, Nara, Japan

Page 2: GNU Guix: the functional GNU/Linux distro that's a Scheme
Page 3: GNU Guix: the functional GNU/Linux distro that's a Scheme

Functional packagemanagement.

Page 4: GNU Guix: the functional GNU/Linux distro that's a Scheme

$ guix package -i gcc-toolchain coreutils sed grep

...

$ eval ‘guix package --search-paths‘

...

$ guix package --manifest=my-software.scm

...

I

Page 5: GNU Guix: the functional GNU/Linux distro that's a Scheme

Want to hack on Guile?

Page 6: GNU Guix: the functional GNU/Linux distro that's a Scheme

guile-2.0.11

pkg-config-0.29

libffi-3.2.1

readline-6.3

bash-4.3.42 libunistring-0.9.6 libltdl-2.4.6 libgc-7.4.2

gmp-6.1.0ncurses-6.0

bison-3.0.4 libatomic-ops-7.4.2

m4-1.4.17perl-5.22.1

flex-2.6.0

bison-2.7.1indent-2.2.10

Page 7: GNU Guix: the functional GNU/Linux distro that's a Scheme

$ guix environment --container guile

...

$ guix environment --container guile \

--ad-hoc git autoconf automake gdb

...

Page 8: GNU Guix: the functional GNU/Linux distro that's a Scheme

Functional package management paradigm:

1. build process = pure function2. built software = persistent graph

Imposing a Memory Management Discipline on SoftwareDeployment, Dolstra et al., 2004 (Nix package manager)

Page 9: GNU Guix: the functional GNU/Linux distro that's a Scheme

build processeschroot, separate UIDs

Gui

le,m

ake,

etc.

Gui

le,m

ake,

etc.

Gui

le,m

ake,

etc. Guile Scheme

(guix packages)

(guix store)

build daemon

Page 10: GNU Guix: the functional GNU/Linux distro that's a Scheme

build processeschroot, separate UIDs

Gui

le,m

ake,

etc.

Gui

le,m

ake,

etc.

Gui

le,m

ake,

etc. Guile Scheme

(guix packages)

(guix store)

build daemon RPCs

Page 11: GNU Guix: the functional GNU/Linux distro that's a Scheme

build processeschroot, separate UIDs

Gui

le,m

ake,

etc.

Gui

le,m

ake,

etc.

Gui

le,m

ake,

etc. Guile Scheme

(guix packages)

(guix store)

build daemon RPCs

Page 12: GNU Guix: the functional GNU/Linux distro that's a Scheme

$ guix build chibi-scheme

/gnu/store/ h2g4sc09h4... -chibi-scheme-0.7.3

Page 13: GNU Guix: the functional GNU/Linux distro that's a Scheme

$ guix build chibi-scheme

/gnu/store/ h2g4sc09h4... -chibi-scheme-0.7.3

hash of all the dependencies

Page 14: GNU Guix: the functional GNU/Linux distro that's a Scheme

(define hello

(package

(name "hello")

(version "2.8")

(source (origin

(method url-fetch)

(uri (string-append

"http://ftp.gnu.org/.../hello-" version

".tar.gz"))

(sha256 (base32 "0wqd...dz6"))))(build-system gnu-build-system)

(synopsis "An example GNU package")

(description "Produce a friendly greeting.")

(home-page "https://gnu.org/software/hello/")

(license gpl3+)))

;; Yields: /gnu/store/...-hello-2.8

Page 15: GNU Guix: the functional GNU/Linux distro that's a Scheme

Scheme all the way down.

Page 16: GNU Guix: the functional GNU/Linux distro that's a Scheme

(operating-system

(host-name "schememachine")

(timezone "Japan")

(locale "ja_JP.utf8")

(bootloader (grub-configuration (device "/dev/sda")))

(file-systems (cons (file-system

(device "my-root")

(title ’label)

(mount-point "/")

(type "ext4"))

%base-file-systems))

(users (cons (user-account

(name "alice")

(group "users")

(home-directory "/home/alice"))

%base-user-accounts))

(services (cons* (dhcp-client-service)

(lsh-service #:port-number 2222)

%base-services)))

Page 17: GNU Guix: the functional GNU/Linux distro that's a Scheme

Linux-libre

Page 18: GNU Guix: the functional GNU/Linux distro that's a Scheme

Linux-libre

initial RAM disk

Page 19: GNU Guix: the functional GNU/Linux distro that's a Scheme

Linux-libre

initial RAM disk Guile

Page 20: GNU Guix: the functional GNU/Linux distro that's a Scheme

Linux-libre

initial RAM disk

PID 1: GNU Shepherdservices...

Guile

Page 21: GNU Guix: the functional GNU/Linux distro that's a Scheme

Linux-libre

initial RAM disk

PID 1: GNU Shepherdservices...

Guile

Guile

Page 22: GNU Guix: the functional GNU/Linux distro that's a Scheme

Linux-libre

initial RAM disk

PID 1: GNU Shepherdservices...

applications

Guile

Guile

Page 23: GNU Guix: the functional GNU/Linux distro that's a Scheme

Code staging.

Page 24: GNU Guix: the functional GNU/Linux distro that's a Scheme

build processeschroot, separate UIDs

Gui

le,m

ake,

etc.

Gui

le,m

ake,

etc.

Gui

le,m

ake,

etc. Guile Scheme

(guix packages)

(guix store)

build daemon RPCs

Page 25: GNU Guix: the functional GNU/Linux distro that's a Scheme

Staging: take #1(define build-exp

;; Build-side code.

’(symlink "/gnu/store/123...-coreutils-8.25""/gnu/store/abc...-result"))

;; ... with unhygienic global variable:

;; (define %build-inputs

;; ’())

(define inputs

;; What goes into the chroot.

‘(("coreutils" ,coreutils)))

(build-expression->derivation store

"symlink-to-coreutils"

build-exp

#:inputs inputs

)

Page 26: GNU Guix: the functional GNU/Linux distro that's a Scheme

Staging: take #1(define build-exp

;; Build-side code.

’(symlink (assoc-ref %build-inputs "coreutils")

%output))

;; ... with unhygienic global variable:

;; (define %build-inputs

;; ’(("coreutils" . "/gnu/store/...-coreutils-8.25")))

(define inputs

;; What goes into the chroot.

‘(("coreutils" ,coreutils)))

(build-expression->derivation store

"symlink-to-coreutils"

build-exp

#:inputs inputs)

Page 27: GNU Guix: the functional GNU/Linux distro that's a Scheme

Staging: take #1(define build-exp

;; Build-side code.

’(symlink (assoc-ref %build-inputs "coreutils")

%output))

;; ... with unhygienic global variable:

;; (define %build-inputs

;; ’())

(define inputs

;; What goes into the chroot.

‘(("coreutils" ,coreutils)))

(build-expression->derivation store

"symlink-to-coreutils"

build-exp

#:inputs inputs

)

Page 28: GNU Guix: the functional GNU/Linux distro that's a Scheme

Take #2: G-expressions

(define build-exp

;; First-class object that carries info

;; about its dependencies.

(gexp (symlink (ungexp coreutils)

(ungexp output))))

;; Leads to a build script like:

;; (symlink "/gnu/store/123...-coreutils-8.25";; (getenv "out"))

(gexp->derivation "symlink-to-coreutils" build-exp)

Page 29: GNU Guix: the functional GNU/Linux distro that's a Scheme

Take #2: G-expressions

(define build-exp

;; First-class object that carries info

;; about its dependencies.

#~(symlink #$coreutils #$output))

;; Leads to a build script like:

;; (symlink "/gnu/store/123...-coreutils-8.25";; (getenv "out"))

(gexp->derivation "symlink-to-coreutils" build-exp)

Page 30: GNU Guix: the functional GNU/Linux distro that's a Scheme

Take #2: G-expressions

(define build-exp

;; First-class object that carries info

;; about its dependencies.

#~(symlink #$coreutils #$output))

;; Leads to a build script like:

;; (symlink "/gnu/store/h8a...-coreutils-8.25";; (getenv "out"))

(gexp->derivation "symlink-to-coreutils" build-exp

#:system "i686-linux")

Page 31: GNU Guix: the functional GNU/Linux distro that's a Scheme

Cross-Compilation(gexp->derivation "vi"

#~(begin

(mkdir #$output)

(system* (string-append #+coreutils "/bin/ln")

"-s"

(string-append #$emacs "/bin/emacs")

(string-append #$output "/bin/vi")))

)

;; Yields:

;; (begin

;; (mkdir (getenv "out"))

;; (system* (string-append "/gnu/store/123..." "/bin/ln")

;; "-s"

;; (string-append "/gnu/store/345..." ...);; (string-append "/gnu/store/567..." ...)))

Page 32: GNU Guix: the functional GNU/Linux distro that's a Scheme

Cross-Compilation(gexp->derivation "vi"

#~(begin

(mkdir #$output)

(system* (string-append #+coreutils "/bin/ln")

"-s"

(string-append #$emacs "/bin/emacs")

(string-append #$output "/bin/vi")))

#:target "mips64el-linux-gnu")

;; Yields:

;; (begin

;; (mkdir (getenv "out"))

;; (system* (string-append "/gnu/store/123..." "/bin/ln")

;; "-s"

;; (string-append "/gnu/store/9ab..." ...);; (string-append "/gnu/store/fc2..." ...)))

Page 33: GNU Guix: the functional GNU/Linux distro that's a Scheme

Modules

(define build-exp

;; Compile (guix build utils) and add it

;; to the chroot.

(with-imported-modules ’((guix build utils))

#~(begin

(use-modules (guix build utils))

(mkdir-p (string-append #$output "/bin"))

(gexp->derivation "empty-bin-dir" build-exp)

;; ERROR: (guix build utils) not found!

Page 34: GNU Guix: the functional GNU/Linux distro that's a Scheme

Modules

(define build-exp

;; Compile (guix build utils) and add it

;; to the chroot.

(with-imported-modules ’((guix build utils))

#~(begin

(use-modules (guix build utils))

(mkdir-p (string-append #$output "/bin")))

(gexp->derivation "empty-bin-dir" build-exp)

Page 35: GNU Guix: the functional GNU/Linux distro that's a Scheme

Modules & Scripts

(define script

(with-imported-modules (source-module-closure

’((guix build gremlin)))

#~(begin

(use-modules (guix build gremlin)

(ice-9 match))

(match (command-line)

((command argument)

(validate-needed-in-runpath argument))))))

(gexp->script "check-runpath" script)

Page 36: GNU Guix: the functional GNU/Linux distro that's a Scheme

Modules & Initial RAM Disk

(expression->initrd

(with-imported-modules (source-module-closure

’((gnu build linux-boot)

(guix build utils)))

#~(begin

(use-modules (gnu build linux-boot)

(guix build utils))

(boot-system #:mounts ’#$file-systems

#:linux-modules ’#$linux-modules

#:linux-module-directory ’#$kodir)))

Page 37: GNU Guix: the functional GNU/Linux distro that's a Scheme

Defining “Compilers”

(define-gexp-compiler (package-compiler (package <package>)

system target)

;; Return a derivation to build PACKAGE.

(if target

(package->cross-derivation package target system)

(package->derivation package system)))

(define-record-type <plain-file>

(plain-file name content)

...)

(define-gexp-compiler (plain-file-compiler (file <plain-file>)

system target)

;; "Compile" FILE by adding it to the store.

(match file

(($ <plain-file> name content)

(text-file name content))))

Page 38: GNU Guix: the functional GNU/Linux distro that's a Scheme

Defining “Compilers”

(define-gexp-compiler (package-compiler (package <package>)

system target)

;; Return a derivation to build PACKAGE.

(if target

(package->cross-derivation package target system)

(package->derivation package system)))

(define-record-type <plain-file>

(plain-file name content)

...)

(define-gexp-compiler (plain-file-compiler (file <plain-file>)

system target)

;; "Compile" FILE by adding it to the store.

(match file

(($ <plain-file> name content)

(text-file name content))))

Page 39: GNU Guix: the functional GNU/Linux distro that's a Scheme

Compilers & “Expanders”

#~(string-append #$coreutils "/bin/ls")

;; Yields:

;; (string-append "/gnu/store/..." "/bin/ls")

(file-append coreutils "/bin/ls")

;; Yields:

;; "/gnu/store/.../bin/ls"

Page 40: GNU Guix: the functional GNU/Linux distro that's a Scheme

Compilers & “Expanders”

#~(string-append #$coreutils "/bin/ls")

;; Yields:

;; (string-append "/gnu/store/..." "/bin/ls")

(file-append coreutils "/bin/ls")

;; Yields:

;; "/gnu/store/.../bin/ls"

Page 41: GNU Guix: the functional GNU/Linux distro that's a Scheme

Implementation

I gexp macroI <gexp> record typeI gexp->sexp linear in the number of ungexp

Page 42: GNU Guix: the functional GNU/Linux distro that's a Scheme

Limitations

I hygiene, oh my!I modules in scope?I serialization of non-primitive data types?I cross-stage debugging info a la Hop?

Page 43: GNU Guix: the functional GNU/Linux distro that's a Scheme

Related Work

Page 44: GNU Guix: the functional GNU/Linux distro that's a Scheme

syntax-case

I gexps similar in spirit to syntax objectsI ... but staging with gexps is not referentially transparent

Writing Hygienic Macros in Scheme with Syntax-Case, R. KentDybvig, 1992

Page 45: GNU Guix: the functional GNU/Linux distro that's a Scheme

MetaScheme

I referentially transparent (“hygienic”) stagingI ... but PoC is simplistic

I modules in scope?I how to determine which forms introduce bindings?

MetaScheme, or untyped MetaOCaml,http://okmij.org/ftp/meta-programming/, O. Kiselyov, 2008

Page 46: GNU Guix: the functional GNU/Linux distro that's a Scheme

Hop

(define-service (shello6 x)

(<HTML>

(<BODY>

:onclick ~(with-hop ($(service ()

(format "Bonjour ~a" x)))

(lambda (v) (alert v)))

"Hello!")))

Page 47: GNU Guix: the functional GNU/Linux distro that's a Scheme

Hop

I staged code is JavaScript, not SchemeI programmers can express modules in scope for staged

codeI ~ and $ implemented as compiler magic

I ~ expressions are not first-class objects

A Multi-Tier Semantics for Hop, Serrano and Queinnec, 2010

Page 48: GNU Guix: the functional GNU/Linux distro that's a Scheme

Nix language

derivation {

name = "foo";

system = "x86 64-linux";

builder = "${./static-bash}";

args = [ "-c" "echo hello > " $out " ];

}

; in derivation {

name = "bar";

system = "x86 64-linux";

builder = "${./static-bash}";

args = [ "-c"

’’ mkdir -p "$out"

ln -s " ${dep} /some-result" "$out/my-result"

’’ ];

PATH = "${coreutils}/bin";

}

Page 49: GNU Guix: the functional GNU/Linux distro that's a Scheme

Nix language

let dep = derivation {

name = "foo";

system = "x86 64-linux";

builder = "${./static-bash}";

args = [ "-c" "echo hello > " $out " ];

} ; in derivation {

name = "bar";

system = "x86 64-linux";

builder = "${./static-bash}";

args = [ "-c"

’’ mkdir -p "$out"

ln -s " ${dep} /some-result" "$out/my-result"

’’ ];

PATH = "${coreutils}/bin";

}

expands to /nix/store/...-foo

Page 50: GNU Guix: the functional GNU/Linux distro that's a Scheme

Nix language

I has string interpolationI strings retain info about their dependenciesI built into the interpreter

NixOS: A Purely Functional Linux Distribution, Dolstra and Loh, 2008

Page 51: GNU Guix: the functional GNU/Linux distro that's a Scheme
Page 52: GNU Guix: the functional GNU/Linux distro that's a Scheme

Wrap up.

Page 53: GNU Guix: the functional GNU/Linux distro that's a Scheme

Summary

I Guix provides functional OS deploymentI it’s a Scheme library and toolboxI it’s a multi-tier Scheme system

Page 54: GNU Guix: the functional GNU/Linux distro that's a Scheme

Lots of other niceties!

I system service architectureI ... and services written in Scheme (Shepherd, mcron)I the “store monad”!I Emacs integration (awesome!)I whole-system test suite (staging!)I distributed deployment with Guile-SSH (staging!)I ...

Page 55: GNU Guix: the functional GNU/Linux distro that's a Scheme
Page 56: GNU Guix: the functional GNU/Linux distro that's a Scheme

Join us now, share the parens!

I install the distributionI use it, report bugs, add packagesI share your ideas!

Page 57: GNU Guix: the functional GNU/Linux distro that's a Scheme

[email protected] https://gnu.org/software/guix/

Page 58: GNU Guix: the functional GNU/Linux distro that's a Scheme

Copyright c© 2010, 2012–2016 Ludovic Courtes [email protected].

GNU GuixSD logo, CC-BY-SA 4.0, https://gnu.org/s/guix/graphicsCopyright of other images included in this document is held by their respective owners.

This work is licensed under the Creative Commons Attribution-Share Alike 3.0 License. To view acopy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/ or send a letter toCreative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.

At your option, you may instead copy, distribute and/or modify this document under the terms of theGNU Free Documentation License, Version 1.3 or any later version published by the Free SoftwareFoundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of thelicense 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.