Makefile๋กœ C ํ”„๋กœ์ ํŠธ ๋˜‘๋˜‘ํ•˜๊ฒŒ ์ปดํŒŒ์ผํ•˜๊ณ  ๋นŒ๋“œํ•˜๊ธฐ! โœŒ๏ธ

7 minute read

๋“ค์–ด๊ฐ€๋ฉฐ

๋Œ€ํ•™์—์„œ ์šด์˜์ฒด์ œ ์ˆ˜์—…์„ ๋“ค์œผ๋ฉด์„œ Pintos ๊ณผ์ œ๋ฅผ ์ง„ํ–‰ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ๊ณผ์ •์—์„œ ์ƒˆ๋กญ๊ฒŒ ์ ‘ํ•˜๊ณ  ์ดํ•ดํ•œ ๊ฒƒ๋“ค์„ ์ •๋ฆฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

Pintos ์ฝ”๋“œ ์ผ๋ถ€

์šด์˜์ฒด์ œ ์ˆ˜์—…์˜ Pintos ๊ณผ์ œ๋Š” C์–ธ์–ด๋‚˜ ์–ด์…ˆ๋ธ”๋ฆฌ๋กœ ์ฝ”๋“œ๋ฅผ ์—„์ฒญ ๋ด์•ผ ํ•ฉ๋‹ˆ๋‹ค ๐Ÿ˜ตโ€๐Ÿ’ซ Pintos ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด, Makefile๋ผ๋Š” ํŒŒ์ผ์ด ์žˆ๋Š”๋ฐ์š”. ์‚ฐ์—…๊ธฐ๋Šฅ์š”์›์œผ๋กœ ๊ทผ๋ฌดํ•˜๋ฉด์„œ ํšŒ์‚ฌ์—์„œ Python๋งŒ ์ฃผ๊ตฌ์žฅ์ฐฝ ํ–ˆ๋˜ ์ €๋กœ์„œ๋Š” ์ƒ์†Œํ•œ ํŒŒ์ผ ๋ญ‰์น˜ ์˜€์Šต๋‹ˆ๋‹ค.

How to learn?

์œ ํŠœ๋ธŒ์— Makefile์„ 60์ดˆ๋งŒ์— ์„ค๋ช…ํ•˜๋Š” ์˜์ƒ์ด ์žˆ์–ด์„œ ์ด๊ฑธ ๋จผ์ € ๋ดค์Šต๋‹ˆ๋‹ค ใ…Žใ…Ž

๊ทธ๋ฆฌ๊ณ  losskatsu๋‹˜์˜ ๋ธ”๋กœ๊ทธ ๊ธ€๋„ ์ดํ•ด์— ๋„์›€์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

Hello, gcc!

์ผ๋‹จ ๋ƒ…๋‹ค hello world ์ฝ”๋“œ๊ฐ€ ์ ํžŒ main.c ํŒŒ์ผ ํ•˜๋‚˜๋ฅผ ์ ์Šต๋‹ˆ๋‹ค.

#include <stdio.h>

int main() {
  printf("Hello, World!");
  return 0;
}

๊ทธ๋ฆฌ๊ณ  ์•„๋ž˜์˜ gcc ์ปค๋งจ๋“œ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด,

$ gcc main.c
$ ls
main.c
a.out
$ ./a.out
Hello, World!

์ด๋Ÿฐ ์‹์œผ๋กœ a.out๋ผ๋Š” ์‹คํ–‰ ํŒŒ์ผ์ด ๋งŒ๋“ค์–ด์ง‘๋‹ˆ๋‹ค.


-c ์˜ต์…˜์„ ์ฃผ๋ฉด, ์ปดํŒŒ์ผ๋งŒ ํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

$ gcc -c main.c
$ ls -al
main.c
main.o

๊ทธ๋Ÿฌ๋ฉด main.o๋ผ๋Š” object ํŒŒ์ผ์ด ๋งŒ๋“ค์–ด์ง‘๋‹ˆ๋‹ค. gcc main.c -c์™€ ๊ฐ™์ด ์ปดํŒŒ์ผ ์˜ต์…˜์„ ๋‚˜์ค‘์— ์ ์–ด๋„ ์ƒ๊ด€ ์—†์Šต๋‹ˆ๋‹ค.


์œ„์—์„œ ๋งŒ๋“  object ํŒŒ์ผ์„ executable๋กœ ๋งŒ๋“ค๊ณ  ์‹ถ๋‹ค๋ฉด,

$ gcc -o main main.o
$ ls -al
main.c
main.o
main
$ ./main
Hello, World!

