λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
  • μž₯원읡 κΈ°μˆ λΈ”λ‘œκ·Έ
🀷🏼‍♀️ Etc.../- C, C++, Python, Android

[C μ–Έμ–΄] λ¦¬λˆ…μŠ€μ—μ„œ Makefile 을 μ΄μš©ν•΄μ„œ ν”„λ‘œμ νŠΈ λΉŒλ“œν•˜κΈ°

by Wonit 2021. 7. 16.

μš°λ¦¬κ°€ ν”„λ‘ νŠΈμ—”λ“œ κ°œλ°œμ΄λ‚˜ λ°±μ—”λ“œ κ°œλ°œμ„ ν•  λ•Œ, λΉŒλ“œ 도ꡬλ₯Ό μ‚¬μš©ν•˜μ—¬ κ°œλ°œμ„ ν•˜κ³€ ν•œλ‹€.

 

이런 λΉŒλ“œ 도ꡬ 덕뢄에 μ‰½κ²Œ μ˜μ‘΄μ„±μ„ κ΄€λ¦¬ν•˜κ³  λΉŒλ“œλ₯Ό ν•  수 μžˆλŠ”λ°, C 언어도 μ΄λŸ¬ν•œ λΉŒλ“œ 도ꡬλ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€.

 

κ·Έ λΉŒλ“œ 도ꡬ가 λ°”λ‘œ make 이닀.

 

λΉŒλ“œ 도ꡬ, make

 

make λŠ” Linux와 같은 μœ λ‹‰μŠ€ 계열 μš΄μ˜μ²΄μ œμ—μ„œ μ‚¬μš©λ˜λŠ” λΉŒλ“œ 도ꡬ(Build Tool) 이닀.

 

λΉŒλ“œ λ„κ΅¬λž€ κ°„λ‹¨νžˆ μ„€λͺ…ν•˜μžλ©΄,

 

μ†ŒμŠ€ μ½”λ“œλ₯Ό 컴파일 ν…ŒμŠ€νŠΈ, 정적 뢄석을 μœ„ν•΄ μ‹€ν–‰ κ°€λŠ₯ν•œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μœΌλ‘œ μžλ™ μƒμ„±ν•΄μ£ΌλŠ” ν”„λ‘œκ·Έλž¨, μΌμ’…μ˜ μ†Œν”„νŠΈμ›¨μ–΄λ₯Ό μ˜λ―Έν•œλ‹€.

 

λŒ€ν‘œμ μΈ λΉŒλ“œ λ„κ΅¬λ‘œλŠ” Ant λ‚˜ Maven, Gradle, NPM 이 μ‘΄μž¬ν•œλ‹€.

 

 

이런 λΉŒλ“œ 도ꡬλ₯Ό μ‚¬μš©ν•œλ‹€λ©΄ μ—¬λŸ¬ νŒŒμΌλ“€λΌλ¦¬μ˜ μ˜μ‘΄μ„±κ³Ό 각 νŒŒμΌμ— ν•„μš”ν•œ λͺ…령을 μ •μ˜ν•΄μ„œ μ‰½κ²Œ 컴파일이 κ°€λŠ₯ν•΄ 진닀.

 

μš°λ¦¬λŠ” make λ₯Ό μ΄μš©ν•΄μ„œ λ¦¬λˆ…μŠ€μ—μ„œ μ‰½κ²Œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ λ§Œλ“€ 수 μžˆλ‹€.

 

make μ—μ„œλŠ” λΉŒλ“œλ₯Ό ν•˜κΈ° μœ„ν•΄μ„œ make ꡬ쑰둜 μ§œμ—¬μ§„ νŒŒμΌμ„ makeκ°€ ν•΄μ„ν•˜λ„λ‘ λ§Œλ“€λ©΄ λ˜λŠ”λ°, κ·Έ λŒ€ν‘œμ μΈ 것이 λ°”λ‘œ Makefile 이닀.

 

Makefile μ΄λž€?

 

Makefile 은 make λ₯Ό μ‹€ν–‰ν•΄μ„œ λΉŒλ“œν•˜κΈ° 전에 컴파일 κ·œμΉ™ 및 링크 κ·œμΉ™μ„ λ§Œλ“œλŠ” λͺ…μ„Έ 파일 이닀.

 

npm 의 application.json μ΄λ‚˜ gradle 의 build.gradle κ³Ό 같이 make 도 μ—­μ‹œ κ³ μœ ν•œ λΉŒλ“œ 문법 이 μ‘΄μž¬ν•œλ‹€.

 

