mirror of
https://git.in.rschanz.org/ryan77627/guix.git
synced 2024-12-24 05:18:07 -05:00
profiles: Generate an 'etc/profile' file.
Suggested by 宋文武 <iyzsong@gmail.com> in <http://bugs.gnu.org/20255>. * guix/build/profiles.scm (abstract-profile, write-environment-variable-definition): New procedures. (build-profile): Add #:search-paths parameter. Create OUTPUT/etc/profile. * guix/profiles.scm (profile-derivation)[builder]: Add 'search-paths' variable and pass it to 'build-profile'. Adjust #:modules argument. * tests/profiles.scm ("etc/profile"): New test. * doc/guix.texi (Invoking guix package): Mention etc/profile.
This commit is contained in:
parent
611adb1ee5
commit
d664f1b431
5 changed files with 118 additions and 7 deletions
|
@ -14,6 +14,7 @@
|
||||||
((indent-tabs-mode . nil)
|
((indent-tabs-mode . nil)
|
||||||
(eval . (put 'eval-when 'scheme-indent-function 1))
|
(eval . (put 'eval-when 'scheme-indent-function 1))
|
||||||
(eval . (put 'test-assert 'scheme-indent-function 1))
|
(eval . (put 'test-assert 'scheme-indent-function 1))
|
||||||
|
(eval . (put 'test-assertm 'scheme-indent-function 1))
|
||||||
(eval . (put 'test-equal 'scheme-indent-function 1))
|
(eval . (put 'test-equal 'scheme-indent-function 1))
|
||||||
(eval . (put 'test-eq 'scheme-indent-function 1))
|
(eval . (put 'test-eq 'scheme-indent-function 1))
|
||||||
(eval . (put 'call-with-input-string 'scheme-indent-function 1))
|
(eval . (put 'call-with-input-string 'scheme-indent-function 1))
|
||||||
|
|
|
@ -950,6 +950,16 @@ created in @file{$HOME/.guix-profile}. This symlink always points to the
|
||||||
current generation of the user's default profile. Thus, users can add
|
current generation of the user's default profile. Thus, users can add
|
||||||
@file{$HOME/.guix-profile/bin} to their @code{PATH} environment
|
@file{$HOME/.guix-profile/bin} to their @code{PATH} environment
|
||||||
variable, and so on.
|
variable, and so on.
|
||||||
|
@cindex search paths
|
||||||
|
If you are not using the Guix System Distribution, consider adding the
|
||||||
|
following lines to your @file{~/.bash_profile} (@pxref{Bash Startup
|
||||||
|
Files,,, bash, The GNU Bash Reference Manual}) so that newly-spawned
|
||||||
|
shells get all the right environment variable definitions:
|
||||||
|
|
||||||
|
@example
|
||||||
|
GUIX_PROFILE="$HOME/.guix-profile" \
|
||||||
|
source "$HOME/.guix-profile/etc/profile"
|
||||||
|
@end example
|
||||||
|
|
||||||
In a multi-user setup, user profiles are stored in a place registered as
|
In a multi-user setup, user profiles are stored in a place registered as
|
||||||
a @dfn{garbage-collector root}, which @file{$HOME/.guix-profile} points
|
a @dfn{garbage-collector root}, which @file{$HOME/.guix-profile} points
|
||||||
|
|
|
@ -18,6 +18,10 @@
|
||||||
|
|
||||||
(define-module (guix build profiles)
|
(define-module (guix build profiles)
|
||||||
#:use-module (guix build union)
|
#:use-module (guix build union)
|
||||||
|
#:use-module (guix build utils)
|
||||||
|
#:use-module (guix search-paths)
|
||||||
|
#:use-module (srfi srfi-26)
|
||||||
|
#:use-module (ice-9 match)
|
||||||
#:use-module (ice-9 pretty-print)
|
#:use-module (ice-9 pretty-print)
|
||||||
#:export (build-profile))
|
#:export (build-profile))
|
||||||
|
|
||||||
|
@ -28,14 +32,71 @@ (define-module (guix build profiles)
|
||||||
;;;
|
;;;
|
||||||
;;; Code:
|
;;; Code:
|
||||||
|
|
||||||
|
(define (abstract-profile profile)
|
||||||
|
"Return a procedure that replaces PROFILE in VALUE with a reference to the
|
||||||
|
'GUIX_PROFILE' environment variable. This allows users to specify what the
|
||||||
|
user-friendly name of the profile is, for instance ~/.guix-profile rather than
|
||||||
|
/gnu/store/...-profile."
|
||||||
|
(let ((replacement (string-append "${GUIX_PROFILE:-" profile "}")))
|
||||||
|
(match-lambda
|
||||||
|
((search-path . value)
|
||||||
|
(let* ((separator (search-path-specification-separator search-path))
|
||||||
|
(items (string-tokenize* value separator))
|
||||||
|
(crop (cute string-drop <> (string-length profile))))
|
||||||
|
(cons search-path
|
||||||
|
(string-join (map (lambda (str)
|
||||||
|
(string-append replacement (crop str)))
|
||||||
|
items)
|
||||||
|
separator)))))))
|
||||||
|
|
||||||
|
(define (write-environment-variable-definition port)
|
||||||
|
"Write the given environment variable definition to PORT."
|
||||||
|
(match-lambda
|
||||||
|
((search-path . value)
|
||||||
|
(display (search-path-definition search-path value #:kind 'prefix)
|
||||||
|
port)
|
||||||
|
(newline port))))
|
||||||
|
|
||||||
(define* (build-profile output inputs
|
(define* (build-profile output inputs
|
||||||
#:key manifest)
|
#:key manifest search-paths)
|
||||||
"Build a user profile from INPUTS in directory OUTPUT. Write MANIFEST, an
|
"Build a user profile from INPUTS in directory OUTPUT. Write MANIFEST, an
|
||||||
sexp, to OUTPUT/manifest."
|
sexp, to OUTPUT/manifest. Create OUTPUT/etc/profile with Bash definitions for
|
||||||
|
all the variables listed in SEARCH-PATHS."
|
||||||
|
;; Make the symlinks.
|
||||||
(union-build output inputs
|
(union-build output inputs
|
||||||
#:log-port (%make-void-port "w"))
|
#:log-port (%make-void-port "w"))
|
||||||
|
|
||||||
|
;; Store meta-data.
|
||||||
(call-with-output-file (string-append output "/manifest")
|
(call-with-output-file (string-append output "/manifest")
|
||||||
(lambda (p)
|
(lambda (p)
|
||||||
(pretty-print manifest p))))
|
(pretty-print manifest p)))
|
||||||
|
|
||||||
|
;; Add a ready-to-use Bash profile.
|
||||||
|
(mkdir-p (string-append output "/etc"))
|
||||||
|
(call-with-output-file (string-append output "/etc/profile")
|
||||||
|
(lambda (port)
|
||||||
|
;; The use of $GUIX_PROFILE described below is not great. Another
|
||||||
|
;; option would have been to use "$1" and have users run:
|
||||||
|
;;
|
||||||
|
;; source ~/.guix-profile/etc/profile ~/.guix-profile
|
||||||
|
;;
|
||||||
|
;; However, when 'source' is used with no arguments, $1 refers to the
|
||||||
|
;; first positional parameter of the calling scripts, so we can rely on
|
||||||
|
;; it.
|
||||||
|
(display "\
|
||||||
|
# Source this file to define all the relevant environment variables in Bash
|
||||||
|
# for this profile. You may want to define the 'GUIX_PROFILE' environment
|
||||||
|
# variable to point to the \"visible\" name of the profile, like this:
|
||||||
|
#
|
||||||
|
# GUIX_PROFILE=/path/to/profile
|
||||||
|
# source /path/to/profile/etc/profile
|
||||||
|
#
|
||||||
|
# When GUIX_PROFILE is undefined, the various environment variables refer
|
||||||
|
# to this specific profile generation.
|
||||||
|
\n" port)
|
||||||
|
(let ((variables (evaluate-search-paths (cons $PATH search-paths)
|
||||||
|
(list output))))
|
||||||
|
(for-each (write-environment-variable-definition port)
|
||||||
|
(map (abstract-profile output) variables))))))
|
||||||
|
|
||||||
;;; profile.scm ends here
|
;;; profile.scm ends here
|
||||||
|
|
|
@ -598,17 +598,30 @@ (define inputs
|
||||||
|
|
||||||
(define builder
|
(define builder
|
||||||
#~(begin
|
#~(begin
|
||||||
(use-modules (guix build profiles))
|
(use-modules (guix build profiles)
|
||||||
|
(guix search-paths))
|
||||||
|
|
||||||
(setvbuf (current-output-port) _IOLBF)
|
(setvbuf (current-output-port) _IOLBF)
|
||||||
(setvbuf (current-error-port) _IOLBF)
|
(setvbuf (current-error-port) _IOLBF)
|
||||||
|
|
||||||
|
(define search-paths
|
||||||
|
;; Search paths of MANIFEST's packages, converted back to their
|
||||||
|
;; record form.
|
||||||
|
(map sexp->search-path-specification
|
||||||
|
'#$(map search-path-specification->sexp
|
||||||
|
(append-map manifest-entry-search-paths
|
||||||
|
(manifest-entries manifest)))))
|
||||||
|
|
||||||
(build-profile #$output '#$inputs
|
(build-profile #$output '#$inputs
|
||||||
#:manifest '#$(manifest->gexp manifest))))
|
#:manifest '#$(manifest->gexp manifest)
|
||||||
|
#:search-paths search-paths)))
|
||||||
|
|
||||||
(gexp->derivation "profile" builder
|
(gexp->derivation "profile" builder
|
||||||
#:modules '((guix build union)
|
#:modules '((guix build profiles)
|
||||||
(guix build profiles))
|
(guix build union)
|
||||||
|
(guix build utils)
|
||||||
|
(guix search-paths)
|
||||||
|
(guix records))
|
||||||
#:local-build? #t)))
|
#:local-build? #t)))
|
||||||
|
|
||||||
(define (profile-regexp profile)
|
(define (profile-regexp profile)
|
||||||
|
|
|
@ -29,6 +29,8 @@ (define-module (test-profiles)
|
||||||
#:use-module ((gnu packages guile) #:prefix packages:)
|
#:use-module ((gnu packages guile) #:prefix packages:)
|
||||||
#:use-module (ice-9 match)
|
#:use-module (ice-9 match)
|
||||||
#:use-module (ice-9 regex)
|
#:use-module (ice-9 regex)
|
||||||
|
#:use-module (ice-9 popen)
|
||||||
|
#:use-module (rnrs io ports)
|
||||||
#:use-module (srfi srfi-11)
|
#:use-module (srfi srfi-11)
|
||||||
#:use-module (srfi srfi-64))
|
#:use-module (srfi srfi-64))
|
||||||
|
|
||||||
|
@ -220,6 +222,30 @@ (define glibc
|
||||||
(manifest-entry-search-paths entry)
|
(manifest-entry-search-paths entry)
|
||||||
(package-native-search-paths
|
(package-native-search-paths
|
||||||
packages:guile-2.0)))))))))
|
packages:guile-2.0)))))))))
|
||||||
|
|
||||||
|
(test-assertm "etc/profile"
|
||||||
|
;; Make sure we get an 'etc/profile' file that at least defines $PATH.
|
||||||
|
(mlet* %store-monad
|
||||||
|
((guile -> (package
|
||||||
|
(inherit %bootstrap-guile)
|
||||||
|
(native-search-paths
|
||||||
|
(package-native-search-paths packages:guile-2.0))))
|
||||||
|
(entry -> (package->manifest-entry guile))
|
||||||
|
(drv (profile-derivation (manifest (list entry))
|
||||||
|
#:hooks '()))
|
||||||
|
(profile -> (derivation->output-path drv)))
|
||||||
|
(mbegin %store-monad
|
||||||
|
(built-derivations (list drv))
|
||||||
|
(let* ((pipe (open-input-pipe
|
||||||
|
(string-append "source "
|
||||||
|
profile "/etc/profile; "
|
||||||
|
"unset GUIX_PROFILE; set")))
|
||||||
|
(env (get-string-all pipe)))
|
||||||
|
(return
|
||||||
|
(and (zero? (close-pipe pipe))
|
||||||
|
(string-contains env
|
||||||
|
(string-append "PATH=" profile "/bin"))))))))
|
||||||
|
|
||||||
(test-end "profiles")
|
(test-end "profiles")
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue