들어가기 전

GCC에 대해 알아보기 전, C 소스의 컴파일 과정에 대해 간략히 짚어보고 들어가자.

C의 컴파일 과정

NOTE

gcc와 GCC는 전혀 다른 의미이다.
gcc는 GNU C Compiler의 약어이고,
GCC는 GNU Compiler Collection의 약어이다.

/usr/bin/gcc는 엄밀한 의미에서는 C 컴파일러가 아니다.
/usr/bin/gcc는 내부적으로 전처리기인 cpp0 또는 cc1 -E명령을 통해 전처리 과정을 수행하고
실제적인 C 컴파일러인 cc1을 통해 컴파일한 후
어셈블러인 as를 통해 목적 코드를 만들고,
링커를 호출하는 collect2를 호출해 collect2가 실제적인 링커 ld를 호출함으로써 라이브러리와 링크해 실행 파일로 만들어낸다.

따라서 진짜 C 컴파일러는 /usr/libexec/gcc/i386-redhatlinux/4.1.2/cc1이라 할 수 있다.

다음은 /usr/libexec/gcc/i386-redhatlinux/4.1.2/ 내부에 있는 실행파일의 역할에 대한 설명이다.

  • cc1: C 컴파일러, -E 옵션을 붙이면 전처리기로 동작
  • cc1plus: C++컴파일러, -E 옵션을 붙이면C++ 전처리기로 동작
  • cpp0: 전처리기(old ver, 현재는 컴파일러에 전처리 과정이 통합되어 있다)
  • cc1obj: Objective-C 컴파일러, -E 옵션을 붙이면 전처리기로 동작
  • collect2: 링커(내부적으로 링커인 ld를 호출해 링크)
  • ld: 링커(실제로는 존재하지 않지만 설명을 위해 써 놓음)

다음은 /usr/bin/ 디렉토리에 존재하는 컴파일러 드라이버들이다.

  • cc: C 컴파일러 드라이버, gcc와 동일
  • gcc: C 컴파일러 드라이버
  • c++: C++ 컴파일러 드라이버, g++과 동일
  • g++: C++ 컴파일러 드라이버

위 컴파일러 드라이버는 전처리기, 컴파일러, 어셈블러, 링커를 각각 호출해 주는 역할만을 담당한다. 또한 자신이 지원하는 언어의 소스가 아닐지라도 해당 소스에 맞는 전처리기와 컴파일러를 호출해 주기도 한다. 따라서 gcc가 C++ 소스를 컴파일 할 수도 있는 것이다. 하지만 C++ 소스를 컴파일하기 위해 기본적으로 요구되는 라이브러리를 알지 못하므로 lstdc++ 옵션을 컴파일 명령시 추가해 주지 않으면 오류가 발생할 것이다.

다음은 간략한 컴파일 과정 전개도이다.

main.c --'cc1 -E'--> main.c 전처리 결과 --'cc1'--> main.s 어셈블리 파일 --'as'--> like.o 오브젝트 파일 --'ld|collect2'--> main.exe

이러한 과정들을 직접 눈으로 확인하고 싶다면 다음의 명령어를 사용하라.

gcc -v -save-temps -o main main.c

여기서 -v 옵션은 verbose의 약어로 컴파일 과정을 화면으로 출력하는 옵션이고,
-save-temps 옵션은 컴파일 과정 중 발생되는 중간 파일을 지우지 않고 저장하는 옵션이다.

+ Recent posts