강좌 글을 올릴 때면, 이해를 돕기 위해 가급적 샘플 프로그램을 올리려 노력합니다. 그러나 문제는 제 글을 보시는 분의 환경이 저와 다르기 때문에 Makefile이 있다고 하더라도 컴파일부터 안 되는 경우가 발생합니다. Microsoft(이하 MS) DOS나 Windows에서 프로그램을 작성했을 때에는 이런 불편이 없었습니다만, 리눅스에서는 환경에 따라 컴파일이 안 되는 경우가 많습니다.

사족(蛇足)

오늘 주제는 이 이야기가 아니지만 제가 MS에서 개발하다가 리눅스로 넘어오면서 매우 고생한 기억이 있어서 사족입니다만 신세한탄하듯 적겠습니다.

리눅스에서는 같은 프로그램 소스인데, 어느 PC에서는 잘 컴파일되고 실행이 되는데, 같은 리눅스인데도 다른 PC에서 문제가 발생하는 가장 큰 이유는 gcc 버전이 다르고, 같더라도 리눅스 배포 버전이 다르거나 어떻게 설치했느냐에 따라 문제가 발생합니다. 비단 저의 샘플 프로그램만 그런 것이 아닙니다. 대표적인 예가 QT인데, 포럼에 올라오는 글을 보면, 프로그램에 대한 말씀 보다는 설치에 대한 질문이 참으로 많습니다. 그러나 MS 같은 경우는 사용하는 언어와 툴이 같다면 이런 경우가 거의 없습니다. 이 이유를 생각해 보면 사용자 별로 환경이 다른 것도 있습니다만, 개발 툴이나 라이브러리가 컴파일러를 함께 제공하지 않기 때문이라고 생각합니다.

예를 들어 같은 버전의 QT를 설치하면서도 어떤 분은 되고, 어떤 분은 며칠을 밤을 세도 안되는 경우가 있습니다. 만일 QT가 디자이너나 라이브러리만 제공하는 것이 아니라 MS의 개발툴에서처럼 컴파일러까지 함께 설치된다면, 설치하는 것에 정력을 낭비하는 그런 소모적인 일이 적지 않나 생각됩니다.

쉽게 생각하셔서 MS사의 비주얼 C/C++나 요즘 한창 뜨고 있는 .Net 개발툴 같은 경우, 한번의 설치로 IDE, 디자인너, 라이브러리, 샘플, 도움말과 함께 컴파일러까지 모두 설치되기 때문에, 개발툴이 설치 안 되서 밤을 세는 경우가 적습니다. 바로 학습 모드로 전환할 수 가 있죠.

그러나 QT같은 경우 이게 안 됩니다. 오죽하면 선택할 수 있는 라이브러리가 많은 것도 문제라는 말이 나올 정도입니다. 너무 많으니까 통일이 안되는 것이죠. 그리고 처음 입문하는 개발자는 방황하게 된다는 것이죠.

gccmakedep 가 없답니다.

사족이 매우 길었습니다. 이제 본론부터 말씀드리겠습니다. 가끔 제가 올려 드린 샘플을 컴파일하려는데, 컴파일부터 에러가 발생한다는 말씀을 받을 때가 있습니다. 그래서 make 하시기 전에,

]$ make dep

를 먼저 실행하셔서, Makefile의 내용을 컴파일에 필요한 파일 정보를 갱신하라는 말씀을 드립니다. make dep를 제대로 실행되었다면, 그리고 Makefile을 열어 보시면 아래와 같이 관련 파일과 위치가 정리되어 나열됩니다. 이후에 make를 실행하면, 이 정보를 이용하여 컴파일하고 링크를 실행하게 됩니다.

dep :
        gccmakedep $(INCLUDEDIRS) $(SRCS)

# DO NOT DELETE
sample.o: sample.c /usr/include/stdio.h /usr/include/features.h \
  /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
  /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
  /usr/lib/gcc/i386-redhat-linux/4.1.2/include/stddef.h \
  /usr/include/bits/types.h /usr/include/bits/typesizes.h \
  /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
  /usr/include/bits/wchar.h /usr/include/gconv.h \
  
                     ....

그런데 문제는 아래와 같이 gccmakedep 명령을 못 찾았답니다.

]$ make dep
gccmakedep -I. sample.c gx.c gxbmp.c gxbdf.c fontinfo.c ksc5601.c
make: gccmakedep: 명령을 찾지 못했음
make: *** [dep] 오류 127
]$

참 황당합니다. 샘플을 올린 사람은 잘되니까 올렸을 텐데, 에러가 나네요. 그럼 gccmakedep를 설치해야 하는데, 몸이 피곤하면 짜증이 나려 합니다.

그러나 결론부터 말씀드리면 gccmakedep를 따로 찾아서 설치하실 필요가 없습니다. gcc 에도 gccmakedep 기능이 있다네요. 그래서 Makefile에서 파일 의존 관계를 갱신하기 위해 아래와 같이 gccmakedep를 사용하도록 하는 대신에 gcc 를 이용하시면 됩니다.

즉,

dep :
        gccmakedep $(INCLUDEDIRS) $(SRCS)

대신에 gcc 에 -M 옵션을 주어 아래와 같이 Makefile을 갱신할 수 있습니다.

dep :
        gcc   -M      $(INCLUDEDIRS)  $(SRCS) > .depend

이제 gccmakedep를 구하러 다니실 필요가 없습니다. 또 Makefile 안에 구질구질하게 파일 의존 관계를 적지 않고, .depend 파일을 생성하고 그 파일 안에 정리하도록 했습니다. 이제 make를 실행할 때면 .depend를 포함하여 실행하도록 하면 되겠습니다. 그래서 Makefile 하단에 아래와 같이 포함하는 내용을 추가합니다.

ifeq (.depend,$(wildcard .depend))
include .depend
endif

여기서 상기해 보면, gcc 버전이 너무 낮아서 -M 옵션을 처리하지 못한다면, 역시 gcc -M 이 에러를 발생하겠지요. ^^ 여하튼 gcc -M 을 이용하면서 gxLib의 새로운 Makefile의 내용을 올리면서 이번 글을 마치겠습니다. 매일매일 건강하세요. ^^

#CC = mipsel-linux-gcc
CC = gcc

TARGET      = sample
OBJS        = sample.o gx.o gxbmp.o gxbdf.o fontinfo.o ksc5601.o
SRCS        = $(OBJS:.o=.c)
INCLUDEDIRS += -I.
LIVDIRS     +=
CFLAGS      = $(INCLUDEDIRS) -W -Wall -O2
LDFLAGS     = $(LIVDIRS)

$(TARGET): $(OBJS)
   $(CC) -lm -o $(LDFLAGS) $@ $^

.c.o:
   $(CC) -c $(CFLAGS) $<

dep :
   $(CC) -M $(INCLUDEDIRS) $(SRCS) > .depend

clean:
   rm -f *.bak
   rm -f *.map
   rm -f *.o
   rm $(TARGET)
   @echo "파일을 삭제했습니다."

distclean: clean
   rm -rf .depend

ifeq (.depend,$(wildcard .depend))
include .depend
endif