๐ Make, Makefile์ด๋? / Makefile์ด ํ์ํ ์ด์
make๋ ํ์ผ์ ๊ด๋ฆฌํด์ฃผ๋ ์ ํธ๋ฆฌํฐ๋ก, ์์ ๋ ์์คํ์ผ์ recompile์ ์ฉ์ดํ๊ฒ ํด์ฃผ๋ ์ ํธ๋ฆฌํฐ์ ๋๋ค.
make
๋ช
๋ น์ด๋ Makefile(๊ธฐ์ ํ์ผ)์ ์ฝ๋ ๋ด์ฉ์ ๋ฐ๋ผ make๊ฐ ์ปดํ์ผ๋ฌ์๊ฒ SHELL ๋ช
๋ น์ด๋ฅผ ์์ฐจ์ ์ผ๋ก ์คํํ๋๋ก ๋ช
๋ นํ์ฌ ์์คํ์ผ์ ์๋์ผ๋ก ์ปดํ์ผ ํ ์ ์์ต๋๋ค.
๊ทธ๋ผ Makefile์ด ํ์ํ ์ด์ ๋ ๋ฌด์์ผ๊น์?
1. ์ค๋๊ฑธ๋ฆฌ๊ณ ๋ฐ๋ณต๋๋ ์ปดํ์ผ ์์ ์ ์๋ํํ ์ ์๋ค.
2. ์์ ๋ ์์คํ์ผ๋ง ์ปดํ์ผ ํ ์ ์๋ค. ๋ฐ๋ผ์ ์ฌ์ปดํ์ผ ์๊ฐ์ ๋งค์ฐ ๋จ์ถ์ํฌ ์ ์๋ค.
์ด๋ฌํ ์ด์ ๋๋ถ์ ์์คํ์ผ์ด ๋งค์ฐ ๋ง์ ๋๊ท๋ชจ ํ๋ก์ ํธ์ ๊ฒฝ์ฐ, Makefile์ ๊ฑฐ์ ํ์์ ์ผ๋ก ์ฌ์ฉ๋ฉ๋๋ค.
๋น๊ต๋ฅผ ์ํด, Makefile์์ด ์ปดํ์ผ๊ณผ ์คํํ์ผ์ ๋ง๋๋ ๊ณผ์ ์ ๋์ดํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
์์ค ํ์ผ์ ์คํํ์ผ๋ก ๋ง๋๋ ๊ณผ์ (๋น๋)๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ผ๋ฐ์ ์ผ๋ก gcc compiler๋ก ์ง์ ์ปดํ์ผํ๊ณ ์คํํ์ผ์ ๋ง๋๋ ๊ณผ์ ์ ์์๋ก ๋ค์ด๋ณด๊ฒ ์ต๋๋ค.
์ฐ์ , ๋ค์๊ณผ ๊ฐ์ด ๋งค์ฐ ๋ง์ ์์ค ํ์ผ์ด ์๋ ํ๋ก์ ํธ๊ฐ ์์ต๋๋ค.
gcc ์ปดํ์ผ๋ฌ๋ก -c ์ต์ ์ผ๋ก ์ปดํ์ผ๋ง ํด๋ณด๊ฒ ์ต๋๋ค.
์ปดํ์ผ ํ, ๊ฐ ์์คํ์ผ์ ๋ํ ๋ชฉ์ ํ์ผ(.o / object file)์ด ์์ฑ๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
๋ค์์ผ๋ก ์์ฑ๋ ๋ชฉ์ ํ์ผ๋ค์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ผ๊ณผ ๋งํฌ(link)ํ์ฌ ์คํํ์ผ์ ๋ง๋ค์ด๋ณด๊ฒ ์ต๋๋ค. -o ์ต์ ๋ค์ ft_a.out์ด๋ผ๋ ์ด๋ฆ์ ์คํํ์ผ์ ๋ช ์ํด์ฃผ๊ณ ๊ทธ ๋ค์ ๋งํนํ ๋ชฉ์ ํ์ผ๋ค์ ๋์ดํฉ๋๋ค.
์ด๋ ๊ฒ ft_a.out ์คํ ํ์ผ์ด ๋ง๋ค์ด์ก์ต๋๋ค.
์ฌ๊ธฐ์ ๋ง์ฝ ์ด๋ค ํ๋์ ์์คํ์ผ๋ง ๋ฐ๋์๋ค๋ฉด ์ฒ์๋ถํฐ ์ปดํ์ผ ๊ณผ์ ์ ๋ค์ ์งํํ์ฌ ์๋ก์ด ์คํ ํ์ผ์ ๋ค์ ๋ง๋ค์ด์ผ ํ๊ฒ ์ฃ ?๐คฎํ์ง๋ง Makefile์ ์ฌ์ฉํ๋ค๋ฉด ์ด๋ฌํ ๊ณผ์ ์ ๋ชจ๋ ์๋ํํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค!
๊ทธ๋ผ, ๋ณธ๊ฒฉ์ ์ผ๋ก Makefile์ ๋ง๋ค์ด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
๐ Makefile ๊ตฌ์ฑ์์
- target: ๋ง๋ค๊ณ ์ถ์ ๋ณ์๋ช
- prerequisites: target์ ๋ง๋ค๊ธฐ ์ํด ํ์ํ ์ ์ ์กฐ๊ฑด (target์ ๋ง๋ค ๋ ํ์ํ ํ์ผ)
- recipe: ์คํ๋์ด์ผํ ๋ช ๋ น์ด
Makefile ์์ฑ ๊ธฐ๋ณธ ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
target … : prerequisites …
recipe
…
…
๐ Makefile ๋ง๋ค๊ธฐ
์์คํ์ผ์ ์ปดํ์ผํ์ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(.a)๋ฅผ ๋ง๋๋ Makefile์ ์์ฑํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
1. ๋งคํฌ๋ก ๋ง๋ค๊ธฐ
๋ณดํต Makefile์์๋ ๋งคํฌ๋ก๋ฅผ ์ฌ์ฉํ์ฌ ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ ๋๋ค. ์๋ํ๋ฉด ์ปดํ์ผ๋ฌ๋ฅผ ๋ณ๊ฒฝํ๊ฑฐ๋ ๊ทธ ์ต์ ๋ค์ ๋ณ๊ฒฝํ ๋ ๋ชจ๋ ์ฝ๋๋ฅผ ์์ ํ์ง ์๊ณ ๋งคํฌ๋ก๋ง ์์ ํ์ฌ ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ปดํ์ผ๋ฌ์ ์ปดํ์ผ ํ๋๊ทธ(์ต์ ), ์์นด์ด๋ธ ๋ช ๋ น์ด(ar)๊ณผ ํ๋๊ทธ, ์ต์ข ์ ์ผ๋ก ๋ง๋ค ์์นด์ด๋ธ ํ์ผ ์ด๋ฆ, ํค๋ ํ์ผ, ์์คํ์ผ, ์ค๋ธ์ ํธ ํ์ผ ์ ๋งคํฌ๋ก๋ก ์ง์ ํด์ฃผ์์ต๋๋ค.
CC = cc
CFLAGS = -Wall -Wextra -Werror
AR = AR
ARFLAGS = crs
NAME = libftprintf.a
INCLUDES = ./ft_printf.h
SRCS = \
./ft_atoi.c \
./ft_isdigit.c \
./ft_itoa.c \
./ft_printf.c \
./ft_putchar.c \
./ft_putnbr_base.c \
./ft_putstr.c \
./ft_strdup.c \
./ft_strlen.c
OBJS = $(SRCS:.c=.o)
2. rule ์์ฑํ๊ธฐ
์์์ ์ง์ ํ ๋งคํฌ๋ก๋ฅผ ์ฌ์ฉํ ๋์๋ $(๋งคํฌ๋ก ์ด๋ฆ)
์ผ๋ก ์์ฑํ์ฌ ์ฌ์ฉํฉ๋๋ค.
2-1. make all
all : $(NAME)
$(NAME) : $(OBJS)
${AR} ${ARFLAGS} $(NAME) $(OBJS)
์์ฑํ ์ฝ๋๋ฅผ ์ดํด๋ณด๋ฉด all์ ์ํํ๊ธฐ ์ํด์๋ $(NAME)
์ฆ, libftprintf.a
๊ฐ ํ์ํฉ๋๋ค. recipe์ด ๋ฐ๋ก ์๊ธฐ ๋๋ฌธ์ make all
์ ํ๋ผ๋ ๊ฒ์ make libft.a
๋ฅผ ํ๋ผ๋ ๊ฒ๊ณผ ๊ฐ์ ๊ฒ์
๋๋ค.
๋ค์ ๋ฃฐ์ ๋ณด๋ฉด libftprintf.a๋ฅผ ๋ง๋ค๊ธฐ ์ํด์๋ $(OBJS)
๊ฐ ํ์ํฉ๋๋ค. ์์ ๋งคํฌ๋ก์์ OBJS๋ฅผ $(SRCS:.c=.o)
๋ก ์ง์ ํ๋๋ฐ SRCS์ .cํ์ผ์ ๋ชจ๋ .o๋ก ๋ง๋ค๋ผ๋ ์๋ฏธ์
๋๋ค.
terminal์ make all
๋ช
๋ น์ด๋ฅผ ์ณ๋ณด๋ฉด ์ค๋ธ์ ํธ ํ์ผ(.o)๋ค์ด ๋ง๋ค์ด์ง๊ณ ์์นด์ด๋ธ ํ์ผ(.a)๊น์ง ๋ง๋ค์ด์ง๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
2-2. make clean
clean :
rm -f $(OBJS)
clean์ ์ ์ ์กฐ๊ฑด์ด ์๊ณ recipe๋ง ์์ต๋๋ค. recipe๋ฅผ ๋ณด๋ฉด ๋ง๋ค์ด์ง ์ค๋ธ์ ํธ ํ์ผ๋ค์ ์ญ์ ํ๋ผ๋ ๋ช ๋ น์ด์ ๋๋ค. ๋ช ๋ น์ด๋ฅผ ์ณ๋ณด๋ฉด ์ค๋ธ์ ํธ ํ์ผ๋ง ์ญ์ ๋๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
2-3. make fclean
fclean : clean
rm -f $(NAME)
fclean
์๋ prerequisites๊ฐ clean์ผ๋ก ์์ฑ๋์ด์๊ณ , recipe์๋ libftprintf.a
๋ฅผ ์ญ์ ํ๋ผ๋ ์ฝ๋๊ฐ ์์ฑ๋์ด์์ต๋๋ค. ์ฆ, clean
๋ช
๋ น์ ์คํํ ํ, ์์นด์ด๋ธ ํ์ผ์ ์ญ์ ํ๋ผ๋ ์๋ฏธ์ด๋, ๋ง๋ค์ด์ง ์ค๋ธ์ ํธ ํ์ผ๊ณผ ์ค๋ธ์ ํธ ํ์ผ์ด ๋ชจ๋ ์ญ์ ๋ฉ๋๋ค.
2-4. make re
re : fclean all
re
์๋ recipe๊ฐ ์๊ณ prerequisites๋ง ์์ต๋๋ค. ์ฆ, make re
๋ฅผ ํ๋ฉด make fclean
ํ, make all
์ด ์คํ๋๊ฒ ์ฃ ! ๋ค์ ์ญ์ ํ๊ณ ๋ค์ ๋ง๋ค์ด์ง๋๋ค.
+) ์์ฃผ ์ฐ์ด๋ ๋ฌธ๋ฒ
$@
: ๋ชฉํ ์ด๋ฆ$*
: ๋ชฉํ ์ด๋ฆ์์ ํ์ฅ์๊ฐ ์๋ ์ด๋ฆ$<
: ์ฒซ ๋ฒ์งธ ์ ์ ์กฐ๊ฑด์ ํ์ผ ์ด๋ฆ$?
: ๋ชฉํ ํ์ผ ๋ณด๋ค ๋ ์ต๊ทผ์ ๊ฐฑ์ ๋ ํ์ผ ์ด๋ฆ$^
: ํ์ฌ Target์ด ์์กดํ๋ ๋์๋ค์ ์ ์ฒด ๋ชฉ๋ก$?
: ํ์ฌ Target์ด ์์กดํ๋ ๋์๋ค ์ค ๋ณ๊ฒฝ๋ ๊ฒ๋ค์ ๋ชฉ๋ก$%
: ๋์์ ์ด๋ฆ (ํด๋น ๊ท์น ๋์์ด ์์นด์ด๋ธ ์ธ ๊ฒฝ์ฐ)
(์ฐธ๊ณ : https://velog.io/@hidaehyunlee/Makefile-์์ฃผ-์ฌ์ฉํ๋-๋ฌธ๋ฒ-์ ๋ฆฌ)
3. Phony Target ์ง์ ํ๊ธฐ
.PHONY
๋ built-in target์ผ๋ก .PHONY
์ prerequisites๋ phony target์ผ๋ก ์ทจ๊ธ๋ฉ๋๋ค. phony๋ ๊ฐ์ง๋ผ๋ ์๋ฏธ๋ก, ์ค์ ํ์ผ ์ด๋ฆ๊ณผ ์ถฉ๋ํ๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ต๋๋ค. .PHONY
์ prerequisites๋ make
๋ช
๋ น์ด์ ํจ๊ป ์ฐ์์ ๋๋ ๊ทธ recipe์ด ๋ฌด์กฐ๊ฑด์ ์ผ๋ก ์คํ๋ฉ๋๋ค.
.PHONY: all clean fclean re
์์ ์์์์ .PHONY
์ prerequisites๋ก ์์ฑ๋ all, clean, fclean, re๋ ์ด๋ฏธ ๊ทธ ๋๋ ํ ๋ฆฌ์ ๊ฐ์ ์ด๋ฆ์ ํ์ผ์ด ์กด์ฌํด๋ ๊ทธ๊ฒ๊ณผ ์๊ด์์ด makefile์ recipe์ด ์ํ๋๋ค๋ ๊ฒ์
๋๋ค!
phony target์ ์ฌ์ฉํ๋ ์ด์ ๋ 2๊ฐ์ง๋ก ์ด์ผ๊ธฐํ ์ ์์ต๋๋ค.
1. ๊ฐ์ ์ด๋ฆ์ ํ์ผ๊ณผ์ ์ถฉ๋์ ํผํ๊ธฐ ์ํด์
clean:
rm *.o temp
1๋ฒ์ ์์์ ์ด์ผ๊ธฐํ ๋ด์ฉ๊ณผ ๊ฐ์ ๋ด์ฉ์
๋๋ค. ์๋ฅผ๋ค์ด clean์ด๋ผ๋ ํ์ผ์ด ์กด์ฌํ๋ค๊ณ ํ๋๋ผ๋ make clean
์ ํญ์ ๊ทธ recipe๋ฅผ ์ํํฉ๋๋ค.
2. ์ฑ๋ฅ ํฅ์์ ์ํด์
์๋ฅผ ๋ค์ด ๋ค์๊ณผ ๊ฐ์ด subdirectory(foo, bar, baz)์ ๊ฐ๊ฐ make command๋ฅผ ์คํํ๋ ค๊ณ ํ๋ค๊ณ ํด๋ณด๊ฒ ์ต๋๋ค.
/main
|_ Makefile
|_ /foo
|_ Makefile
|_ ... // other files
|_ /bar
|_ Makefile
|_ ... // other files
|_ /baz
|_ Makefile
|_ ... // other files
SUBDIRS = foo bar baz
subdirs:
for dir in $(SUBDIRS); do \
$(MAKE) -C $$dir; \
done
์์ rule์ฒ๋ผ loop๋ฅผ ์ด์ฉํด์ ํ๋์ rule์ ์์ฑํด์ ๊ฐ๊ฐ์ directory์ make ๋ช
๋ น์ ๋ด๋ฆด ์ ์์ต๋๋ค! ํ์ง๋ง ์ฌ๊ธฐ์๋ 2๊ฐ์ง ๋ฌธ์ ์ ์ด ์๊น๋๋ค. ์ฒซ๋ฒ์งธ๋ ์ด๋ค ํ๋์ subdirectory์์ ์ค๋ฅ๊ฐ ๋ฐ์ํด๋ ๋ฌด์๋๋ค๋ ๊ฒ์
๋๋ค. ๋๋ฒ์งธ๋ make์ ์ด์ ์ธ ๋ณ๋ ฌ์ ์ํ(parallel execution)์ ์ฌ์ฉํ ์ ์๋ค๋ ๊ฒ์
๋๋ค. make
๋ -j
๋๋ --j
์ต์
์ ์ ์ฉํ๋ฉด ์ฌ๋ฌ ๊ฐ์ rule์ ๋์์ ์ํํ ์ ์๋๋ฐ, ์์ ์ฝ๋์์๋ rule ์์ฒด๊ฐ ํ๋์ด๋ ๋น์ฐํ -j
์ต์
์ ์ ์ฉํ์ฌ๋ ๋ณ๋ ฌ์ ์ํ์ด ๋ถ๊ฐ๋ฅํ๊ฒ ์ฃ !
์ด๋ subdirectory๋ค์ phony target์ผ๋ก ์ ์ธํ๋ฉด ์ด๋ฐ ๋ฌธ์ ์ ๋ค์ ํด๊ฒฐํ ์ ์์ต๋๋ค.
SUBDIRS = foo bar baz
.PHONY: subdirs $(SUBDIRS)
subdirs: $(SUBDIRS)
$(SUBDIRS):
$(MAKE) -C $@
foo: baz
foo: baz
rule์ ์์ฑํจ์ผ๋ก์จ baz๊ฐ ์๋ฃ๋ ๋๊น์ง foo๊ฐ ์ํ๋ ์ ์๋๋ก ํ์์ต๋๋ค. ์ด๋ฐ ์ข
์ ๊ด๊ณ๋ฅผ ์ค์ ํด์ฃผ๋ ๊ฒ์ด parallel execution์ ์ ์ฉ์ํค๋๋ฐ ๋งค์ฐ ์ค์ํฉ๋๋ค!
์ฌ๊ธฐ๊น์ง Makefile์ ๋ํ์ฌ ์์๋ณด์์ต๋๋ค. ์์ค ํ์ผ์ด ๋งค์ฐ ๋ง์ ๊ฒฝ์ฐ๋ ํฐ ํ๋ก์ ํธ์ ๊ฒฝ์ฐ ํ์์ ์ผ๋ก ์ฐ์ด๋ ํ์ผ์ด๊ณ , ๋งค์ฐ ํจ์จ์ ์ธ ์ปดํ์ผ์ ๋์์ฃผ๋ ์ ์ดํดํ๊ณ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข๊ฒ ์ต๋๋ค.
๋๊ธ