[C] 파일을 쪼개어 프로그램을 만들기

C는 언뜻 작은 프로그램을 만드는 데 적합해 보이는 언어이나, 실제로 많은 운영체제 혹은 프로그래밍 언어 등의 대규모 프로젝트가 “이식성”을 이유로 C로 만들어진다. 우리가 예제가 가득한 C 책에서 나 보는 것과는 달리, C프로그램은 실제로 여러 개의 파일로 나뉘어져서 만들어질 수 있고 한꺼번에 컴파일 되는 대신, 새롭게 업데이트된 부분만 컴파일해서 새로운 버전의 프로그램을 만드는 것이 가능하다.

어떤 계산 프로그램을 만들 때 특정 분야의 계산 로직을 다른 모듈로 구분했다고 하자. 대략적인 프로젝트의 구조는 다음과 같다. cal.c 는 계산기의 본체(main 함수가 있는)이고 hfcal.c 파일은 이 본체에서 사용하는 외부 함수를 정의해 놓는 파일이다. 물론 hfcal.h 에는 해당 함수가 선언되어 있다.

/root
    |--- cal.c 
    |---/myproj
        |--- hfcal.h
        |--- hfcal.c

이 때 cal.c 파일에서 #include "myproj/hfcal.h"와 같은 식으로 상대경로를 지정해주면 문제없이 컴파일 될 수 있다. 만약 표준 라이브러리처럼 #include <hfcal.h>와 같은 식으로 썼다면 어떻게 해야할까? 이 때는 gcc에 -I옵션을 주고 include 경로를 확장할 수 있다.

$ gcc -Imyproj cal.c -o cal

만약 각각의 파일을 따로 컴파일해서 하나로 합치겠다면 다음과 같은 순서를 따르면 된다.

$ gcc -Imyproj -c myproj/hfcal.c -o hfcal.o
$ gcc -Imyproj -c cal.c -o cal.o
$ gcc cal.o hfcal.o -o cal

첫 번째로 외부 C파일을 목적파일로 컴파일하고, 두 번째로는 메인 파일을 따로 컴파일 한다음. 마지막 명령으로 두 오브젝트 파일을 합쳐서 실행파일로 만들어 준다.[1. -c 옵션은 프로그램을 링크하지 않고 단순히 컴파일만 하여 오브젝트 파일을 생성하는 옵션이다.]

두 번째로 본체가 아닌 외부 함수를 정의한 모듈은 실질적으로 프로그램의 본체와는 구분되어 있으며, 만약 본체의 내용을 수정했으나, 여기에 정의된 함수는 그대로 유지되었다면, 한 번에 프로젝트 전체를 컴파일하는 것보다,

$ mkdir libs
$ gcc -Imyproj -c myproj/hfcal.c -o myproj/hfcal.o
$ ar -rcs libs/libhfcal.a hfcal.o 
$ gcc cal.o -Llibs -lhfcal -o cal

세 번째 행에서 ar 명령을 사용하여 오브젝트 파일을 정적 라이브러리로 합쳐주고 (여러 개의 오브젝트 파일을 하나로 합치는 게 가능하다.) 마지막 명령에서는 -L 옵션과 -l 옵션을 사용하여 라이브러리를 포함시켜준다. -L은 라이브러리의 경로를, -l은 라이브러리 내에서 참조할 오브젝트 파일(=모듈)의 이름이다.