make λŠ” μ΄λŸ¬ν•œ μ‰˜ λͺ…령을 쑰건에 따라 기술된 Makefile 을 λΆ„μ„ν•˜κ³  μ‹€ν–‰ν•˜λŠ” 역할을 μˆ˜ν–‰ν•œλ‹€.

 

Makefile 의 문법

 

Makefile 은 λ‹€μ–‘ν•œ λΉŒλ“œλ₯Ό μœ„ν•΄ μ—¬λŸ¬ 문법을 μ œκ³΅ν•˜λŠ”λ°, κ°€μž₯ λŒ€ν‘œμ μΈ λ¬Έλ²•μœΌλ‘œλŠ” λ‹€μŒκ³Ό 같은 3가지가 μžˆλ‹€.

 

TARGET []: PREREQUISITES []
  RECIPE
  []

 

  • TARGET
    • μ‹€ν–‰ κ°€λŠ₯ν•œ νƒ€κ²Ÿ 파일, object 파일
  • PREREQUISITES
    • TARGET 을 λ§Œλ“€ λ•Œ ν•„μš”ν•œ 의쑴 관계λ₯Ό λͺ…μ‹œν•œλ‹€
  • RECIPE
    • TARGET 을 λ§Œλ“€κΈ° μœ„ν•œ μ‹€ν–‰ 파일 및 λͺ…λ Ήμ–΄λ₯Ό λͺ…μ‹œν•œλ‹€.
    • νƒ­μœΌλ‘œ κ΅¬λΆ„ν•˜κ³  슀페이슀λ₯Ό λ„£μœΌλ©΄ λ™μž‘ν•˜μ§€ μ•ŠλŠ”λ‹€.
    • 주둜 ccλ‚˜ λ¦¬λˆ…μŠ€ λͺ…λ Ήμ–΄λ₯Ό μ‚¬μš©ν•œλ‹€

 

make 둜 Makefile 에 λͺ…μ‹œλœ c μ†ŒμŠ€ λΉŒλ“œν•˜κΈ°

 

ν•΄λ‹Ή μ‹€μŠ΅μ„ λ”°λΌν•˜κΈ° μœ„ν•΄μ„œλŠ” 컴파일(Compile) κ³Ό 링킹(Linking) 에 λŒ€ν•œ 이해가 μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€. ν•΄λ‹Ή λΈ”λ‘œκ·Έμ˜ gcc 둜 c μ–Έμ–΄λ‘œ μž‘μ„±λœ μ†ŒμŠ€ μ½”λ“œ μ»΄νŒŒμΌν•˜κΈ° λ₯Ό μ°Έκ³ ν•˜μ„Έμš”!

 

[λ¦¬λˆ…μŠ€] gcc 둜 c μ–Έμ–΄λ‘œ μž‘μ„±λœ μ†ŒμŠ€ μ½”λ“œ μ»΄νŒŒμΌν•˜κΈ° (헀더 파일둜 λ‚˜λˆ μ„œ μ»΄νŒŒμΌν•˜κΈ°)

μš°λ¦¬κ°€ 일반적으둜 c μ–Έμ–΄λ₯Ό μ»΄νŒŒμΌν•˜κΈ° μœ„ν•΄μ„œλŠ” Visual Studioλ‚˜ CLion 을 μ΄μš©ν•΄μ„œ Run ν˜Ήμ€ Debugging 을 ν•˜μ˜€μ—ˆλ‹€. ν•˜μ§€λ§Œ λ¦¬λˆ…μŠ€ ν™˜κ²½μ—μ„œλŠ” Visual Studio λ‚˜ CLion 을 μ„€μΉ˜ν•˜κΈ°λž€ 맀우 κΉŒλ‹€λ‘­κ³  QT-Creat..

wonit.tistory.com

 

λ‹€μŒκ³Ό 같은 파일이 μ‘΄μž¬ν•œλ‹€κ³  κ°€μ •ν•΄λ³΄μž.

 

$ tree
.
└── src
    β”œβ”€β”€ main.c
    β”œβ”€β”€ hello.h
    β”œβ”€β”€ hello.c
    β”œβ”€β”€ bye.h
    β”œβ”€β”€ bye.c
    └── Makefile

 

main ν•¨μˆ˜μ—μ„œλŠ” hello.c 와 bye.c μ—μ„œ μ •μ˜ν•œ 인사말 좜λ ₯ν•˜λŠ” ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜κ³ , 각각의 νŒŒμΌμ—λŠ” λ‹€μŒκ³Ό 같이 μ†ŒμŠ€κ°€ μ •μ˜λ˜μ–΄ μžˆλ‹€.

 

