summaryrefslogtreecommitdiff
path: root/guix
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2013-04-30 17:06:00 +0200
committerLudovic Courtès <ludo@gnu.org>2013-04-30 17:06:00 +0200
commit0734a9a8131525d6da2e7bf802402dc0350eda98 (patch)
treef43bef210f6513b12c14ee9494bb47e4f80e99d0 /guix
parente0fbbc889d724678e9e310432ad3a3fb8345cf9a (diff)
parent01155b1808b17f0a4f54388261ab0c6f5fee2f1b (diff)
downloadguix-patches-0734a9a8131525d6da2e7bf802402dc0350eda98.tar
guix-patches-0734a9a8131525d6da2e7bf802402dc0350eda98.tar.gz
Merge branch 'core-updates'
Diffstat (limited to 'guix')
-rw-r--r--guix/build-system/cmake.scm6
-rw-r--r--guix/build-system/gnu.scm45
-rw-r--r--guix/build-system/perl.scm8
-rw-r--r--guix/build-system/trivial.scm6
-rw-r--r--guix/build/gnu-build-system.scm44
-rw-r--r--guix/build/perl-build-system.scm4
-rw-r--r--guix/build/utils.scm143
-rw-r--r--guix/download.scm3
-rw-r--r--guix/packages.scm49
-rw-r--r--guix/scripts/package.scm66
-rw-r--r--guix/utils.scm28
11 files changed, 331 insertions, 71 deletions
diff --git a/guix/build-system/cmake.scm b/guix/build-system/cmake.scm
index 2a9db80cf8..3347dc502c 100644
--- a/guix/build-system/cmake.scm
+++ b/guix/build-system/cmake.scm
@@ -38,11 +38,11 @@
(define* (cmake-build store name source inputs
#:key (guile #f)
(outputs '("out")) (configure-flags ''())
+ (search-paths '())
(make-flags ''())
(patches ''()) (patch-flags ''("--batch" "-p1"))
(cmake (@ (gnu packages cmake) cmake))
(out-of-source? #f)
- (path-exclusions ''())
(tests? #t)
(test-target "test")
(parallel-build? #t) (parallel-tests? #f)
@@ -71,13 +71,15 @@ provides a 'CMakeLists.txt' file as its build system."
#:system ,system
#:outputs %outputs
#:inputs %build-inputs
+ #:search-paths ',(map search-path-specification->sexp
+ (append search-paths
+ (standard-search-paths)))
#:patches ,patches
#:patch-flags ,patch-flags
#:phases ,phases
#:configure-flags ,configure-flags
#:make-flags ,make-flags
#:out-of-source? ,out-of-source?
- #:path-exclusions ,path-exclusions
#:tests? ,tests?
#:test-target ,test-target
#:parallel-build? ,parallel-build?
diff --git a/guix/build-system/gnu.scm b/guix/build-system/gnu.scm
index 8049e7510f..b64bce7dae 100644
--- a/guix/build-system/gnu.scm
+++ b/guix/build-system/gnu.scm
@@ -27,6 +27,7 @@
#:use-module (ice-9 match)
#:export (gnu-build
gnu-build-system
+ standard-search-paths
standard-inputs
package-with-explicit-inputs
package-with-extra-configure-variable
@@ -135,6 +136,24 @@ use `--strip-all' as the arguments to `strip'."
;; Store passed to STANDARD-INPUTS.
(make-parameter #f))
+(define (standard-packages)
+ "Return the list of (NAME PACKAGE OUTPUT) or (NAME PACKAGE) tuples of
+standard packages used as implicit inputs of the GNU build system."
+
+ ;; Resolve (gnu packages base) lazily to hide circular dependency.
+ (let ((distro (resolve-module '(gnu packages base))))
+ (module-ref distro '%final-inputs)))
+
+(define (standard-search-paths)
+ "Return the list of <search-path-specification> for the standard (implicit)
+inputs."
+ (append-map (match-lambda
+ ((_ (? package? p) _ ...)
+ (package-native-search-paths p))
+ (_
+ '()))
+ (standard-packages)))
+
(define standard-inputs
(memoize
(lambda (system)
@@ -148,9 +167,7 @@ System: GCC, GNU Make, Bash, Coreutils, etc."
(z
(error "invalid standard input" z)))
- ;; Resolve (gnu packages base) lazily to hide circular dependency.
- (let* ((distro (resolve-module '(gnu packages base)))
- (inputs (module-ref distro '%final-inputs)))
+ (let ((inputs (standard-packages)))
(append inputs
(append-map (match-lambda
((name package _ ...)
@@ -159,11 +176,12 @@ System: GCC, GNU Make, Bash, Coreutils, etc."
(define* (gnu-build store name source inputs
#:key (guile #f)
- (outputs '("out")) (configure-flags ''())
+ (outputs '("out"))
+ (search-paths '())
+ (configure-flags ''())
(make-flags ''())
(patches ''()) (patch-flags ''("--batch" "-p1"))
(out-of-source? #f)
- (path-exclusions ''())
(tests? #t)
(test-target "check")
(parallel-build? #t) (parallel-tests? #t)
@@ -190,6 +208,16 @@ the builder's environment, from the host. Note that we distinguish
between both, because for Guile's own modules like (ice-9 foo), we want
to use GUILE's own version of it, rather than import the user's one,
which could lead to gratuitous input divergence."
+ (define implicit-inputs
+ (and implicit-inputs?
+ (parameterize ((%store store))
+ (standard-inputs system))))
+
+ (define implicit-search-paths
+ (if implicit-inputs?
+ (standard-search-paths)
+ '()))
+
(define builder
`(begin
(use-modules ,@modules)
@@ -199,13 +227,15 @@ which could lead to gratuitous input divergence."
#:system ,system
#:outputs %outputs
#:inputs %build-inputs
+ #:search-paths ',(map search-path-specification->sexp
+ (append implicit-search-paths
+ search-paths))
#:patches ,patches
#:patch-flags ,patch-flags
#:phases ,phases
#:configure-flags ,configure-flags
#:make-flags ,make-flags
#:out-of-source? ,out-of-source?
- #:path-exclusions ,path-exclusions
#:tests? ,tests?
#:test-target ,test-target
#:parallel-build? ,parallel-build?
@@ -233,8 +263,7 @@ which could lead to gratuitous input divergence."
'())
,@inputs
,@(if implicit-inputs?
- (parameterize ((%store store))
- (standard-inputs system))
+ implicit-inputs
'()))
#:outputs outputs
#:modules imported-modules
diff --git a/guix/build-system/perl.scm b/guix/build-system/perl.scm
index 537c29e799..1ff9fd2674 100644
--- a/guix/build-system/perl.scm
+++ b/guix/build-system/perl.scm
@@ -38,6 +38,7 @@
(define* (perl-build store name source inputs
#:key
(perl (@ (gnu packages perl) perl))
+ (search-paths '())
(tests? #t)
(make-maker-flags ''())
(phases '(@ (guix build perl-build-system)
@@ -53,6 +54,10 @@
(guix build utils))))
"Build SOURCE using PERL, and with INPUTS. This assumes that SOURCE
provides a `Makefile.PL' file as its build system."
+ (define perl-search-paths
+ (append (package-native-search-paths perl)
+ (standard-search-paths)))
+
(define builder
`(begin
(use-modules ,@modules)
@@ -60,6 +65,9 @@ provides a `Makefile.PL' file as its build system."
#:source ,(if (and source (derivation-path? source))
(derivation-path->output-path source)
source)
+ #:search-paths ',(map search-path-specification->sexp
+ (append perl-search-paths
+ search-paths))
#:make-maker-flags ,make-maker-flags
#:system ,system
#:test-target "test"
diff --git a/guix/build-system/trivial.scm b/guix/build-system/trivial.scm
index e5bbeaa91d..2eb15aa2e0 100644
--- a/guix/build-system/trivial.scm
+++ b/guix/build-system/trivial.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2012 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2012, 2013 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -26,7 +26,9 @@
#:export (trivial-build-system))
(define* (trivial-build store name source inputs
- #:key outputs guile system builder (modules '()))
+ #:key
+ outputs guile system builder (modules '())
+ search-paths)
"Run build expression BUILDER, an expression, for SYSTEM. SOURCE is
ignored."
(define guile-for-build
diff --git a/guix/build/gnu-build-system.scm b/guix/build/gnu-build-system.scm
index b7b9fdac95..47820aa02e 100644
--- a/guix/build/gnu-build-system.scm
+++ b/guix/build/gnu-build-system.scm
@@ -48,33 +48,22 @@
#f
dir))
-(define* (set-paths #:key inputs (path-exclusions '())
+(define* (set-paths #:key inputs (search-paths '())
#:allow-other-keys)
- (define (relevant-input-directories env-var)
- ;; Return the subset of INPUTS that should be considered when setting
- ;; ENV-VAR.
- (match (assoc-ref path-exclusions env-var)
- (#f
- (map cdr inputs))
- ((excluded ...)
- (filter-map (match-lambda
- ((name . dir)
- (and (not (member name excluded))
- dir)))
- inputs))))
+ (define input-directories
+ (match inputs
+ (((_ . dir) ...)
+ dir)))
- (set-path-environment-variable "PATH" '("bin")
- (relevant-input-directories "PATH"))
- (set-path-environment-variable "CPATH" '("include")
- (relevant-input-directories "CPATH"))
- (set-path-environment-variable "LIBRARY_PATH" '("lib" "lib64")
- (relevant-input-directories "LIBRARY_PATH"))
+ (set-path-environment-variable "PATH" '("bin" "sbin")
+ input-directories)
- ;; FIXME: Eventually move this to the `search-paths' field of the
- ;; `pkg-config' package.
- (set-path-environment-variable "PKG_CONFIG_PATH"
- '("lib/pkgconfig" "lib64/pkgconfig")
- (relevant-input-directories "PKG_CONFIG_PATH"))
+ (for-each (match-lambda
+ ((env-var (directories ...) separator)
+ (set-path-environment-variable env-var directories
+ input-directories
+ #:separator separator)))
+ search-paths)
;; Dump the environment variables as a shell script, for handy debugging.
(system "export > environment-variables"))
@@ -120,9 +109,10 @@ makefiles."
(base (basename out))
(dash (string-rindex base #\-)))
;; XXX: We'd rather use `package-name->name+version' or similar.
- (if dash
- (substring base 0 dash)
- base)))
+ (string-drop (if dash
+ (substring base 0 dash)
+ base)
+ (+ 1 (string-index base #\-)))))
(let* ((prefix (assoc-ref outputs "out"))
(bindir (assoc-ref outputs "bin"))
diff --git a/guix/build/perl-build-system.scm b/guix/build/perl-build-system.scm
index d625ef3ed6..793b6aacb5 100644
--- a/guix/build/perl-build-system.scm
+++ b/guix/build/perl-build-system.scm
@@ -50,10 +50,6 @@
(define* (perl-build #:key inputs (phases %standard-phases)
#:allow-other-keys #:rest args)
"Build the given Perl package, applying all of PHASES in order."
- (set-path-environment-variable "PERL5LIB" '("lib/perl5/site_perl")
- (match inputs
- (((_ . path) ...)
- path)))
(apply gnu:gnu-build
#:inputs inputs #:phases phases
args))
diff --git a/guix/build/utils.scm b/guix/build/utils.scm
index 6921e31bdd..a4a82a5f8c 100644
--- a/guix/build/utils.scm
+++ b/guix/build/utils.scm
@@ -1,5 +1,7 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2012, 2013 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2013 Andreas Enge <andreas@enge.fr>
+;;; Copyright © 2013 Nikita Karetnikov <nikita@karetnikov.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -31,6 +33,7 @@
with-directory-excursion
mkdir-p
copy-recursively
+ delete-file-recursively
find-files
set-path-environment-variable
@@ -49,9 +52,10 @@
patch-shebang
patch-makefile-SHELL
fold-port-matches
- remove-store-references))
+ remove-store-references
+ wrap-program))
+
-
;;;
;;; Directories.
;;;
@@ -120,8 +124,11 @@ return values of applying PROC to the port."
(() #t))))
(define* (copy-recursively source destination
- #:optional (log (current-output-port)))
- "Copy SOURCE directory to DESTINATION."
+ #:key
+ (log (current-output-port))
+ (follow-symlinks? #f))
+ "Copy SOURCE directory to DESTINATION. Follow symlinks if FOLLOW-SYMLINKS?
+is true; otherwise, just preserve them. Write verbose output to the LOG port."
(define strip-source
(let ((len (string-length source)))
(lambda (file)
@@ -132,7 +139,12 @@ return values of applying PROC to the port."
(let ((dest (string-append destination
(strip-source file))))
(format log "`~a' -> `~a'~%" file dest)
- (copy-file file dest)))
+ (case (stat:type stat)
+ ((symlink)
+ (let ((target (readlink file)))
+ (symlink target dest)))
+ (else
+ (copy-file file dest)))))
(lambda (dir stat result) ; down
(mkdir-p (string-append destination
(strip-source dir))))
@@ -144,7 +156,31 @@ return values of applying PROC to the port."
file (strerror errno))
#f)
#t
- source))
+ source
+
+ (if follow-symlinks?
+ stat
+ lstat)))
+
+(define (delete-file-recursively dir)
+ "Delete DIR recursively, like `rm -rf', without following symlinks. Report
+but ignore errors."
+ (file-system-fold (const #t) ; enter?
+ (lambda (file stat result) ; leaf
+ (delete-file file))
+ (const #t) ; down
+ (lambda (dir stat result) ; up
+ (rmdir dir))
+ (const #t) ; skip
+ (lambda (file stat errno result)
+ (format (current-error-port)
+ "warning: failed to delete ~a: ~a~%"
+ file (strerror errno)))
+ #t
+ dir
+
+ ;; Don't follow symlinks.
+ lstat))
(define (find-files dir regexp)
"Return the list of files under DIR whose basename matches REGEXP."
@@ -426,7 +462,7 @@ bytes transferred and the continuation of the transfer as a thunk."
(stat:mtimensec stat)))
(define patch-shebang
- (let ((shebang-rx (make-regexp "^[[:blank:]]*([[:graph:]]+)(.*)$")))
+ (let ((shebang-rx (make-regexp "^[[:blank:]]*([[:graph:]]+)[[:blank:]]*([[:graph:]]*)(.*)$")))
(lambda* (file
#:optional
(path (search-path-as-string->list (getenv "PATH")))
@@ -465,16 +501,29 @@ FILE are kept unchanged."
(let ((line (false-if-exception (read-line p))))
(and=> (and line (regexp-exec shebang-rx line))
(lambda (m)
- (let* ((cmd (match:substring m 1))
- (bin (search-path path (basename cmd))))
+ (let* ((interp (match:substring m 1))
+ (arg1 (match:substring m 2))
+ (rest (match:substring m 3))
+ (has-env (string-suffix? "/env" interp))
+ (cmd (if has-env arg1 (basename interp)))
+ (bin (search-path path cmd)))
(if bin
- (if (string=? bin cmd)
+ (if (string=? bin interp)
#f ; nothing to do
- (begin
- (format (current-error-port)
- "patch-shebang: ~a: changing `~a' to `~a'~%"
- file cmd bin)
- (patch p bin (match:substring m 2))))
+ (if has-env
+ (begin
+ (format (current-error-port)
+ "patch-shebang: ~a: changing `~a' to `~a'~%"
+ file (string-append interp " " arg1) bin)
+ (patch p bin rest))
+ (begin
+ (format (current-error-port)
+ "patch-shebang: ~a: changing `~a' to `~a'~%"
+ file interp bin)
+ (patch p bin
+ (if (string-null? arg1)
+ ""
+ (string-append " " arg1 rest))))))
(begin
(format (current-error-port)
"patch-shebang: ~a: warning: no binary for interpreter `~a' found in $PATH~%"
@@ -605,6 +654,70 @@ known as `nuke-refs' in Nixpkgs."
(put-u8 out (char->integer char))
result))))))
+(define* (wrap-program prog #:rest vars)
+ "Rename PROG to .PROG-real and make PROG a wrapper. 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-program \"foo\"
+ '(\"PATH\" \":\" = (\"/nix/.../bar/bin\"))
+ '(\"CERT_PATH\" suffix (\"/nix/.../baz/certs\"
+ \"/qux/certs\")))
+
+will copy 'foo' to '.foo-real' and create the file 'foo' with the following
+contents:
+
+ #!location/of/bin/bash
+ export PATH=\"/nix/.../bar/bin\"
+ export CERT_PATH=\"$CERT_PATH${CERT_PATH:+:}/nix/.../baz/certs:/qux/certs\"
+ exec location/of/.foo-real
+
+This is useful for scripts that expect particular programs to be in $PATH, for
+programs that expect particular shared libraries to be in $LD_LIBRARY_PATH, or
+modules in $GUILE_LOAD_PATH, etc."
+ (let ((prog-real (string-append (dirname prog) "/." (basename prog) "-real"))
+ (prog-tmp (string-append (dirname prog) "/." (basename prog) "-tmp")))
+ (define (export-variable lst)
+ ;; Return a string that exports an environment variable.
+ (match lst
+ ((var sep '= rest)
+ (format #f "export ~a=\"~a\""
+ var (string-join rest sep)))
+ ((var sep 'prefix rest)
+ (format #f "export ~a=\"~a${~a~a+~a}$~a\""
+ var (string-join rest sep) var sep sep var))
+ ((var sep 'suffix rest)
+ (format #f "export ~a=\"$~a${~a~a+~a}~a\""
+ var var var sep sep (string-join rest sep)))
+ ((var '= rest)
+ (format #f "export ~a=\"~a\""
+ var (string-join rest ":")))
+ ((var 'prefix rest)
+ (format #f "export ~a=\"~a${~a:+:}$~a\""
+ var (string-join rest ":") var var))
+ ((var 'suffix rest)
+ (format #f "export ~a=\"$~a${~a:+:}~a\""
+ var var var (string-join rest ":")))))
+
+ (copy-file prog prog-real)
+
+ (with-output-to-file prog-tmp
+ (lambda ()
+ (format #t
+ "#!~a~%~a~%exec \"~a\" \"$@\"~%"
+ (which "bash")
+ (string-join (map export-variable vars)
+ "\n")
+ (canonicalize-path prog-real))))
+
+ (chmod prog-tmp #o755)
+ (rename-file prog-tmp prog)))
+
;;; Local Variables:
;;; eval: (put 'call-with-output-file/atomic 'scheme-indent-function 1)
;;; eval: (put 'with-throw-handler 'scheme-indent-function 1)
diff --git a/guix/download.scm b/guix/download.scm
index b315b4c1d0..99353be8b0 100644
--- a/guix/download.scm
+++ b/guix/download.scm
@@ -107,8 +107,7 @@
"http://mirrors.ircam.fr/pub/apache/"
"http://apache-mirror.rbc.ru/pub/apache/")
(xorg ; from http://www.x.org/wiki/Releases/Download
- "http://xorg.freedesktop.org/releases/" ; main mirrors
- "http://www.x.org/pub/"
+ "http://www.x.org/releases/" ; main mirrors
"ftp://mirror.csclub.uwaterloo.ca/x.org/" ; North America
"ftp://xorg.mirrors.pair.com/"
"http://mirror.csclub.uwaterloo.ca/x.org/"
diff --git a/guix/packages.scm b/guix/packages.scm
index e8ae2fb817..1cbbd2ec47 100644
--- a/guix/packages.scm
+++ b/guix/packages.scm
@@ -37,6 +37,11 @@
origin-file-name
base32
+ <search-path-specification>
+ search-path-specification
+ search-path-specification?
+ search-path-specification->sexp
+
package
package?
package-name
@@ -49,6 +54,7 @@
package-native-inputs
package-propagated-inputs
package-outputs
+ package-native-search-paths
package-search-paths
package-synopsis
package-description
@@ -105,8 +111,22 @@ representation."
((_ str)
#'(nix-base32-string->bytevector str)))))
-;; A package.
+;; The specification of a search path.
+(define-record-type* <search-path-specification>
+ search-path-specification make-search-path-specification
+ search-path-specification?
+ (variable search-path-specification-variable)
+ (directories search-path-specification-directories)
+ (separator search-path-specification-separator (default ":")))
+
+(define (search-path-specification->sexp spec)
+ "Return an sexp representing SPEC, a <search-path-specification>. The sexp
+corresponds to the arguments expected by `set-path-environment-variable'."
+ (match spec
+ (($ <search-path-specification> variable directories separator)
+ `(,variable ,directories ,separator))))
+;; A package.
(define-record-type* <package>
package make-package
package?
@@ -129,10 +149,13 @@ representation."
(outputs package-outputs ; list of strings
(default '("out")))
- (search-paths package-search-paths ; list of (ENV-VAR (DIRS ...))
- (default '())) ; tuples; see
- ; `set-path-environment-variable'
- ; (aka. "setup-hook")
+
+ ; lists of
+ ; <search-path-specification>,
+ ; for native and cross
+ ; inputs
+ (native-search-paths package-native-search-paths (default '()))
+ (search-paths package-search-paths (default '()))
(synopsis package-synopsis) ; one-line description
(description package-description) ; one or two paragraphs
@@ -328,16 +351,22 @@ PACKAGE for SYSTEM."
(($ <package> name version source (= build-system-builder builder)
args inputs propagated-inputs native-inputs self-native-input?
outputs)
- ;; TODO: For `search-paths', add a builder prologue that calls
- ;; `set-path-environment-variable'.
- (let ((inputs (map expand-input
- (package-transitive-inputs package))))
+ (let* ((inputs (package-transitive-inputs package))
+ (input-drvs (map expand-input inputs))
+ (paths (delete-duplicates
+ (append-map (match-lambda
+ ((_ (? package? p) _ ...)
+ (package-native-search-paths
+ p))
+ (_ '()))
+ inputs))))
(apply builder
store (package-full-name package)
(and source
(package-source-derivation store source system))
- inputs
+ input-drvs
+ #:search-paths paths
#:outputs outputs #:system system
(args))))))))
diff --git a/guix/scripts/package.scm b/guix/scripts/package.scm
index cea49a57f4..5eddb7defe 100644
--- a/guix/scripts/package.scm
+++ b/guix/scripts/package.scm
@@ -330,6 +330,53 @@ but ~a is available upstream~%")
((getaddrinfo-error ftp-error) #f)
(else (apply throw key args))))))
+(define* (search-path-environment-variables packages profile
+ #:optional (getenv getenv))
+ "Return environment variable definitions that may be needed for the use of
+PACKAGES in PROFILE. Use GETENV to determine the current settings and report
+only settings not already effective."
+
+ ;; The search path info is not stored in the manifest. Thus, we infer the
+ ;; search paths from same-named packages found in the distro.
+
+ (define package-in-manifest->package
+ (match-lambda
+ ((name version _ ...)
+ (match (append (find-packages-by-name name version)
+ (find-packages-by-name name))
+ ((p _ ...) p)
+ (_ #f)))))
+
+ (define search-path-definition
+ (match-lambda
+ (($ <search-path-specification> variable directories separator)
+ (let ((values (or (and=> (getenv variable)
+ (cut string-tokenize* <> separator))
+ '()))
+ (directories (filter file-exists?
+ (map (cut string-append profile
+ "/" <>)
+ directories))))
+ (if (every (cut member <> values) directories)
+ #f
+ (format #f "export ~a=\"~a\""
+ variable
+ (string-join directories separator)))))))
+
+ (let* ((packages (filter-map package-in-manifest->package packages))
+ (search-paths (delete-duplicates
+ (append-map package-native-search-paths
+ packages))))
+ (filter-map search-path-definition search-paths)))
+
+(define (display-search-paths packages profile)
+ "Display the search path environment variables that may need to be set for
+PACKAGES, in the context of PROFILE."
+ (let ((settings (search-path-environment-variables packages profile)))
+ (unless (null? settings)
+ (format #t (_ "The following environment variable definitions may be needed:~%"))
+ (format #t "~{ ~a~%~}" settings))))
+
;;;
;;; Command-line options.
@@ -354,6 +401,8 @@ Install, remove, or upgrade PACKAGES in a single transaction.\n"))
-u, --upgrade[=REGEXP] upgrade all the installed packages matching REGEXP"))
(display (_ "
--roll-back roll back to the previous generation"))
+ (display (_ "
+ --search-paths display needed environment variable definitions"))
(newline)
(display (_ "
-p, --profile=PROFILE use PROFILE instead of the user's default profile"))
@@ -408,6 +457,9 @@ Install, remove, or upgrade PACKAGES in a single transaction.\n"))
(option '("roll-back") #f #f
(lambda (opt name arg result)
(alist-cons 'roll-back? #t result)))
+ (option '("search-paths") #f #f
+ (lambda (opt name arg result)
+ (cons `(query search-paths) result)))
(option '(#\p "profile") #t #f
(lambda (opt name arg result)
(alist-cons 'profile arg
@@ -728,7 +780,9 @@ Install, remove, or upgrade PACKAGES in a single transaction.\n"))
(build-derivations (%store) (list prof-drv)))
(begin
(switch-symlinks name prof)
- (switch-symlinks profile name))))))))))
+ (switch-symlinks profile name)
+ (display-search-paths packages
+ profile))))))))))
(define (process-query opts)
;; Process any query specified by OPTS. Return #t when a query was
@@ -776,6 +830,16 @@ Install, remove, or upgrade PACKAGES in a single transaction.\n"))
(for-each (cute package->recutils <> (current-output-port))
(find-packages-by-description regexp))
#t))
+
+ (('search-paths)
+ (let* ((manifest (profile-manifest profile))
+ (packages (manifest-packages manifest))
+ (settings (search-path-environment-variables packages
+ profile
+ (const #f))))
+ (format #t "~{~a~%~}" settings)
+ #t))
+
(_ #f))))
(let ((opts (parse-options)))
diff --git a/guix/utils.scm b/guix/utils.scm
index aec07301da..7c8e914c01 100644
--- a/guix/utils.scm
+++ b/guix/utils.scm
@@ -61,6 +61,7 @@
version-compare
version>?
package-name->name+version
+ string-tokenize*
file-extension
call-with-temporary-output-file
fold2
@@ -517,6 +518,33 @@ introduce the version part."
(let ((dot (string-rindex file #\.)))
(and dot (substring file (+ 1 dot) (string-length file)))))
+(define (string-tokenize* string separator)
+ "Return the list of substrings of STRING separated by SEPARATOR. This is
+like `string-tokenize', but SEPARATOR is a string."
+ (define (index string what)
+ (let loop ((string string)
+ (offset 0))
+ (cond ((string-null? string)
+ #f)
+ ((string-prefix? what string)
+ offset)
+ (else
+ (loop (string-drop string 1) (+ 1 offset))))))
+
+ (define len
+ (string-length separator))
+
+ (let loop ((string string)
+ (result '()))
+ (cond ((index string separator)
+ =>
+ (lambda (offset)
+ (loop (string-drop string (+ offset len))
+ (cons (substring string 0 offset)
+ result))))
+ (else
+ (reverse (cons string result))))))
+
(define (call-with-temporary-output-file proc)
"Call PROC with a name of a temporary file and open output port to that
file; close the file and delete it when leaving the dynamic extent of this