[리눅스 시스템 프로그래밍] 1.2 GCC 컴파일러 사용법

이 책에서는 작성한 코드를 GCC 컴파일러를 통해 컴파일하고 테스트하는 부분이 많습니다. 이를 위해 GCC 컴파일러를 사용하는 방법을 소개할게요.

먼저 명령행에서 gcc 메뉴얼을 확인하세요.

$ man gcc

GCC(1)                                    GNU

NAME

gcc – GNU project C and C++ compiler

SYNOPSIS

gcc [-c|-S|-E] [-std=standard]

[-g] [-pg] [-Olevel]

[-Wwarn…][-pendantic]

[-Idir…][-Ldir…]

[-Dmacro[=def]…][-Umacro]

[-foption…][-mmachine-option…]

[-o output] [@file] infile…

옵션을 사용하지 않고 gcc 명령을 내리면 컴파일후에 링킹 과정을 거쳐 a.out 결과물이 만들어집니다.

//ex_gcc1.c
#include <stdio.h>
int main()
{
    printf("Hello Linux\n");
    return 0;
}

$gcc ex_gcc1.c

[그림 1.3] gcc 사용 예
[그림 1.3] gcc 사용 예

만약 원하는 출력 결과로 만들려면 -o [출력 결과]를 사용하세요.

$gcc -o ex_gcc1 ex_gcc1.c

[그림 1.4] gcc 사용 예
[그림 1.4] gcc 사용 예

-c 옵션을 사용하면 컴파일을 수행하고 확장자가 o인 목적 파일을 만들어 줍니다. 실행이 가능하려면 링킹 과정을 거쳐야 실행 파일이 만들어집니다.

//ex_gcc2.c
int Add(int a,int b)
{
    return a+b;
}

$ gcc -c ex_gcc2.c

$ gcc -c ex_gcc2.c
[그림 1.5] gcc 사용 예

목적 파일을 포함하여 컴파일 할 때는 단순히 목적 파일도 입력 파일 목록에 열거합니다.

#include <stdio.h>
int main()
{
    printf("result:%d\n",Add(3,4));
    return 0;
}

$ gcc -o ex_gcc3  ex_gcc2.o  ex_gcc3.c

$ gcc -o ex_gcc3  ex_gcc2.o  ex_gcc3.c
[그림 1.6] gcc 사용 예

소스 파일 여러 개를 입력 파일 목록에 열거하여 컴파일할 수도 있습니다.

$ gcc -o ex_demo  ex_gcc2.c  ex_gcc3.c

$ gcc -o ex_demo  ex_gcc2.c  ex_gcc3.c
[그림 1.7] gcc 사용 예

-D 옵션을 사용하면 매크로 상수를 옵션으로 정의할 수 있습니다. 단순히 -DTEST처럼 매크로 상수명을 정의하면 1로 정의하며 -DTEST=8처럼 매크로 상수 값도 지정할 수 있습니다.

//ex_gcc4.c
#include <stdio.h>
int main()
{
#ifdef TEST
    printf("%d\n",TEST);
#else
    printf("Not defined\n");
#endif
    return 0;
}

$ gcc -o ex_gcc4 ex_gcc4.c

$ gcc -o ex_gcc4 -DTEST ex_gcc4.c

$ gcc -o ex_gcc4 -DTEST=8 ex_gcc4.c

$ gcc -o ex_gcc4 ex_gcc4.c

$ gcc -o ex_gcc4 -DTEST ex_gcc4.c

$ gcc -o ex_gcc4 -DTEST=8 ex_gcc4.c
[그림 1.8] gcc 사용 예

목적 파일을 라이브러리로 만들 때는 ar 명령어를 사용합니다. 이 때 만들려고 하는 라이브러리 이름의 시작을 lib로 시작하게 작성하세요.

$ ar rscv libdemo.a ex_gcc2.o

$ ar rscv libdemo.a ex_gcc2.o
[그림 1.9] ar 사용

그리고 이와 같이 작성한 라이브러리를 포함하여 컴파일할 때는 -l 옵션을 주고 라이브러리 파일을 표현하는데 파일명 앞의 lib부분과 뒤쪽 .a를 생략합니다. 그리고 라이브러리 파일이 있는 경로를 -L 옵션으로 표시하세요.

$ gcc -o test ex_gcc3.c -L./ -ldemo

$ gcc -o test ex_gcc3.c -L./ -ldemo
[그림 1.10] gcc 사용 예

공유 라이브러리로 컴파일 할 때는 -shared -fPIC -o 옵션을 사용합니다.

$ gcc -shared -fPIC -o libshare.so ex_gcc2.o

$ gcc -shared -fPIC -o libshare.so ex_gcc2.o
[그림 1.11] gcc 사용 예

공유 라이브러리를 포함하여 컴파일하는 방법은 정적 라이브러리를 포함하여 컴파일하는 방법과 같습니다. 하지만 실행해보면 제대로 동작하지 않습니다.

$ gcc -o test2 ex_gcc3.c -L./ -lshare

$ gcc -o test2 ex_gcc3.c -L./ -lshare
[그림 1.12] gcc 사용 예

공유 라이브러리를 사용하는 프로그램은 라이브러리 디렉토리에 참조하는 라이브러리 파일이 존재해야 동작합니다. 슈퍼 유저 권한으로 로긴 계정을 변경한 후에 libshare.so 파일을 /usr/lib 디렉토리로 옮겨주세요.

$ cp libshare.so /usr/lib/

$ cp libshare.so /usr/lib/
[그림 1. 13] /usr/lib/ 디렉토리로 공유 라이브러리 이동

정적 라이브러리는 컴파일 결과물에 포함하지만 공유라이브러리는 결과물에 포함하지 않습니다. 공유 라이브러리는 프로그램 동작 시에 라이브러리를 사용할 수 있게 링크하여 사용하므로 /usr/lib 디렉토리에 배치해야 동작하는 것입니다. 만약 라이브러리의 규모가 크고 이를 참조하여 사용할 수 있는 프로그램의 종류가 많을 수 있다면 공유라이브러리로 만들 것을 고민해 보세요.

이 외에도 gcc 컴파일 옵션에는 경고를 출력 결과에 echo하지 않게 -w 옵션을 줄 수 있고 헤더 파일의 경로를 지정하는  -I 옵션과 gdb 유틸로 디버깅할 수 있게 -g 옵션 등을 사용할 수 있습니다.

보다 자세한 사항은 별도의 레퍼런스를 참고하세요. 그리고 이 책에서는 make 명령을 이용하여 효과적인 프로젝트 관리 기법을 다루지 않으므로 별도로 학습을 권합니다.