κ΅¬ν˜„ν•˜κΈ°

 

main ν•¨μˆ˜ 생성 및 κ΅¬ν˜„ν•˜κΈ°

#include <stdio.h>
#include "hello.h"

int main() {

  say_hello();
  say_bye();

  return 0;
}

 

header 파일 생성 및 κ΅¬ν˜„ν•˜κΈ°

// hello.h
void say_hello():

// hello.c
#include <stdio.h>
#include "hello.h"

void say_hello() {
  printf("(hello.h) => μ•ˆλ…•ν•˜μ„Έμš”! \n");
}

// bye.c
#include <stdio.h>
#include "bye.h"

void say_bye() {
  printf("(bye.h) => μ•ˆλ…•νžˆ κ°€μ„Έμš”! \n");
}

 

Makefile μ •μ˜ν•˜κΈ°

 

이제 build λ₯Ό μœ„ν•œ Makefile 을 μ •μ˜ν•΄λ³΄λ„λ‘ ν•˜μž.

 

κ·Έ 전에!

 

gcc λ₯Ό μ΄μš©ν•΄μ„œ λΉŒλ“œλ₯Ό ν•˜λŠ” 과정을 μž μ‹œ 보자.

 

각각의 c νŒŒμΌμ„ ν†΅ν•΄μ„œ object νŒŒμΌμ„ λ§Œλ“€κ³ 

 

$ gcc -c main.c # main.o 파일 생성
$ gcc -c hello.c # hello.o 파일 생성
$ gcc -c bye.c # bye.o 파일 생성

$ gcc main.o hello.o bye.o -o Greeting # 각각의 Object 파일 링킹을 톡해 Greeting μ΄λΌλŠ” exe 파일 생성

 

Makefile 을 μž‘μ„±ν•˜λŠ” 과정은 μœ„μ˜ κ³Όμ •κ³Ό μ •ν™•νžˆ λ™μΌν•˜λ‹€.

 

Makefile 이 ν•˜λŠ” 일은 μœ„μ™€ 같이 ν„°λ―Έλ„μ—μ„œ λΉŒλ“œ μ˜΅μ…˜κ³Ό 링킹을 ν•˜λ‚˜μ˜ 파일 μ—μ„œ ν•  수 μžˆλ„λ‘ ν•˜λŠ” 것이닀.

 

docker-compose 와 λΉ„μŠ·ν•œ λŠλ‚Œμ΄λ‹€

 

이제 μœ„μ˜ μˆ˜λ™ μ»΄νŒŒμΌμ„ ν† λŒ€λ‘œ Makefile 을 λ§Œλ“€μ–΄λ³΄μž.

 

hello.o : hello.h hello.c
  gcc -c hello.c

bye.o : bye.h bye.c
  gcc -c bye.c

main.o : main.c hello.h bye.h
  gcc -c main.c

Greeting : hello.o bye.o main.o
  gcc hello.h bye.h main.o -o Greeting

 

그리고 make λͺ…λ Ήμ–΄λ₯Ό ν†΅ν•΄μ„œ λΉŒλ“œλ₯Ό μˆ˜ν–‰ν•΄λ³΄μž.

 

$ make Greeting

gcc -c hello.c
gcc -c bye.c
gcc -c main.c
gcc hello.o bye.o main.o -o Greeting

 

μ΄λ ‡κ²Œ μžλ™μœΌλ‘œ λΉŒλ“œλ₯Ό μˆ˜ν–‰ν•˜κ²Œ λœλ‹€.

 

그리고 ls λͺ…령을 ν†΅ν•΄μ„œ 잘 컴파일이 μ™„λ£Œλ˜μ—ˆλŠ”μ§€ ν™•μΈν•˜κΈ° μœ„ν•΄ ls λͺ…령을 μˆ˜ν–‰ν•΄λ³΄μž

 

$ ls

main.c   main.o   hello.h   hello.c   hello.o   bye.h   bye.c   bye.o   Greeting

 

그럼 μš°λ¦¬κ°€ μƒμ„±ν•˜κΈ°λ‘œ ν•œ Greeting 파일이 잘 λ§Œλ“€μ–΄μ§„ 것을 λ³Ό 수 μžˆλ‹€.

 

μ‹€ν–‰μ‹œμΌœλ³΄μž!

$ ./Greeting

(hello.h) => μ•ˆλ…•ν•˜μ„Έμš”!
(bye.h) => μ•ˆλ…•νžˆ κ°€μ„Έμš”!

λŒ“κΈ€