guix package: Add `--search-paths' & co.

* guix/scripts/package.scm (search-path-environment-variables,
  display-search-paths): New procedures.
  (show-help, %options): Add `--search-paths'.
  (guix-package)[process-actions]: Call `display-search-paths' once the
  profile is ready.
  [process-query]: Honor `search-paths'.
This commit is contained in:
Ludovic Courtès 2013-04-28 23:05:57 +02:00
parent 2bcfb9e065
commit 5924080dcc
3 changed files with 94 additions and 2 deletions

View File

@ -517,8 +517,13 @@ Thus, when installing MPC, the MPFR and GMP libraries also get installed
in the profile; removing MPC also removes MPFR and GMP---unless they had in the profile; removing MPC also removes MPFR and GMP---unless they had
also been explicitly installed independently. also been explicitly installed independently.
Besides, packages sometime rely on the definition of environment
variables for their search paths (see explanation of
@code{--search-paths} below.) Any missing or possibly incorrect
environment variable definitions are reported here.
@c XXX: keep me up-to-date @c XXX: keep me up-to-date
Besides, when installing a GNU package, the tool reports the Finally, when installing a GNU package, the tool reports the
availability of a newer upstream version. In the future, it may provide availability of a newer upstream version. In the future, it may provide
the option of installing directly from the upstream version, even if the option of installing directly from the upstream version, even if
that version is not yet in the distribution. that version is not yet in the distribution.
@ -566,6 +571,21 @@ Installing, removing, or upgrading packages from a generation that has
been rolled back to overwrites previous future generations. Thus, the been rolled back to overwrites previous future generations. Thus, the
history of a profile's generations is always linear. history of a profile's generations is always linear.
@item --search-paths
@cindex search paths
Report environment variable definitions, in Bash syntax, that may be
needed in order to use the set of installed packages. These environment
variables are used to specify @dfn{search paths} for files used by some
of the installed packages.
For example, GCC needs the @code{CPATH} and @code{LIBRARY_PATH}
environment variables to be defined so it can look for headers and
libraries in the user's profile (@pxref{Environment Variables,,, gcc,
Using the GNU Compiler Collection (GCC)}). If GCC and, say, the C
library are installed in the profile, then @code{--search-paths} will
suggest setting these variables to @code{@var{profile}/include} and
@code{@var{profile}/lib}, respectively.
@item --profile=@var{profile} @item --profile=@var{profile}
@itemx -p @var{profile} @itemx -p @var{profile}
Use @var{profile} instead of the user's default profile. Use @var{profile} instead of the user's default profile.

View File

@ -330,6 +330,53 @@ but ~a is available upstream~%")
((getaddrinfo-error ftp-error) #f) ((getaddrinfo-error ftp-error) #f)
(else (apply throw key args)))))) (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. ;;; 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")) -u, --upgrade[=REGEXP] upgrade all the installed packages matching REGEXP"))
(display (_ " (display (_ "
--roll-back roll back to the previous generation")) --roll-back roll back to the previous generation"))
(display (_ "
--search-paths display needed environment variable definitions"))
(newline) (newline)
(display (_ " (display (_ "
-p, --profile=PROFILE use PROFILE instead of the user's default profile")) -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 (option '("roll-back") #f #f
(lambda (opt name arg result) (lambda (opt name arg result)
(alist-cons 'roll-back? #t 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 (option '(#\p "profile") #t #f
(lambda (opt name arg result) (lambda (opt name arg result)
(alist-cons 'profile arg (alist-cons 'profile arg
@ -728,7 +780,9 @@ Install, remove, or upgrade PACKAGES in a single transaction.\n"))
(build-derivations (%store) (list prof-drv))) (build-derivations (%store) (list prof-drv)))
(begin (begin
(switch-symlinks name prof) (switch-symlinks name prof)
(switch-symlinks profile name)))))))))) (switch-symlinks profile name)
(display-search-paths packages
profile))))))))))
(define (process-query opts) (define (process-query opts)
;; Process any query specified by OPTS. Return #t when a query was ;; 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)) (for-each (cute package->recutils <> (current-output-port))
(find-packages-by-description regexp)) (find-packages-by-description regexp))
#t)) #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)))) (_ #f))))
(let ((opts (parse-options))) (let ((opts (parse-options)))

View File

@ -47,6 +47,10 @@ test -L "$profile" && test -L "$profile-1-link"
! test -f "$profile-2-link" ! test -f "$profile-2-link"
test -f "$profile/bin/guile" test -f "$profile/bin/guile"
# No search path env. var. here.
guix package --search-paths -p "$profile"
test "`guix package --search-paths -p "$profile" | wc -l`" = 0
# Check whether we have network access. # Check whether we have network access.
if guile -c '(getaddrinfo "www.gnu.org" "80" AI_NUMERICSERV)' 2> /dev/null if guile -c '(getaddrinfo "www.gnu.org" "80" AI_NUMERICSERV)' 2> /dev/null
then then
@ -119,6 +123,10 @@ then
rm "$profile-1-link" rm "$profile-1-link"
guix package --bootstrap -p "$profile" --roll-back guix package --bootstrap -p "$profile" --roll-back
test "`readlink_base "$profile"`" = "$profile-0-link" test "`readlink_base "$profile"`" = "$profile-0-link"
# Make sure LIBRARY_PATH gets listed by `--search-paths'.
guix package --bootstrap -p "$profile" -i guile-bootstrap -i gcc-bootstrap
guix package --search-paths -p "$profile" | grep LIBRARY_PATH
fi fi
# Make sure the `:' syntax works. # Make sure the `:' syntax works.