Special Variables

CURDIR

make 실행시 현재 디렉토리 경로를 나타냅니다.

$(info CURDIR : $(CURDIR))

# recursive make 에서 CURDIR 값을 출력할 경우
CURDIR : /home/mug896/make
make[1]: Entering directory '/home/mug896/make/dir1'
CURDIR : /home/mug896/make/dir1
make[1]: Leaving directory '/home/mug896/make/dir1'

.DEFAULT_GOAL

make 명령 실행 시에 아무런 타겟 인수를 주지 않으면 기본적으로 makefile 작성시 제일 위에 위치한 explicit rule 이 실행됩니다. 만약에 이것을 변경하고 싶으면 .DEFAULT_GOAL 변수를 설정하면 됩니다.

foo:
    @echo target: $@

bar:
    @echo target: $@

.DEFAULT_GOAL := bar   # foo 타겟 대신에 bar 타겟이 실행된다.

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

target: bar

.INCLUDE_DIRS

include 지시자를 이용해 makefile 을 include 할때 파일명이 / 로 시작하지 않으면 현재 디렉토리로부터의 경로를 검색한 후 없을 경우 다음 순으로 디렉토리를 검색합니다.

  1. make 명령 라인에서 -I or --include-dir 옵션으로 지정한 디렉토리
  2. .INCLUDE_DIRS 변수에 있는 디렉토리
$(info $(.INCLUDE_DIRS))

/usr/include /usr/local/include /usr/include

.LIBPATTERNS

make 이 라이브러리 파일을 검색할 때 사용하는 파일 패턴입니다. 디폴트 값은 lib%.so lib%.a 이므로 만약에 prerequisites 으로 -lm 을 설정하였다면 libm.so libm.a 순으로 찾게 됩니다.

$(info $(.LIBPATTERNS))

######  실행 결과  ######
lib%.so lib%.a

MAKECMDGOALS

make 명령을 실행할 때 명령 라인에서 설정한 타겟 이름이 들어있는 변수입니다. 옵션이나 변수 정의는 포함되지 않습니다. 조건 지시자를 이용해 선택적으로 include 문을 실행시키거나 sub-make 실행시 인수를 전달때, argument processing 등에 활용할 수 있습니다.


$(info $(MAKECMDGOALS))

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

# -rR --keep-going 같은 옵션과 release=1 변수 정의는 포함되지 않는다.
sh$ make -rR --keep-going foobar release=1
foobar

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

.DEFAULT_GOAL := all

foo : ;@echo 2222222222
all : ;@echo 1111111111

$(info $(MAKECMDGOALS))

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

sh$ make      # .DEFAULT_GOAL 값은 포함되지 않는다.

1111111111

sh$ make all
all
1111111111

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

# 실행할 타겟이 clean 일 경우 *.d 파일은 삭제되므로 include 할 필요가 없다.
ifneq "$(MAKECMDGOALS)" "clean"
  include $(OBJS:.o=.d)
endif

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

TOPTARGETS := all clean

SUBDIRS := $(wildcard */)

$(TOPTARGETS) : $(SUBDIRS)
$(SUBDIRS) :
    $(MAKE) -C $@ $(MAKECMDGOALS)   # sub-make 실행시 인수를 전달할 때

.PHONY: $(TOPTARGETS) $(SUBDIRS)

MAKEFILE_LIST

make 명령에 의해 처리되는 makefile 의 목록이 저장되는 변수입니다.
include 지시자에 의해 makefile 파일이 include 될 때마다 변수에 추가 됩니다.

$(info 1: $(MAKEFILE_LIST))
include inc1.mk
$(info 2: $(MAKEFILE_LIST))
include inc2.mk
$(info 3: $(MAKEFILE_LIST))
include inc3.mk
$(info 4: $(MAKEFILE_LIST))

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

1:  Makefile    # top makefile
2:  Makefile inc1.mk
3:  Makefile inc1.mk inc2.mk
4:  Makefile inc1.mk inc2.mk inc3.mk

MAKEFLAGS

make 명령 실행시 명령 라인에서 사용한 옵션이 1 문자 플래그로 저장됩니다. --directory (-C), --file (-f), --old-file (-o), --new-file (-W) 옵션은 예외로 저장되지 않습니다. 기본적으로 변수가 export 되므로 sub-make 에도 적용됩니다.


$(info $(MAKEFLAGS))

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

sh$ make -k -s --no-builtin-rules --no-builtin-variables
krRs     # 1 문자 플래그로 저장된다.
--------------------------------------------------------

# 특정 옵션은 1 문자 플래그로 저장되지 않으므로 값을 체크할 때는 filter-out 함수를 사용합니다.
sh$ make -k -s --no-print-directory --trace
ks --trace --no-print-directory

