2017-09-04 232 views
2

Makefile在第一個示例中正常工作並且絕對無法在第二個示例中工作,只是有點困惑。混淆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 [email protected] $(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 [email protected] $(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. 

有誰看到我的錯誤?

回答

2

在生成文件,其受擴張的上下文是形式 $(...)${...}

的圖案規則不是那些之一。所以:

%.o: %.c 
    ... 

make解釋爲意味着stem.ostem.c...,爲stem任何價值製成,但%.o: %.c的形式$(...)的不是,這是 沒有展開。

因此,在上下文中,

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

所述的含義:

$(subst obj,src, %.c) 

很簡單:字符串src替換的obj所有出現的結果%.c。 字符串%.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 [email protected] $(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 [email protected] $(CFLAGS) -I includes/ 

obj: 
    mkdir -p [email protected] 

clean: 
    rm -fr obj $(NAME) 

或相似。順便說一句,這個makefile確保目錄obj存在 ,然後嘗試編譯任何目標文件,方法是將該目錄設置爲order-only prerequisite ,$(OBJS)