gcc main.o๋งŒ ์ž…๋ ฅํ•ด๋„ executable์ธ a.out์ด ์ƒ๊ธฐ์ง€๋งŒ, ๋„ˆ๋ฌด ๋Œ€์ถฉ ์ง€์€ ์ด๋ฆ„์ด๋‹ˆ;; -o ์˜ต์…˜์œผ๋กœ ์ถœ๋ ฅ ์ด๋ฆ„์„ ์ง€์ • ํ•ด์ค๋‹ˆ๋‹ค. gcc main.o -o main์™€ ๊ฐ™์ด ์ถœ๋ ฅ ์˜ต์…˜์„ ๋‚˜์ค‘์— ์ ์–ด๋„ ์ƒ๊ด€ ์—†์Šต๋‹ˆ๋‹ค.

Hello, Makefile!

Makefile์€ ์•ž์—์„œ ํ–ˆ๋˜ gcc ๋ช…๋ น์–ด๋ฅผ ๋‹ด์•„๋‘๋Š” ํŒŒ์ผ์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๋ฉ์ฒญ(?)ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ปดํŒŒ์ผํ•  ํŒŒ์ผ์ด ๋งŽ๊ฑฐ๋‚˜ ๋งํ‚น(linking)ํ•  ํŒŒ์ผ์ด ๋งŽ๋‹ค๋ฉด ์ผ์ผ์ด ์ ์–ด๋‘๊ธฐ ํž˜๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. shell script ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด ๋‘˜ ์ˆ˜๋„ ์žˆ๊ฒ ์ง€๋งŒ, C์–ธ์–ด์—์„œ๋Š” Makefile๋ผ๋Š” ์ข‹์€ ๋„๊ตฌ๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

๋นˆ Makefile์„ ํ•˜๋‚˜ ๋งŒ๋“ค๊ณ , ์•„๋ž˜์™€ ๊ฐ™์ด ์ ์–ด๋ด…๋‹ˆ๋‹ค.

hello-compile: main.c
	gcc -c main.c

๊ทธ๋ฆฌ๊ณ  make hello-compile๋ผ๊ณ  ํ•˜๋ฉด, ์ ์–ด๋‘” gcc ๋ช…๋ น์–ด๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ์ด์–ด์„œ executable ํŒŒ์ผ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ make ๋ช…๋ น์–ด๋„ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค. (์ด๋•Œ, ๋ช…๋ น์–ด ์ง‘ํ•ฉ์„ ํ‘œ์‹œํ•˜๊ธฐ ์œ„ํ•ด tab์„ ์จ์•ผ ํ•ฉ๋‹ˆ๋‹คโ€ฆ;; ๊ณต๋ฐฑ์œผ๋กœ ๋„ฃ์œผ๋ฉด *** missing separator.๋ฅผ ๋งŒ๋‚˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.)

hello-compile: main.c
	gcc -c main.c

hello-executable: hello-compile
	gcc -o hello.out main.o

๊ทธ๋ฆฌ๊ณ  make hello-executable๋ผ๊ณ  ํ•˜๋ฉด, hello.out๋ผ๋Š” executable ํŒŒ์ผ์ด ๋งŒ๋“ค์–ด์ง‘๋‹ˆ๋‹ค.


Makefile์˜ ๋ช…๋ น์— gcc๋งŒ ์“ธ ์ˆ˜ ์žˆ๋Š”๊ฑด ์•„๋‹™๋‹ˆ๋‹ค. ์•„๋ž˜์™€ ๊ฐ™์ด echo๋“ฑ ๊ฐ์ข… CLI ๋ช…๋ น์–ด ์ง‘ํ•ฉ์„ ๋ฌถ์–ด make ๋ช…๋ น์–ด๋กœ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (์–ด๋–ป๊ฒŒ ๋ณด๋ฉด, shell script๋ž‘ ์ •๋ง ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค.)

hello:
	echo "Hello, World!"

๊ทธ๋ž˜์„œ executable์„ ๋งŒ๋“ค๊ณ , ๋ฐ”๋กœ ์‹คํ–‰ํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

hello-executable: hello-compile
	gcc -o hello.out main.o
	./hello-executable

Makefile: Deep Dive

Makefile์ด ๋ญ”์ง€๋Š” ๋Œ€์ถฉ ๊ฐ์„ ์ตํžŒ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค ๐Ÿ˜ผ ์ด์ œ Makefile์˜ ์„ธ๋ถ€์ ์ธ ์‚ฌํ•ญ์„ ์ข€ ์‚ดํŽด๋ณด์ฃ !

Syntax

Makefile์—์„œ ์ •์˜ํ•˜๋Š” ๋ช…๋ น์–ด๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ๊ตฌ์กฐ๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.

targets: prerequisites
	command
	command
	command

