Makefile 变量的交互式输入

问题描述 投票:0回答:2

我想用输入变量运行makefile。我想要的是,如果我写下项目名称,将创建一个具有该名称的文件夹。

所以我写

read
命令:

CC = gcc
CFLAGS = -W -Wall
FILE := hi
src = $(wildcard *.c)
OBJ = $(src:.c=.o)

all : $(FILE)
$(FILE) : $(OBJ)
    $(CC) $(CFLAGS) -o $@ $^

.PHONY: clean

clean : 
    rm *.o $(FILE)

move : 
    mkdir -p ../../bin/$(FILE);
    mkdir -p ../../exe/$(FILE);
    mv *.o ../../bin/$(FILE);
    mv $(FILE) ../../exe/$(FILE)

afterclean :
    rm ../../bin/$(FILE)/*.o;
    rm ../../exe/$(FILE)/$(FILE)

execute :
    ./../../exe/$(FILE)/$(FILE)


read :
    @read -p "Enter : " enter; \
    $(FILE) := enter; \
    echo $FILE

我想做的是如果我通过

FILE
获得
read
名字我想改变
FILE
变量,但我不能改变它。我该怎么做?

makefile gnu
2个回答
4
投票

简而言之,您不能轻易做到这一点(您可能不想这样做,向下滚动以了解基本原理)。如果你仔细看看你的

Makefile
你会发现你混合了
make
和 shell 语法......以及它们的上下文。

在你的例子中,它从字面上将以下字符串传递给 shell(

SHELL
的值,可能默认为
/bin/sh
)和
-c

read -p "Enter : " enter; \
hi := enter; \
echo ILE

显示了混合语法的效果。

$(FILE)
(值
hi
)和
$F
(未设置 -> 空)是在调用 shell 之前由 make 替换的 make 变量。 (虽然根本没有使用
read
enter
变量,而是使用文字字符串
enter
尝试在正在运行的 shell 中进行变量分配。)

如果你想运行一个 shell 命令并从它所做的/学到的东西中分配一个值给 make 变量,你必须使用

shell
函数(或者生成一个(临时)文件你会
include
,但这更混乱):

FILE := $(shell read -p "Enter: " enter ; echo $${enter})

然而,这总是会问......除非你使用条件赋值(

?=
),在这种情况下你可以从命令行中选择(
make FILE=something
,此时我们即将关闭圆圈)。我通常不确定您的意图是如何告诉
make
何时询问以及何时使用
hi
的默认值。

这让我明白为什么这个概念一开始对我来说听起来很可疑,以及为什么 @HolyBlackCat 提出的建议是自定义调用

make
.

的更好方式

此外,任何运行时用户交互通常都会破坏自动化(这是我们

make
的目的)并且还会使构建不可重现。因此,最好避免使用它们。

换句话说,如果你真的需要,我会说为这种类型的调用写一个

interactive_make_call.sh

#!/bin/bash
read -p "Enter : " enter
make FILE="${enter}" "$@"

甚至:

#!/bin/bash
read -p "Enter : " enter
if [[ -n "${enter}" ]] ; then
        make FILE="${enter}" "$@"
else
        make "$@"
fi     

如果您只需按

enter
,则从
FILE
回退到Makefile的默认值。


0
投票

这与其说是对原始发帖人问题的回答,不如说是澄清:是的, 可以在 Makefile 配方中读取用户输入。您只是不能指望从

read
读取的值会传播到 Makefile 中的其他配方,而没有其他令人震惊的杂乱无章,例如
$(eval …)
,或写入临时文件或类似的东西。

这是 OP 试图在

read
目标中完成的正确语法,并带有上述警告:

read :
    @read -p "Enter : " enter; \
    echo $$enter

回想一下 make 的默认行为是在其自己的 shell 中运行配方的每一行;作为副作用,

$enter
的值在分号-反斜杠停止后失去范围。所以它的生命周期只存在于 Makefile 中的那条语句中。

额外的琐事:如果您已经定义了

SHELL = bash
,那么就没有必要分配一个变量来保存回复;默认情况下使用环境变量
REPLY
。但是,Bourne shell 并非如此,我不能代表其他 shell。

© www.soinside.com 2019 - 2024. All rights reserved.