Automatic Variables

recipe 실행 시 자동으로 설정되는 변수들입니다. 기본적으로 1 문자 변수인데 뒤에 D 가 붙은 것은 Directory 부분을, F 가 붙은 것은 File 부분을 나타냅니다.

automatic 변수는 eval 함수로 재정의해 사용할 수 없습니다.

$@ , $(@D) , $(@F)

타겟 파일 이름을 나타냅니다.

foo/bar/zoo.o :
    @echo $@ : $(@D) : $(@F)

######  실행 결과  ######

foo/bar/zoo.o : foo/bar : zoo.o

$< , $(<D) , $(<F)

prerequisite 리스트에서 첫 번째 파일을 나타냅니다. 소스 파일을 컴파일 해서 오브젝트 파일을 만들때 $< 를 사용해야지 $^ 를 사용하면 헤더 파일까지 컴파일됩니다.

main : aaa/bbb/foo.o ccc/ddd/bar.o eee/fff/zoo.o
    @echo $< : $(<D) : $(<F)

.DEFAULT: ;

######  실행 결과  ######

aaa/bbb/foo.o : aaa/bbb : foo.o

-------------------------------------------

lib/%.o: lib/%.c lib/%.h
    @echo $< : $(<D) : $(<F)

%.c %.h: ;

######  실행 결과  ######

sh$ make lib/foo/bar.o
lib/foo/bar.c : lib/foo : bar.c

$^ , $(^D) , $(^F)

$+ , $(+D) , $(+F)

prerequisites 에 존재하는 파일 리스트 전체를 나타냅니다. $^ 는 중복되는 파일이 있을 경우 제거되는데 반해, $+ 는 중복을 포함하여 있는 그대로 출력합니다. 링크 시에는 라이브러리가 중복되어 나타날 수 있는데 그때 사용할 수 있습니다. 여기에 order-only prerequisites 은 포함되지 않습니다.

main : xxx/yyy/libfoo.a aaa/bbb/libbar.a xxx/yyy/libfoo.a     
    @echo $^                              # xxx/yyy/libfoo.a 는 중복되는 파일
    @echo $(^D) : $(^F)
    @echo
    @echo $+
    @echo $(+D) : $(+F)

.DEFAULT: ;

######  실행 결과  ######

xxx/yyy/libfoo.a aaa/bbb/libbar.a         # '$^' 는 xxx/yyy/libfoo.a 중복이 제거된다.
xxx/yyy aaa/bbb : libfoo.a libbar.a

xxx/yyy/libfoo.a aaa/bbb/libbar.a xxx/yyy/libfoo.a       # '$+' 는 있는 그대로 출력된다.
xxx/yyy aaa/bbb xxx/yyy : libfoo.a libbar.a libfoo.a

$? , $(?D) , $(?F)

prerequisites 리스트에서 타겟 파일보다 newer 파일이 있을 경우 설정됩니다.

# prog 파일보다 xxx/yyy/zoo.o 파일이 최신이라면
prog : aaa/bbb/foo.o ccc/ddd/bar.o xxx/yyy/zoo.o
    @echo $?
    @echo $(?D) : $(?F)

.DEFAULT: ;

######  실행 결과  ######

xxx/yyy/zoo.o               # aaa/bbb/foo.o ccc/ddd/bar.o 파일은 제외된다.
xxx/yyy : zoo.o

$* , $(*D) , $(*F)

pattern rule 에서 stem ( % 패턴에 해당하는 부분 ) 을 나타냅니다.

lib/%.o: lib/%.c
    @echo $* : $(*D) : $(*F)

%.c: ;

######  실행 결과  ######

sh$ make lib/foo/bar/zoo.o
foo/bar/zoo : foo/bar : zoo

다음은 활용하여 make 변수값을 조회하는 예입니다.

AA := 100

print-%:
    @echo $* = $($*) from $(origin $*)

######  실행 결과  ######

sh$ make print-AA            # 변수 AA 값을 조회
AA = 100 from file

sh$ BB=200 make print-BB
BB = 200 from environment

sh$ make print-CC
CC = cc from default

sh$ make print-DD DD=300
DD = 300 from command line

$%

타겟 파일이 archive 파일( .a )의 멤버일 경우 설정됩니다 ( ( ) 안에 들어있는 파일 ). 이때 $@ 값은 archive 파일 이름이 됩니다.

이 변수를 pattern rule 의 stem 을 나타내는 변수로 사용하는 것이 더 좋아 보이기는 하지만 원래 make 초기에는 implicit rule 로 pattern rule 대신에 suffix rule 이 사용됐기 때문에 그런것 같습니다.

libfoo.a(aaa/bbb/foo.o ccc/ddd/bar.o) :
    @echo $% : $(%D) : $(%F)
    @echo $@

######  실행 결과  ######

sh$ make                           
aaa/bbb/foo.o : aaa/bbb : foo.o     # 디폴트 타겟은 첫 번째 멤버 파일이 된다.
libfoo.a                            # '$@' 값은 archive 파일 이름 

sh$ make 'libfoo.a(aaa/bbb/foo.o)'  # 같은 결과
aaa/bbb/foo.o : aaa/bbb : foo.o
libfoo.a

sh$ make 'libfoo.a(ccc/ddd/bar.o)'
ccc/ddd/bar.o : ccc/ddd : bar.o
libfoo.a

$|

rule 정의에서 | 문자 뒤에 오는 order-only prerequisite 리스트를 나타냅니다.
이 변수는 따로 $(|D), $(|F) 변수가 없습니다.

main : aaa bbb ccc | foo bar zoo
    @echo $|

.DEFAULT: ;

######  실행 결과  ######

foo bar zoo