Richard Kiefer
Richard Kiefer

Reputation: 1954

Why does including a file in my Makefile change my Makefile-directory variable?

In order invoke my Makefile from different locations without messing up relative paths, I reference paths using a Makefile variable as given in another answer:

DIR=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))

I get that MAKEFILE_LIST differs when I include other files, but since I store its value in a variable before making any includes, I am surprised that the variable value differs.

Example:

$ tree .
.
├── another_file
└── subdirectory
    └── Makefile

$ cat Makefile
DIR=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))

test:
    @echo $(DIR)

#include $(DIR)/../another_file

$ make
/subdirectory

Just as expected. But if I uncomment the include line, I get

$ make
/

Which does not make sense to me, because another_file is still included without errors indicating that the value of $(DIR) is /subdirectory.

Note that the make target is placed before the include statement, and the behavior does not change when the order is switched. Guess this is due to preprocessing, but it still does not explain to me why $(DIR) seems to have different values.

$ make --version
GNU Make 3.81
...
This program built for i386-apple-darwin11.3.0

Upvotes: 0

Views: 277

Answers (1)

Lesmana
Lesmana

Reputation: 27063

this is because the value of MAKEFILE_LIST changes after include and the expansion of the variable DIR happens at use time.

I sprinkled your Makefile with info for demonstration

DIR=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))

$(info list1 $(MAKEFILE_LIST))
$(info dir1 $(DIR))

test:
    @echo $(DIR)

include $(DIR)/../another_file

$(info list2 $(MAKEFILE_LIST))
$(info dir2 $(DIR))

output

$ make
list1  Makefile
dir1 /home/lesmana/tmp/maek/subdir
list2  Makefile /home/lesmana/tmp/maek/subdir/../another_file
dir2 /home/lesmana/tmp/maek
/home/lesmana/tmp/maek

note how the value of MAKEFILE_LIST changed after the include and with it the value of DIR.

one way to fix this is by forcing immediate expansion of DIR by using := instead of =

DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))

that way the value of DIR is calculated once and does not change even if MAKEFILE_LIST changed.

another way would be to use firstword instead of lastword.

also note that the expansion of DIR in the recipe for test happens just before executing that recipe. That is why it does not matter where the include happens relative to test.

read here for more info:


I do not know how to feel about this shell construct to get the dir of the Makefile. Usually Makefiles from higher up include the Makefile from the subdirs. But you have your use case. I will not argue about that here. I hope my explanation of the flavors of variable helps.

Upvotes: 1

Related Questions