2017-11-18 292 views
1

我注意到有很多人有消息「make:沒有爲'all'完成」的問題,但是我的問題恰恰相反。 這是我的生成文件:連續兩次「make all」不返回「make:'all'沒有任何事情要做。」

################# 
## VARIABLES ## 
################# 

# Environment 
OS :=      $(shell uname) 

# Output 
NAME :=      libft.a 
DYNAMIC_NAME :=    ${NAME:a=so} 

# Compiler 
CC :=      gcc 

ifneq ($(OS), Linux) 
    FLAGS +=    -Wall -Wextra -Werror 
endif 

DYN_FLAG :=     -shared 
HEADERS :=     -I ./includes/ 
O_FLAG :=     -O2 

# Directories 
ADDITIONAL_FUNCTIONS =  $(addprefix ./additional_functions/, $(ADDITIONAL)) 
BONUS_FUNCTIONS =   $(addprefix ./bonus_functions/, $(BONUS)) 
LIBC_FUNCTIONS =   $(addprefix ./libc_functions/, $(LIBC)) 
PERSONAL_FUNCTIONS =  $(addprefix ./personal_functions/, $(PERSONAL)) 

DYN_OBJDIR =    dyn_build/ 
OBJDIR :=     build/ 

# Sources 
ADDITIONAL +=    ft_itoa.c 
ADDITIONAL +=    ft_memalloc.c ft_memdel.c 
ADDITIONAL +=    ft_putchar.c ft_putchar_fd.c 
ADDITIONAL +=    ft_putendl.c ft_putendl_fd.c 
ADDITIONAL +=    ft_putnbr.c ft_putnbr_fd.c 
ADDITIONAL +=    ft_putstr.c ft_putstr_fd.c 
ADDITIONAL +=    ft_strclr.c ft_strdel.c 
ADDITIONAL +=    ft_strnew.c ft_strjoin.c 
ADDITIONAL +=    ft_strequ.c ft_strnequ.c 
ADDITIONAL +=    ft_striter.c ft_striteri.c 
ADDITIONAL +=    ft_strmap.c ft_strmapi.c 
ADDITIONAL +=    ft_strsplit.c ft_strsub.c ft_strtrim.c 
BONUS +=     ft_lstadd.c ft_lstnew.c 
BONUS +=     ft_lstdel.c ft_lstdelone.c 
BONUS +=     ft_lstiter.c ft_lstmap.c 
LIBC +=      ft_atoi.c 
LIBC +=      ft_isalnum.c ft_isalpha.c ft_isascii.c 
LIBC +=      ft_isdigit.c ft_isprint.c 
LIBC +=      ft_memcpy.c ft_memccpy.c ft_memchr.c ft_memcmp.c 
LIBC +=      ft_bzero.c ft_memmove.c ft_memset.c 
LIBC +=      ft_strcat.c ft_strlcat.c ft_strncat.c 
LIBC +=      ft_strchr.c ft_strrchr.c 
LIBC +=      ft_strcmp.c ft_strncmp.c 
LIBC +=      ft_strcpy.c ft_strncpy.c ft_strdup.c 
LIBC +=      ft_strlen.c 
LIBC +=      ft_strstr.c ft_strnstr.c 
LIBC +=      ft_tolower.c ft_toupper.c 
PERSONAL +=     ft_intlen.c 
PERSONAL +=     ft_invert.c ft_islower.c ft_isupper.c 
PERSONAL +=     ft_lstgetnode.c ft_lstsize.c 
PERSONAL +=     ft_kill.c ft_putuchar.c ft_putuchar_fd.c 
PERSONAL +=     ft_strrev.c ft_strrevcpy.c 
PERSONAL +=     get_next_line.c 

DYN_OBJECTS =    $(patsubst %.c,$(DYN_OBJDIR)%.o,$(SRCS)) 
OBJECTS =     $(patsubst %.c,$(OBJDIR)%.o,$(SRCS)) 

SRCS +=      $(ADDITIONAL_FUNCTIONS) 
SRCS +=      $(BONUS_FUNCTIONS) 
SRCS +=      $(LIBC_FUNCTIONS) 
SRCS +=      $(PERSONAL_FUNCTIONS) 

################# 
## RULES ## 
################# 

all: $(NAME) 

$(NAME): $(OBJECTS) 
    @ar rcs [email protected] $(patsubst %.c,$(OBJDIR)%.o,$(notdir $(SRCS))) 
    ranlib [email protected] 
    @echo "Static library created." 

$(OBJECTS): | $(OBJDIR) 

$(OBJDIR): 
    @mkdir -p [email protected] 

