make는 주어진 쉘 명령어들을 조건에 맞게 실행하는 프로그램이다.
이때 어떠한 조건으로 명령어를 실행할지 담은 파일을 Makefile이라고 부른다!
그러면 Shell Script를 사용하면 되지 않나?
Makefile을 사용하면 변화가 생긴 소스파일만 컴파일 하지만,
Shell Script를 사용하게 하면 전체를 다 컴파일 하게 된다.
따라서 Makefile을 사용하는게 효율적이다.
NAME = libft.a
CC = gcc
CFLAG = -Wall -Wextra -Werror
RM = rm -f
AR = ar
ARFLAGS = rcs
INC = libft.h
SRCS = ft_isalpha.c ft_isdigit.c ...
OBJS = $(SRCS:.c=.o)
all : $(NAME)
$(NAME) : $(OBJ_FILES)
$(AR) $(ARFLAGS) $@ $^
.c.o:
$(CC) -I $(INC) $(CFLAG) -c -o $@ $<
clean:
$(RM) $(OBJS)
fclean: clean
$(RM) $(NAME)
re: fclean all
.PHONY : all clean fclean re
NAME (TARGET) : 최종적으로 만들어 낼 아카이브 명
CC : 컴파일 종류
CFLAG : 컴파일 옵션
RM : 삭제 옵션
AR : ar (여러 오브젝트를 하나의 아카이브로 묶음)
ARFLAGS : ar 옵션
INC : include 될 header file
SRCS : 컴파일 할 c file
OBJS : object 파일 srcs:.c=.o) 명령어를 통해 SRCS의 .c 파일을 .o로 변환
all : 결과물
.PHONY : 만약 target과 겹치는 파일이 있을 때 해당 명령어 실행이 불가능한 것을 막기 위함.
기본적인 명령어 형식
target : dependency1 ....2 .... n
command1
command2
$(NAME) : $(OBJ_FILES)
$(AR) $(ARFLAGS) $@ $^
$(NAME) : target
$(OBJ_FILES) : dependency1
$(AR) $(ARFLAGS) $@ $^ : command
해석 : 다음과 같은 명령어로. dependency를 이용해 target을 생성함.
실제 수행되는 명령어 : ar rcs libft.a ft_isalpha.o ...
$@ : 타켓 이름에 대응된다.
$< : 의존 파일 목록에 첫 번째 파일에 대응된다.
$^ : 의존 파일 목록 전체에 대응된다.
$? : 타켓보다 최신인 의존 파일에 대응된다.
$+ : $^ 와 비슷하지만, 중복된 파일 이름까지 모두 포함된다.
확장자 규칙 (Suffix rule)
파일의 확장자를 보고, 그에 따라 적절한 연산을 수행시키는 규칙이다.
.c.o:
$(CC) -I $(INC) $(CFLAG) -c -o $@ $<
.c.o 표현은 .c와 .o 확장자를 가진 파일들을 확장자 규칙에 의거해서 처리될 수 있도록 표현된 것 이다.
즉 아래 명령어를 통해 .c를 컴파일해서 .o를 만들어 내는 루틴이 자동적으로 동작한다.
$(CC) -I $(INC) $(CFLAG) -c -o $@ $<
실제 수행되는 명령어 : gcc -I libft.h -Wall -Wextra -Werror -c -o ft_isalpha.a ... .a ft_isalpha.c ... .c