CrossCompile

GCC 가 무엇일까요?

sh1mj1 2022. 11. 10. 22:55

GCC

원래 C 언어용 컴파일러로 시작하여 GNU C Compiler의 약자였다.

2.9 버전에 이르러 C 언어뿐 아니라 Objective C, 파스칼, 에이다 같은 언어를 지원하게 되면서 GNU Compiler Collection 으로 변경되었다.

  • Linux, 윈도우, 등 많은 OS를 지원하고 계승하여 호환성이 매우 높다.
  • 자동 레지스터 할당
  • 반복적인 코드 제거
  • 상수 곱셈 최적화

등 의 많은 최적화를 수행하는 Compiler 이다. IDE 를 가지고 있지 않은 Command Line Compiler 이다.

Installing GCC on Mac OS X

터미널에서

❯ gcc --version 혹은 ❯ gcc --v

입력 시 아래처럼 나온다. 보통 설치되어 있다. 설치되어 있지 않다면 설치하라고 말해줄 것이다.

Apple clang version 13.1.6 (clang-1316.0.21.2.5)
Target: x86_64-apple-darwin21.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

More details can be obtained via -v option, for example,

Getting Started

간단한 Hello-world C program hello.c 을 만들어보자.

#include <stdio.h>

int main() {
        printf("Hello, world! \\n");
        return 0;
}

hello.c 을 컴파일 하려면

gcc hello.c

→ 기본 값으로 a.exe (윈도우) 혹은 a.out (Mac) 으로 실행 파일이 생긴다.

윈도우에서는

a

맥이나 유직스 에서는

./a out

(Bash shell 에서는 기본 경로는 현재 디렉토리를 포함하지 않아서 ./ 로 현 파일 경로를 포함해야 한다.

윈도우에서는 기본 경로를 현재 디렉토리를 포함해서 바로 a 만 작성해도 된다.)

output filename 을 지정하려면. -o option 을 사용.

// (Windows) In CMD shell
> gcc -o hello.exe hello.c
// Compile and link source file hello.c into executable hello.exe
> hello// Execute hello.exe under CMD shell

// (Unixes / Mac OS X) In Bash shell
$ gcc -o hello hello.c
$ chmod a+x hello
$ ./hello

그런데 chmod a+x hello 을 기입하지 않아도 실행이 된다…

컴파일, 링크 분리

위에서 제시한 커맨드는 source file을 object file 로 컴파일하고 object file 과 시스템 라이브러리를 실행 가능하게 한 번에 링크한다. 그런데 이를 분리할 수 도 있다.

// Compile-only with -c option > gcc -c -Wall -g Hello.c

hello.o 파일로 컴파일한다. 기본적으로 object file은 .o 확장자이다.

// Link object file(s) into an executable > gcc -g -o Hello.exe Hello.o

여러 소스 파일 컴파일하고 링크

Suppose that your program has two source files: file1.cpp, file2.cpp. You could compile all of them in a single command:

> gcc -o myprog file1.c file2.c

However, we usually compile each of the source files separately into object file, and link them together in the later stage.

In this case, changes in one file does not require re-compilation of the other files.

> gcc -c file1.c
> gcc -c file2.c
> gcc -o myprog file1.o file2.o

GCC 컴파일 과정

출처 https://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html

예시 코드

#include <stdio.h>

int main() {
        printf("Hello, world! \\n");
        return 0;
}

1. PreProcessing

Pre-processing: via the GNU C Preprocessor (cpp.exe), which includes the headers (#include) and expands the macros (#define).The resultant intermediate file "hello.i" contains the expanded source code.

#include, #define, typedef, extern 같은 구문을 처리하는 단계이다.

stdio.h 에 있는 모든 코드들이 main 함수 위에 등록된다.

그러니까 어떤 라이브러리에 있는 내용을 사용한다는 뜻인 #include ~~~~ 을 처리한다느 것으로 보인다.

gcc -E hello.c -o hello.i

이렇게 생성된 전처리 완료된 파일 hello.i 파일 실행 시 아래와 같다.

> cpp hello.c > hello.i
# 1 "hello.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 370 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "hello.c" 2
# 1 "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/stdio.h" 1 3 4
# 64 "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/stdio.h" 3 4
# 1 "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/_stdio.h" 1 3 4
# 68 "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/_stdio.h" 3 4
# 1 "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h" 1 3 4
# 659 "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h" 3 4
# 1 "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/_symbol_aliasing.h" 1 3 4
# 660 "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h" 2 3 4
# 725 "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h" 3 4

/* 엄청 코드가 긴
것들이 여기에 배치되네요
... (중략)
*/
extern int __vsnprintf_chk (char * restrict, size_t, int, size_t,
       const char * restrict, va_list);
# 400 "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/stdio.h" 2 3 4
# 2 "hello.c" 2

int main() {
 printf("Hello, world! \\n");
 return 0;
}

우리가 작성한 코드는 가장 하단에 있구나…

2. Compilation

Compilation: The compiler compiles the pre-processed source code into assembly code for a specific processor.The S option specifies to produce assembly code, instead of object code. The resultant assembly file is "hello.s".

> gcc -S hello.i

전처리된 파일(고수준의 언어)을 어셈블리어(저수준의 언어)로 바꿔주는 역할을 한다.

컴파일 단계에서 어셈블리어로 만드는 과정에서 실제로 호출되고 사용되는 부분만 번역하기 때문에 전처리 완료된 파일인 hello.i 보다 줄쑤가 짧다.

❯ gcc -S hello.i -o hello.s

코드로 생성한 컴파일된 파일 hello.s 을 실행해보자.

.section	__TEXT,__text,regular,pure_instructions
	.build_version macos, 12, 0	sdk_version 12, 3
	.globl	_main                           ## -- Begin function main
	.p2align	4, 0x90
_main:                                  ## @main
	.cfi_startproc
## %bb.0:
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset %rbp, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register %rbp
	subq	$16, %rsp
	movl	$0, -4(%rbp)
	leaq	L_.str(%rip), %rdi
	movb	$0, %al
	callq	_printf
	xorl	%eax, %eax
	addq	$16, %rsp
	popq	%rbp
	retq
	.cfi_endproc
                                        ## -- End function
	.section	__TEXT,__cstring,cstring_literals
L_.str:                                 ## @.str
	.asciz	"Hello, world! \\n"

.subsections_via_symbols

한 눈 감고 봐도 어셈블리어 코드인 것을 확인할 수 있다.

3. Assemblier

Assembly: The assembler (as.exe) converts the assembly code into machine code in the object file "hello.o".

생성된 hello.o 파일을 실행해보자.

> as -o hello.o hello.s

??????

이제 컴퓨터가 알아든는 머신 랭귀지가 되어서 위가 확인할 수가 없다.

4. Linker

Linker: Finally, the linker (ld.exe) links the object code with the library code to produce an executable file "hello.exe".

> ld -o hello.exe hello.o ...libraries...

gcc hello.o -o hello

 

 

 

[C/C++] GCC가 무엇인가요? GCC의 컴파일 과정 4단계

GCC and Make