如何在我的 makefile 中提示用户输入 [y/n](使用纯 make 语法)?

How to prompt user for [y/n] in my makefile (with pure make syntaxis)?

我正在编写一个应该在 Windows 和 Linux 上工作的 makefile。因此,只要有可能,我都会避免使用 OS-specific shell 命令。

这是我的 makefile 的一个片段,结尾有 clean 函数:

# OS specific part
# -----------------
ifeq ($(OS),Windows_NT)
    RM = del /F /Q
    RMDIR = -RMDIR /S /Q
    MKDIR = -mkdir
    ERRIGNORE = 2>NUL || (exit 0)
    SEP=\
else
    RM = rm -rf 
    RMDIR = rm -rf 
    MKDIR = mkdir -p
    ERRIGNORE = 2>/dev/null
    SEP=/
endif
PSEP = $(strip $(SEP))

# Definitions for nullstring and space
# -------------------------------------
nullstring :=
space := $(nullstring) #End

# Lists of all files and folders to keep or remove
# -------------------------------------------------
buildFiles_toKeep := ...    # I wrote some scripts to
buildDirs_toKeep := ...     # automatically generate
buildFiles_toRemove := ...  # these lists. But that would lead
buildDirs_toRemove := ...   # us too far here.


.PHONY: clean
clean:
    @echo.
    @echo ----------------------------------------------------------
    @echo.$(space)        __         **************    $(space)
    @echo.$(space)      __\ \___     * make clean *    $(space)
    @echo.$(space)      \ _ _ _ \    **************    $(space)
    @echo.$(space)       \_`_`_`_\                     $(space)
    @echo.$(space)                                     $(space)
    @echo.$(space)Keep these files:
    @echo.$(space)  $(buildFiles_toKeep)
    @echo.$(space)
    @echo $(space)Keep these directories:
    @echo.$(space)  $(buildDirs_toKeep)
    @echo.$(space)
    @echo.$(space)Remove these files:
    @echo.$(space)  $(buildFiles_toRemove)
    $(RM) $(buildFiles_toRemove)
    @echo.
    @echo.$(space)Remove these directories:
    @echo.$(space)  $(buildDirs_toRemove)
    $(RMDIR) $(buildDirs_toRemove)
    @echo.
@echo ----------------------------------------------------------

这个生成文件效果很好。在 Windows 和 Linux 上,它用正确的 shell 命令替换 $(RM)$(RMDIR) 来删除文件和文件夹。但我想提示用户 he/she 可以按 Y 或 N。我不想删除 he/she 想保留的文件。我试图将一些批处理命令插入到 clean 目标的 recipeee 中,以提示用户输入。但是没有显示提示。可能是因为 GNU make 延迟了输入流。

我想知道是否可以使用 'pure' make syntaxis 生成 [Y/N] 提示符(没有 OS-specific shell 命令)。我知道 make 语言有其局限性。也许一个聪明的解决方案可以在一个操作系统上运行(例如 Linux)并以最小的开销移植到另一个操作系统(例如 Windows)。

有人有想法吗?


编辑:

我提到了这个 link:How do I get `make` to prompt the user for a password and store it in a Makefile variable?

Gnu make 将通过提示用户创建变量 PASSWORD

$ cat Makefile 
PASSWORD ?= $(shell bash -c 'read -s -p "Password: " pwd; echo $$pwd')

只要您希望在 parsed 时提示出现,这种提示用户输入的方法就可以正常工作。但我的情况不同。我想在 makefile already 运行ning 时提示用户,换句话说,当 makefile 中的 recipeee 正在执行时。


编辑:

当您运行设置为多线程时,将无法提示用户。所以我完全可以调用 clean 单线程函数:

    >> make clean -j1

毕竟,clean 功能不需要很长时间就可以完成。我不打算在 build 函数中提示用户任何内容,以便可以多线程执行:-)

    >> make all -j8 --output-sync=target

从概念上讲,make 是一个非常简单的应用程序,只有一个目的 - 构建依赖树,并重新制作具有较新祖先的东西。交互不应该是一个因素,所以 make 不会在本地提供它,理想情况下 make 应该已经拥有它需要的所有信息。如果您确实需要,可以使用 shell!= 解决此问题,甚至可以使用 guile 或 load.

提供您自己的扩展

虽然这并不真正适用于 clean 规则,因为 clean 一开始并没有重新制作任何东西,它只是一个快速的 hack,让你方便地表达一个非-make 操作使用 make 语法。

就我个人而言,我看不到提示用户删除文件的价值,除非你要删除你不负责的东西,这本身就是一种反模式。

如果您绝对肯定需要这个,那么将 clean 配方包装在脚本中,并为 bash 和 windows 提供两个版本。您也可以假设 运行 GNU make on windows 已经在使用 MSYS2、Cygwin 或 MS 认可的 bash for Windows 10 版本,并完全放弃 cmd / powershell 脚本。

如果您想在一行中使用是/否来执行某些操作(这里是另一个 makefile 目标):

request-test:
    @echo -n "Are you sure? [y/N] " && read ans && if [ $${ans:-'N'} = 'y' ]; then make ENV=test spec-tests; fi
  1. 问题会提示;
  2. 将读取响应并将其存储到名为 ans;
  3. 的变量中
  4. if用默认值读取ans变量的值,避免出错。