각 컴파일러 Make 방법

admin의 아바타

각 컴파일러별로 컴파일 하는 방법에 대해서 짚어보도록 하겠습니다.

gcc

main함수를 가지는 실행 프로그램을 만들 경우

Makefile은 이렇습니다. (아래의 Makefile은 sample.c을 컴파일 하고, sample을 만듭니다.)

CC      = gcc
CFLAGS  = -O2 -I/usr/local/include
LIBS    = -L/usr/local/lib -ltcl8.4 -lm
.c.o:
   $(CC) -c $(CFLAGS) $*.c
sample: sample.o
   $(CC) -o $@ sample.o $(LIBS)

-I와 -L에는 각각 tcl.h가 있는 디렉토리와 libtcl 8.4.so가 있는 디렉토리를 지정합니다. SunOS, FreeBSD등 일부의 UNIX에서는 「libtcl84.a」가 있을수도 있어, 이 경우는 「-ltcl8.4」대신 「-ltcl84」이라고 지정합니다. 몇개의 UNIX 계열 OS에서는, 링크타임에 「-lm」등 이외의 몇개 라이브러리도 링크할 필요가 있습니다. 예를 들면 Solaris라면「-lnsl -lsocket」, Linux라면 「-ldl」, HP-UX라면 「-ldld」입니다.

Tk을 사용하고, main함수를 가지는 실행 프로그램을 만들 경우

CC      = gcc
CFLAGS  = -O2 -I/usr/local/include -I/usr/X11R6/include
LIBS    = -L/usr/local/lib -ltk8.4 -ltcl8.4 \ 
          -L/usr/X11R6/lib -lX11 -lm
.c.o:
   $(CC) -c $(CFLAGS) $*.c
sampletk: sampletk.o
   $(CC) -o $@ sample.o $(LIBS)

이 경우에는 Tk의 라이브러리와 X윈도우 시스템 라이브러리를 링크할 필요가 있습니다.

공유 라이브러리(library)를 만들 경우

CC      = gcc
SHLD    = gcc -shared
CFLAGS  = -O2 -fPIC -I/usr/local/include
LIBS    =
.c.o:
   $(CC) -c $(CFLAGS) $*.c
libsample.so: sample.o
   $(SHLD) -o $@ sample.o $(LIBS)

공유 라이브러리를 만들 때 compiler나 linker의 옵션은 OS의 컴파일러에 따라 달라집니다. 여기에서는 만국 공통 컴파일러인 gcc을 사용하고 있으므로, 어느 OS에서도 거의 동일합니다. 보통 gcc을 사용할 경우는, 컴파일러의 옵션에 「-fPIC」를 지정해주고, linker의 옵션에 「-shared」를 지정해줍니다. 휴렛 펙커드의 HP-UX등 일부의 OS에서는, -shared에서 연동하는 모든 object module이 반드시 로케이션(location) 독립이 (-fPIC을 붙여서 컴파일 컴파일 한 것) 아니면 안됩니다. 또한, 완성되는 공유 라이브러리의 확장자는, 그 OS의 표준에 준 할 필요가 있습니다. 대부분의 OS(SunOS, Solaris, IRIX, Linux, FreeBSD등)는 위와 같이 「.so」 그러나, HP-UX의 「.sl」과 같은 예외도 있습니다. 한편, gcc가 아닌, 시스템(system)의 cccompiler를 사용할 경우는 컴파일러 옵션을 해당 메뉴얼에서 찿아보시면 됩니다. 일례를 들면, 실리콘 그래픽스의 IRIX에서는 컴파일러 옵션의 linker에서「-shared」를 빼줍니다. FreeBSD는 cccompiler의 스위치(switch)는 gcc과 같아서 linker의 옵션을 「-ld -Bshareable -x」라고 지정해줍니다. HP-UX로는 컴파일러 옵션에 「+z」 또는 「+Z」를 붙입니다. Linux의 cccompiler는 gcc 컴파일러이기 때문에, 어느쪽을 사용해도 동일합니다.

Visual C++

이번은, Microsoft Visual C++의 CL.EXE와 LINK.EXE를 사용하며, NMAKE에서 사용가능한 Makefile의 예입니다.

main함수를 가지는 실행 프로그램을 만들 경우

여기에서는 sampletk.c을 컴파일하고, sampletk.exe를 만듭니다.

CC   = cl
TCLROOT   = C:\TCL
CFLAGS   = /nologo /O2 /I"$(TCLROOT)\include"
LDFLAGS   = /nologo
LIBS   = "$(TCLROOT)\lib\tcl84.lib" "$(TCLROOT)\lib\tk84.lib"
.c.obj:
   $(CC) $(CFLAGS) -c $*.c
