混淆Makefile规则

混淆Makefile规则,makefile,gnu-make,Makefile,Gnu Make,在第一个示例中Makefile工作正常,而在第二个示例中完全不工作,这让我有点困惑 工作: CC=gcc CFLAGS=-Wall -Wextra -Werror FILES=$(addprefix src/, ft_putnbr ft_putchar main) OBJ=$(addsuffix .o, $(FILES)) NAME=put $(NAME): $(OBJ) $(CC) -o $(NAME) $(OBJ) %.o: %.c gcc -c $^ -o $@ $(CF

在第一个示例中Makefile工作正常,而在第二个示例中完全不工作,这让我有点困惑

工作:

CC=gcc
CFLAGS=-Wall -Wextra -Werror
FILES=$(addprefix src/, ft_putnbr ft_putchar main)
OBJ=$(addsuffix .o, $(FILES))
NAME=put

$(NAME): $(OBJ)
    $(CC) -o $(NAME) $(OBJ)
%.o: %.c
    gcc -c $^ -o $@ $(CFLAGS) -I includes/
clean:
    rm -f $(OBJ)
不工作:

CC=gcc
CFLAGS=-Wall -Wextra -Werror
FILES=$(addprefix obj/, ft_putnbr ft_putchar main)
OBJ=$(addsuffix .o, $(FILES))
NAME=put

$(NAME): $(OBJ)
    $(CC) -o $(NAME) $(OBJ)
%.o: $(subst obj,src, %.c)
    gcc -c $^ -o $@ $(CFLAGS) -I includes/
clean:
    rm -f $(OBJ)
唯一的区别是将FILES前缀设置为obj/,因为我想将obj文件与源文件分开,所以需要使用$(substitute)函数来更改其中一个规则中的目录。 第二个Makefile生成:

make: *** No rule to make target 'obj/ft_putnbr.o', needed by 'put'.  Stop.

有人看到我的错误了吗?

在makefile中,需要扩展的上下文是
$(…)
${…}

模式规则不是其中之一。因此:

%.o: %.c
    ...
make
解释为
stem.o
stem.c
通过执行
,对于
stem
的任何值,但
%.o:%.c
的形式不是
$(…)
,而是 没有扩大

因此,在上下文中

%.o: $(subst obj,src, %.c)
含义:

$(subst obj,src, %.c)
简单地说就是:将字符串
%.c
中所有出现的
obj
替换为
src
。 字符串
%.c
中没有出现
obj
。所以结果就是
%.c
, 不变。因此,您的第二个makefile相当于:

CC=gcc
CFLAGS=-Wall -Wextra -Werror
FILES=$(addprefix obj/, ft_putnbr ft_putchar main)
OBJ=$(addsuffix .o, $(FILES))
NAME=put

$(NAME): $(OBJ)
    $(CC) -o $(NAME) $(OBJ)
%.o: %.c
    gcc -c $^ -o $@ $(CFLAGS) -I includes/
clean:
    rm -f $(OBJ)
其中,例如,目标
obj/ft_putnbr.o
将满足 规则
%.o:%.c
当且仅当存在一个先决条件
obj/ft\u putnbr.c
。 但它并不存在。因此:

No rule to make target 'obj/ft_putnbr.o
而是使用:

Makefile

CC=gcc
CFLAGS=-Wall -Wextra -Werror
SRCS=ft_putnbr.c ft_putchar.c main.c
OBJS=$(addprefix obj/,$(SRCS:.c=.o))
NAME=put

$(NAME): $(OBJS)
    $(CC) -o $(NAME) $(OBJS)

obj/%.o: src/%.c | obj
    gcc -c $< -o $@ $(CFLAGS) -I includes/

obj:
    mkdir -p $@

clean:
    rm -fr obj $(NAME)
CC=gcc
CFLAGS=-Wall-Wextra-Werror
SRCS=ft_putnbr.c ft_putchar.c main.c
OBJS=$(addprefix obj/,$(SRCS:.c=.o))
NAME=put
$(名称):$(OBJS)
$(CC)-o$(名称)$(OBJS)
obj/%.o:src/%.c | obj
gcc-c$<-o$@$(CFLAGS)-I包括/
obj:
mkdir-p$@
清洁:
rm-fr obj$(名称)
或类似的。顺便提一下,这个makefile确保目录
obj
存在 在尝试将任何对象文件编译到其中之前,请将该目录设置为
$(OBJS)