이번 글은 Tcl의 구문을 이용해 Makefile과 비슷한 스크립트를 기술하는 방법에 대해서 간단히 구현해 봅니다.
make 프로시져
아래의 코드는 make룰을 정의하기 위한 프로시져입니다. make.tcl 등의 이름으로 저장하세요.
proc make {target source procedure} {
if {[regexp {^\. } $target]} {
proc $target {name} [format {
set targetsuffix %s
set sourcesuffix %s
if {
! [file exists $name$targetsuffix] ||
[file mtime $name$sourcesuffix] > [file mtime $name$targetsuffix]
} {
eval {%s}
}
} $target $source $procedure]
} else {
proc $target {} [format {
set target %s
foreach source {%s} {
regexp {^(. +)(\. [a-z]+)$} $source fullname name suffix
if {[info procs $source] ! = ""} {
$source
} elseif {[info procs $suffix] ! = ""} {
$suffix $name
}
if {
! [file exists $target] ||
! [file exists $source] ||
[file mtime $source] > [file mtime $target]
} {
eval {%s}
}
}
} $target $source $procedure]
}
}
사용법
앞의 코드를 읽어 들이면(source), 아래와 같이 Tcl의 구문을 이용해 Makefile의 기능과 비슷한 동작을 할 수 있습니다.
source make.tcl
make target.exe {source1.obj source2.obj} {
exec ilink32 -Tpd -c -x -Lc:\borland\bcc55\lib c0d32.obj+source1.obj+source2.obj, target.exe, , import32.lib+cw32.lib,
}
make . obj . c {
exec bcc32 -c -tWD -Ic:\borland\bcc55\include -o$name.obj $name.c
}
target.exe
make 프로시져는 make의 룰을 정의합니다. 첫 번째 인자로 타겟(target) 파일의 이름을, 두 번째 인자는 타겟이 의존하는 원시파일, 세 번째 인자는 타겟을 구축하기 위한 커맨드를 입력합니다. 두번째 인자는 복수의 파일명을 포함하며 Tcl 리스트로 위와같이 구현가능합니다. 또 두번째 인자와 세번째 인자는 확장자를 상관하지 않습니다. 개별 파일명에 정의된 make룰이 존재하지 않는 경우, 확장자로 정의된 룰이 적용됩니다. 세번째 인자의 커맨드는 원시파일이 하나라도 새롭게 갱신 된 것이 있을 때 실행됩니다. 위의 Tcl로 구현된 Makefile은 실제 아래의 Makefile과 동일한 결과를 가져옵니다.
all: target.exe
taget.exe: source1.obj source2.obj
ilink32 -Tpd -c -x -Lc:\borland\bcc55\lib c0d32.obj+source1.obj+source2.obj, target.exe, , import32.lib+cw32.lib,
. c.obj:
bcc32 -c -tWD -Ic:\borland\bcc55\include -o$*.obj $*. c