본문 바로가기
Programming

C 컴파일 과정

by 나무수피아는 지식의 가지를 뻗어가는 공간입니다. 2025. 8. 23.
반응형

 

컴파일 과정

1. 컴파일 과정

C 언어로 작성된 소스 코드는 컴퓨터가 직접 이해할 수 없는 고급 언어이므로, 실행 가능한 프로그램으로 변환되기 위해 여러 단계를 거칩니다. 이 과정을 이해하는 것은 디버깅, 최적화, 빌드 자동화 등을 위한 필수 지식입니다.

① 전처리 (Preprocessing)

전처리는 컴파일러가 실제로 소스 코드를 해석하기 전에 먼저 수행되는 단계입니다. #include, #define, #ifdef 등과 같은 전처리 지시문을 처리하여, 코드에 포함된 다른 파일을 병합하거나, 매크로를 치환하는 작업이 이뤄집니다.
결과물: 전처리된 소스 코드 (. i 파일)

② 컴파일 (Compiling)

이 단계에서는 전처리된 코드를 바탕으로 어셈블리 언어로 변환합니다. 변수, 함수, 제어문 등의 C 언어 구문이 CPU가 이해할 수 있는 저수준 명령어로 바뀌게 됩니다. 코드 최적화가 일부 이루어지기도 합니다.
결과물: 어셈블리 코드 (. s 파일)

③ 어셈블 (Assembling)

어셈블 단계에서는 어셈블리 코드를 이진 기계어로 변환하여 목적 파일(Object File)을 생성합니다. 이 파일은 아직 독립적으로 실행할 수 없으며, 링커를 통해 완성됩니다.
결과물: 목적 파일 (. o 또는. obj)

④ 링킹 (Linking)

링커는 여러 개의 목적 파일(. o)과 라이브러리(. a 또는. so/. dll)를 연결하여 하나의 실행 파일을 만듭니다. 이 과정에서는 외부 함수나 전역 변수의 주소를 해결하고, 필요한 라이브러리 코드를 결합합니다. 링킹 단계에서 오류가 발생하는 경우는 보통 함수 선언 누락, 중복 정의, 외부 심벌 미정의 등이 있습니다.
결과물: 실행 파일 (예: a.out, main.exe)

2. 전체 흐름 요약

소스 코드 (main.c)
   ↓ 전처리 (gcc -E main.c → main.i)
전처리된 코드
   ↓ 컴파일 (gcc -S main.i → main.s)
어셈블리 코드
   ↓ 어셈블 (gcc -c main.s → main.o)
목적 코드
   ↓ 링킹 (gcc main.o → a.out)
실행 파일 생성
        

위 흐름을 보면 C 프로그램이 단순히 컴파일러 한 번 실행해서 끝나는 것이 아니라, 내부적으로 여러 단계를 거치며 점차 기계가 이해할 수 있는 코드로 바뀌는 것을 알 수 있습니다. 개발자는 이 과정을 명확히 이해함으로써 더 깊이 있는 디버깅과 성능 분석을 할 수 있습니다.

3. 객체 파일 구조

객체 파일(. o)은 단순한 기계어 덩어리가 아니라 내부적으로 여러 섹션으로 구성됩니다. 이 구조를 이해하면 링커 에러의 원인을 분석하거나 바이너리 분석 시 큰 도움이 됩니다.

  • 텍스트 섹션 (.text) - 실제 실행 코드가 위치하는 공간입니다.
  • 데이터 섹션 (.data, .bss) - 전역 및 정적 변수. 초기화된 변수는 .data, 초기화되지 않은 변수는 .bss에 위치합니다.
  • 심벌 테이블 (Symbol Table) - 함수 및 변수의 이름, 주소, 속성 등의 메타 정보가 포함됩니다.

nm, objdump, readelf 같은 도구를 사용하면 객체 파일의 내부 구조를 분석할 수 있으며, 특정 함수의 위치나 미정의 심벌 등을 확인할 수 있습니다.

4. Makefile 사용법

여러 소스 파일로 구성된 C 프로젝트에서는 매번 수작업으로 컴파일하기보다는, Makefile을 통해 자동화된 빌드 환경을 구축하는 것이 효율적입니다. Makefile은 의존성 기반으로 동작하여, 변경된 파일만 다시 컴파일하므로 개발 시간을 줄여줍니다.

예시 Makefile

# 파일명: Makefile
CC = gcc
CFLAGS = -Wall -g

all: main

main: main.o calc.o
	$(CC) $(CFLAGS) -o main main.o calc.o

main.o: main.c calc.h
	$(CC) $(CFLAGS) -c main.c

calc.o: calc.c calc.h
	$(CC) $(CFLAGS) -c calc.c

clean:
	rm -f *.o main
        

사용법

  • make: Makefile에 정의된 규칙에 따라 프로그램을 빌드합니다.
  • make clean: 생성된 중간 파일(.o)과 실행 파일을 삭제하여 빌드 환경을 초기화합니다.

Makefile은 단순하지만 강력한 도구입니다. 복잡한 프로젝트에서는 자동 의존성 생성, 다중 타깃, 변수 재사용, 조건부 빌드 등 다양한 기법이 활용됩니다.

반응형

'Programming' 카테고리의 다른 글

C 저수준 입출력 (Low-Level I/O)  (51) 2025.08.25
C 시스템 콜과 POSIX API  (46) 2025.08.24
C 메모리 모델 심층 분석  (66) 2025.08.22
C 디버깅과 오류 처리  (50) 2025.08.21
C 라이브러리와 헤더 파일  (58) 2025.08.20