# 먼저 '--' 로 시작하는 옵션을 제거
ifeq "$(findstring s,$(filter-out --%,$(MAKEFLAGS)))" "s"
    quiet = silent_
endif
--------------------------------------------------------

# 만약에 sub-make 에는 전달되지 않게 하려면 다음과 같이하면 됩니다.
subsystem:
    $(MAKE) -C subdir MAKEFLAGS=

옵션을 명령 라인에서 설정하지 않고 Makefile 내에서 직접 설정해 사용할 수도 있습니다.
( 이때는 1 문자로 변경되지 않고 문자 그대로 저장됩니다. )

MAKEFLAGS += -rR

MAKELEVEL

recursive make 에서 sub-make 의 depth 정도를 나타냅니다. top makefile 에서는 0 이 되고 첫 번째 sub-make 에서는 1 이 되는데 여기서 또 sub-make 이 실행되면 2 가 됩니다.

# '[1]' 안의 숫자는 MAKELEVEL 을 나타냄
make[1]: Entering directory '/home/mug896/tmp/foo'
. . .
make[2]: Entering directory '/home/mug896/tmp/foo/bar'
. . .
make[2]: Leaving directory '/home/mug896/tmp/foo/bar'
. . .
make[1]: Leaving directory '/home/mug896/tmp/foo'

MAKEOVERRIDES

make 명령 라인에서 설정한 변수값은 기본적으로 makefile 에서 설정한 변수값에 우선해서 사용되는데 MAKEOVERRIDES 변수는 이와 같은 기능이 sub-make 에도 동일하게 적용되게 합니다. 따라서 만약에 sub-make 에서는 명령 라인에서 설정한 변수값이 사용되지 않게 하려면 다음과 같이 하면 됩니다.

MAKEOVERRIDES =
                                     # 이 변수는 다음과 같이 사용할 수는 없습니다.
foo :                                foo :
    @$(MAKE) -C subdir                   @$(MAKE) -C subdir MAKEOVERRIDES=

MAKE_RESTARTS

remake 에의해 make 이 재실행될 경우 값이 설정됩니다.

ifdef MAKE_RESTARTS
  $(info defined !!!)
else
  $(info not defined)
endif

$(info top MAKE_RESTARTS: $(MAKE_RESTARTS))

include mod_1.mk

mod_1.mk :
    @echo '$$(info $@ MAKE_RESTARTS: $$(MAKE_RESTARTS))' > $@
    @echo include mod_2.mk >> $@

mod_2.mk :
    @echo '$$(info $@ MAKE_RESTARTS: $$(MAKE_RESTARTS))' > $@

$(info --------------------------- )

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

sh$ ls                        # 현재 include 파일은 존재하지 않는 상태.
Makefile

sh$ make                      # remake 에의해 make 이 3 번 실행된다.
not defined                   # 첫 번째 실행
top MAKE_RESTARTS: 
--------------------------- 
defined !!!                   # 두 번째 실행
top MAKE_RESTARTS: 1
mod_1.mk MAKE_RESTARTS: 1
--------------------------- 
defined !!!                   # 세 번째 실행
top MAKE_RESTARTS: 2
mod_1.mk MAKE_RESTARTS: 2
mod_2.mk MAKE_RESTARTS: 2
--------------------------- 

sh$ ls                        # remake 에의해 include 파일이 새로 생성됨.
Makefile  mod_1.mk  mod_2.mk

sh$ make                      # include 파일이 존재하므로 다시 remake 이 발생하지 않는다.
not defined
top MAKE_RESTARTS: 
mod_1.mk MAKE_RESTARTS: 
mod_2.mk MAKE_RESTARTS: 
---------------------------

MAKE_TERMOUT , MAKE_TERMERR

make 명령 실행시 stdout, stderr 가 터미널에 연결되어 있는지 아닌지 이 변수를 통해서 알 수 있습니다. 터미널에 연결되어 있지 않으면 empty 가 반환됩니다.

이 변수는 make 4.1 버전에서 추가된 변수 입니다.

$(warning stdout: $(MAKE_TERMOUT))   # stderr 로 출력하기 위해 warning 함수를 사용
$(warning stderr: $(MAKE_TERMERR))

$(if $(MAKE_TERMOUT),,$(warning stdout is not terminal))

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

sh$ make
Makefile:1: stdout: /dev/pts/7
Makefile:2: stderr: /dev/pts/7

sh$ make | cat                    # stdout 이 터미널이 아닌 파이프에 연결되어 있으므로
Makefile:1: stdout:               # 변수 $(MAKE_TERMOUT) 값은 empty 이다.
Makefile:2: stderr: /dev/pts/7
Makefile:4: stdout is not terminal

