C

거믄마루 2012. 11. 3. 09:00

프리랜서로 SI 프로그램을 작성하는 일을 주로 하다 보니...


데이터베이스를 다루는 프로그램을 많이 작성한다.


개인적으로는 Oracle 의 OCI API 방식의 개발을 선호하지만

현실은 시궁창이라...

만지기는 싫지만 어쩔 수 없이 프래컴파일러 또는 전처리기 인 Pro*C 를 다루어야 할 때가 있다.


그런데... 기존에 작성된 make 스크립트를 보면 정말 그 조악하고 복잡함에 입이 벌어진다.


그래서 여기서 Oracle Pro*C 를 사용하는 프로그래머들을 위해서 작은 팁을 선사하려 한다.


일단 .SUFFIXES 라는 것을 사용해서 프로그램 확장자간의 의존도를 정해준다.


기본적으로 .SUFFIXES 규칙은 아무것도 지정하지 않으면 .SUFFIXES 는 다음과 같다.


.SUFFIXES: .out .a .ln .o .c .cc .C .cpp .p .f .F .r .y .l .s .S .mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo .w .ch .web .sh .elc .el


.pc 확장자는 없기때문에 프로그램을 어떻게 다루어야 할지 모르므로 컴파일이 되지 않는 것이다.

make 스크립트 파일에서 다음과 같이 .SUFFIXES 규칙을 추가하자.


.SUFFIXES: .c .pc

즉 .pc 파일로 .c 파일을 만든다는 ... 그런 의미의 규칙을 위와 같이 적는 것이다.

이렇게 하면 .SUFFIXES 는 내부규칙에 위의 규칙을 추가하여 다음과 같이 변경된다.


 .SUFFIXES: .out .a .ln .o .c .cc .C .cpp .p .f .F .r .y .l .s .S .mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo .w .ch .web .sh .elc .el .c .pc


C++ 도 다음과 같이 추가해보자


.SUFFIXES: .cpp .pc


마찬가지로 다음과 같이 .SUFFIXES 가 변경된다.


 .SUFFIXES: .out .a .ln .o .c .cc .C .cpp .p .f .F .r .y .l .s .S .mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo .w .ch .web .sh .elc .el .c .pc .cpp .pc


계속 규칙이 추가되었음을 알 수 있다.


그러나 당연하겠지만 .SUFFIXES 규칙만 추가한다고 컴파일이 가능해지는 것은 아니다. 다음과 같이 내부규칙을 추가한다.


.SUFFIXES: .c .pc

PROC = proc
COMPILE.pc = ${PROC} ${PROCFLAGS} 

.pc.c:
        ${COMPILE.pc} ${addprefix include=, ${INCLUDES}} iname=$< oname=$@


주의할 점은 ${COMPILE.pc} 앞의 공백은 탭문자 하나이상으로 시작되어야 한다.  물론 이글을 읽는 분들중 그런것을 모르는 분들은 없을 것이라 본다.


${addprefix include=, ${INCLUDES}} 은 그 원리가 이전 게시물에 나왔던 것이다. Pro*C 는 인클루드하는 옵션을 "include=헤더파일" 식으로 지정하는데 INCLUDES 에 헤더파일 패스들을 지정하기만 하면 여기서 자동으로 앞에 include= 을 붙여주므로 매우 간단하게 헤더패스를 처리할 수 있다.  무슨 전매특허라도 내야한다는 생각이 든다... ^^


그럼 ora.pc 를 작성하였고 이를 ora-test 라는 프로그램으로 실제로 컴파일하는 예제를 보이겠다.


all: ora-test

.SUFFIXES: .c .pc

PROC = proc
COMPILE.pc = ${PROC} ${PROCFLAGS} 

.pc.c:
        ${COMPILE.pc} ${addprefix include=, ${INCLUDES}} iname=$< oname=$@

ora-test: INCLUDES += ${ORACLE_HOME}/precomp/public
ora-test: INCLUDES += ${ORACLE_HOME}/rdbms/public
ora-test: INCLUDES += ${ORACLE_HOME}/network/public
ora-test: PROCFLAGS += lines=yes
ora-test: LDFLAGS += -L ${ORACLE_HOME}/lib
ora-test: LDLIBS += -l clntsh
ora-test: ora.o


PROCFLAGS 의 활용예를 보이기 위해서 lines=yes 라는 Pro*C 옵션을 추가해두었다. 

참고로 lines=yes 옵션을 켜면 gdb 등에서 쉽게 Pro*C 를 디버깅할 수 있게 된다.

디폴트가 아니므로 반드시 위와 같이 켜야 한다.


자 이제 지옥에서 벗어나라...


그리고 팁으로 한가지 더! ㅋ


.pc 파일을 전처리하면서 .c 파일이 생긴다. clean 시에 이런 .c 파일들만 지울 수 있다면 코드를 관리하기 훨씬 쉬워질 것이다.

다음과 같이 ora-clean 규칙을 정의해서 사용해보라~


ora-clean:
        -for i in `ls *.pc | perl -p -e 's/\.pc//g'`; do ${RM} $$i.c; done


이제 make ora-clean 이라고만 명령을 내리면 .c 파일만 말끔하게 제거될 것이다.

동작원리는 숙제다... 각자 연구해보길~


그럼 오늘은 여기까지...