$(OBJDIR)%.o: %.c 
    $(CC) $(FLAGS) $(O_FLAG) -c $< $(HEADERS) -o $(OBJDIR)$(notdir [email protected]) 

$(DYN_OBJECTS): | $(DYN_OBJDIR) 

$(DYN_OBJDIR): 
    @mkdir -p [email protected] 

$(DYN_OBJDIR)%.o: %.c 
    $(CC) $(FLAGS) $(O_FLAG) -c $< $(HEADERS) -fpic -o $(DYN_OBJDIR)$(notdir [email protected]) 

clean: 
    @/bin/rm -rfv $(OBJDIR) 
    @/bin/rm -rfv $(DYN_OBJDIR) 

fclean: clean 
    @/bin/rm -fv $(NAME) 
    @/bin/rm -fv $(DYNAMIC_NAME) 

re: fclean all 

so: $(DYN_OBJECTS) 
     @$(CC) $(DYN_FLAG) -o $(DYNAMIC_NAME) $(patsubst %.c,$(DYN_OBJDIR)%.o,$(notdir $(SRCS))) 
    @echo "Dynamic library created." 

.PHONY: all build clean dynbuild fclean re so 

makefile工作得很好。它將不同目錄中的每個.c文件創建一個對象目錄,編譯/如果該庫是靜態的,並且dyn_build /如果它是動態的,則將目標文件放入該目錄中並從它們編譯庫。

我的問題是,如果我連續兩次運行make,第二次不應該做任何事情,因爲對象文件和庫仍然存在並且是最新的。但是,不知怎的,連續兩次導致第二次重複操作。

這是什麼原因造成的,有沒有辦法解決這個問題?

+0

試着去'make --trace'或使用['remake'](http://bashdb.sourceforge.net/remake /)用'-x'來了解更多發生了什麼 –

+0

我看到了從現在開始的地方,謝謝! –

+0

'$(OBJDIR)$(notdir $ @)'和'$(DYN_OBJDIR)$(notdir $ @)'打破第二條規則[here](http://make.mad-scientist.net/papers/rules- of-makefiles /),對象文件的配方不會創建您在規則中指定的文件。 – user657267

回答

1

你的問題可以減少到這一點:

ADDITIONAL +=   ft_strsplit.c 
BONUS +=    ft_lstadd.c 

ADDITIONAL_FUNCTIONS = $(addprefix ./add/, $(ADDITIONAL)) 
BONUS_FUNCTIONS =  $(addprefix ./bonus/, $(BONUS)) 

SRCS +=    $(ADDITIONAL_FUNCTIONS) 
SRCS +=    $(BONUS_FUNCTIONS) 

OBJECTS =    $(patsubst %.c,./build/%.o,$(SRCS)) 

# OBJECTS contains ./build/./add/ft_strsplit.o and ./build/./bonus/ft_lstadd.o 

all: $(OBJECTS) 

$(OBJDIR)%.o: %.c 
    $(CC) ... 

所以要運行與例如最後的規則作爲目標的是build/./add/ft_strsplit.o,以及add/ft_strsplit.c作爲前提條件。問題是如何編寫配方以構建build/ft_strsplit.o

正如@ user657267指出的那樣,有一個(非PHONY)規則不會生成一個名稱是規則目標的文件是錯誤的。因此,讓我們首先要問做出我們實際需要的文件:

ADDITIONAL += ft_strsplit.c 
BONUS +=  ft_lstadd.c 

SRCS +=  $(ADDITIONAL) 
SRCS +=  $(BONUS) 

OBJECTS =  $(patsubst %.c,./build/%.o,$(SRCS)) 
# OBJECTS contains ./build/ft_strsplit.o and ./build/ft_lstadd.o 

到目前爲止好,但現在如何使找到來源?當我們要求Make製造./build/ft_strsplit.o時,它怎麼知道ft_strsplit.c是哪裏?

我們使用vpath

vpath %.c add bonus 

現在的makefile正常工作。並vpath線自動寫入這一點,我們可以只拉目錄名了分配:

# Directories 
ADDITIONAL_DIR := ./additional_functions 
BONUS_DIR :=  ./bonus_functions 
... 

ADDITIONAL_FUNCTIONS = $(addprefix $(ADDITIONAL_DIR)/, $(ADDITIONAL)) 
BONUS_FUNCTIONS =  $(addprefix $(BONUS_DIR)/, $(BONUS)) 
... 

vpath %.c $(ADDITIONAL_DIR) 
vpath %.c $(BONUS_DIR) 
... 
+0

正是我需要的。感謝您的回答,並讓我瞭解vpath。 –

相關問題