sampletk.exe: sampletk.obj
   $(CC) /o $@ $(LDFLAGS) sampletk.obj $(LIBS)

위의 예로 만들어지는 프로그램은, 통합 개발 환경에서 말하는 것의 「콘솔 어플리케이션(Console Application)」이 됩니다. Tk을 사용하지 않을 경우에는 tk84.lib을 링크하지 않아도 됩니다.

Tk을 사용하고, winMain함수를 가지는 실행 프로그램을 만들 경우

Makefile은 아래와 같습니다. Tcl/Tk 인터프리터의 소스 파일인 winMain.c을 개조해서 다른 버전의 wish를 만들 경우는 아래와 같이 됩니다. 여기에서는 sampletk.c을 컴파일하고, sampletk.exe를 만듭니다.

CC   = cl
TCLROOT   = C:\TCL
CFLAGS   = /nologo /O2 /I"$(TCLROOT)\include"
LDFLAGS   = /nologo /SUBSYSTEM:WINDOWS
LIBS   = "$(TCLROOT)\lib\tcl84.lib" "$(TCLROOT)\lib\tk84.lib"
.c.obj:
   $(CC) $(CFLAGS) -c $*.c
sampletk.exe: sampletk.obj
   $(CC) /o $@ $(LDFLAGS) sampletk.obj $(LIBS)

dynamic link library(DLL)을 만들 경우

Makefile은 다음과 같습니다. 여기에서는 sample.c을 컴파일하고, libsample.dll 을 만듭니다.

SHLD   = cl /LD
TCLROOT   = C:\TCL
CFLAGS   = /nologo /O2 /I"$(TCLROOT)\include"
LDFLAGS   = /nologo
LIBS   = "$(TCLROOT)\lib\tcl84.lib" "$(TCLROOT)\lib\tk84.lib"
.c.obj:
   $(CC) $(CFLAGS) -c $*.c
libsample.dll: sample.obj
   $(SHLD) /o $@ $(LDFLAGS) sample.obj $(LIBS)

CL.EXE의 DLL을 만드는 옵션은 「/LD」입니다.

Borland C++

Borland C++은 무료 컴파일러가 제공되므로 http://borland.co.kr/products/downloads/download_cbuilder.html# 에서 쉽게 구하실수 있습니다. Tcl/Tk의 확장은 BC++에서도 쉽게 할수 있습니다. 단, Tcl/Tk 인터프리터에 대해서 딸려오는 라이브러리가 Visual C++용이므로, BC++용으로의 변환과정이 필요합니다.

우선, BC++의 유틸리티 implib을 사용하여, Tcl과 Tk의 BC++용 라이브러리를 만듭니다.

implib -a tcl84bcc.lib C:\tcl\bin\tcl84.dll
implib -a tk84bcc.lib C:\tcl\bin\tk84.dll

-a 는, VC++ compiler가

__CDECL

의 함수이름의 머리에 자동적으로 「_」를 붙이는 처리에 호환성을 가지게 하는 스위치로 필수적입니다. 변환한후 이 tcl84bcc.lib 와 tk84bcc.lib를 적당한 디렉토리, 여기에서는 C:\tcl\lib에 둡니다.

main함수를 가지는 실행 프로그램을 만들 경우

TCLROOT    = C:\TCL
CC         = bcc32
CFLAGS     = -O2 -I"$(TCLROOT)\include"
LIBS       = "$(TCLROOT)\lib\tcl84bcc.lib" "$(TCLROOT)\lib\tk84bcc.lib"
.c.obj:
   $(CC) $(CFLAGS) -c $?
sampletk.exe: sampletk.obj
   $(CC) -e$@ sample.obj $(LIBS)

dynamic link library(DLL)을 만들 경우

Makefile은 아래와 같습니다. 한편, BC++에서는 tcl.h에서 정의되어 있는 매크로 DLLEXPORT 가 통하지 않으므로,

__declspec(dllexport)

이라고 VC++에 맞게 쓸 필요가 있습니다.

TCLROOT   = C:\TCL
CC   = bcc32
SHLD   = bcc32 -tWD
CFLAGS   = -O2 -I"$(TCLROOT)\include"
LIBS   = "$(TCLROOT)\lib\tcl84bcc.lib" "$(TCLROOT)\lib\tk84bcc.lib"
.c.obj:
   $(CC) $(CFLAGS) -c $*.c
libsample.dll: sample.obj
   $(SHLD) -e$@ sample.obj $(LIBS)