2010 3
KulsWiki
목차 |
gcc 기본 컴파일
hello.c라는 파일을 만들었다고 가정했을때,
- gcc hello.c
후에는 다음과 같이 실행시켜야 합니다.
$ ./a.out
맨 앞의 도트 문자(.)는 현재 디렉토리를 의미합니다. 그 다음 디렉토리 구분 문자 슬래쉬(/)를 쓰고 유닉스 C 에서 ``약속한 C 컴파일러의 출력 결과 바이너리 화일인 a.out 을 써줍니다.
현재 디렉토리에서 실행하기 == ./<실행 화일명>
유닉스는 기본적으로 PATH 라는 환경변수에 있는 디렉토리에서만 실행화일을 찾을 뿐입니다. 만약 PATH 라는 환경변수에 현재 디렉토리를 의미하는 도트 문자(.)가 들어있지 않으면 현재 디렉토리의 실행화일은 절대 실행되지 않습니다. 게다가 현재 디렉토리를 PATH 환경 변수에 넣어준다 할 지라도 도스처렁럼 현재 디렉토리를 먼저 찾는다든지 하는 일은 없습니다. 오로지 PATH 에 지정한 순서대로 수행합니다.
mv명령어를 이용하여 a.out의 이름을 바꾸어도 되지만 불편합니다.
-o 옵션
이때 사용하는 것이 -o 옵션입니다.
$ gcc -o hello hello.c
^^^^^^^^
또는 다음과 같이 순서를 바꿔도 무방합니다.
$ gcc hello.c -o hello
이때 -o 뒷쪽에 있는 파일이 목적파일이 됩니다.
-c 옵션
어떤 이유로 오로지 컴파일(compile) 작업만 하고 싶은 경우가 있습니다. 그럴 때는 다음과 같이 합니다.
$ gcc -c hello.c $
그 결과 만들어지는 화일은 전통적으로 hello.c 에서 .c 부분을 떼어내고 .o 를 붙인 화일입니다. 오브젝트 화일, 목적 화일이라고 하지요.
hello.o 라는 화일이 만들어집니다.
여러분은 C 언어로 조금이라도 복잡한 프로그램을 만들기 시작하면 여러 개의 소스로 나누어서 전체 프로그램을 짜게 됩니다. 그럴 때는 각 소스가 전체 기능에 기여하는 특정 기능의 함수들을 가지게 되고 오로지 한 녀석만 main 함수를 가집니다.
방법(1)
$ gcc -o baz foo.c bar.c
$ ./baz
방법(2)
$ gcc -c foo.c
$ gcc -c bar.c
또는
$ gcc -c foo.c bar.c
$ gcc -o baz foo.o bar.o
^^^^^^^^^^^
$ ./baz
두개 다 가능
gcc 는 정확히 말해서 C 컴파일러가 아닙니다. gcc 라는 실행 화일 자체는 "C 컴파일러를 돌리는 녀석"입니다.
더욱 더 정확히 말해보겠습니다.
C 언어는 기본적으로 두 가지 과정을 거쳐야만 실행화일을 만들어냅니다.
1. 컴파일 ( .c -------> .o ) 2. 링크 ( .o -------> 실행화일 a.out )
1. 과정을 실제로 맡는 것은 cc1 이라는 녀석이고 2. 과정을 맡는 것은 ld 라는 링커(linker)입니다.
gcc 는 상당히 편리한 도구로서 .c, .o 등의 화일명 꼬리말을 보고 적절하게 C 컴파일러와 링커를 불러다가 원하는 실행화일을 만들어줍니다. gcc 는 "컴파일러와 링커를 불러주는 대리인"입니다.
hello.c 를 괜히 어렵게 컴파일/링크해봅시다 ^^
$ gcc -c hello.c
^^^^^^^
$ gcc -o hello hello.o
-i 옵션
- include 문장에서 지정한 헤더 화일이 들어있는 곳을 정하는 옵션입니다. 아주 많이 사용되는 옵션 중 하나입니다.
#include <stdio.h> #include "my_header.h"
전자( <> 문자를 쓴 경우 )는 시스템 표준 헤더 디렉토리인 /usr/include를 기준으로 화일을 찾아서 포함시킵니다. 표준 디렉토리이지요.
후자( "" 문자를 쓴 경우 )는 지금 컴파일러가 실행되고 있는 현재 디렉토리를 기준으로 헤더 화일을 찾습니다.
이 두 디렉토리가 아닌 곳에 대해서는 명시적으로 -I<디렉토리> 로 정해줍니다.
$ gcc -c myprog1.c -I.. $ gcc -c myprog1.c -Iinclude
첫번째는 헤더 화일이 현재 소스 하위 디렉토리(..)에 있다는 뜻이며 두번째는 현재 디렉토리의 include라는 디렉토리에 들어있다는 뜻입니다.
-I 옵션은 얼마든지 여러번 쓸 수 있으며 주어진 순서대로 헤더 화일을 검색합니다.
- 유닉스에 있어 표준 헤더 화일 디렉토리는 /usr/include
/usr/include/linux --------------> /usr/src/linux/include/linux
/usr/include/asm --------------> /usr/src/linux/include/asm /usr/include/scsi --------------> /usr/src/linux/include/scsi
( 위에서 /usr/src/linux/include/asm은 사실 대부분의 경우 /usr/src/linux/include/asm-i386 이라는 디렉토리에 대한 링크입니다 )
라이브러리
C 프로그래밍을 하다 보면 반복적으로 사용하게 되는 함수들이 있기 마련이고 그것은 하나의 함수로 떼내어 어디에서든 유용하게 사용할 수 있도록 합니다. 이 함수가 극도로 많이 사용되는 경우에는 ``라이브러리라는 것으로 만들어두고 매번 컴파일해둘 필요없이 가져다 사용할 수 있도록 하지요.
라이브러리는 우리가 컴파일 과정을 거쳐서 만든 .o 화일을 한 곳에 통들어 관리하는 것에 불과합니다. 따라서 archive 를 의미하는 .a 라고 이름을 짓게 된 것이죠. 라이브러리는 ``도서관으로서 그냥 .o 를 무작위로 집어넣은 것은 아니고 당연히 도서관에는 소장하고 있는 책에 대한 목록(index)을 가지듯 포함되어 있는 .o 에 대한 인덱스(index)를 가지고 있습니다.
