spack/share/spack/csh/spack.csh
Greg Becker c9e01ff9d7 shell support: spack load no longer needs modules (#14062)
Previously the `spack load` command was a wrapper around `module load`. This required some bootstrapping of modules to make `spack load` work properly.

With this PR, the `spack` shell function handles the environment modifications necessary to add packages to your user environment. This removes the dependence on environment modules or lmod and removes the requirement to bootstrap spack (beyond using the setup-env scripts).

Included in this PR is support for MacOS when using Apple's System Integrity Protection (SIP), which is enabled by default in modern MacOS versions. SIP clears the `LD_LIBRARY_PATH` and `DYLD_LIBRARY_PATH` variables on process startup for executables that live in `/usr` (but not '/usr/local', `/System`, `/bin`, and `/sbin` among other system locations. Spack cannot know the `LD_LIBRARY_PATH` of the calling process when executed using `/bin/sh` and `/usr/bin/python`. The `spack` shell function now manually forwards these two variables, if they are present, as `SPACK_<VAR>` and recovers those values on startup.

- [x] spack load/unload no longer delegate to modules
- [x] refactor user_environment modification calculations
- [x] update documentation for spack load/unload

Co-authored-by: Todd Gamblin <tgamblin@llnl.gov>
2020-01-22 22:36:02 -08:00

139 lines
4.7 KiB
Tcsh

# Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
########################################################################
# This is a wrapper around the spack command that forwards calls to
# 'spack load' and 'spack unload' to shell functions. This in turn
# allows them to be used to invoke environment-modules functions.
#
# 'spack load' is smarter than just 'load' because it converts its
# arguments into a unique Spack spec that is then passed to environment-modules
# commands. This allows the user to use packages without knowing all
# their installation details.
#
# e.g., rather than requiring a full spec for libelf, the user can type:
#
# spack load libelf
#
# This will first find the available libelf module file and use a
# matching one. If there are two versions of libelf, the user would
# need to be more specific, e.g.:
#
# spack load libelf@0.8.13
#
# This is very similar to how regular spack commands work and it
# avoids the need to come up with a user-friendly naming scheme for
# spack module files.
########################################################################
# Store LD_LIBRARY_PATH variables from spack shell function
# This is necessary because MacOS System Integrity Protection clears
# (DY?)LD_LIBRARY_PATH variables on process start.
if ( ${?LD_LIBRARY_PATH} ) then
setenv SPACK_LD_LIBRARY_PATH $LD_LIBRARY_PATH
endif
if ( ${?DYLD_LIBRARY_PATH} ) then
setenv SPACK_DYLD_LIBRARY_PATH $DYLD_LIBRARY_PATH
endif
# accumulate initial flags for main spack command
set _sp_flags = ""
while ( $#_sp_args > 0 )
if ( "$_sp_args[1]" !~ "-*" ) break
set _sp_flags = "$_sp_flags $_sp_args[1]"
shift _sp_args
end
# h and V flags don't require further output parsing.
if ( "$_sp_flags" =~ *h* || "$_sp_flags" =~ *V* ) then
\spack $_sp_flags $_sp_args
goto _sp_end
endif
# Set up args -- we want a subcommand and a spec.
set _sp_subcommand=""
set _sp_spec=""
[ $#_sp_args -gt 0 ] && set _sp_subcommand = ($_sp_args[1])
[ $#_sp_args -gt 1 ] && set _sp_spec = ($_sp_args[2-])
# Run subcommand
switch ($_sp_subcommand)
case cd:
shift _sp_args # get rid of 'cd'
set _sp_arg=""
[ $#_sp_args -gt 0 ] && set _sp_arg = ($_sp_args[1])
shift _sp_args
if ( "$_sp_arg" == "-h" ) then
\spack cd -h
else
cd `\spack location $_sp_arg $_sp_args`
endif
breaksw
case env:
shift _sp_args # get rid of 'env'
set _sp_arg=""
[ $#_sp_args -gt 0 ] && set _sp_arg = ($_sp_args[1])
if ( "$_sp_arg" == "-h" ) then
\spack env -h
else
switch ($_sp_arg)
case activate:
set _sp_env_arg=""
[ $#_sp_args -gt 1 ] && set _sp_env_arg = ($_sp_args[2])
if ( "$_sp_env_arg" == "" || "$_sp_args" =~ "*--sh*" || "$_sp_args" =~ "*--csh*" || "$_sp_args" =~ "*-h*" ) then
# no args or args contain -h/--help, --sh, or --csh: just execute
\spack $_sp_flags env $_sp_args
else
shift _sp_args # consume 'activate' or 'deactivate'
# actual call to activate: source the output
eval `\spack $_sp_flags env activate --csh $_sp_args`
endif
breaksw
case deactivate:
set _sp_env_arg=""
[ $#_sp_args -gt 1 ] && set _sp_env_arg = ($_sp_args[2])
if ( "$_sp_env_arg" != "" ) then
# with args: execute the command
\spack $_sp_flags env $_sp_args
else
# no args: source the output
eval `\spack $_sp_flags env deactivate --csh`
endif
breaksw
default:
echo default
\spack $_sp_flags env $_sp_args
breaksw
endsw
endif
case load:
case unload:
# Space in `-h` portion is important for differentiating -h option
# from variants that begin with "h" or packages with "-h" in name
if ( "$_sp_spec" =~ "*--sh*" || "$_sp_spec" =~ "*--csh*" || \
" $_sp_spec" =~ "* -h*" || "$_sp_spec" =~ "*--help*") then
# IF a shell is given, print shell output
\spack $_sp_flags $_sp_subcommand $_sp_spec
else
# otherwise eval with csh
eval `\spack $_sp_flags $_sp_subcommand --csh $_sp_spec || \
echo "exit 1"`
endif
breaksw
default:
\spack $_sp_flags $_sp_args
breaksw
endsw
_sp_end:
unset _sp_args _sp_full_spec _sp_sh_cmd _sp_spec _sp_subcommand _sp_flags
unset _sp_arg _sp_env_arg