IT Dictionary

C언어 컴파일 과정(C Compile Process)

Jaebins 2023. 4. 28. 12:48
반응형

우리는 C언어로 컴퓨터 안에서 우리가 힘들게 만든 작품을 눈으로 보기 위해 코드 에디터에서 컴파일이라는 과정을 거치게 된다. 어떻게 고작 문자 몇줄이 이렇게 복잡한 컴퓨터 안에서 우리가 원하는 주문을 하나도 빠뜨리지 않고 정확하게 표현이 가능한걸까?

 

⛳컴파일이란?

인간이 이해 가능한 언어로 작성된 코드를 컴퓨터(CPU)가 이해할 수 있는 언어로 번역하는 작업

 

가장 많이 혼동될 수 있는 것이 컴파일과 빌드인데, 컴파일소스코드를 바이너리 파일로 만드는 행위 자체를 말하는 것이고, 빌드소스코드로 실행 파일을 만드는 과정 전체를 포괄하는 개념이다.

 

이제 본격적으로 컴파일에 대해서 알아보자. 컴파일의 과정으로는 크게 4가지로 나눠질 수 있다.

 

👉 전처리 과정

 

👉 컴파일 과정

 

👉 어셈블리 과정

 

👉 링킹 과정

 

자. 이제 한번 탐구를 해보도록 하자.

 

Frist, 전처리(Preprocessing) 과정

소스 코드 파일(.c | .cpp)을 전처리된 소스코드 파일(*.i)로 변환하는 과정

해당 작업에서의 대표적인 역할로는 헤더 파일에 있는 내용들을 현재 우리 소스코드에 들어오게 한다. 대표적인 전처리기는 #include#define이 있는데, #include는 영어 뜻 그대로 헤더 파일을 우리 소스 코드에 포함 시킬 때 사용하고, #define은 상수나 함수를 문자로 정의시킬 때 사용한다.

 

전처리 과정을 하나 예로 들자면 우리가 C언어로 코드를 작성할 때, #include <stdio.h> 로 stdio.h 라는 헤더 파일을 정의한다. 여기서 stdio.h에 있는 함수들을 우리 소스 코드 파일로 불러오는 전처리 과정을 하는 것이다.

 

Second, 컴파일(Compile) 과정

전처리된 소스코드 파일을 컴파일러를 이용하여 어셈블리어 파일(*.s)로 변환하는 과정

여기서부터 본격적으로 고급 언어를 저급 언어(기계어)로 변환 시키는 역할을 시작하게 된다.

 

이 과정에서 언어의 문법 검사가 이루어지고, 우리가 작성한 소스 코드를 트리 형식으로 나타내는 GIMPLE 트리를 생성하게 된다. 이 GIMPLE 트리 형식은 언어 종속적인 부분을 처리 해주면서 컴파일을 실행할 수 있게 한다. 또한 메모리 할당도 이 컴파일 과정에서 이루어지게 된다.

 

GIMPLE 트리를 이용해 고급 언어와 어셈블리 언어의 중간 형태의 중간 형태의 RTL(Register Transfer Language)를 생성한다. 이 RTL을 이용하여 CPU 아키텍처에 맞춰 어셈블리 파일(*.s)를 생성하게 된다.

 

Third, 어셈블리(Assembly) 과정

어셈블리어 파일(.s)를 오브젝트 파일(.o)로 변환하는 과정

여기서 오브젝트 파일(Object File)이란 어셈블리 코드를 더 이상 사람이 알아볼 수 없는 기계어로 변환시켜 만들어진 파일을 말한다. 이 파일은 어셈블리 코드의 명령어(Instruction)와 데이터(Data)가 들어있는데, 윈도우의 경우 PE 포맷, 리눅스의 경우 ELF 바이너리 포맷의 구조체를 갖게 된다.

 

해당 과정은 4번째 과정인 링킹 과정에서 명령어와 데이터를 구분시켜 효과적으로 각 바이너리 정보를 파악하기 위해서 하는 것이다.

 

Fourth, 링킹(Linking) 과정

링커를 통해 오브젝트 파일들이나 라이브러리를 모두 묶어 연결하여 실행 파일로 만드는 과정

어셈블리 과정에서 만들어진 포맷 구조를 바탕으로 미리 컴파일 되있는 라이브러리 파일이나 오브젝트 파일을 모두 링크(Link) 시킨다. 이제 이 덩어리를 실행파일(*.exe)로 만들어 우리의 작품이 완성되는 것이다.

 

여담으로, 링킹을 하는 방식으로는 정적 링킹과 동적 링킹으로 나눠질 수 있다.
정적 링킹은 링커가 프로그램에서 필요로 하는 기능을 라이브러리에서 찾아 실행 파일에 복사하는 방식이다.
동적 링킹은 해당 내용의 주소만 가지고 있다가 런타임에 해당 주소의 필요한 내용만 가져오는 방식이다.

 

반응형