diff options
-rw-r--r-- | emacs/guix-pcomplete.el | 5 | ||||
-rw-r--r-- | gnu-system.am | 1 | ||||
-rw-r--r-- | gnu/build/file-systems.scm | 9 | ||||
-rw-r--r-- | gnu/packages/audio.scm | 27 | ||||
-rw-r--r-- | gnu/packages/bioinformatics.scm | 59 | ||||
-rw-r--r-- | gnu/packages/commencement.scm | 1 | ||||
-rw-r--r-- | gnu/packages/gcc.scm | 26 | ||||
-rw-r--r-- | gnu/packages/gnome.scm | 10 | ||||
-rw-r--r-- | gnu/packages/llvm.scm | 51 | ||||
-rw-r--r-- | gnu/packages/patches/clang-libc-search-path.patch | 19 | ||||
-rw-r--r-- | gnu/packages/patches/guile-linux-syscalls.patch | 22 | ||||
-rw-r--r-- | gnu/packages/ruby.scm | 33 | ||||
-rw-r--r-- | gnu/packages/video.scm | 4 | ||||
-rw-r--r-- | gnu/system/file-systems.scm | 27 | ||||
-rw-r--r-- | guix/gexp.scm | 8 | ||||
-rw-r--r-- | guix/store.scm | 11 | ||||
-rw-r--r-- | tests/gexp.scm | 23 |
17 files changed, 297 insertions, 39 deletions
diff --git a/emacs/guix-pcomplete.el b/emacs/guix-pcomplete.el index fa71dd5e21..dd42556163 100644 --- a/emacs/guix-pcomplete.el +++ b/emacs/guix-pcomplete.el @@ -254,7 +254,8 @@ group - the argument.") "Complete argument for guix COMMAND." (cond ((member command - '("archive" "build" "environment" "lint" "refresh")) + '("archive" "build" "edit" "environment" "lint" "refresh" + "size")) (while t (pcomplete-here (guix-pcomplete-all-packages)))) (t (pcomplete-here* (pcomplete-entries))))) @@ -302,7 +303,7 @@ INPUT is the current partially completed string." ((option? "-m" "--manifest") (complete* (pcomplete-entries))))) - ((and (command? "archive" "build") + ((and (command? "archive" "build" "size") (option? "-s" "--system")) (complete* guix-pcomplete-systems)) diff --git a/gnu-system.am b/gnu-system.am index 81cfd7bfff..a420d71a2f 100644 --- a/gnu-system.am +++ b/gnu-system.am @@ -394,6 +394,7 @@ dist_patch_DATA = \ gnu/packages/patches/calibre-no-updates-dialog.patch \ gnu/packages/patches/cdparanoia-fpic.patch \ gnu/packages/patches/chmlib-inttypes.patch \ + gnu/packages/patches/clang-libc-search-path.patch \ gnu/packages/patches/clucene-pkgconfig.patch \ gnu/packages/patches/cmake-fix-tests.patch \ gnu/packages/patches/coreutils-dummy-man.patch \ diff --git a/gnu/build/file-systems.scm b/gnu/build/file-systems.scm index dc99d60d3d..72c8bd59f3 100644 --- a/gnu/build/file-systems.scm +++ b/gnu/build/file-systems.scm @@ -286,16 +286,13 @@ run a file system check." (when check? (check-file-system source type)) (mkdir-p mount-point) - (mount source mount-point type flags - (if options - (string->pointer options) - %null-pointer)) + (mount source mount-point type flags options) ;; For read-only bind mounts, an extra remount is needed, as per ;; <http://lwn.net/Articles/281157/>, which still applies to Linux 4.0. (when (and (= MS_BIND (logand flags MS_BIND)) (= MS_RDONLY (logand flags MS_RDONLY))) - (mount source mount-point type (logior MS_BIND MS_REMOUNT MS_RDONLY) - %null-pointer)))))) + (let ((flags (logior MS_BIND MS_REMOUNT MS_RDONLY))) + (mount source mount-point type flags #f))))))) ;;; file-systems.scm ends here diff --git a/gnu/packages/audio.scm b/gnu/packages/audio.scm index f6881883bb..6dd4bd7ffe 100644 --- a/gnu/packages/audio.scm +++ b/gnu/packages/audio.scm @@ -1034,6 +1034,33 @@ buffers, and audio capture.") and ALSA.") (license license:gpl3+))) +(define-public raul + (package + (name "raul") + (version "0.8.0") + (source (origin + (method url-fetch) + (uri (string-append "http://download.drobilla.net/raul-" + version ".tar.bz2")) + (sha256 + (base32 + "09ms40xc1x6qli6lxkwn5ibqh62nl9w7dq0b6jh1q2zvnrxwsd8b")))) + (build-system waf-build-system) + (arguments + `(#:python ,python-2 + #:tests? #f)) ; no check target + (inputs + `(("glib" ,glib) + ("boost" ,boost))) + (native-inputs + `(("pkg-config" ,pkg-config))) + (home-page "http://drobilla.net/software/raul/") + (synopsis "Real-time audio utility library") + (description + "Raul (Real-time Audio Utility Library) is a C++ utility library primarily +aimed at audio/musical applications.") + (license license:gpl2+))) + (define-public rubberband (package (name "rubberband") diff --git a/gnu/packages/bioinformatics.scm b/gnu/packages/bioinformatics.scm index 12c9175ed3..8dfaff3e00 100644 --- a/gnu/packages/bioinformatics.scm +++ b/gnu/packages/bioinformatics.scm @@ -780,6 +780,65 @@ analysis (from RNA-Seq), transcription factor binding quantification in ChIP-Seq, and analysis of metagenomic data.") (license license:artistic2.0))) +(define-public fasttree + (package + (name "fasttree") + (version "2.1.8") + (source (origin + (method url-fetch) + (uri (string-append + "http://www.microbesonline.org/fasttree/FastTree-" + version ".c")) + (sha256 + (base32 + "0dzqc9vr9iiiw21y159xfjl2z90vw0y7r4x6456pcaxiy5hd2wmi")))) + (build-system gnu-build-system) + (arguments + `(#:tests? #f ; no "check" target + #:phases + (modify-phases %standard-phases + (delete 'unpack) + (delete 'configure) + (replace 'build + (lambda* (#:key source #:allow-other-keys) + (and (zero? (system* "gcc" + "-O3" + "-finline-functions" + "-funroll-loops" + "-Wall" + "-o" + "FastTree" + source + "-lm")) + (zero? (system* "gcc" + "-DOPENMP" + "-fopenmp" + "-O3" + "-finline-functions" + "-funroll-loops" + "-Wall" + "-o" + "FastTreeMP" + source + "-lm"))))) + (replace 'install + (lambda* (#:key outputs #:allow-other-keys) + (let ((bin (string-append (assoc-ref outputs "out") + "/bin"))) + (mkdir-p bin) + (copy-file "FastTree" + (string-append bin "/FastTree")) + (copy-file "FastTreeMP" + (string-append bin "/FastTreeMP")) + #t)))))) + (home-page "http://www.microbesonline.org/fasttree") + (synopsis "Infers approximately-maximum-likelihood phylogenetic trees") + (description + "FastTree can handle alignments with up to a million of sequences in a +reasonable amount of time and memory. For large alignments, FastTree is +100-1,000 times faster than PhyML 3.0 or RAxML 7.") + (license license:gpl2+))) + (define-public fastx-toolkit (package (name "fastx-toolkit") diff --git a/gnu/packages/commencement.scm b/gnu/packages/commencement.scm index db91bec5da..ebf770bfa7 100644 --- a/gnu/packages/commencement.scm +++ b/gnu/packages/commencement.scm @@ -518,6 +518,7 @@ exec ~a/bin/~a-~a -B~a/lib -Wl,-dynamic-linker -Wl,~a/~a \"$@\"~%" (define libstdc++ ;; Intermediate libstdc++ that will allow us to build the final GCC ;; (remember that GCC-BOOT0 cannot build libstdc++.) + ;; TODO: Write in terms of 'make-libstdc++'. (package-with-bootstrap-guile (package (inherit gcc-4.9) (name "libstdc++") diff --git a/gnu/packages/gcc.scm b/gnu/packages/gcc.scm index beb007e95b..c370fe8212 100644 --- a/gnu/packages/gcc.scm +++ b/gnu/packages/gcc.scm @@ -345,6 +345,32 @@ Go. It also includes runtime support libraries for these languages.") '("gcc-arm-link-spec-fix.patch" "gcc-5.0-libvtv-runpath.patch"))))))) +(define-public (make-libstdc++ gcc) + "Return a libstdc++ package based on GCC. The primary use case is when +using compilers other than GCC." + (package + (inherit gcc) + (name "libstdc++") + (arguments + `(#:out-of-source? #t + #:phases (alist-cons-before + 'configure 'chdir + (lambda _ + (chdir "libstdc++-v3")) + %standard-phases) + #:configure-flags `("--disable-libstdcxx-pch" + ,(string-append "--with-gxx-include-dir=" + (assoc-ref %outputs "out") + "/include")))) + (outputs '("out" "debug")) + (inputs '()) + (native-inputs '()) + (propagated-inputs '()) + (synopsis "GNU C++ standard library"))) + +(define-public libstdc++-4.9 + (make-libstdc++ gcc-4.9)) + (define* (custom-gcc gcc name languages #:key (separate-lib-output? #t)) "Return a custom version of GCC that supports LANGUAGES." (package (inherit gcc) diff --git a/gnu/packages/gnome.scm b/gnu/packages/gnome.scm index 30f834a168..f7a6465eb6 100644 --- a/gnu/packages/gnome.scm +++ b/gnu/packages/gnome.scm @@ -2402,15 +2402,17 @@ settings, themes, mouse settings, and startup of other daemons.") (native-inputs `(("intltool" ,intltool) ("glib" ,glib "bin") + ("gobject-introspection" ,gobject-introspection) ("pkg-config" ,pkg-config))) - (inputs + (propagated-inputs `(("glib" ,glib) ("gmime" ,gmime) - ("libarchive" ,libarchive) + ("libxml2" ,libxml2))) + (inputs + `(("libarchive" ,libarchive) ("libgcrypt" ,libgcrypt) ("nettle" ,nettle) - ("libsoup" ,libsoup) - ("libxml2" ,libxml2))) + ("libsoup" ,libsoup))) (home-page "https://projects.gnome.org/totem") (synopsis "Library to parse and save media playlists for GNOME") (description "Totem-pl-parser is a GObjects-based library to parse and save diff --git a/gnu/packages/llvm.scm b/gnu/packages/llvm.scm index 6cf1fdab0a..47710e69fc 100644 --- a/gnu/packages/llvm.scm +++ b/gnu/packages/llvm.scm @@ -1,6 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2014 Eric Bavier <bavier@member.fsf.org> ;;; Copyright © 2015 Mark H Weaver <mhw@netris.org> +;;; Copyright © 2015 Ludovic Courtès <ludo@gnu.org> ;;; ;;; This file is part of GNU Guix. ;;; @@ -25,6 +26,8 @@ #:use-module (guix build-system gnu) #:use-module (guix build-system cmake) #:use-module (gnu packages) + #:use-module (gnu packages gcc) + #:use-module (gnu packages bootstrap) ;glibc-dynamic-linker #:use-module (gnu packages perl) #:use-module (gnu packages python) #:use-module (gnu packages xml)) @@ -84,7 +87,8 @@ tools as well as libraries with equivalent functionality.") (method url-fetch) (uri (string-append "http://llvm.org/releases/" version "/cfe-" version ".src.tar.xz")) - (sha256 (base32 hash)))) + (sha256 (base32 hash)) + (patches (list (search-patch "clang-libc-search-path.patch"))))) ;; Using cmake allows us to treat llvm as an external library. There ;; doesn't seem to be any way to do this with clang's autotools-based ;; build system. @@ -92,10 +96,53 @@ tools as well as libraries with equivalent functionality.") (native-inputs (package-native-inputs llvm)) (inputs `(("libxml2" ,libxml2) + ("gcc-lib" ,gcc-4.9 "lib") ,@(package-inputs llvm))) (propagated-inputs `(("llvm" ,llvm))) - (arguments `(#:configure-flags '("-DCLANG_INCLUDE_TESTS=True"))) + (arguments + `(#:configure-flags + (list "-DCLANG_INCLUDE_TESTS=True" + + ;; Find libgcc_s, crtbegin.o, and crtend.o. + (string-append "-DGCC_INSTALL_PREFIX=" + (assoc-ref %build-inputs "gcc-lib")) + + ;; Use a sane default include directory. + (string-append "-DC_INCLUDE_DIRS=" + (assoc-ref %build-inputs "libc") + "/include")) + + ;; Don't use '-g' during the build to save space. + #:build-type "Release" + + #:phases (modify-phases %standard-phases + (add-after + 'unpack 'set-glibc-file-names + (lambda* (#:key inputs #:allow-other-keys) + (let ((libc (assoc-ref inputs "libc"))) + ;; Patch the 'getLinuxDynamicLinker' function to that + ;; it uses the right dynamic linker file name. + (substitute* "lib/Driver/Tools.cpp" + (("/lib64/ld-linux-x86-64.so.2") + (string-append libc + ,(glibc-dynamic-linker)))) + + ;; Same for libc's libdir, to allow crt1.o & co. to be + ;; found. + (substitute* "lib/Driver/ToolChains.cpp" + (("@GLIBC_LIBDIR@") + (string-append libc "/lib"))))))))) + + ;; Clang supports the same environment variables as GCC. + (native-search-paths + (list (search-path-specification + (variable "CPATH") + (files '("include"))) + (search-path-specification + (variable "LIBRARY_PATH") + (files '("lib" "lib64"))))) + (home-page "http://clang.llvm.org") (synopsis "C language family frontend for LLVM") (description diff --git a/gnu/packages/patches/clang-libc-search-path.patch b/gnu/packages/patches/clang-libc-search-path.patch new file mode 100644 index 0000000000..327336ac09 --- /dev/null +++ b/gnu/packages/patches/clang-libc-search-path.patch @@ -0,0 +1,19 @@ +Clang attempts to guess file names based on the OS and distro (yes!), +but unfortunately, that doesn't work for us. + +This patch makes it easy to insert libc's $libdir so that Clang passes the +correct absolute file name of crt1.o etc. to 'ld'. + +--- cfe-3.6.0.src/lib/Driver/ToolChains.cpp 2015-02-18 22:03:07.000000000 +0100 ++++ cfe-3.6.0.src/lib/Driver/ToolChains.cpp 2015-06-19 16:37:20.459701044 +0200 +@@ -3085,6 +3085,10 @@ Linux::Linux(const Driver &D, const llvm + + addPathIfExists(SysRoot + "/lib", Paths); + addPathIfExists(SysRoot + "/usr/lib", Paths); ++ ++ // Add libc's lib/ directory to the search path, so that crt1.o, crti.o, ++ // and friends can be found. ++ addPathIfExists("@GLIBC_LIBDIR@", Paths); + } + + bool Linux::HasNativeLLVMSupport() const { diff --git a/gnu/packages/patches/guile-linux-syscalls.patch b/gnu/packages/patches/guile-linux-syscalls.patch index 25a5e90e35..ac74d021d7 100644 --- a/gnu/packages/patches/guile-linux-syscalls.patch +++ b/gnu/packages/patches/guile-linux-syscalls.patch @@ -3,11 +3,9 @@ This patch adds bindings to Linux syscalls for which glibc has symbols. Using the FFI would have been nice, but that's not an option when using a statically-linked Guile in an initrd that doesn't have libc.so around. -diff --git a/libguile/posix.c b/libguile/posix.c -index 324f21b..cbee94d 100644 ---- a/libguile/posix.c -+++ b/libguile/posix.c -@@ -2245,6 +2245,263 @@ scm_init_popen (void) +--- guile-2.0.11/libguile/posix.c.orig 2014-02-28 15:01:27.000000000 -0500 ++++ guile-2.0.11/libguile/posix.c 2015-06-21 14:28:23.624251038 -0400 +@@ -2245,6 +2245,269 @@ } #endif @@ -26,15 +24,18 @@ index 324f21b..cbee94d 100644 +#define FUNC_NAME s_scm_mount +{ + int err; -+ char *c_source, *c_target, *c_type; ++ char *c_source, *c_target, *c_type, *c_data; + unsigned long c_flags; -+ void *c_data; + + c_source = scm_to_locale_string (source); + c_target = scm_to_locale_string (target); + c_type = scm_to_locale_string (type); + c_flags = SCM_UNBNDP (flags) ? 0 : scm_to_ulong (flags); -+ c_data = SCM_UNBNDP (data) ? NULL : scm_to_pointer (data); ++ ++ if (SCM_UNBNDP (data) || scm_is_false (data)) ++ c_data = NULL; ++ else ++ c_data = scm_to_locale_string (data); + + err = mount (c_source, c_target, c_type, c_flags, c_data); + if (err != 0) @@ -44,6 +45,9 @@ index 324f21b..cbee94d 100644 + free (c_target); + free (c_type); + ++ if (c_data != NULL) ++ free (c_data); ++ + if (err != 0) + { + errno = err; @@ -271,5 +275,3 @@ index 324f21b..cbee94d 100644 void scm_init_posix () { --- -2.4.1 diff --git a/gnu/packages/ruby.scm b/gnu/packages/ruby.scm index ff30c4988a..af87cf551f 100644 --- a/gnu/packages/ruby.scm +++ b/gnu/packages/ruby.scm @@ -88,6 +88,39 @@ a focus on simplicity and productivity.") (home-page "https://ruby-lang.org") (license license:ruby))) +(define-public ruby-2.1 + (package (inherit ruby) + (version "2.1.6") + (source + (origin + (method url-fetch) + (uri (string-append "http://cache.ruby-lang.org/pub/ruby/" + (version-major+minor version) + "/ruby-" version ".tar.bz2")) + (sha256 + (base32 + "1sbcmbhadcxk0509svwxbm2vvgmpf3xjxr1397bgp9x46nz36lkv")))) + (arguments + `(#:test-target "test" + #:parallel-tests? #f + #:phases + (alist-cons-before + 'configure 'replace-bin-sh + (lambda _ + (substitute* '("Makefile.in" + "ext/pty/pty.c" + "io.c" + "lib/mkmf.rb" + "process.c") + (("/bin/sh") (which "sh")))) + %standard-phases))) + (native-search-paths + (list (search-path-specification + (variable "GEM_PATH") + (files (list (string-append "lib/ruby/gems/" + (version-major+minor version) + ".0")))))))) + (define-public ruby-1.8 (package (inherit ruby) (version "1.8.7-p374") diff --git a/gnu/packages/video.scm b/gnu/packages/video.scm index b923e47444..c118b2fe50 100644 --- a/gnu/packages/video.scm +++ b/gnu/packages/video.scm @@ -296,14 +296,14 @@ standards (MPEG-2, MPEG-4 ASP/H.263, MPEG-4 AVC/H.264, and VC-1/VMW3).") (define-public ffmpeg (package (name "ffmpeg") - (version "2.7") + (version "2.7.1") (source (origin (method url-fetch) (uri (string-append "http://www.ffmpeg.org/releases/ffmpeg-" version ".tar.bz2")) (sha256 (base32 - "0jl43b63b20db3yia5xxp0hh8zwdbirk5k9p1d7416nq1b5ckfx8")))) + "087pyx1wxvniq3wgj6z80wrb7ampwwsmwndmr7lymzhm4iyvj1vy")))) (build-system gnu-build-system) (inputs `(("fontconfig" ,fontconfig) diff --git a/gnu/system/file-systems.scm b/gnu/system/file-systems.scm index db861baed2..05c77fe3e8 100644 --- a/gnu/system/file-systems.scm +++ b/gnu/system/file-systems.scm @@ -39,6 +39,7 @@ %pseudo-terminal-file-system %devtmpfs-file-system %immutable-store + %control-groups %base-file-systems @@ -152,13 +153,31 @@ file system." (check? #f) (flags '(read-only bind-mount)))) +(define %control-groups + (cons (file-system + (device "cgroup") + (mount-point "/sys/fs/cgroup") + (type "tmpfs") + (check? #f)) + (map (lambda (subsystem) + (file-system + (device "cgroup") + (mount-point (string-append "/sys/fs/cgroup/" subsystem)) + (type "cgroup") + (check? #f) + (options subsystem) + (create-mount-point? #t))) + '("cpuset" "cpu" "cpuacct" "memory" "devices" "freezer" + "blkio" "perf_event" "hugetlb")))) + (define %base-file-systems ;; List of basic file systems to be mounted. Note that /proc and /sys are ;; currently mounted by the initrd. - (list %devtmpfs-file-system - %pseudo-terminal-file-system - %shared-memory-file-system - %immutable-store)) + (append (list %devtmpfs-file-system + %pseudo-terminal-file-system + %shared-memory-file-system + %immutable-store) + %control-groups)) diff --git a/guix/gexp.scm b/guix/gexp.scm index 10056e5a1f..0b5c43e2b8 100644 --- a/guix/gexp.scm +++ b/guix/gexp.scm @@ -157,7 +157,7 @@ cross-compiling.)" (recursive? local-file-recursive?)) ;Boolean (define* (local-file file #:optional (name (basename file)) - #:key (recursive? #t)) + #:key recursive?) "Return an object representing local file FILE to add to the store; this object can be used in a gexp. FILE will be added to the store under NAME--by default the base name of FILE. @@ -167,7 +167,11 @@ designates a flat file and RECURSIVE? is true, its contents are added, and its permission bits are kept. This is the declarative counterpart of the 'interned-file' monadic procedure." - (%local-file file name recursive?)) + ;; Canonicalize FILE so that if it's a symlink, it is resolved. Failing to + ;; do that, when RECURSIVE? is #t, we could end up creating a dangling + ;; symlink in the store, and when RECURSIVE? is #f 'add-to-store' would just + ;; throw an error, both of which are inconvenient. + (%local-file (canonicalize-path file) name recursive?)) (define-gexp-compiler (local-file-compiler (file local-file?) system target) ;; "Compile" FILE by adding it to the store. diff --git a/guix/store.scm b/guix/store.scm index 933708defc..7b13334952 100644 --- a/guix/store.scm +++ b/guix/store.scm @@ -610,11 +610,12 @@ path." store-path))) (lambda (server basename recursive? hash-algo file-name) "Add the contents of FILE-NAME under BASENAME to the store. When -RECURSIVE? is true and FILE-NAME designates a directory, the contents of -FILE-NAME are added recursively; if FILE-NAME designates a flat file and -RECURSIVE? is true, its contents are added, and its permission bits are -kept. HASH-ALGO must be a string such as \"sha256\"." - (let* ((st (stat file-name #f)) +RECURSIVE? is false, FILE-NAME must designate a regular file--not a directory +nor a symlink. When RECURSIVE? is true and FILE-NAME designates a directory, +the contents of FILE-NAME are added recursively; if FILE-NAME designates a +flat file and RECURSIVE? is true, its contents are added, and its permission +bits are kept. HASH-ALGO must be a string such as \"sha256\"." + (let* ((st (false-if-exception (lstat file-name))) (args `(,st ,basename ,recursive? ,hash-algo)) (cache (nix-server-add-to-store-cache server))) (or (and st (hash-ref cache args)) diff --git a/tests/gexp.scm b/tests/gexp.scm index 7e14073fd4..32031663f5 100644 --- a/tests/gexp.scm +++ b/tests/gexp.scm @@ -101,7 +101,7 @@ (let* ((file (search-path %load-path "guix.scm")) (local (local-file file)) (exp (gexp (display (ungexp local)))) - (intd (add-to-store %store (basename file) #t + (intd (add-to-store %store (basename file) #f "sha256" file))) (and (gexp? exp) (match (gexp-inputs exp) @@ -109,6 +109,25 @@ (eq? x local))) (equal? `(display ,intd) (gexp->sexp* exp))))) +(test-assert "one local file, symlink" + (let ((file (search-path %load-path "guix.scm")) + (link (tmpnam))) + (dynamic-wind + (const #t) + (lambda () + (symlink (canonicalize-path file) link) + (let* ((local (local-file link "my-file" #:recursive? #f)) + (exp (gexp (display (ungexp local)))) + (intd (add-to-store %store "my-file" #f + "sha256" file))) + (and (gexp? exp) + (match (gexp-inputs exp) + (((x "out")) + (eq? x local))) + (equal? `(display ,intd) (gexp->sexp* exp))))) + (lambda () + (false-if-exception (delete-file link)))))) + (test-assert "one plain file" (let* ((file (plain-file "hi" "Hello, world!")) (exp (gexp (display (ungexp file)))) @@ -360,7 +379,7 @@ (test-assertm "gexp->derivation, local-file" (mlet* %store-monad ((file -> (search-path %load-path "guix.scm")) - (intd (interned-file file)) + (intd (interned-file file #:recursive? #f)) (local -> (local-file file)) (exp -> (gexp (begin (stat (ungexp local)) |