diff options
author | Maxim Cournoyer <maxim.cournoyer@gmail.com> | 2022-01-25 23:36:11 -0500 |
---|---|---|
committer | Maxim Cournoyer <maxim.cournoyer@gmail.com> | 2022-01-25 23:48:37 -0500 |
commit | 0d41fe4855588fb659b8adafe215d5573517a79b (patch) | |
tree | 38b274bd03375f4fa5b7d3a9fb3f64a19786bef2 /guix/build | |
parent | 7c57821c68d199ad56a8ed750b36eccc7ef238dd (diff) | |
parent | 1a5302435ff0d2822b823f5a6fe01faa7a85c629 (diff) |
Merge branch 'staging' into core-updates.
With "conflicts" resolved in (mostly in favor of master/staging):
gnu/packages/admin.scm
gnu/packages/gnuzilla.scm
gnu/packages/gtk.scm
gnu/packages/kerberos.scm
gnu/packages/linux.scm
guix/lint.scm
Diffstat (limited to 'guix/build')
-rw-r--r-- | guix/build/clojure-build-system.scm | 43 | ||||
-rw-r--r-- | guix/build/clojure-utils.scm | 12 | ||||
-rw-r--r-- | guix/build/compile.scm | 32 | ||||
-rw-r--r-- | guix/build/gnu-build-system.scm | 2 | ||||
-rw-r--r-- | guix/build/go-build-system.scm | 26 | ||||
-rw-r--r-- | guix/build/julia-build-system.scm | 33 | ||||
-rw-r--r-- | guix/build/node-build-system.scm | 236 | ||||
-rw-r--r-- | guix/build/syscalls.scm | 2 | ||||
-rw-r--r-- | guix/build/utils.scm | 8 |
9 files changed, 331 insertions, 63 deletions
diff --git a/guix/build/clojure-build-system.scm b/guix/build/clojure-build-system.scm index d8f7c89f85..7d494078ea 100644 --- a/guix/build/clojure-build-system.scm +++ b/guix/build/clojure-build-system.scm @@ -34,8 +34,24 @@ ;; ;; Code: +(define* (compile-java #:key + java-source-dirs java-compile-dir + #:allow-other-keys) + "Compile java sources for use in clojure-build-system." + (let ((java-files (append-map (lambda (dir) + (find-files dir "\\.java$")) + java-source-dirs))) + (mkdir-p java-compile-dir) + (when (not (null? java-files)) + (apply invoke + "javac" + "-verbose" + "-d" java-compile-dir + java-files)))) + (define* (build #:key - source-dirs compile-dir + source-dirs java-source-dirs + compile-dir java-compile-dir jar-names main-class omit-source? aot-include aot-exclude #:allow-other-keys) @@ -46,19 +62,24 @@ #:all-list libs))) (mkdir-p compile-dir) (eval-with-clojure `(run! compile ',libs*) - source-dirs) + (cons* compile-dir + java-compile-dir + source-dirs)) (let ((source-dir-files-alist (map (lambda (dir) (cons dir (find-files* dir))) - source-dirs)) + (append source-dirs + java-source-dirs))) ;; workaround transitive compilation in Clojure (classes (filter (lambda (class) (any (cut compiled-from? class <>) libs*)) (find-files* compile-dir)))) - (for-each (cut create-jar <> (cons (cons compile-dir classes) - (if omit-source? - '() - source-dir-files-alist)) + (for-each (cut create-jar <> (cons* (cons compile-dir classes) + (cons java-compile-dir + (find-files* java-compile-dir)) + (if omit-source? + '() + source-dir-files-alist)) #:main-class main-class) jar-names) #t))) @@ -78,8 +99,11 @@ priority over TEST-INCLUDE." (for-each (lambda (jar) (eval-with-clojure `(do (apply require '(clojure.test ,@libs*)) - (apply clojure.test/run-tests - ',libs*)) + (if (clojure.test/successful? + (apply clojure.test/run-tests + ',libs*)) + (System/exit 0) + (System/exit 1))) (cons jar test-dirs))) jar-names))) #t) @@ -91,6 +115,7 @@ priority over TEST-INCLUDE." (define-with-docs %standard-phases "Standard build phases for clojure-build-system." (modify-phases %standard-phases@ant + (add-before 'build 'compile-java compile-java) (replace 'build build) (replace 'check check) (replace 'install install) diff --git a/guix/build/clojure-utils.scm b/guix/build/clojure-utils.scm index a9ffad3c8f..c5322141d3 100644 --- a/guix/build/clojure-utils.scm +++ b/guix/build/clojure-utils.scm @@ -32,8 +32,10 @@ install-doc %source-dirs + %java-source-dirs %test-dirs %compile-dir + %java-compile-dir package-name->jar-names %main-class %omit-source? @@ -101,6 +103,10 @@ DOC-REGEX can be compiled or uncompiled." "A default list of source directories." '("src/")) +(define-with-docs %java-source-dirs + "A default list of java source directories." + '()) + (define-with-docs %test-dirs "A default list of test directories." '("test/")) @@ -109,6 +115,10 @@ DOC-REGEX can be compiled or uncompiled." "Default directory for holding class files." "classes/") +(define-with-docs %java-compile-dir + "Default directory for holding java class files." + "java-classes/") + (define (package-name->jar-names name) "Given NAME, a package name like \"foo-0.9.1b\", return the list of default jar names: (\"foo-0.9.1b.jar\" \"foo.jar\")." @@ -135,7 +145,7 @@ all libraries found under the source directories." (define-with-docs %aot-exclude "A default list of symbols deciding what not to compile. See the doc string of '%aot-include' for more details." - '()) + '(data-readers)) (define-with-docs %tests? "Enable tests by default." diff --git a/guix/build/compile.scm b/guix/build/compile.scm index b86ec3b743..5b27b55d02 100644 --- a/guix/build/compile.scm +++ b/guix/build/compile.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2013, 2014, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org> +;;; Copyright © 2013-2014, 2016-2020, 2022 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2015 Taylan Ulrich Bayırlı/Kammer <taylanbayirli@gmail.com> ;;; ;;; This file is part of GNU Guix. @@ -37,6 +37,21 @@ ;;; ;;; Code: +(define (clear-keyword-arguments keywords args) + "Set to #f the value associated with each of the KEYWORDS in ARGS." + (let loop ((args args) + (result '())) + (match args + (() + (reverse result)) + (((? keyword? kw) arg . rest) + (loop rest + (if (memq kw keywords) + (cons* #f kw result) + (cons* arg kw result)))) + ((head . tail) + (loop tail (cons head result)))))) + (define optimizations-for-level (or (and=> (false-if-exception (resolve-interface '(system base optimize))) @@ -60,9 +75,18 @@ (loop rest `(#f ,kw ,@result)))))) (lambda (level) - (if (<= level 1) - %lightweight-optimizations - %default-optimizations))))) + ;; In the upcoming Guile 3.0.8, .go files include code of their + ;; inlinable exports and free variables are resolved at compile time + ;; (both are enabled at -O1) to permit cross-module inlining + ;; (enabled at -O2). Unfortunately, this currently leads to + ;; non-reproducible and more expensive builds, so we turn it off + ;; here: + ;; <https://wingolog.org/archives/2021/05/13/cross-module-inlining-in-guile>. + (clear-keyword-arguments '(#:inlinable-exports? #:resolve-free-vars? + #:cross-module-inlining?) + (if (<= level 1) + %lightweight-optimizations + %default-optimizations)))))) (define (supported-warning-type? type) "Return true if TYPE, a symbol, denotes a supported warning type." diff --git a/guix/build/gnu-build-system.scm b/guix/build/gnu-build-system.scm index d0f7413268..d84411c090 100644 --- a/guix/build/gnu-build-system.scm +++ b/guix/build/gnu-build-system.scm @@ -598,6 +598,8 @@ and 'man/'. This phase moves directories to the right place if needed." (string-suffix? ".tgz" file)) (gzip-file? file))) #:stat lstat))) + ;; Ensure the files are writable. + (for-each make-file-writable files) (for-each reset-gzip-timestamp files))) (match outputs diff --git a/guix/build/go-build-system.scm b/guix/build/go-build-system.scm index 4768ee8562..7f25e05d0d 100644 --- a/guix/build/go-build-system.scm +++ b/guix/build/go-build-system.scm @@ -5,6 +5,7 @@ ;;; Copyright © 2020 Jack Hill <jackhill@jackhill.us> ;;; Copyright © 2020 Jakub Kądziołka <kuba@kadziolka.net> ;;; Copyright © 2020, 2021 Efraim Flashner <efraim@flashner.co.il> +;;; Copyright © 2021 Sarah Morgensen <iskarian@mgsn.dev> ;;; ;;; This file is part of GNU Guix. ;;; @@ -138,9 +139,28 @@ of the package being built and its dependencies, and GOBIN, which determines where executables (\"commands\") are installed to. This phase is sometimes used by packages that use (guix build-system gnu) but have a handful of Go dependencies, so it should be self-contained." - ;; The Go cache is required starting in Go 1.12. We don't actually use it but - ;; we need it to be a writable directory. - (setenv "GOCACHE" "/tmp/go-cache") + (define (search-input-directories dir) + (filter directory-exists? + (map (match-lambda + ((name . directory) + (string-append directory "/" dir))) + inputs))) + + ;; Seed the Go build cache with the build caches from input packages. + (let ((cache (string-append (getcwd) "/go-build"))) + (setenv "GOCACHE" cache) + (union-build cache + (search-input-directories "/var/cache/go/build") + ;; Creating all directories isn't that bad, because there are + ;; only ever 256 of them. + #:create-all-directories? #t + #:log-port (%make-void-port "w")) + + ;; Tell Go that the cache was recently trimmed, so it doesn't try to. + (call-with-output-file (string-append cache "/trim.txt") + (lambda (port) + (format port "~a" (current-time))))) + ;; Using the current working directory as GOPATH makes it easier for packagers ;; who need to manipulate the unpacked source code. (setenv "GOPATH" (getcwd)) diff --git a/guix/build/julia-build-system.scm b/guix/build/julia-build-system.scm index b4e0044567..03d669be64 100644 --- a/guix/build/julia-build-system.scm +++ b/guix/build/julia-build-system.scm @@ -1,7 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2019, 2020 Nicolò Balzarotti <nicolo@nixo.xyz> ;;; Copyright © 2021 Jean-Baptiste Volatier <jbv@pm.me> -;;; Copyright © 2021 Simon Tournier <zimon.toutoune@gmail.com> +;;; Copyright © 2021, 2022 Simon Tournier <zimon.toutoune@gmail.com> ;;; ;;; This file is part of GNU Guix. ;;; @@ -27,8 +27,8 @@ #:use-module (ice-9 regex) #:use-module (ice-9 rdelim) #:use-module (ice-9 popen) + #:use-module (srfi srfi-1) #:export (%standard-phases - julia-create-package-toml julia-build)) ;; Commentary: @@ -138,6 +138,8 @@ Project.toml)." (define* (link-depot #:key source inputs outputs julia-package-name julia-package-uuid #:allow-other-keys) (let* ((out (assoc-ref outputs "out")) + (name+version (strip-store-file-name out)) + (version (last (string-split name+version #\-))) (package-name (or julia-package-name (project.toml->name "Project.toml"))) @@ -148,6 +150,14 @@ Project.toml)." println(Base.version_slug(Base.UUID(\"~a\"), Base.SHA1(Pkg.GitTools.tree_hash(\".\"))))" uuid))) (slug (string-trim-right (get-string-all pipe)))) + ;; Few packages do not have the regular Project.toml file, then when they + ;; are propagated, dependencies do not find them and an raise error. + (unless (file-exists? "Project.toml") + (julia-create-package-toml (getcwd) + julia-package-name julia-package-uuid + version + #:file "Project.toml")) + ;; When installing a package, julia looks first at in the JULIA_DEPOT_PATH ;; for a path like packages/PACKAGE/XXXX ;; Where XXXX is a slug encoding the package UUID and SHA1 of the files @@ -157,17 +167,16 @@ println(Base.version_slug(Base.UUID(\"~a\"), (symlink package-dir (string-append out "/share/julia/packages/" package-name "/" slug)))) -(define (julia-create-package-toml outputs source - name uuid version - deps) - "Some packages are not using the new Package.toml dependency specifications. -Write this file manually, so that Julia can find its dependencies." +(define* (julia-create-package-toml location + name uuid version + #:optional + (deps '()) + #:key + (file "Project.toml")) + "Some packages are not using the new Project.toml dependency specifications. +Write this FILE manually, so that Julia can find its dependencies." (let ((f (open-file - (string-append - (assoc-ref outputs "out") - %package-path - (string-append - name "/Project.toml")) + (string-append location "/" file) "w"))) (display (string-append " diff --git a/guix/build/node-build-system.scm b/guix/build/node-build-system.scm index 70a367618e..bee3792e93 100644 --- a/guix/build/node-build-system.scm +++ b/guix/build/node-build-system.scm @@ -2,6 +2,8 @@ ;;; Copyright © 2015 David Thompson <davet@gnu.org> ;;; Copyright © 2016, 2020 Jelle Licht <jlicht@fsfe.org> ;;; Copyright © 2019, 2021 Timothy Sample <samplet@ngyro.com> +;;; Copyright © 2021, 2022 Philip McGrath <philip@philipmcgrath.com> +;;; Copyright © 2022 Liliana Marie Prikler <liliana.prikler@gmail.com> ;;; ;;; This file is part of GNU Guix. ;;; @@ -23,16 +25,108 @@ #:use-module (guix build utils) #:use-module (guix build json) #:use-module (ice-9 ftw) + #:use-module (ice-9 regex) #:use-module (ice-9 match) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-71) #:export (%standard-phases + with-atomic-json-file-replacement + delete-dependencies node-build)) -;; Commentary: -;; -;; Builder-side code of the standard Node/NPM package install procedure. -;; -;; Code: +(define (with-atomic-json-file-replacement file proc) + "Like 'with-atomic-file-replacement', but PROC is called with a single +argument---the result of parsing FILE's contents as json---and should a value +to be written as json to the replacement FILE." + (with-atomic-file-replacement file + (lambda (in out) + (write-json (proc (read-json in)) out)))) + +(define* (assoc-ref* alist key #:optional default) + "Like assoc-ref, but return DEFAULT instead of #f if no value exists." + (match (assoc key alist) + (#f default) + ((_ . value) value))) + +(define* (jsobject-ref obj key #:optional default) + (match obj + (('@ . alist) (assoc-ref* alist key default)))) + +(define* (alist-pop alist key #:optional (= equal?)) + "Return two values, the first pair in ALIST with key KEY, and the other +elements. Equality calls are made as (= KEY ALISTCAR)." + (define (found? pair) + (= key (car pair))) + + (let ((before after (break found? alist))) + (if (pair? after) + (values (car after) (append before (cdr after))) + (values #f before)))) + +(define* (alist-update alist key proc #:optional default (= equal?)) + "Return an association list like ALIST, but with KEY mapped to the result of +PROC applied to the first value found under the comparison (= KEY ALISTCAR). +If no such value exists, use DEFAULT instead. +Unlike acons, this removes the previous association of KEY (assuming it is +unique), but the result may still share storage with ALIST." + (let ((pair rest (alist-pop alist key =))) + (acons key + (proc (if (pair? pair) + (cdr pair) + default)) + rest))) + +(define (jsobject-update* js . updates) + "Return a json object like JS, but with all UPDATES applied. Each update is +a list (KEY PROC [DEFAULT]), so that KEY is mapped to the result of PROC +applied to the value to which KEY is mapped in JS. If no such mapping exists, +PROC is instead applied to DEFAULT, or to '#f' is no DEFAULT is specified. +The update takes place from left to right, so later UPDATERs will receive the +values returned by earlier UPDATERs for the same KEY." + (match js + (('@ . alist) + (let loop ((alist alist) + (updates updates)) + (match updates + (() (cons '@ alist)) + (((key proc) . updates) + (loop (alist-update alist key proc #f equal?) updates)) + (((key proc default) . updates) + (loop (alist-update alist key proc default equal?) updates))))))) + +(define (jsobject-union combine seed . objects) + "Merge OBJECTS into SEED by applying (COMBINE KEY VAL0 VAL), where VAL0 +is the value found in the (possibly updated) SEED and VAL is the new value +found in one of the OBJECTS." + (match seed + (('@ . aseed) + (match objects + (() seed) + ((('@ . alists) ...) + (cons + '@ + (fold (lambda (alist aseed) + (if (null? aseed) alist + (fold + (match-lambda* + (((k . v) aseed) + (let ((pair tail (alist-pop alist k))) + (match pair + (#f (acons k v aseed)) + ((_ . v0) (acons k (combine k v0 v) aseed)))))) + aseed + alist))) + aseed + alists))))))) + +;; Possibly useful helper functions: +;; (define (newest key val0 val) val) +;; (define (unkeyed->keyed proc) (lambda (_key val0 val) (proc val0 val))) + + +;;; +;;; Phases. +;;; (define (set-home . _) (with-directory-excursion ".." @@ -49,7 +143,7 @@ (define (module-name module) (let* ((package.json (string-append module "/package.json")) (package-meta (call-with-input-file package.json read-json))) - (assoc-ref package-meta "name"))) + (jsobject-ref package-meta "name"))) (define (index-modules input-paths) (define (list-modules directory) @@ -73,27 +167,58 @@ (define index (index-modules (map cdr inputs))) - (define (resolve-dependencies package-meta meta-key) - (fold (lambda (key+value acc) - (match key+value - ('@ acc) - ((key . value) (acons key (hash-ref index key value) acc)))) - '() - (or (assoc-ref package-meta meta-key) '()))) + (define resolve-dependencies + (match-lambda + (('@ . alist) + (cons '@ (map (match-lambda + ((key . value) + (cons key (hash-ref index key value)))) + alist))))) - (with-atomic-file-replacement "package.json" - (lambda (in out) - (let ((package-meta (read-json in))) - (assoc-set! package-meta "dependencies" - (append - '(@) - (resolve-dependencies package-meta "dependencies") - (resolve-dependencies package-meta "peerDependencies"))) - (assoc-set! package-meta "devDependencies" - (append - '(@) - (resolve-dependencies package-meta "devDependencies"))) - (write-json package-meta out)))) + (with-atomic-json-file-replacement "package.json" + (lambda (pkg-meta) + (jsobject-update* + pkg-meta + `("devDependencies" ,resolve-dependencies (@)) + `("dependencies" ,(lambda (deps) + (resolve-dependencies + (jsobject-union + (lambda (k a b) b) + (jsobject-ref pkg-meta "peerDependencies" '(@)) + deps))) + (@))))) + #t) + +(define (delete-dependencies absent) + "Rewrite 'package.json' to allow the build to proceed without packages +listed in ABSENT, a list of strings naming npm packages. + +To prevent the deleted dependencies from being reintroduced, use this function +only after the 'patch-dependencies' phase." + (define delete-from-jsobject + (match-lambda + (('@ . alist) + (cons '@ (filter (match-lambda + ((k . _) + (not (member k absent)))) + alist))))) + + (with-atomic-json-file-replacement "package.json" + (lambda (pkg-meta) + (jsobject-update* + pkg-meta + `("devDependencies" ,delete-from-jsobject (@)) + `("dependencies" ,delete-from-jsobject (@)))))) + +(define* (delete-lockfiles #:key inputs #:allow-other-keys) + "Delete 'package-lock.json', 'yarn.lock', and 'npm-shrinkwrap.json', if they +exist." + (for-each (lambda (pth) + (when (file-exists? pth) + (delete-file pth))) + '("package-lock.json" + "yarn.lock" + "npm-shrinkwrap.json")) #t) (define* (configure #:key outputs inputs #:allow-other-keys) @@ -103,9 +228,7 @@ (define* (build #:key inputs #:allow-other-keys) (let ((package-meta (call-with-input-file "package.json" read-json))) - (if (and=> (assoc-ref package-meta "scripts") - (lambda (scripts) - (assoc-ref scripts "build"))) + (if (jsobject-ref (jsobject-ref package-meta "scripts" '(@)) "build" #f) (let ((npm (string-append (assoc-ref inputs "node") "/bin/npm"))) (invoke npm "run" "build")) (format #t "there is no build script to run~%")) @@ -142,15 +265,68 @@ "install" "../package.tgz") #t)) +(define* (avoid-node-gyp-rebuild #:key outputs #:allow-other-keys) + "Adjust the installed 'package.json' to remove an 'install' script that +would try to run 'node-gyp rebuild'." + ;; We want to take advantage of `npm install`'s automatic support for + ;; building native addons with node-gyp: in particular, it helps us avoid + ;; hard-coding the specifics of how npm's internal copy of node-gyp is + ;; currently packaged. However, the mechanism by which the automatic support + ;; is implemented causes problems for us. + ;; + ;; If a package contains a 'binding.gyp' file and does not define an + ;; 'install' or 'preinstall' script, 'npm install' runs a default install + ;; script consisting of 'node-gyp rebuild'. In our 'install' phase, this + ;; implicit 'install' script, if it is applicable, is explicitly added to + ;; the "package.json" file. However, if another Guix package were to use a + ;; Node.js package with such an 'install' script, the dependent package's + ;; build process would fail, because 'node-gyp rebuild' would try to write + ;; to the store. + ;; + ;; Here, if the installed "package.json" defines scripts.install as + ;; "node-gyp rebuild", we replace it with a no-op. Importantly, deleting the + ;; install script definition would not be enough, because the default + ;; install script would cause the same problem. + ;; + ;; For further details, see: + ;; - https://docs.npmjs.com/cli/v8/configuring-npm/package-json#default-values + ;; - https://docs.npmjs.com/cli/v8/using-npm/scripts#best-practices + (define installed-package.json + (search-input-file outputs (string-append "/lib/node_modules/" + (module-name ".") + "/package.json"))) + ;; We don't want to use an atomic replacement here, because we often don't + ;; even need to overwrite this file. Therefore, let's use some helpers + ;; that we'd otherwise not need. + (define pkg-meta + (call-with-input-file installed-package.json read-json)) + (define scripts + (jsobject-ref pkg-meta "scripts" '(@))) + (define (jsobject-set js key val) + (jsobject-update* js (list key (const val)))) + + (when (equal? "node-gyp rebuild" (jsobject-ref scripts "install" #f)) + (call-with-output-file installed-package.json + (lambda (out) + (write-json + (jsobject-set pkg-meta + "scripts" + (jsobject-set scripts + "install" + "echo Guix: avoiding node-gyp rebuild")) + out))))) + (define %standard-phases (modify-phases gnu:%standard-phases (add-after 'unpack 'set-home set-home) (add-before 'configure 'patch-dependencies patch-dependencies) + (add-after 'patch-dependencies 'delete-lockfiles delete-lockfiles) (replace 'configure configure) (replace 'build build) (replace 'check check) (add-before 'install 'repack repack) - (replace 'install install))) + (replace 'install install) + (add-after 'install 'avoid-node-gyp-rebuild avoid-node-gyp-rebuild))) (define* (node-build #:key inputs (phases %standard-phases) #:allow-other-keys #:rest args) diff --git a/guix/build/syscalls.scm b/guix/build/syscalls.scm index 45f95c509d..a7401fd73f 100644 --- a/guix/build/syscalls.scm +++ b/guix/build/syscalls.scm @@ -132,6 +132,7 @@ CLONE_CHILD_CLEARTID CLONE_CHILD_SETTID + CLONE_NEWCGROUP CLONE_NEWNS CLONE_NEWUTS CLONE_NEWIPC @@ -1025,6 +1026,7 @@ caller lacks root privileges." ;; Linux clone flags, from linux/sched.h (define CLONE_CHILD_CLEARTID #x00200000) (define CLONE_CHILD_SETTID #x01000000) +(define CLONE_NEWCGROUP #x02000000) (define CLONE_NEWNS #x00020000) (define CLONE_NEWUTS #x04000000) (define CLONE_NEWIPC #x08000000) diff --git a/guix/build/utils.scm b/guix/build/utils.scm index 39e581b0fa..b822caf619 100644 --- a/guix/build/utils.scm +++ b/guix/build/utils.scm @@ -8,6 +8,7 @@ ;;; Copyright © 2020 Efraim Flashner <efraim@flashner.co.il> ;;; Copyright © 2020, 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com> ;;; Copyright © 2021 Maxime Devos <maximedevos@telenet.be> +;;; Copyright © 2021 Brendan Tildesley <mail@brendan.scot> ;;; ;;; This file is part of GNU Guix. ;;; @@ -1473,10 +1474,9 @@ not supported." `(let ((cl (command-line))) (apply execl ,interpreter (car cl) - (cons (car cl) - (append - ',(string-split args #\space) - cl)))))) + (append + ',(string-tokenize args char-set:graphic) + cl))))) (template (string-append prog ".XXXXXX")) (out (mkstemp! template)) (st (stat prog)) |