diff options
author | Mark H Weaver <mhw@netris.org> | 2018-01-19 23:59:20 -0500 |
---|---|---|
committer | Mark H Weaver <mhw@netris.org> | 2018-01-19 23:59:20 -0500 |
commit | e074a655dd6497daafbd62737e3b63f3d5aa7985 (patch) | |
tree | 2b198ba5c664cdd58e155f3c0113d1cebde0fc91 /guix | |
parent | 6d7b26a39faf42c37f15dc64a30a77e5e194ea23 (diff) | |
parent | ccb5cac17be98aaa9c3225605d6170c675d8e8e6 (diff) |
Merge branch 'master' into core-updates
Diffstat (limited to 'guix')
-rw-r--r-- | guix/build/go-build-system.scm | 10 | ||||
-rw-r--r-- | guix/build/ruby-build-system.scm | 184 | ||||
-rw-r--r-- | guix/packages.scm | 5 | ||||
-rw-r--r-- | guix/scripts/offload.scm | 72 | ||||
-rw-r--r-- | guix/scripts/system.scm | 4 | ||||
-rw-r--r-- | guix/ssh.scm | 118 | ||||
-rw-r--r-- | guix/ui.scm | 11 |
7 files changed, 288 insertions, 116 deletions
diff --git a/guix/build/go-build-system.scm b/guix/build/go-build-system.scm index eaad9d8751..3114067aa9 100644 --- a/guix/build/go-build-system.scm +++ b/guix/build/go-build-system.scm @@ -37,7 +37,7 @@ ;; process for Go libraries, so we use `go install`, which preserves the ;; results. [0] -;; Go software is developed and built within a particular filesystem hierarchy +;; Go software is developed and built within a particular file system hierarchy ;; structure called a 'workspace' [1]. This workspace is found by Go ;; via the GOPATH environment variable. Typically, all Go source code ;; and compiled objects are kept in a single workspace, but it is @@ -48,7 +48,7 @@ ;; an 'import path'. The import path is based on the URL of the ;; software's source. Since most source code is provided over the ;; internet, the import path is typically a combination of the remote -;; URL and the source repository's filesystem structure. For example, +;; URL and the source repository's file system structure. For example, ;; the Go port of the common `du` command is hosted on github.com, at ;; <https://github.com/calmh/du>. Thus, the import path is ;; <github.com/calmh/du>. [3] @@ -58,12 +58,12 @@ ;; the go-build-system. ;; ;; Modules of modular Go libraries are named uniquely with their -;; filesystem paths. For example, the supplemental but "standardized" +;; file system paths. For example, the supplemental but "standardized" ;; libraries developed by the Go upstream developers are available at ;; <https://golang.org/x/{net,text,crypto, et cetera}>. The Go IPv4 ;; library's import path is <golang.org/x/net/ipv4>. The source of ;; such modular libraries must be unpacked at the top-level of the -;; filesystem structure of the library. So the IPv4 library should be +;; file system structure of the library. So the IPv4 library should be ;; unpacked to <golang.org/x/net>. This is handled in the ;; go-build-system with the optional #:unpack-path key. ;; @@ -72,7 +72,7 @@ ;; that all modules of modular libraries cannot be built with a single ;; command. Each module must be built individually. This complicates ;; certain cases, and these issues are currently resolved by creating a -;; filesystem union of the required modules of such libraries. I think +;; file system union of the required modules of such libraries. I think ;; this could be improved in future revisions of the go-build-system. ;; ;; [0] `go build`: diff --git a/guix/build/ruby-build-system.scm b/guix/build/ruby-build-system.scm index c2d2766279..09ae2390a5 100644 --- a/guix/build/ruby-build-system.scm +++ b/guix/build/ruby-build-system.scm @@ -21,14 +21,15 @@ (define-module (guix build ruby-build-system) #:use-module ((guix build gnu-build-system) #:prefix gnu:) #:use-module (guix build utils) + #:use-module (ice-9 ftw) #:use-module (ice-9 match) #:use-module (ice-9 popen) + #:use-module (ice-9 rdelim) #:use-module (ice-9 regex) #:use-module (srfi srfi-1) #:use-module (srfi srfi-26) #:export (%standard-phases - ruby-build - gem-home)) + ruby-build)) ;; Commentary: ;; @@ -129,43 +130,179 @@ GEM-FLAGS are passed to the 'gem' invokation, if present." (assoc-ref inputs "ruby")) 1)) (out (assoc-ref outputs "out")) - (gem-home (string-append out "/lib/ruby/gems/" ruby-version ".0")) + (vendor-dir (string-append out "/lib/ruby/vendor_ruby")) (gem-file (first-matching-file "\\.gem$")) (gem-file-basename (basename gem-file)) (gem-name (substring gem-file-basename 0 - (- (string-length gem-file-basename) 4))) - (gem-directory (string-append gem-home "/gems/" gem-name))) - (setenv "GEM_HOME" gem-home) - (mkdir-p gem-home) - (and (apply system* "gem" "install" gem-file - "--local" "--ignore-dependencies" - ;; Executables should go into /bin, not /lib/ruby/gems. - "--bindir" (string-append out "/bin") - gem-flags) + (- (string-length gem-file-basename) 4)))) + (setenv "GEM_VENDOR" vendor-dir) + (and (let ((install-succeeded? + (zero? + (apply system* "gem" "install" gem-file + "--local" "--ignore-dependencies" "--vendor" + ;; Executables should go into /bin, not + ;; /lib/ruby/gems. + "--bindir" (string-append out "/bin") + gem-flags)))) + (or install-succeeded? + (begin + (simple-format #t "installation failed\n") + (let ((failed-output-dir (string-append (getcwd) "/out"))) + (mkdir failed-output-dir) + (copy-recursively out failed-output-dir)) + #f))) (begin ;; Remove the cached gem file as this is unnecessary and contains ;; timestamped files rendering builds not reproducible. - (let ((cached-gem (string-append gem-home "/cache/" gem-file))) + (let ((cached-gem (string-append vendor-dir "/cache/" gem-file))) (log-file-deletion cached-gem) (delete-file cached-gem)) ;; For gems with native extensions, several Makefile-related files ;; are created that contain timestamps or other elements making ;; them not reproducible. They are unnecessary so we remove them. - (if (file-exists? (string-append gem-directory "/ext")) + (if (file-exists? (string-append vendor-dir "/ext")) (begin (for-each (lambda (file) (log-file-deletion file) (delete-file file)) (append - (find-files (string-append gem-home "/doc") + (find-files (string-append vendor-dir "/doc") "page-Makefile.ri") - (find-files (string-append gem-home "/extensions") + (find-files (string-append vendor-dir "/extensions") "gem_make.out") - (find-files (string-append gem-directory "/ext") + (find-files (string-append vendor-dir "/ext") "Makefile"))))) #t)))) +(define* (wrap-ruby-program prog #:key (gem-clear-paths #t) #:rest vars) + "Make a wrapper for PROG. VARS should look like this: + + '(VARIABLE DELIMITER POSITION LIST-OF-DIRECTORIES) + +where DELIMITER is optional. ':' will be used if DELIMITER is not given. + +For example, this command: + + (wrap-ruby-program \"foo\" + '(\"PATH\" \":\" = (\"/gnu/.../bar/bin\")) + '(\"CERT_PATH\" suffix (\"/gnu/.../baz/certs\" + \"/qux/certs\"))) + +will copy 'foo' to '.real/fool' and create the file 'foo' with the following +contents: + + #!location/of/bin/ruby + ENV['PATH'] = \"/gnu/.../bar/bin\" + ENV['CERT_PATH'] = (ENV.key?('CERT_PATH') ? (ENV['CERT_PATH'] + ':') : '') + '/gnu/.../baz/certs:/qux/certs' + load location/of/.real/foo + +This is useful for scripts that expect particular programs to be in $PATH, for +programs that expect particular gems to be in the GEM_PATH. + +This is preferable to wrap-program, which uses a bash script, as this prevents +ruby scripts from being executed with @command{ruby -S ...}. + +If PROG has previously been wrapped by 'wrap-ruby-program', the wrapper is +extended with definitions for VARS." + (define wrapped-file + (string-append (dirname prog) "/.real/" (basename prog))) + + (define already-wrapped? + (file-exists? wrapped-file)) + + (define (last-line port) + ;; Return the last line read from PORT and leave PORT's cursor right + ;; before it. + (let loop ((previous-line-offset 0) + (previous-line "") + (position (seek port 0 SEEK_CUR))) + (match (read-line port 'concat) + ((? eof-object?) + (seek port previous-line-offset SEEK_SET) + previous-line) + ((? string? line) + (loop position line (+ (string-length line) position)))))) + + (define (export-variable lst) + ;; Return a string that exports an environment variable. + (match lst + ((var sep '= rest) + (format #f "ENV['~a'] = '~a'" + var (string-join rest sep))) + ((var sep 'prefix rest) + (format #f "ENV['~a'] = '~a' + (ENV.key?('~a') ? ('~a' + ENV['~a']) : '')" + var (string-join rest sep) var sep var)) + ((var sep 'suffix rest) + (format #f "ENV['~a'] = (ENV.key?('~a') ? (ENV['~a'] + '~a') : '') + '~a'" + var var var sep (string-join rest sep))) + ((var '= rest) + (format #f "ENV['~a'] = '~a'" + var (string-join rest ":"))) + ((var 'prefix rest) + (format #f "ENV['~a'] = '~a' + (ENV.key?('~a') ? (':' + ENV['~a']) : '')" + var (string-join rest ":") var var)) + ((var 'suffix rest) + (format #f "ENV['~a'] = (ENV.key?('~a') ? (ENV['~a'] + ':') : '') + '~a'" + var var var (string-join rest ":"))))) + + (if already-wrapped? + + ;; PROG is already a wrapper: add the new "export VAR=VALUE" lines just + ;; before the last line. + (let* ((port (open-file prog "r+")) + (last (last-line port))) + (for-each (lambda (var) + (display (export-variable var) port) + (newline port)) + vars) + (display last port) + (close-port port)) + + ;; PROG is not wrapped yet: create a shell script that sets VARS. + (let ((prog-tmp (string-append wrapped-file "-tmp"))) + (mkdir-p (dirname prog-tmp)) + (link prog wrapped-file) + + (call-with-output-file prog-tmp + (lambda (port) + (format port + "#!~a~%~a~%~a~%load '~a'~%" + (which "ruby") + (string-join (map export-variable vars) "\n") + ;; This ensures that if the GEM_PATH has been changed, + ;; then that change will be noticed. + (if gem-clear-paths "Gem.clear_paths" "") + (canonicalize-path wrapped-file)))) + + (chmod prog-tmp #o755) + (rename-file prog-tmp prog)))) + +(define* (wrap #:key inputs outputs #:allow-other-keys) + (define (list-of-files dir) + (map (cut string-append dir "/" <>) + (or (scandir dir (lambda (f) + (let ((s (stat (string-append dir "/" f)))) + (eq? 'regular (stat:type s))))) + '()))) + + (define bindirs + (append-map (match-lambda + ((_ . dir) + (list (string-append dir "/bin") + (string-append dir "/sbin")))) + outputs)) + + (let* ((out (assoc-ref outputs "out")) + (var `("GEM_PATH" prefix + (,(string-append out "/lib/ruby/vendor_ruby") + ,(getenv "GEM_PATH"))))) + (for-each (lambda (dir) + (let ((files (list-of-files dir))) + (for-each (cut wrap-ruby-program <> var) + files))) + bindirs))) + (define (log-file-deletion file) (display (string-append "deleting '" file "' for reproducibility\n"))) @@ -177,18 +314,9 @@ GEM-FLAGS are passed to the 'gem' invokation, if present." (add-after 'extract-gemspec 'replace-git-ls-files replace-git-ls-files) (replace 'build build) (replace 'check check) - (replace 'install install))) + (replace 'install install) + (add-after 'install 'wrap wrap))) (define* (ruby-build #:key inputs (phases %standard-phases) #:allow-other-keys #:rest args) (apply gnu:gnu-build #:inputs inputs #:phases phases args)) - -(define (gem-home store-path ruby-version) - "Return a string to the gem home directory in the store given a STORE-PATH -and the RUBY-VERSION used to build that ruby package" - (string-append - store-path - "/lib/ruby/gems/" - (regexp-substitute #f - (string-match "^[0-9]+\\.[0-9]+" ruby-version) - 0 ".0"))) diff --git a/guix/packages.scm b/guix/packages.scm index be0a5eeedb..b5c0b60440 100644 --- a/guix/packages.scm +++ b/guix/packages.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org> +;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2014, 2015, 2017 Mark H Weaver <mhw@netris.org> ;;; Copyright © 2015 Eric Bavier <bavier@member.fsf.org> ;;; Copyright © 2016 Alex Kost <alezost@gmail.com> @@ -789,7 +789,8 @@ when CUT? returns true for a given package." (location (package-location p)) (inputs (map rewrite (package-inputs p))) (native-inputs (map rewrite (package-native-inputs p))) - (propagated-inputs (map rewrite (package-propagated-inputs p))))))) + (propagated-inputs (map rewrite (package-propagated-inputs p))) + (replacement (and=> (package-replacement p) proc)))))) replace) diff --git a/guix/scripts/offload.scm b/guix/scripts/offload.scm index 7e114fa2c9..56d6de6308 100644 --- a/guix/scripts/offload.scm +++ b/guix/scripts/offload.scm @@ -358,26 +358,19 @@ MACHINE." (parameterize ((current-build-output-port (build-log-port))) (build-derivations store (list drv)))) - (retrieve-files* outputs store) + (retrieve-files* outputs store + + ;; We cannot use the 'import-paths' RPC here because we + ;; already hold the locks for FILES. + #:import + (lambda (port) + (restore-file-set port + #:log-port (current-error-port) + #:lock? #f))) + (format (current-error-port) "done with offloaded '~a'~%" (derivation-file-name drv))) -(define (retrieve-files* files remote) - "Retrieve FILES from REMOTE and import them using 'restore-file-set'." - (let-values (((port count) - (file-retrieval-port files remote))) - (format #t (N_ "retrieving ~a store item from '~a'...~%" - "retrieving ~a store items from '~a'...~%" count) - count (remote-store-host remote)) - - ;; We cannot use the 'import-paths' RPC here because we already - ;; hold the locks for FILES. - (let ((result (restore-file-set port - #:log-port (current-error-port) - #:lock? #f))) - (close-port port) - result))) - ;;; ;;; Scheduling. @@ -407,7 +400,7 @@ allowed on MACHINE. Return +∞ if MACHINE is unreachable." +inf.0 ;MACHINE does not respond, so assume it is infinitely loaded (match (string-tokenize line) ((one five fifteen . x) - (let* ((raw (string->number five)) + (let* ((raw (string->number one)) (jobs (build-machine-parallel-builds machine)) (normalized (/ raw jobs))) (format (current-error-port) "load on machine '~a' is ~s\ @@ -549,8 +542,7 @@ slot (which must later be released with 'release-build-slot'), or #f and #f." "Bail out if NODE is not running Guile." (match (node-guile-version node) (#f - (leave (G_ "Guile could not be started on '~a'~%") - name)) + (report-guile-error name)) ((? string? version) ;; Note: The version string already contains the word "Guile". (info (G_ "'~a' is running ~a~%") @@ -558,18 +550,34 @@ slot (which must later be released with 'release-build-slot'), or #f and #f." (define (assert-node-has-guix node name) "Bail out if NODE lacks the (guix) module, or if its daemon is not running." - (match (node-eval node - '(begin - (use-modules (guix)) - (with-store store - (add-text-to-store store "test" - "Hello, build machine!")))) - ((? string? str) - (info (G_ "Guix is usable on '~a' (test returned ~s)~%") - name str)) - (x - (leave (G_ "failed to use Guix module on '~a' (test returned ~s)~%") - name x)))) + (catch 'node-repl-error + (lambda () + (match (node-eval node + '(begin + (use-modules (guix)) + (and add-text-to-store 'alright))) + ('alright #t) + (_ (report-module-error name)))) + (lambda (key . args) + (report-module-error name))) + + (catch 'node-repl-error + (lambda () + (match (node-eval node + '(begin + (use-modules (guix)) + (with-store store + (add-text-to-store store "test" + "Hello, build machine!")))) + ((? string? str) + (info (G_ "Guix is usable on '~a' (test returned ~s)~%") + name str)) + (x + (leave (G_ "failed to talk to guix-daemon on '~a' (test returned ~s)~%") + name x)))) + (lambda (key . args) + (leave (G_ "remove evaluation on '~a' failed:~{ ~s~}~%") + args)))) (define %random-state (delay diff --git a/guix/scripts/system.scm b/guix/scripts/system.scm index ebcf3e4f3b..55a02fb96d 100644 --- a/guix/scripts/system.scm +++ b/guix/scripts/system.scm @@ -709,8 +709,8 @@ and TARGET arguments." "Perform ACTION for OS. INSTALL-BOOTLOADER? specifies whether to install bootloader; BOOTLOADER-TAGET is the target for the bootloader; TARGET is the target root directory; IMAGE-SIZE is the size of the image to be built, for -the 'vm-image' and 'disk-image' actions. The root filesystem is created as a -FILE-SYSTEM-TYPE filesystem. FULL-BOOT? is used for the 'vm' action; it +the 'vm-image' and 'disk-image' actions. The root file system is created as a +FILE-SYSTEM-TYPE file system. FULL-BOOT? is used for the 'vm' action; it determines whether to boot directly to the kernel or to the bootloader. When DERIVATIONS-ONLY? is true, print the derivation file name(s) without diff --git a/guix/ssh.scm b/guix/ssh.scm index cb560c0e9c..5e442024bc 100644 --- a/guix/ssh.scm +++ b/guix/ssh.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2016, 2017 Ludovic Courtès <ludo@gnu.org> +;;; Copyright © 2016, 2017, 2018 Ludovic Courtès <ludo@gnu.org> ;;; ;;; This file is part of GNU Guix. ;;; @@ -28,7 +28,9 @@ #:use-module (ssh session) #:use-module (ssh dist) #:use-module (ssh dist node) + #:use-module (srfi srfi-1) #:use-module (srfi srfi-11) + #:use-module (srfi srfi-26) #:use-module (srfi srfi-34) #:use-module (srfi srfi-35) #:use-module (ice-9 match) @@ -38,9 +40,11 @@ connect-to-remote-daemon send-files retrieve-files + retrieve-files* remote-store-host - file-retrieval-port)) + report-guile-error + report-module-error)) ;;; Commentary: ;;; @@ -102,42 +106,36 @@ Throw an error on failure." ;; hack. `(begin (use-modules (ice-9 match) (rnrs io ports) - (rnrs bytevectors) (system foreign)) - - (define read! - ;; XXX: We would use 'get-bytevector-some' but it always returns a - ;; single byte in Guile <= 2.2.3---see <https://bugs.gnu.org/30066>. - ;; This procedure works around it. - (let ((proc (pointer->procedure int - (dynamic-func "read" (dynamic-link)) - (list int '* size_t)))) - (lambda (port bv) - (proc (fileno port) (bytevector->pointer bv) - (bytevector-length bv))))) + (rnrs bytevectors)) (let ((sock (socket AF_UNIX SOCK_STREAM 0)) (stdin (current-input-port)) - (stdout (current-output-port)) - (buffer (make-bytevector 65536))) - (setvbuf stdin _IONBF) + (stdout (current-output-port))) (setvbuf stdout _IONBF) + + ;; Use buffered ports so that 'get-bytevector-some' returns up to the + ;; whole buffer like read(2) would--see <https://bugs.gnu.org/30066>. + (setvbuf stdin _IOFBF 65536) + (setvbuf sock _IOFBF 65536) + (connect sock AF_UNIX ,socket-name) (let loop () (match (select (list stdin sock) '() '()) ((reads () ()) (when (memq stdin reads) - (match (read! stdin buffer) - ((? zero?) ;EOF + (match (get-bytevector-some stdin) + ((? eof-object?) (primitive-exit 0)) - (count - (put-bytevector sock buffer 0 count)))) + (bv + (put-bytevector sock bv) + (force-output sock)))) (when (memq sock reads) - (match (read! sock buffer) - ((? zero?) ;EOF + (match (get-bytevector-some sock) + ((? eof-object?) (primitive-exit 0)) - (count - (put-bytevector stdout buffer 0 count)))) + (bv + (put-bytevector stdout bv)))) (loop)) (_ (primitive-exit 1))))))) @@ -235,6 +233,10 @@ be read. When RECURSIVE? is true, the closure of FILES is exported." (write `(invalid-items ,invalid)) (exit 1)) + ;; TODO: When RECURSIVE? is true, we could send the list of store + ;; items in the closure so that the other end can filter out + ;; those it already has. + (write '(exporting)) ;we're ready (force-output) @@ -339,10 +341,11 @@ to the length of FILES.)" (&message (message (format #f fmt args ...)))))))) -(define* (retrieve-files local files remote - #:key recursive? (log-port (current-error-port))) - "Retrieve FILES from REMOTE and import them using the 'import-paths' RPC on -LOCAL. When RECURSIVE? is true, retrieve the closure of FILES." +(define* (retrieve-files* files remote + #:key recursive? (log-port (current-error-port)) + (import (const #f))) + "Pass IMPORT an input port from which to read the sequence of FILES coming +from REMOTE. When RECURSIVE? is true, retrieve the closure of FILES." (let-values (((port count) (file-retrieval-port files remote #:recursive? recursive?))) @@ -352,25 +355,16 @@ LOCAL. When RECURSIVE? is true, retrieve the closure of FILES." "retrieving ~a store items from '~a'...~%" count) count (remote-store-host remote)) - (let ((result (import-paths local port))) - (close-port port) - result)) + (dynamic-wind + (const #t) + (lambda () + (import port)) + (lambda () + (close-port port)))) ((? eof-object?) - (raise-error (G_ "failed to start Guile on remote host '~A': exit code ~A") - (remote-store-host remote) - (channel-get-exit-status port) - (=> (G_ "Make sure @command{guile} can be found in -@code{$PATH} on the remote host. Run @command{ssh ~A guile --version} to -check.") - (remote-store-host remote)))) + (report-guile-error (remote-store-host remote))) (('module-error . _) - ;; TRANSLATORS: Leave "Guile" untranslated. - (raise-error (G_ "Guile modules not found on remote host '~A'") - (remote-store-host remote) - (=> (G_ "Make sure @code{GUILE_LOAD_PATH} includes Guix' -own module directory. Run @command{ssh ~A env | grep GUILE_LOAD_PATH} to -check.") - (remote-store-host remote)))) + (report-module-error (remote-store-host remote))) (('connection-error file code . _) (raise-error (G_ "failed to connect to '~A' on remote host '~A': ~a") file (remote-store-host remote) (strerror code))) @@ -386,4 +380,36 @@ check.") (raise-error (G_ "failed to retrieve store items from '~a'") (remote-store-host remote)))))) +(define* (retrieve-files local files remote + #:key recursive? (log-port (current-error-port))) + "Retrieve FILES from REMOTE and import them using the 'import-paths' RPC on +LOCAL. When RECURSIVE? is true, retrieve the closure of FILES." + (retrieve-files* (remove (cut valid-path? local <>) files) + remote + #:recursive? recursive? + #:log-port log-port + #:import (lambda (port) + (import-paths local port)))) + + +;;; +;;; Error reporting. +;;; + +(define (report-guile-error host) + (raise-error (G_ "failed to start Guile on remote host '~A'") host + (=> (G_ "Make sure @command{guile} can be found in +@code{$PATH} on the remote host. Run @command{ssh ~A guile --version} to +check.") + host))) + +(define (report-module-error host) + "Report an error about missing Guix modules on HOST." + ;; TRANSLATORS: Leave "Guile" untranslated. + (raise-error (G_ "Guile modules not found on remote host '~A'") host + (=> (G_ "Make sure @code{GUILE_LOAD_PATH} includes Guix' +own module directory. Run @command{ssh ~A env | grep GUILE_LOAD_PATH} to +check.") + host))) + ;;; ssh.scm ends here diff --git a/guix/ui.scm b/guix/ui.scm index 895179744b..fb2380b68a 100644 --- a/guix/ui.scm +++ b/guix/ui.scm @@ -195,7 +195,16 @@ messages." (catch #t (lambda () ;; XXX: Force a recompilation to avoid ABI issues. - ;; (set! %fresh-auto-compile #t) + ;; + ;; In 2.2.3, the bogus answer to <https://bugs.gnu.org/29226> was to + ;; ignore all available .go, not just those from ~/.cache, which in turn + ;; meant that we had to rebuild *everything*. Since this is too costly, + ;; we have to turn auto '%fresh-auto-compile' with that version, at the + ;; risk of getting ABI breakage in the user's config file. See + ;; <https://bugs.gnu.org/29881>. + (unless (string=? (version) "2.2.3") + (set! %fresh-auto-compile #t)) + (set! %load-should-auto-compile #t) (save-module-excursion |