GCC Compile and Linking

haeryong·2023년 7월 11일
0

GCC compiler

GCC(GNU Compiler Collection) : C, C++, Java 등의 컴파일 언어를 컴파일하는 컴파일러의 일종이다. 여기서는 C언어를 대상으로 이야기한다.


출처

컴파일 : C언어로 작성된 각각의 소스코드를 어셈블리어로 변환. 결과로 오브젝트 파일이 생성됨.

링크 : 모든 오브젝트 파일을 엮어 binary 파일로 변환해 하나의 실행가능한(executable) 파일을 생성. (.exe 또는 .out 등)

executable 생성

  • main.c
int main(){

    foo(); 
    
    return 0;
}
  • func.c

void foo(){
	int a = 1;
}

main.c, func.c 2개의 소스코드를 컴파일하면 컴파일 에러가 발생한다.

gcc -c main.c func.c

그 이유는 모든 소스코드들이 독립적으로 오브젝트파일을 생성해야하는데 main.c에서 사용되는 foo()라는 함수의 정의는 func.c에만 있기 때문이다.

이를 해결하기 위해서는 main.c에 foo()라는 함수를 "선언"해주면 된다.
함수의 정의는 컴파일 과정에서 알 필요 없으므로 에러가 발생하지 않는다.

  • main.c 수정
void foo();

int main(){

    foo(); 
    
    return 0;
}

컴파일을 통해 main.o, func.o가 생성되면 이를 이용해 링크를 수행한다.

gcc main.0 func.0

결과로 실행가능한 a.exe(또는 a.out)파일이 생성되고 이를 실행할 수 있다.

./a.out

이와같이 다른 소스코드의 함수를 사용하려면 함수를 선언해주어야 한다. 이 번거로운 과정을 생략하기 위해 헤더(.h)파일을 이용한다.

  • main.c
#include "func.h"

int main(){

    foo(); 
    
    return 0;
}
  • func.h
void foo();
  • func.c
#include "func.h"

void foo(){
	int a = 1;
}

이전과 같이 컴파일+링크를 진행해보니 별 문제가 없어 보인다.
위에서는 컴파일과 링크를 분리해서 진행했지만, 한번에 할 수도 있다.

gcc main.c func.c 
./a.out

헤더파일이 다른 경로에 있다면 어떻게 될까?
func.h파일을 다른 경로로 옮긴 뒤 똑같이 시도해보니 컴파일 에러가 발생한다.
컴파일 과정에서 현재 경로나 지정된 경로에서만 헤더파일을 탐색하기 때문에 func.h를 찾지 못한 것인데, -I 커맨드를 이용해 헤더파일 탐색 경로를 추가해줄 수 있다.

gcc -I ./dir main.c func.c

static library 생성 및 사용

func.c와 func.h를 이용해서 static library를 생성하고 이를 main.c에서 사용해보자.

우선 func.c, funch를 이용해 컴파일을 진행, func.o를 얻는다.

gcc -c -I ./dir func.c

static library를 만들기 위해서는 archiver를 이용해야하는데, ar 커맨드를 이용해 사용할 수 있다.
윈도우의 경우 정적 라이브러리의 확장자가 lib이고 리눅스의 경우는 a이다.

ar rcs libfunc.a func.o 

결과로 libfunc.a가 생성된다.

libfunc.a의 foo 함수를 main.c에서 사용하기 위해서는 -L 커맨드를 이용해 라이브러리가 존재하는 경로를 라이브러리 탐색 경로로 추가해주어야 하고, -l 커맨드를 이용해 내가 사용할 탐색 경로 내에 있는 라이브러리를 지정해주어야 한다.

gcc -c main.c -I ./dir # main.o 생성. 헤더파일 경로를 추가해주기 위해 -I 사용.
gcc main.o -L . -l func # libfunc.a를 func로 생략가능.

# 위 2줄을 1줄에 수행
gcc main.c -I ./dir -L . -l func

dynamic library 생성 및 사용

func.c에 대한 오브젝트 파일을 생성할 때 -fPIC 옵션을 추가해야한다.

gcc -c -fPIC -I ./dir func.c

-shared 커맨드를 추가하고, -o 옵션에서 libfunc.so로 라이브러리 이름을 정해준다.

gcc -shared -o libfunc.so -I ./dir func.o 

libfunc.so 파일이 생성되고 main.c와 함께 executable을 생성할 수 있다.

gcc main.c -L . -I ./dir -l func

이를 실행하려고하면 libfunc.so를 찾을 수 없다는 에러가 발생하는데, 동적 라이브러리는 실행 중에도 해당 라이브러리가 필요하기 때문에 런타임 중에 시스템이 so파일을 읽어올 수 있도록 so파일의 경로가 LD_LIBRARY_PATH에 포함되어야 한다.

echo 'export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/so파일이/포함된/폴더' >> ~/.bashrc

터미널을 재시작하거나 source ~/.bashrc 커맨드 후 executable을 실행해보니 정상적으로 작동한다.

0개의 댓글