MAKE_VERSION

make 버전 넘버

$(info $(MAKE_VERSION))
결과: 4.1

.RECIPEPREFIX

기본적으로 recipe 라인의 시작을 알리는 문자는 tab 문자인데 변경하고 싶으면 이 변수를 설정하면 됩니다. global 영역에서 순서에 따라 여러번 변경해 사용할 수 있으나 target-specific 변수로는 사용할 수 없습니다.

.RECIPEPREFIX := >    # foo 룰에는 '>' 문자를 사용
foo: bar
> @echo fooooo

.RECIPEPREFIX := !    # bar 룰에는 '!' 문자를 사용
bar:
! @echo barrrr

####  실행 결과  ####
fooooo
barrrr

SHELL

SHELL 변수를 이용하면 recipe 실행시 사용되는 shell 프로그램을 변경할 수 있습니다. global 영역에서 설정하면 모든 rule 에 적용되고 target-specific 변수로도 사용할 수 있습니다.

foo : bar                                foo : bar
    @cat <( echo $@ : $$0 )                  @#cat <( echo $@ : $$0 )
                                             @echo $@ : $$0
bar :                                    
    @cat <( echo $@ : $$0 )              bar : SHELL := /bin/bash
                                         bar :
SHELL := /bin/bash                           @cat <( echo $@ : $$0 )

######  실행 결과  ######                  ######  실행 결과  ######
bar : /bin/bash                          bar : /bin/bash
foo : /bin/bash                          foo : /bin/sh

.SHELLFLAGS

recipe 실행시 사용되는 shell 프로그램에 전달되는 옵션을 설정합니다. .SHELLFLAGS 의 기본값은 -c 이므로 shell 이 실행될때 sh -c 형태로 실행됩니다. 옵션을 추가할 때는 += 연산자를 사용해서 append 합니다. SHELL 변수와 마찬가지로 target-specific 변수로도 사용이 가능합니다.

foo : SHELL := /usr/bash
foo : .SHELLFLAGS += -e
foo :
    command ....

.SHELLSTATUS

!= 대입 연산자나 $(shell ...) 함수에 의해 shell 명령이 실행됐을 때 sh -c 의 종료 상태 값이 저장됩니다.

res != date -@  2> /dev/null              # 'date -@' 는 오류를 위한 명령
$(info status : $(.SHELLSTATUS))
res != date -@  2> /dev/null; date        # 마지막 명령은 정상 종료
$(info status : $(.SHELLSTATUS))

$(info ----------)

res := $(shell date -@ 2> /dev/null )
$(info status : $(.SHELLSTATUS))
res := $(shell date -@ 2> /dev/null; date )
$(info status : $(.SHELLSTATUS))

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

status : 1
status : 0
----------
status : 1
status : 0

SUFFIXES

Suffix rules 에서 사용되는 default 확장자 값들이 저장되어 있습니다. makefile 에서 .SUFFIXES: 타겟을 이용해 변경할 수 있지만 이 변수의 값은 변경되지 않습니다.


$(info $(SUFFIXES))

--------------------
.out .a .ln .o .c .cc .C .cpp .p .f .F .m .r .y .l .ym .yl .s .S .mod .sym .def 
.h .info .dvi .tex .texinfo .texi .txinfo .w .ch .web .sh .elc .el

.VARIABLES

현재 위치에서 설정되어 있는 global 변수 이름 목록을 출력합니다. 여기에는 built-in 변수, 환경 변수 들도 포함되지만 target-specific 변수는 포함되지 않습니다.

# origin 함수를 이용해 make 에 default 로 설정되어 있는 변수들을 출력합니다.
$(foreach V,$(sort $(.VARIABLES)), \
    $(if $(filter default,$(origin $V)),$(info $V=$(value $V)))))

VPATH

관련 페이지 참조

.FEATURES

make 프로그램에서 제공하는 특수 기능의 목록을 가지고 있는 변수입니다.

Feature Description
archives Supports ar (archive) files using special file name syntax
check-symlink Supports the -L (--check-symlink-times) flag
else-if Supports "else if" non-nested conditionals.
jobserver Supports "job server" enhanced parallel builds
output-sync Supports "output sync" when parallel builds
oneshell Supports the .ONESHELL special target.
order-only Supports order-only prerequisites.
second-expansion Supports secondary expansion of prerequisite lists.
shortest-stem Uses the "shortest stem" method of choosing which pattern,
of multiple applicable options, will be used
target-specific Supports target-specific and pattern-specific variable assignments.
undefine Supports the undefine directive.
load Supports dynamically loadable objects for creating custom extensions.
guile Has GNU Guile available as an embedded extension language