이번에는 컴파일 시스템에 대해서 알아보자.
C 소스 코드(텍스트)를 실행 가능한 기계어(바이너리 코드)로 변환하는 과정이다
.
.
.
1️⃣ 전처리 단계 (Preprocessing, cpp)
📌 하는 일:
📂 파일 변환:
// hello.c
#include <stdio.h>
int main() {
printf("Hello, world!\n");
return 0;
}
// stdio.h의 내용이 삽입됨 (생략)
int main() {
printf("Hello, world!\n");
return 0;
}
.
.
.
2️⃣ 컴파일 단계 (Compiling, cc1)
📌 하는 일:
📂 파일 변환:
// hello.s (어셈블리 코드 예시)
main:
subq $8, %rsp
movl $.Lhello, %edi
call printf
addq $8, %rsp
ret
.
.
.
3️⃣ 어셈블 단계 (Assembling, as)
📌 하는 일:
📂 파일 변환:
💡 설명 :
4️⃣ 링크 단계 (Linking, ld)
📌 하는 일:
📂 파일 변환 :
✅ 최종 요약
1️⃣ hello.c → (전처리 cpp) → hello.i
2️⃣ hello.i → (컴파일 cc1) → hello.s
3️⃣ hello.s → (어셈블 as) → hello.o
4️⃣ hello.o + printf.o → (링크 ld) → hello (실행 파일)
이 과정을 통해 우리는 작성한 C 코드를 실행할 수 있다 !
.
.
.
.
.
아무리 봐도 어려운 친구들은 비유법으로 알아보자~~
요리로 비유를 하자면
.
.
1️⃣ 소스 코드 (hello.c) = 요리 레시피 🗞️
→ 우리가 만든 C 코드(hello.c)는 요리로 치면 레시피와 같다.
하지만 이 상태로는 직접 먹을 수 없다! 요리를 해보자.
2️⃣ 전처리 (Preprocessor, cpp) = 레시피 준비하기 🔪
→ #include <stdio.h> 같은 것들을 미리 처리해서 코드에 필요한 내용들을 삽입한다.
요리로 치자면 재료 손질(야채 씻기, 썰기, 양념 준비) 같은 단계이다.
결과 : hello.i (수정된 소스 코드)
3️⃣ 컴파일 (Compiler, cc1) = 재료를 반죽하고 조리하기 🍳
→ C 코드(hello.i)를 기계가 이해할 수 있는 어셈블리어 코드(hello.s)로 변환한다.
요리로 치면 반죽을 만들거나 재료를 익히는 과정이다 !
결과 : hello.s (어셈블리 코드)
4️⃣ 어셈블 (Assembler, as) = 요리를 접시에 담기 🍽️
→ 어셈블리(as)는 어셈블리 코드(hello.s)를 기계어(hello.o)로 변환한다.
요리로 치면, 익힘 요리를 접시에 담는 과정이다 !
결과 : hello.o (객체 파일, 실행 가능하지만 완성 음식은 아니다)
5️⃣ 링크 (Linker, ld) = 음식 완성해서 서빙하기 🍲
→ 여러 개의 객체 파일(hello.o, printf.o 등)을 합쳐서 최종 실행 파일(hello)을 만든다.
요리로 치면, 접시에 담긴 여러 재료(밥, 반찬, 국 등)를 한 끼 식사로 세팅하는 과정이다.
결과: hello (최종 실행 파일, 이제 실행 가능!)
.
.
끝 !