๋ช…๋ น์–ด ์…‹์— targets๋ผ๋Š” ์ด๋ฆ„์„ ๋ถ€์—ฌํ•˜๊ณ , ๊ทธ๊ฒƒ์„ ์œ„ํ•œ pre-requisites๋ฅผ ๋ช…์‹œํ•ฉ๋‹ˆ๋‹ค. prerequisites์—๋Š” (1) ํŒŒ์ผ ์ด๋ฆ„ (2) ๋‹ค๋ฅธ target๋“ค์ด ๋“ค์–ด๊ฐ€๊ฑฐ๋‚˜ (3) ์•„๋ฌด๊ฒƒ๋„ ์•ˆ ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋งŒ์•ฝ, ํŒŒ์ผ ์ด๋ฆ„์„ prerequisites๋กœ ๋„ฃ์—ˆ๋Š”๋ฐ, ํ•ด๋‹น ํŒŒ์ผ์ด ์—†๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์˜ค๋ฅ˜๋ฅผ ๋งŒ๋‚ฉ๋‹ˆ๋‹ค.

make: *** No rule to make target `main.c', needed by `hello-compile'.  Stop.

๋ณดํ†ต์€ ์•„๋ž˜์™€ ๊ฐ™์ด gcc์— ์‚ฌ์šฉํ•˜๋Š” ํŒŒ์ผ๋“ค์„ ๋„ฃ์–ด์ค๋‹ˆ๋‹ค.

hello-compile: main.c
	gcc -c main.c

๊ทธ๋ฆฌ๊ณ  ์•„๋ฌด ํƒ€๊นƒ๋„ ๋ช…์‹œํ•˜์ง€ ์•Š๊ณ  make๋ฅผ ์‹คํ–‰ํ•œ๋‹ค๋ฉด, Makefile์—์„œ ๊ฐ€์žฅ ์ฒซ ๋ฒˆ์žฌ ํƒ€๊นƒ ๋ช…๋ น์–ด๋ฅผ ์ž๋™์œผ๋กœ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

Make clean

Pintos์—์„œ๋Š” make clean์„ ์‚ฌ์šฉํ•ด ๋นŒ๋“œํ•œ ํŒŒ์ผ๋“ค์„ ์ œ๊ฑฐ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์‹ค ์š” clean์ด๋ž€ ๊ฒƒ๋„ ํƒ€๊นƒ ๋ช…๋ น์–ด์ž…๋‹ˆ๋‹ค. (์ €๋Š” ์ฒ˜์Œ์— ์ด๊ฒŒ reserved keyword ์ธ ์ค„ ์•˜์Šต๋‹ˆ๋‹ค ใ…‹ใ…‹)

some_file:
	touch some_file

clean:
	rm -f some_file

clean์€ ๋ฌด์—‡์ธ์ž๋ฅผ ์ง€์šฐ๊ฑฐ๋‚˜ ์ •๋ฆฌํ•˜๋Š” ์šฉ๋„๋กœ ์ž์ฃผ ์‚ฌ์šฉ๋˜๋ฉฐ, ์ฒซ๋ฒˆ์งธ ํƒ€๊นƒ ๋ช…๋ น์–ด๋กœ ๋‘์ง€ ์•Š๋„๋ก ์œ ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Variables

Shell Script์ฒ˜๋Ÿผ Makefile์—๋„ ๋ณ€์ˆ˜๋ฅผ ๋‘˜ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

a := one two   # a is set to the string "one two"
b := 'one two' # Not recommended. b is set to the string "'one two'"
all:
	echo ${a}
	echo ${b}
---
echo one two
one two
echo 'one two'
one two

๋ณ€์ˆ˜์— ๊ฐ’ ํ• ๋‹น์€ := ์—„๋‹ˆ ์—ฐ์‚ฐ์ž๋กœ ์ง„ํ–‰ํ•˜๊ณ ,

์—ฌ๊ธฐ์„œ ์ž ๊น! ๋งŒ์•ฝ ์ด ๊ธ€์„ ์ฝ๋Š” ์—ฌ๋Ÿฌ๋ถ„์ด Makefile์˜ ์ •๋ง ๊ธฐ๋ณธ์ ์ธ ๊ฒƒ๋งŒ ์•Œ๊ณ  ์‹ถ๋‹ค๋ฉด, ์—ฌ๊ธฐ์„œ ๋ฉˆ์ถฐ๋„ ๋ฉ๋‹ˆ๋‹ค ใ…Žใ…Ž

Multiple Targets

์˜์™ธ๋กœ ํƒ€๊นƒ ์ด๋ฆ„๋„ ์—ฌ๋Ÿฌ ๊ฐœ๋ฅผ ๊ฐ€์ง€๋„๋ก ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. $@๋Š” make์—์„œ ์‹คํ–‰ํ•˜๋Š” ํƒ€๊นƒ ์ด๋ฆ„์„ ์ฐธ์กฐํ•˜๋Š” ์˜ˆ์•ฝ ๋ณ€์ˆ˜์ด๋‹ค.

