There are several options that can be used here. Maybe one of the easiest is to install each function as a real script in some directory that is added to the path. Here is how to do this:
First, we choose a path name where to store all these functions, it can be a a directory in our project, where other utility scripts used in our Makefile live. We call it nvm_install_dir
Then we write a _nvm_trampoline
script which use the name it is called as to trigger the right function, and create as many file aliases to _nvm_trampoline
as there are functions in the script. Note the leading underscore, hinting at the “private” character of the script.
This script can go along the lines of
#!/bin/sh
. "${NVM_DIR}/nvm.sh"
if [ "${0##*/}" = '_nvm_driver' ]; then
: NOP
else
eval "${0##*/}" "$@"
fi
Here we use ${0##*/}
to remove any path element from the name under which our script is called. We install that script under ${nvm_install_dir}
and run once the following utility script:
nvm_install_dir='SET-TO-ACTUAL-PARAMETER-VALUE!'
nvm_file="${NVM_DIR}/nvm.sh"
nvm_trampoline='_nvm_trampoline'
nvm_list_functions()
{
awk -F'[(][)]' '$1 ~ /^nvm_[^ ]*$/{print($1)}' "${nvm_file}"
}
nvm_install()
{
nvm_list_functions | {
while read nvm_function; do
ln\
"${nvm_install_dir}/${nvm_driver}"\
"${nvm_install_dir}/${nvm_function}"
chmod 755 "${nvm_install_dir}/${nvm_function}"
done
}
}
nvm_install
It is a good practice to pack the nvm_install procedure in a real function instead of just inlining its body in the script, as it gives better testing options. (It is easier to comment out the call to nvm_install than the body of the function, if we want to experiment with the script.)
Ater this, the directory pointed to by nvm_install_dir is populated with aliases to _nvm_trampoline
that are executable and delegate their work to the corresponding function. We only need to add this directory to our PATH when running make.
A second approach would be to generate pseudo commands for each nvm functions, with the following script:
nvm_file="${NVM_DIR}/nvm.sh"
nvm_list_functions()
{
awk -F'[(][)]' '$1 ~ /^nvm_[^ ]*$/{print($1)}' "${nvm_file}"
}
nvm_generate()
{
nvm_list_functions | {
while read nvm_function; do
nvm_FUNCTION=$(printf '%s' "${nvm_function}" | tr '[a-z]' '[A-Z]')
printf '%s=sh -c \047source "${NVM_DIR}/nvm.sh"; %s "$$@"\047 %s\n'\
"${nvm_FUNCTION}"\
"${nvm_function}"\
"${nvm_function}"
done
}
}
nvm_generate
The output of this program consists of make variable assignments
NVM_ECHO=sh -c 'source "${NVM_DIR}/nvm.sh"; nvm_echo "$$@"' nvm_echo
NVM_CD=sh -c 'source "${NVM_DIR}/nvm.sh"; nvm_cd "$$@"' nvm_cd
…
NVM_COMMAND_INFO=sh -c 'source "${NVM_DIR}/nvm.sh"; nvm_command_info "$$@"' nvm_command_info
…
It can be saved to a file Makefile.nvm
or nvmtools.mk
that can be included our Makefiles. Calling the function nvm_command_info
is done with
${NVM_COMMAND_INFO} arg1 arg2 …
Using a customised bash profile is possible, using the assignment
SHELL=/bin/bash --rcfile PATH-TO-CUSTOM-PROFILE -i
but I would consider this esoteric enough to puzzle the maintenance programmer.
source ...
to every line of my makefile, for example, but clearly that's sub-optimal. – Assaf Lavie Mar 23 '17 at 12:43export -f <funcname>
for each nvm function of your parent shell. (if this is the case I assumedeclare -F | sed 's/declare/export/' > func.sh
and then asource funcs.sh
within the makefile should do.) – Tensibai Mar 23 '17 at 13:04