令人困惑的Makefile规则

时间:2017-09-04 08:01:12

标签: 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 $@ $(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文件与源文件分开,所以我需要使用$(替换)函数来更改其中一个规则中的目录。 第二个Makefile产生:

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

有人在这看到我的错误吗?

1 个答案:

答案 0 :(得分:2)

在makefile中,需要扩展的上下文具有形式 $(...)${...}

模式规则不是其中之一。所以:

%.o: %.c
    ...
make解释

意味着stem.o来自stem.c...的任何值进行stem,但%.o: %.c的格式不是$(...),而是 没有扩大。

因此,在上下文中,

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

意思是:

$(subst obj,src, %.c)

只是: obj 中所有出现的 src 替换为字符串 {{ 1}}。 字符串%.c中不会出现obj。所以结果只是%.c, 不变。所以你的第二个makefile相当于:

%.c

其中,例如,目标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_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) 存在 在尝试将任何目标文件编译到其中之前,将该目录设为order-only prerequisite obj