CS(computer science)

Makefile 뜯어보기

ebang 2022. 11. 29. 23:00
반응형

 

Makefile

기본적인 문법:

target: ingredient
	command1
    command2
    
    
target1 : ingredient
	command1
    command2

1. 기본 틀

  타겟 : 타겟을 만드는 데 필요한 재료

        실행할 쉘 명령어

 

2. 변수 선언

CC = cc , CFLAGS = -Wall -Wextr -Werror  선언 한 뒤, 

$(CC) 이런 식으로 사용한다.  

예시:               

CC = cc
CFLAGS = -Wall -Wextra -Werror

%o : %c
	$(CC) $(CFLAGS) ^@ ^<

이런 짤막한 예시에서는 이런 것들이 중요도가 낮아보인다. 

하지만 makefile이 길어진다면, 그리고 파일 명이 한번 수정되었을 때 바뀌어야 하는 코드의 개수를 고려하면, 

처음에 변수 선언에서 수정할 수 있다는 것이 얼마나 큰 장점이 될 수 있을 지 생각해볼만 하다

 

좀 더 신빙성을 위해 github에서 리눅스의 makefile을 직접 캡쳐해보았다. (ㅋㅋ)

가장 첫줄에서 역시나 변수선언을 하는 것이 보인다. 

 

 

 

3. 와일드 문자

   ^@ : 타겟 (%o)가 해당.

   $< :  재료 중 첫번 째 . (%.c 중 첫번째)

   $^ :  재료 전체 (% .c 전체)

 

4. OBJS = $(SRCS_C:.c=.o)

   .c를 .o로 바꾸어서 대입. 

ex)SRCS_C = main.c  utils.c

OBJS = $(SRC_CS:.c=.o) 하고 나면

OBJS = main.o utils.o 가 된 것과 같다. 

 

 

5. $(addprefix $(SRCS_DIR), $(SRCS_C))

  디렉토리 명 뒤에 파일을 붙이고 싶을 때 사용.

 

 ex) SRS_DIR = ./includes/ 
       SRCS_C = main.c  utils.c

    $(addprefix $(SRCS_DIR), $(SRCS_C)) 하고 나면 ./includes/main.c.  ./includes/utils.c

 

6. j 옵션: job (프로세스 개수 )

make -j 를 사용시, 여러 프로세스로 나누어 make를 실행할 수 있다.

make가 오래걸리는 경우, 이 옵션을 사용하면 시간을 줄일 수 있다.

 

7.Makefile의 의존성

기본적으로 Makefile은 위에서부터 아래로 읽으며 수행하지만,

반드시 순서대로 짤 필요는 없다. 

Makefile의 가장 특징이 바로 의존성인데, 타겟을 만들기 위해 필요한 재료가 아직 없다면

아래로 내려가서 그 재료를 만드는 명령어를 또 실행한다.

따라서 기본적으로 어떤 명령어를 먼저 실행시키도록 짤 것이냐의 문제에서 벗어날 수 있다. 

 

      

 

CC = cc
CFLAGS = -Wall -Wextra -Werror
NAME = #만드려는 프로그램명
SRCS = main.c utils.c
OBJS = (SRCS:.c=.o) #main.o utils.o
%o : %c
	$(CC) $(CFLAGS) ^@ ^< 
#위의 사항은 기본이라서 저렇게 필요하다면 생략가능하다. 

all : $(NAME)
#만드려는 궁극적인 타겟

re : 
	$(MAKE) fclean
	$(MAKE) all

clean : 
	rm -rf $(OBJS)

fclean : 
		$(MAKE) clean
		rm -rf $(NAME)
	
.PHONY: re clean fclean
#업데이트가 안되어도 매번 실행할 파일들 명령. 
#가독성을 위해

#.PHONY re
#re : ..

#.PHONY clean
# clean: ..
#이런 식으로 하나씩 쓰는 경우도 있다. (리눅스 makefile)

 

8. 주의점

re : fclean all

이렇게 타겟 옆에 재료가 병행으로 있으면 순서가 정해져있지 않다. 

 

re 에서 fclean all을 하면, j 옵션을 주었을 때 동시에 실행되는 문제가 발생한다:

두 명령의 순서가 정해져 있지 않아서

all 을 실행하고 fclean을 하거나 fclean을 하고 all이 실행 되는 등의 문제. 

 

따라서 개행을 줘서 위에서 아래로 순차적으로 실행할 수 있도록 한 줄 띄어서 하도록 하자!

요렇게:

re : fclean
	all

 

9. 팁

$(INC) = 포함시켜야 할 헤더파일 들어간 폴더. 

NAME : $(OBJ_FILES) $(CC) $(CFLAGS) -o $@ $^ $(INC)

위처럼 적고 여기서 $(INC)를 적지 않아도 되는 이유는, 어차피 .c 파일 내에 #include "./include.h" 가 있어야 하고

그러면 $(INC)가 없어도 잘 되기 때문.

 

즉 $(INC) 을 애초에 안적어도 된다. 

 

 

 

 

 

------

for more: 

*리눅스 메이크 파일 뜯어보기:

https://github.com/torvalds/linux/blob/master/Makefile

반응형