컴파일은 사람이 이해할 수 있는 HLL인 c언어 소스코드를 기계가 이해할 수 있는 기계어로 변환하는 과정이다.
기계어는 0과1로만 이루어진 Binary 코드이며 사람이 보고 이해하기 어렵다. 그래서 프로그래머들은 주로 C언어로 코딩하여 기계가 어떻게 동작할지 정해두고, 컴파일 과정을 거쳐서 프로그래머의 명령을 기계가 이해할 수 있는 언어로 바꾸고, 기계는 그 언어를 보고 이해하고 명령을 수행하는 것이다.
.c와 .h등의 파일을 input으로 하여 컴파일 하면 assembly코드(.s)가 만들어지고, .s파일을 .o파일로 만들고, .o파일을 link하여 실행파일 .out 이 만들어진다.
.c -(c-compile) -> .s -(assembler) -> .o -(linker) -> .out
이 같은 과정을 거치는데 추후의 내용에서 자세하게 다룰 것이다.
그리고 .c를 .s로 만들기 전에 preprocess(전처리)과정을 먼저 진행한다. #include, #define, #ifdef 같은 #구문을 처리해주고 syntax error를 점검하는 과정이다.
#include<" ">는 해당 소스코드에 " "에 대항하는 파일을 포함하는 처리를 하고, #define은 소스코드에서 사용한 define된 단어를 치환하는 작업을 하고, #ifdef는 조건에 맞는 코드만 남겨주는 처리를 한다.
전처리 과정을 마치면 .i 파일이 만들어진다.
전처리는 -E option을 추가하면 .i파일을 만들어서 어떤 코드로 구성되는지 확인할 수 있다.
/*
name : example.c
*/
#define Equal =
#include "header.c"
int main(){
a +Equal 1;
b +Equal 1;
}
/*
header.c
int a = 2;
int b = 3;
*/
이 같은 소스코드를 전처리 하면
/*
example.i
*/
int a = 2;
int b = 3;
int main(){
a += 1;
b += 1;
}
이와 같이 #include 자리에는 해당하는 소스코드(header.c)가 추가되고, define한 구문은 치환되어 =로 바뀐다.
.c 하나를 컴파일 하면
1. 전처리를 하여 define, include를 잘 가져와서 c 형식의 i 파일을 만듦.
2. 전처리된 i 파일을 어셈블리로 만든다.
3. 어셈블리를 기계어로 만든다. (elf형식의 o파일로)
4. o파일을 링크한다.
5. .out 파일을 만든다.