一千萬個為什麽

搜索

我如何在makefile中使用bash函數?



如果我需要在makefile中使用類似NVM的東西,我會遇到一個問題,因為NVM導出一些在Make中不可用的bash函數,即使我的shell在makefile中被定義為bash。

我如何讓make“繼承”所有父shell的函數?有沒有辦法讓一個makefile文件可以訪問NVM,而不需要寫一個非常小的NVM bash函數的 export -f

轉載註明原文: 我如何在makefile中使用bash函數?

一共有 2 個回答:

這裏有幾個選項可以使用。也許最簡單的一種方法是將每個函數作為實際腳本安裝在添加到路徑中的某個目錄中。這是如何做到這一點:

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

然後,我們編寫一個 _nvm_trampoline 腳本,它使用被調用的名稱來觸發正確的函數,並為腳本中的函數創建許多文件別名到 _nvm_trampoline 。請註意前面的下劃線,暗示腳本的“私人”特征。

這個腳本可以沿著

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

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

這裏我們使用 $ {0 ## * /} 從我們的腳本被調用的名稱中刪除任何路徑元素。我們在 $ {nvm_install_dir} 下安裝該腳本,並運行以下實用程序腳本:

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

將真正的函數打包到 nvm_install 過程中是一種很好的做法,而不是僅僅在腳本中內聯它的正文,因為它提供了更好的測試選項。 (如果我們想要對腳本進行實驗,那麽將對 nvm_install 的調用註釋掉比函數的主體更容易)。

在此情況下,由 nvm_install_dir 指向的目錄會填充別名為 _nvm_trampoline 的可執行文件,並將其工作委托給相應的函數。運行 make 時,我們只需將此目錄添加到我們的 PATH 中。

第二種方法是使用以下腳本為每個 nvm 函數生成偽命令:

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 "[email protected]"\047 %s\n'\
                   "${nvm_FUNCTION}"\
                   "${nvm_function}"\
                   "${nvm_function}"
        done
    }
}

nvm_generate

該程序的輸出由 make 變量賦值組成

NVM_ECHO=sh -c 'source "${NVM_DIR}/nvm.sh"; nvm_echo "[email protected]"' nvm_echo
NVM_CD=sh -c 'source "${NVM_DIR}/nvm.sh"; nvm_cd "[email protected]"' nvm_cd
…
NVM_COMMAND_INFO=sh -c 'source "${NVM_DIR}/nvm.sh"; nvm_command_info "[email protected]"' nvm_command_info
…

它可以保存到可以包含在我們的Makefiles中的文件 Makefile.nvmnvmtools.mk 。調用函數 nvm_command_info 完成

${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.

一個可能的問題是,NVM安裝腳本只會寫入命令以將其自身設置為 .bash_profile.bashrc 。根據您的系統配置,它可能只設置為交互式shell,而不是其他程序產生的shell(更多信息)。正如先前的評論指出的那樣,采購nvm安裝腳本可能是一個不錯的選擇。如果您有多個命令要運行1個目標,請查看。ONESHELL 。采購 $ NVM_DIR/nvm.sh 應該照顧它。

Another option that invokes bash directly with the interactive flag might work as well.