Linux에서 gcc 컴파일러의 컴파일 프로세스

1. GCC 란?

GCC는 GPL 라이선스에 따라 배포 된 무료 소프트웨어이며 GNU 프로젝트의 핵심 부분이기도합니다. GCC의 원래 의도는 GNU 운영 체제 용 컴파일러를 작성하는 것이 었으며 대부분의 유닉스 계열 운영 체제 (예 : Linux, BSD, MacOS X 등)에서 표준 컴파일러로 채택되었으며 Microsoft Windows GCC에서 사용됩니다. GCC는 x86, ARM, MIPS 등과 같은 다양한 컴퓨터 아키텍처 칩을 지원하며 다양한 다른 하드웨어 플랫폼으로 포팅되었습니다. 여기서 우리는 먼저 Linux에서 C 언어 gcc의 사용을 주로 설명합니다.

1. gcc 사용 방법

gcc [选项] 文件名
在linux下我们可以使用 gcc --help 查看gcc的各个选项

2. gcc의 일반적인 옵션

여기에 사진 설명 삽입

gcc의 컴파일 과정

gcc 컴파일 과정은 크게 4 단계로 나눌 수 있습니다.

전처리 (전처리)
컴파일 (컴파일)
어셈블리 (어셈블리)
링크 (링크)

여기에 사진 설명 삽입

gcc 컴파일의 특정 단계에 대해 이야기하겠습니다.

1. 전처리

전처리는 c 소스 프로그램을 읽고 그 안에있는 의사 명령어와 특수 기호를 "교체"하는 것입니다.이 처리 후 매크로 정의가없는 출력 파일, 조건부 컴파일 명령어 및 특수 기호가 생성되지 않습니다. 이 파일의 의미는 전처리되지 않은 소스 파일과 동일하며 여전히 C 파일이지만 내용이 다릅니다. 의사 명령어는 주로 다음 세 가지 측면을 포함합니다.
(1) #define NAME TokenString, #undef 및 __DATE__, FILE, LINE, TIME, __FUNCTION__ 등과 같은 컴파일러의 일부 내장 매크로와 같은 매크로 정의 명령어 .
(2) #ifdef, #ifndef, #else, #elif, #endif 등과 같은 조건부 컴파일 명령.
(3) 헤더 파일에는 #include "FileName"또는 #include 등과 같은 명령어가 포함되어 있습니다.

전처리 과정에는 주로 다음 과정이 포함됩니다.

  • 모든 #defines를 삭제하고 모든 매크로 정의를 확장합니다.
  • #if, #ifdef, #elif, #else, #endif 등과 같은 모든 조건부 사전 컴파일 지침을 처리합니다.
  • #include 사전 컴파일 된 지시문을 처리하고 포함 된 파일을 사전 컴파일 된 지시문의 위치에 삽입하십시오.
  • 모든 주석 "//"및 "/ * * /"삭제
  • 컴파일 중에 디버깅 줄 번호와 컴파일 오류 경고 줄 번호가 생성 될 수 있도록 줄 번호와 파일 식별자를 추가합니다.
  • 컴파일러가 사용해야하므로 모든 #pragma 컴파일러 지시문을 유지하십시오.

다음 명령은 일반적으로 전처리에 사용됩니다. 매개 변수 -E는 전처리 만 의미합니다.
gcc -E hello.c -o hello.i
다음 명령을 사용하여 전처리 프로세스를 완료 할 수도 있습니다. 여기서 cpp는 전 처리기입니다.
cpp hello. c> hello.i

전처리 된 결과 hello.i는 여전히 c 언어 소스 코드입니다. cat 또는 vim 명령을 사용하여 코드를 볼 수 있습니다.
vim hello.i

2. 컴파일

컴파일러가 수행해야하는 작업은 모든 명령어가 문법 규칙을 준수하는지 확인한 후 어휘 분석 및 문법 분석을 전달 하고이를 동등한 중간 코드 표현 또는 어셈블리 코드로 변환하는 것 입니다. 컴파일 과정에 대해 더 알고 싶다면 다른 블로그를 참조하세요.

다음 명령을 사용하여 어셈블리 파일을 컴파일하고 생성 할 수 있습니다.
gcc -S hello.i> hello.s
cat 명령을 사용하여 코드를 볼 수 있습니다.
cat hello.s

3. 편집

어셈블리 프로세스는 실제로 어셈블리 언어 코드를 대상 기계 명령어로 변환합니다 . 번역 시스템에서 처리하는 각 c 언어 소스 프로그램에 대해 프로세스를 통해 최종적으로 해당 대상 파일을 얻습니다.

다음 명령을 사용하여 어셈블 할 수 있습니다.
gcc -c hello.s -o hello.o

4. 링크

어셈블러에 의해 생성 된 오브젝트 파일은 즉시 실행할 수 없으며 해결되지 않은 문제가 많을 수 있습니다. 예를 들어, 소스 파일의 함수는 다른 소스 파일 (예 : 변수 또는 함수 호출 등)에 정의 된 기호를 참조 할 수 있으며 라이브러리 파일의 함수는 프로그램 등에서 호출 될 수 있습니다. 링커의 주된 작업은 관련 개체 파일을 서로 연결하는 것입니다. 즉, 한 파일에서 참조하는 심볼을 다른 파일의 심볼 정의와 연결하여 오브젝트 파일은 운영 체제, 즉 실행 가능한 프로그램에서로드 및 실행할 수있는 통합 된 전체가되며, 개발자가 지정한 라이브러리 기능의 서로 다른 연결 방법에 따라 연결 프로세스는 두 가지 유형으로 나눌 수 있습니다. ① 정적 연결 ② 동적 링크.

실행 파일의 함수 호출을 위해 동적 링크 또는 정적 링크 방법을 각각 채택 할 수 있습니다. 동적 연결을 사용하면 공유 객체의 코드 사본이 하나만 메모리에 저장되어야하므로 공유 객체가 여러 프로세스에서 사용될 때 최종 실행 파일을 더 짧게 만들고 일부 메모리를 절약 할 수 있습니다 . 그러나 동적 연결을 사용하는 것이 정적 연결을 사용하는 것보다 낫다고는 할 수 없으며 경우에 따라 동적 연결로 인해 성능이 저하 될 수 있습니다 .

추천

출처blog.csdn.net/KingRing_/article/details/115051281