如果我需要在makefile中使用诸如NVM之类的东西,则会遇到问题,因为NVM会导出一些Make中不可用的bash函数,即使我的shell在makefile中被定义为bash。

如何使make“继承”所有父shell的函数?有没有一种方法可以使Makefile可以访问NVM,而无需为大量的NVM bash函数编写export -f

评论

可能相关。

确实。但不能提供一个好的解决方案。例如,我可以使它与源代码一起工作到我的makefile的每一行,但显然这不是最佳选择。

关于您已经尝试过/发现的内容以及为什么它不能解决您的问题,也许这可能值得您提一问,我认为一个示例Makefile可以解决该问题。

让我看看我是否正确:您的问题是避免为父外壳程序的每个nvm函数编写export -f 。 (如果是这种情况,我假设要声明-F | sed's / declare / export /'> func.sh,然后应该在makefile中使用源funcs.sh。)

我会在SF,SO或这里说这个话题。如果OP明确了他们希望从NVM获得哪些功能,那就太好了。

#1 楼

这里可以使用几个选项。也许最简单的方法之一是将每个函数作为真实脚本安装在添加到路径的某个目录中。操作方法如下:

首先,我们选择一个路径名称来存储所有这些功能,它可以是我们项目中的目录,其中包含我们Makefile中使用的其他实用程序脚本。我们将其称为nvm_install_dir

,然后编写一个_nvm_trampoline脚本,使用该脚本的名称来触发正确的函数,并为_nvm_trampoline创建与脚本中的函数一样多的文件别名。请注意下划线,提示脚本的“私有”字符。我们使用${0##*/}从调用脚本的名称中删除所有路径元素。我们在${nvm_install_dir}下安装该脚本,然后运行以下实用程序脚本:

#!/bin/sh
. "${NVM_DIR}/nvm.sh"

if [ "${0##*/}" = '_nvm_driver' ]; then
    : NOP
else
    eval "${0##*/}" "$@"
fi


将nvm_install过程包装在实际函数中是一种好习惯,而不仅仅是对其内联脚本中的正文,因为它提供了更好的测试选项。 (如果要尝试使用脚本,则对nvm_install的调用要比函数主体更容易注释。)

此后,由nvm_install_dir指向的目录填充了别名_nvm_trampoline是可执行文件,并将其工作委托给相应的功能。我们只需要在运行make时将此目录添加到PATH中。

第二种方法是使用以下脚本为每个nvm函数生成伪命令:

nvm_install_dir='SET-TO-ACTUAL-PARAMETER-VALUE!'
nvm_file="${NVM_DIR}/nvm.sh"
nvm_trampoline='_nvm_trampoline'

nvm_list_functions()
{
    awk -F'[(][)]' ' ~ /^nvm_[^ ]*$/{print()}' "${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


该程序的输出包含make变量分配

nvm_file="${NVM_DIR}/nvm.sh"

nvm_list_functions()
{
    awk -F'[(][)]' ' ~ /^nvm_[^ ]*$/{print()}' "${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 7source "${NVM_DIR}/nvm.sh"; %s "$$@"7 %s\n'\
                   "${nvm_FUNCTION}"\
                   "${nvm_function}"\
                   "${nvm_function}"
        done
    }
}

nvm_generate


它可以保存到文件Makefile.nvmnvmtools.mk中,这些文件可以包含在我们的文件中生成文件。调用函数nvm_command_info是通过

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
…




完成的可以使用自定义的bash配置文件,并使用赋值SHELL=/bin/bash --rcfile PATH-TO-CUSTOM-PROFILE -i,但是我认为这很神秘,足以使维护程序员感到困惑。

#2 楼

一个可能的问题是NVM安装脚本仅编写命令以将自身设置为.bash_profile.bashrc。根据您的系统配置,它可能仅针对交互式外壳设置,而不是由其他程序生成的外壳(更多信息)。如先前的注释所述,采购nvm设置脚本可能是一个不错的选择。如果要运行多个命令以执行1个make target,请查看.ONESHELL。采购$NVM_DIR/nvm.sh时应注意这一点。

另一个通过交互式标志直接调用bash的选项也可能有效。