본문 바로가기
c++

Cpp의 컴파일 과정을 알아보자.

by chunma1126 2025. 1. 12.

 

Cpp 프로젝트들을 열다 보면 특이한 확장자의 파일을 볼수 있다.

 

.obj
난 이런 확장자를 cpp를 하면서 처음 봤고, 여기서 시작한 궁금증이 C++의 컴파일 과정으로 날 이끌었다.
그런 긴 말 않고 바로 알아보도록 하자.

 

1. 전처리

전처리는 C++에서 #으로 시작하는 구문들로 이루어져 있으며, 컴파일 전에 미리 처리되는 명령어들을 말한다. 전처리 과정에서는 주로 다음과 같은 작업이 이루어진다.

include

#include는 다른 파일(헤더 파일)의 내용을 단순히 "복사 붙여넣기"하는 역할을 한다. 표준 라이브러리(< >)나 사용자 정의 
파일(" ")을 포함할 때 사용한다.


define
매크로를 정의하고, 코드에서 이를 대체한다. 예를 들어, #define PI 3.14는 코드에서 PI를 모두 3.14로 치환한다.


pragma once
#pragma once는 헤더 파일의 중복 포함을 방지하기 위해 사용하는 전처리 지시문이다. 기존의 헤더 가드(#ifndef, #define, #endif)를 간단하게 대체할 수 있는 방식으로, 특정 파일이 여러 번 포함되더라도 한 번만 처리되도록 보장한다.

 

2. 컴파일

컴파일 과정은 우리가 작성한 cpp 코드를 가장 낮은 단계의 언어인 어셈블리어로 변환하는 과정을 말한다. 이 단계에서 우리가 쓴 소스코드에서 문법 오류는 없는지 한번 검사해준다.
그리고 기계가 이해할 수 있도록 어셈블리어로 번역하는 과정 또한 여기서 일어난다. 번역한 어셈블리어 파일은 텍스트 파일이기 때문에 궁금하면 볼 수 있다.

 

3. 어셈블

어셈블 과정은 어셈블리 파일을 목적 코드로 변환하는 과정을 말한다. 여기서 목적 코드는 완전 기계어로 이루어져 있으며, 윈도우에서는 .obj, 리눅스/유닉스 계열에서는 .o 확장자를 가지는 파일들을 말한다.

이런 확장자 차이가 생기는 이유는 윈도우와 리눅스가 서로 다른 형식의 파일 구조를 사용하기 때문이다.

목적 파일은 아직 실행 파일이 아니며 링커를 통해 다른 목적 파일들과 결합되어야 한다. 이 파일들은 재배치 정보와 심볼 테이블을 포함하고 있고, 외부 함수나 변수에 대한 참조 정보도 담고 있다.

 

4. 링킹

링킹 단계는 목적 코드들이 서로 참조하고 있는 부분들을 연결해주는 역할과 라이브러리들을 연결해주는 단계이다. 여기서 라이브러리는 정적 라이브러리(.lib, .a)와 동적 라이브러리(.dll, .so)로 나뉜다.

정적 라이브러리는 컴파일 시점에 실행 파일에 완전히 포함되어 독립적으로 실행될 수 있게 하고, 동적 라이브러리는 프로그램 실행 시점에 필요한 부분만 메모리에 로드되어 여러 프로그램이 공유할 수 있게 한다.

이 과정을 거쳐 최종적으로 실행 가능한 프로그램 파일이 만들어진다. 윈도우에서는 .exe 파일이 되고, 리눅스에서는 확장자가 없는 실행 파일이 된다.

 

 

exe파일 하나를 만들기 까지 정말 험난한 여정이 필요한거 같다..

하지만 이러한 과정들 덕분에 오류없는 실행 파일을 만들수 있는거 아닐까 싶다.