OCaml 언어에 예전부터 관심이 많았었는데, 오랜만에 다시 보니 새롭군요. 그전에 배우면서 CVS에 올렸던 날짜를 보니 2002년이네요. 5년이 지났지만 실전에 아직 OCaml를 쓸 기회가 없다보니 조금 안쓰다보면 까먹어서 자꾸 다시 배우게 되네요.
그 전에 배울때는 OCaml에 포함된 기본 컴파일러만 make와 병행해서 사용했었는데, ocaml-event 라이브러리를 깔다보니 ocamlfind라는 실행파일을 통해서 인스톨하게 되어 있더군요. ocaml-event는 libevent의 ocaml에서 사용할수 있도록 하는 라이브러리입니다. FreeBSD ports중에 /usr/ports/devel/ocaml-findlib를 깔고, ocaml-event는 수동으로 소스를 컴파일하여 인스톨했습니다. /usr/ports/devel/ocaml-event 에 있지만 여기서 인스톨하면 ocamlfind에 등록이 이상하게 안되더군요…
ocaml-findlib를 깔면 중심 실행파일이 ocamlfind인데, 이 파일이 상당히 다양한 기능들은 가지고 있습니다. Ocaml 라이브러리/프로그램 인스톨, 언인스톨, 컴파일, 소스에서 문서 추출, 라이브러리 종속성 조회, 라이브러리 브라우징 등의 기능을 제공하며, 브라우징의 경우 Tk를 이용하여 X11 환경에서만 실행됩니다. 자세한 것은 man 페이지나 findlib user guide 문서를 참고하세요.
저는 컴파일 할때 ocamlc나 ocamlopt를 바로 호출하지 않고 ocamlfind를 통해서 호출한 방법만 설명드리도록 하겠습니다. ocamlc는 자바처럼 byte code 형태로 컴파일되고, ocamlopt는 타겟 CPU에서만 실행되는 native 형태로 컴파일이 됩니다. 한 ocaml 프로그램 내에서 byte code와 native code로 컴파일된것을 링크할수 없으므로 Makefile를 이용한다면 이를 따로따로 관리해야합니다. ocamlfind를 이용하면 cmo(byte code object)나 cmx(native object)를 지정하지 않아도 되서 Makefile의 크기가 많이 줄어드는것 같네요. 라이브러리 지정도 cma, cmxa를 따로 지정하지 않으며, 또한 라이브러리의 종속성을 자동으로 판단하여 라이브러리 링크 순서도 자동으로 판단해주는거 같습니다.
예전에 짰던 echo_server fork버전과 thread버전의 Makefile.old와 변경된 Makefile.new을 비교해보시면 ocamlfind가 유용하다는걸 느끼실수 있을겁니다. 그리고 Makefile.old는 native로 컴파일할려면 많은 부분 고쳐야하지만, Makefile.new에서는 한줄만 바꾸면 됩니다.
[CODE type=make]
# Makefile.old
# Copyright (c) 2002 Chun-Koo Park
OCAMLC=ocamlc
OCAMLCFLAGS=-thread
.SUFFIXES: .ml .mli .cmo .cmi
LIBS=unix.cma
EXEC=echo_server_fork echo_server_thread
all: $(EXEC)
clean:
rm -f *.cmo *.cmi *.cmx *.o $(EXEC) .depend
.mli.cmi:
$(OCAMLC) $(OCAMLCFLAGS) -c $<
.ml.cmo:
$(OCAMLC) $(OCAMLCFLAGS) -c $<
echo_server_fork: $@.cmo $(OBJS)
$(OCAMLC) -o $@ $(OCAMLCFLAGS) $(LIBS) $@.cmo
echo_server_thread: $@.cmo $(OBJS)
$(OCAMLC) -thread -o $@ $(OCAMLCFLAGS) unix.cma threads.cma $@.cmo
# vi:set noet:
[/HTML][/CODE]
[CODE type=make]
# Makefile.new
# Copyright (c) 2007 Chun-Koo Park
OCAMLC=ocamlfind ocamlc
#OCAMLC=ocamlfind ocamlopt
EXEC=echo_server_fork echo_server_thread
all: $(EXEC)
echo_server_fork: echo_server_fork.ml
$(OCAMLC) -o $@ -package unix -linkpkg $<
echo_server_thread: echo_server_thread.ml
$(OCAMLC) -o $@ -thread -package “threads unix” -linkpkg $<
clean:
rm -f *.cmo *.cmi *.cmx *.o $(EXEC) .depend
# vi:set noet:
[/HTML][/CODE]
위 Makefile 들은 FreeBSD에서 BSD Parallel Make에서 테스트된 파일들입니다. 마지막 줄은 vim에서 탭을 자동으로 공백으로 확장하지 않도록 하는 명령입니다. (noexpandtab)
findlib에 포함된 make_wizard를 사용하면 위저드 형태로 7단계로 Makefile를 만들어줍니다. 생성되는 Makefile이 상당히 길고, 생성된 Makefile은 위저드로 편집이 불가능하기 때문에 사용이 꺼려지긴 합니다. 하지만, 참고할만한 마땅한 Makefile이 별로 없었는데 소스만 봐도 큰 도움이 될듯하네요. 다음은 make_wizard를 실행한 화면입니다.