all: f1.o f2.o

f1.o f2.o:
	echo $@
# Equivalent to:
# f1.o:
#	 echo f1.o
# f2.o:
#	 echo f2.o

Double-Colon Rules

์ •๋ง ๋“œ๋ฌผ๊ฒŒ ์‚ฌ์šฉํ•˜๊ธด ํ•˜์ง€๋งŒ, ๊ฐ™์€ ์ด๋ฆ„์„ ๊ฐ€์ง„ ํƒ€๊นƒ์„ ์ •์˜ํ•˜๊ณ  ์‹ถ์„ ๋–„ ์‚ฌ์šฉํ•œ๋‹ค.

all: blah

blah::
	echo "hello"

blah::
	echo "hello again"

์ด ๊ฒฝ์šฐ, ์œ„์—์„œ๋ถ€ํ„ฐ blah๋ผ๋Š” ์ด๋ฆ„์„ ๊ฐ€์ง„ ๋ชจ๋“  ํƒ€๊นƒ์ด ์ˆœ์ฐจ์ ์œผ๋กœ ์‹คํ–‰๋œ๋‹ค.

Disable Command Echo

Makefile์„ ์‹คํ–‰ํ•ด๋ณด๋ฉด, ํƒ€๊นƒ์—์„œ ์–ด๋–ค ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๋Š”์ง€ ์ •์˜๋œ ๋ช…๋ น์–ด๋ฅผ ๊ผญ ์ถœ๋ ฅํ•˜๊ณ  ์‹คํ–‰ํ•œ๋‹ค. ๋งŒ์•ฝ ์ด๊ฑธ ๋ณด์—ฌ์ฃผ๊ณ  ์‹ถ์ง€ ์•Š๋‹ค๋ฉด, sliencing ์˜ต์…˜์„ ๋„ฃ์–ด make -s๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๋œ๋‹ค.

all:
	@echo "This make line will not be printed"
	echo "But this will"

๋˜๋Š”, ๋ช…๋ น์–ด ๋ผ์ธ์˜ ๋งจ ์•ž์— @๋ฅผ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค.

๋งบ์Œ๋ง

Pintos ์ฝ”๋“œ ์ผ๋ถ€ - 2

Pintos ์ฝ”๋“œ ๊ตฌ์กฐ๋ฅผ ๋ณด๋ฉด์„œ, ๊ณผ์—ฐ Makefile์ด๋ž€๊ฒŒ ๋ฌด์—‡์ผ๊นŒ๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์–ด ์ข€ ์‚ดํŽด๋ณด๊ฒŒ ๋˜์—ˆ๋‹ค. ์–ด์ง€๋Ÿฝ๊ฒŒ๋„ Makefile์ด 4๊ฐœ๋‚˜ ์žˆ๊ณ , Make.config๋ผ๋Š” ํŒŒ์ผ๋„ ์žˆ๋‹ค.

๋ฐ์ดํ„ฐ ์—”์ง€๋‹ˆ์–ด๋กœ์„œ ์•ž์œผ๋กœ C/C++์„ ์“ธ์ผ์ด ๋งŽ์„๊นŒ??๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค๊ธฐ๋„ ํ•œ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ƒ๊ฐํ•ด๋ณด๋‹ˆ Istio์—์„œ ์“ฐ๋Š” โ€œEnvoyโ€๊ฐ€ C๋กœ ์งœ์—ฌ์ง„ Proxy๋ผ๊ณ  ๋“ค์—ˆ๋˜ ๊ฒƒ ๊ฐ™๋‹ค ๐Ÿ˜ฎ ๋‚ด๊ฐ€ ์ •๋ง ์ฝ”์–ด ๋ ˆ๋ฒจ์˜ ๋กœ์ง์„ ๊ฑด๋“œ๋ฆฌ๋Š” ๋‚ ์ด ์˜จ๋‹ค๋ฉด, ์ด๋ ‡๊ฒŒ ๊ณต๋ถ€ํ•ด๋‘” ๊ฒƒ๋„ ์–ธ์  ๊ฐ€ ์“ธ๋ชจ๊ฐ€ ์žˆ๊ฒ ์ง€!!

์ด๊ฒƒ๋ง๊ณ ๋„ Makefile์— ๋Œ€ํ•œ ๋” ๋งŽ์€ ๋ฌธ๋ฒ•์ด ์žˆ์ง€๋งŒโ€ฆ ๋‚˜๋จธ์ง€๋Š” ํ•„์š”ํ•ด์ง€๋ฉด ์ ์–ด๋ณด๊ฒ ๋‹ค ใ…‹ใ…‹ ์ด ํฌ์ŠคํŠธ๋Š” Makefile์— ๋Œ€ํ•œ 101์ด๋‹ˆ๊นŒ!!

References