컴퓨터활용/유닉스

외부 binary 링크하여 컴파일하기

멜번초이 2008. 9. 19. 16:26
반응형
외부 파일에 함수를 만들어 놓고 별도 컴파일 한 후에 최종 실행 파일을 만들 때 이것을 같이 묶어서 컴파일 하는 것을 C 프로젝트에서 많이 사용하게 된다. 이 기초적인 작업의 샘플을 여기에 쉽게 써 보겠다.

두개의 파일을 작성한다. 하나는 func.c 이고 또 하나는 call.c 이다. func.c 에는 함수만 들어 있고 call.c 에는 main함수가 들어 있어 실행이 가능하게 된다. 

먼저 func.c 를 다음과 같이 작성했다.
#include <stdio.h>

long func_a();

long func_a() {
    printf("here is func_a!\n");
    return 0;
}

함수 이름 앞에는 return type 으로 long 을 지정 했다. 만일  static long func_a() 라고 선언하게 되면 외부에서 이 함수를 호출 할 수 없게 되므로 주의한다. 

[cbs]cc func.c
[cbs]ls -al  func*
-rw-rw-rw-    1 csh cbsdev           85  9월 19일 16:22 func.c
-rw-rw-rw-    1 csh  cbsdev         1071  9월 19일 16:24 func.o
[cbs]

컴파일이 제대로 잘 되었으면 func.o 라는 바이너리 파일이 생성되었을 것이다. 

다음에 이 함수를 호출하는  call.c 를 다음과 같이 작성하였다. 
#include <stdio.h>

extern long func_a();  /* 외부파일에 있는 함수라는 뜻으로 extern을 붙임 */

main() {

    func_a();          /* 이 func_a 라는 함수는 외부파일인 func.c 속에 있음 */

    printf("here is main!!\n");

};

이 call.c 를 컴파일 한다. 실제적으로 컴파일은 두번에 걸쳐서 실행된다. call.c 를 컴파일 하여 call.o 를 만드는 1차 컴파일과 call.o 와 func.o 를 묶어서 실제 실행되는 실행파일을 만드는 2차 컴파일이 필요하다. 

[cbs]cc call.c
[cbs]ls -al call*
-rw-rw-rw-    1 csh  cbsdev          111  9월 19일 16:28 call.c
-rw-rw-rw-    1 csh  cbsdev         1115  9월 19일 16:31 call.o
[cbs]

1차 컴파일할 때 비록 func_a() 라는 함수가 call.c 파일 속에 작성이 되어 있지 않지만 프로그램 시작머리에 extern long func_a(); 라고 기술해 놓았기 때문에 컴파일러는 알아서 외부 어딘가에 있다고 믿고 오류 없이 컴파일을 통과시켜 주게 된다.  

call.o 가 만들어 진 것을 확인하고 다시 2차 컴파일을 다음과 같이 한다.
[cbs]cc -o call call.o func.o
[cbs]ll call*
-rw-rw-rw-    1 csh  cbsdev          111  9월 19일 16:28 call.c
-rw-rw-rw-    1 csh  cbsdev         1115  9월 19일 16:31 call.o
-rwxrwxrwx    1 csh  cbsdev         5331  9월 19일 16:32 call
[cbs]

call 의 속성이 rwxrwxrwx 로 생성되었고 실행이 가능하다. 실제로 실행을 해 보면 다음과 같은 결과를 얻을 수 있다. 2차 컴파일에서 cc 다음에 있는 -o 옵션은 생성될 실행 파일의 이름을 지정하는 것이다. 이것을 생략하면 a.out이라는 이름으로 실행파일이 생성된다.  그 뒤에 link 할 object 파일들을 주욱 나열해 주면 같이 실행파일에 묶여진다. 

[cbs]call
here is func_a!
here is main!!
[cbs]
즉 func.c 속의 func 함수를 먼저 호출하고 main 함수 속에 있는 printf 문이 수행되었음을 최종 확인할 수 있겠죠.. 

그럼 깍두기로 다음과 같이 해 보자.  컴파일 할 때 일일이 하지 않고 뒤에 .c 파일을 주욱 나열해 주면 한꺼번에 컴파일을 하고 link 까지 해 주게 된다. 편하실 대로 하세요.

[cbs]cc -o call call.c func.c
call.c:
func.c:
[cbs]call
here is func_a!
here is main!!
[cbs]

프로그램 동작은 동일하게 하는군요. 

그리고 만약에 func.c 나 call.c 에 func_a 라는 함수가 없을 경우에는  0711-317 ERROR: Undefined symbol 오류를  컴파일할 때 만나게 된다. 대부분의 경우 함수이름을 대소문자를 잘못 쓰거나 해서 언뜻보기에 비슷하지만 잘못 쓰는 경우가 흔히 있다. 특히 알파벳 엘(l) 자를 숫자 일(1)로 잘못 쓰거나 대문자  아이(I) 와 소문자 엘(l) 을 잘못 쓰거나 하면 위의 에러를 흔히 만나게 된다. 

여하튼 이렇게 cc 컴파일 할 때 옵션도 많아지고 링크해야할 바이너리도 점점 많아지면 일일 컴파일 명령을 다 기억하기 어렵게 된다. 이러한 컴파일 명령 스트링을 자동으로 만들어주는 파일이 make 파일인 것이다.
반응형