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.
有人在这看到我的错误吗?
答案 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
。