컴파일(Compile)
컴파일이란?
컴파일(Compile)이란 인간이 이해할 수 있는 언어를 컴퓨터가 이해할 수 있는 언어로 변환하는 작업을 말한다. 컴퓨터는 모든 명령을 CPU가 처리하고 CPU는 모든 명령을 이진법, 즉 0과 1 단 두 개의 숫자만을 이용하여 이해하고 실행한다. 'A'라는 알파벳을 입력할 때 우리는 'A'라고 해석하지만 컴퓨터는 00110010와 같은 이진코드로 해석하고 명령을 처리한다는 것이다. 즉, 우리의 언어는 컴퓨터가 이해하지 못하므로 컴퓨터가 이해할 수 있는 통역사인 컴파일이 필요하다.
컴파일의 과정
컴파일 과정은 전처리 과정, 컴파일 과정, 어셈블 과정, 링킹 과정 등의 총 4가지 단계로 나누어 지며, 이 4가지 단계를 묶어서 컴파일 과정, 또는 빌드 과정이라고 부르기도 하고 컴파일 과정과 링킹 과정을 따로 나눠서 부르기도 한다.
1. 전처리(Pre-processing) 과정 : 전처리기(Preprocessor)를 통해 소스 코드 파일(*.c)을 전처리된 소스 코드 파일(*.i)로 변환하는 과정으로 대표적으로 세가지 작업을 수행한다.
- 주석 제거 : 주석은 사람들의 이해를 위해 남긴 내용으로 컴퓨터와는 관계가 없기에 소스 코드에서 주석을 전부 제거한다.
- 헤더 파일 삽입 : #include 지시문을 만나면 해당하는 헤더 파일을 찾아 헤더 파일에 있는 모든 내용을 복사해서 소스 코드에 삽입한다.
- 매크로 치환 및 적용 : #define 지시문에 정의된 매크로를 저장하고 같은 문자열을 만나면 #define 된 내용으로 치환한다. 간단하게 말해 매크로 이름을 찾아서 정의한 값으로 전부 바꿔준다.
2. 컴파일(Compilation) 과정 : 컴파일러(Compiler)를 통해 전처리된 소스 코드 파일(*.i)을 어셈블리어 파일(*.s)로 변환하는 과정으로 이 과정에서 우리가 일반적으로 컴파일하면 생각하는 언어의 문법 검사가 이루어진다. 또한 또한 Static한 영역(Data, BSS 영역)들의 메모리 할당을 수행한다. 컴파일러는 언어 종속적인 부분을 처리하는 프론트엔드(Front-end), 아키텍쳐 비종속적인 최적화를 수행하는 미들엔드(Middle-end), 아키텍쳐 종속적인 최적화를 수행하는 백엔드(Back-end)의 총 3단계로 구성되어 있다.
3. 어셈블리(Assembly) 과정 : 어셈블러(Assembler)를 통해 어셈블리어 파일(*.s)을 오브젝트 파일(*.o)로 변환하는 과정을 말한다. 더 이상 사람이 알아볼 수 없는 기계어로 변환되는 어셈블리 코드를 오브젝트 코드라 부르며 이러한 오브젝트 코드로 구성된 파일을 오브젝트 파일(Object File)이라 부르며 이 오브젝트 파일은 특정한 파일 포맷을 가진다.
4. 링킹(Linking) 과정 : 링커(Linker)를 통해 오브젝트 파일(*.o)들을 묶어 실행 파일로 만드는 과정을 말하며, 이 과정에서 오브젝트 파일들과 프로그램에서 사용하는 라이브러리 파일들을 링크하여 하나의 실행 파일을 만든다. 이때 라이브러리를 링크하는 방법에 따라 정적 링킹(Static Linking)과 동적 링킹(Dynamic Linking)으로 나눌 수 있다.