C언어의 기본적인 컴파일과 링크방법에 대해 알아보고 실습해봅시다.
gcc -c test.c
gcc -o test test.o
실행모듈과 라이브러리를 제작하여 컴파일 후, 링크하여 실행 결과를 출력한다.
func.c
int add(int a, int b)
{
return a + b;
}
int mul(int a, int b)
{
return a * b;
}
test.c
#include <stdio.h>
int main(int argc, char *argv[])
{
if (argc <=2) {
printf("two parameters required!\n");
return -1;
}
int a = atoi(argv[1]);
int b = atoi(argv[2]);
int c = add(a, b);
printf("%d + %d = %d\n", a, b, c);
return 0;
}
# func.o 생성
gcc -c func.c
# main.o 생성
gcc -c test.c
# test 생성
gcc -o test.c func.o
./test 1 2
# 출력 : 1 + 2 = 3
# 정적 라이브러리 생성
ar crf libtest.a test.o
# 정적 라이브러리 링크
gcc -o main main.o -L. -ltest
# dynamic dependency 체크
ldd main
# 동적 라이브러리 생성
gcc -shared -fPIC -o libtest.so test.o
# 동적 라이브러리 링크 (동적라이브러리가 우선)
gcc -o main main.o -L. -ltest
# dynamic dependency 체크
ldd main
프로젝트 구성이 방대할 경우, gcc를 이용하여 일일이 빌드하는 것은 효율적이지 않습니다. make
유틸을 활용하면 보다 효율적으로 빌드를 수행할 수 있습니다.
make
를 사용하기 위해서는 makefile
을 먼저 구성해야 합니다. 해당 파일을 구성하고 make
를 실행하면 자동으로 빌드가 되며 -f
파라미터를 이용하여 파일명을 지정할 수 있습니다.
makefile
은 크게 목표(Target), 의존성(Dependency), 명령(Command)의 3 부분으로 이루어집니다.
target: dependencyList
commandList
요소 | 설명 |
---|---|
targetList | 명령이 수행되어 생성될 결과 파일 지정 |
dependencyList | target(목표)을 수행하기 위해 필요한 의존 관계 설정 |
commandList | target을 수행하기 위해 여기에 정의된 명령이 실행됨 |
Command(명령)의 경우 다양한 유틸리티를 사용할 수 있습니다. 예를 들어 gcc
외에도 clear
, cp
등의 대부분의 명령어를 사용할 수 있습니다. 명령의 앞 부분은 반드시 Tab을 이용해서 공백을 만들어주어야 합니다.
다음과 같은 파일들이 존재한다고 가정해봅시다.
위의 파일들은 gcc
를 이용했을 때 다음과 같이 빌드할 수 있습니다.
$ gcc -o snowdeerApp main.c input.c output.c
이 경우 make를 위한 makefile로 만들어보면 다음과 같습니다.
snowdeerApp :
gcc -o snowdeerApp main.c input.c output.c
기본적으로 위와 같은 makefile을 이용하면 되지만, 향후 확장을 위해 다음과 같이 좀 더 유연하게 만들어 줄 수 있습니다.
main : main.o func1.o func2.o
gcc -o main main.o func1.o func2.o
main.o : main.c
gcc -c main.c
func1.o : func1.c
gcc -c func1.c
func2.o : func2.c
gcc -c func2.c
위에서 작성한 makefile
에 ‘$(매크로)’ 같은 형식의 매크로 기능을 사용할 수 있습니다.
OBJECTS = main.o func1.o func2.o
SRC = main.c func1.c func2.c
CFLAGS = -g
TARGET = main
$(TARGET) : $(OBJECTS)
$(CC) -o $(TARGET) $(OBJECTS)
clear :
rm -f $(OBJECTS) $(TARGET) core
main.o : main.c
func1.o : func1.c
func2.o : func2.c