diff --git a/etc/fslconf/createFSLWrapper.sh b/etc/fslconf/createFSLWrapper.sh new file mode 100755 index 0000000000000000000000000000000000000000..101e50506f366fb8f3254173665f86208a8c362b --- /dev/null +++ b/etc/fslconf/createFSLWrapper.sh @@ -0,0 +1,87 @@ +#!/bin/sh +# +# Create wrapper scripts in $FSLDIR/share/bin/ which invoke commands that +# are installed in $FSLDIR/bin/. +# +# This script is used to create isolated versions of all executables +# provided by FSL projects, so they can be added to the user $PATH without +# any other executables that are installed into the conda environment that +# is $FSLDIR/bin (for example, python, pip, tcl, etc). +# +# This script should only be invoked when FSL is being installed via the +# fslinstaller.py script - it is not intended to be used when individual +# FSL projects are explicitly installed into a custom conda environment. +# +# Early versions of this script would create symlinks from $FSLDIR/bin/ into +# $FSLDIR/fslpython/envs/fslpython/bin/ (and, later, into +# $FSLDIR/share/bin/). However, wrapper scripts are now used instead to work +# around a couple of problems: +# +# - We need python executables to exclusively use the libraries installed in +# the FSL conda environment. Users may have other Python environments +# activated, and/or libraries installed into a local site-packages +# directory. So we need to invoke the python interpreter in isolated mode, +# with the -I flag: +# +# https://docs.python.org/3/using/cmdline.html#id2 +# +# - There is no guarantee that a shell supports shebang lines longer than 127 +# characters. Depending on where FSL is installed, it may not be possible +# to have a shebang line pointing to $FSLDIR/bin/python which does not +# exceed 127 characters. + +# Names of all executables for which wrapper +# scripts are to be created are passed as +# arguments +targets=$@ + +# Only create wrappers if scripts +# are in subdirectory of FSLDIR +if [ -z "$FSLDIR" ]; then + exit 1 +fi + +case "$PREFIX" in "$FSLDIR"*) + + for script in $targets; do + sourceScript="${PREFIX}/bin/$script" + targetScript="${FSLDIR}/share/bin/$script" + + if [ ! -f "$sourceScript" ]; then + continue + fi + + # remove target script if it already exists + if [ -e "$targetScript" ]; then + rm "$targetScript" + fi + + # Figure out whether this is a python + # executable or some other type of + # executable. We search for these strings + # in source file headers to ID them as + # python scripts. We need to check both + # match "#!/usr/bin/env python" and + # "#!<fsldir>/bin/python...", because + # conda might generate one or the other + # in different scenarios. + id1=$(head -c 1024 "$sourceScript" | grep "#!/usr/bin/env python") + id2=$(head -c 1024 "$sourceScript" | grep "/fslpython/bin/python") + + # Non-python executable - use a + # pass-through script + if [ -z "$id1" ] && [ -z "$id2" ]; then + echo "#!/bin/sh" > "$targetScript" + echo "$FSLDIR/bin/$script \"$@\"" >> "$targetScript" + else + + # Python executable - run it via + # $FSLDIR/bin/python in isolated mode + echo "#!/bin/sh" > "$targetScript" + echo "$FSLDIR/bin/python -I $sourceScript \"$@\"" >> "$targetScript" + fi + + # Preserve file permissions + chmod --reference="$sourceScript" "$targetScript" + done +esac diff --git a/etc/fslconf/removeFSLWrapper.sh b/etc/fslconf/removeFSLWrapper.sh new file mode 100755 index 0000000000000000000000000000000000000000..625409beeade83aa6b9959921550bcb605139f7b --- /dev/null +++ b/etc/fslconf/removeFSLWrapper.sh @@ -0,0 +1,23 @@ +#!/bin/sh +# +# Remove wrapper script/links in $FSLDIR/share/bin/ which invoke commands +# that are installed in $FSLDIR/bin/. See createFSLWrapper.sh for more +# information. + +targets="$@" + +if [ -z "$FSLDIR" ]; then + exit 1 +fi + +# Only remove if scripts are in subdirectory of FSLDIR +case "$PREFIX" in "$FSLDIR"*) + + for script in $targets; do + targetScript="${FSLDIR}/share/bin/$script" + + if [ -f "$targetScript" ]; then + rm "$targetScript" + fi + done +esac