为什么在我的 Makefile 中包含一个文件会更改我的 Makefile 目录变量?
Why does including a file in my Makefile change my Makefile-directory variable?
为了从不同位置调用我的 Makefile 而不会弄乱相对路径,我使用 another answer:
中给出的 Makefile 变量引用路径
DIR=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
我知道当我包含其他文件时 MAKEFILE_LIST
不同,但由于我在进行任何包含之前将其值存储在变量中,我很惊讶变量值不同。
示例:
$ tree .
.
├── another_file
└── subdirectory
└── Makefile
$ cat Makefile
DIR=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
test:
@echo $(DIR)
#include $(DIR)/../another_file
$ make
/subdirectory
果然不出所料。但是如果我取消注释 include 行,我会得到
$ make
/
这对我来说没有意义,因为 another_file
仍然包含而没有错误表明 $(DIR)
的值是 /subdirectory
。
注意make目标放在include语句之前,顺序切换时行为不会改变。猜猜这是由于预处理,但它仍然没有向我解释为什么 $(DIR)
似乎有不同的值。
$ make --version
GNU Make 3.81
...
This program built for i386-apple-darwin11.3.0
这是因为 MAKEFILE_LIST
的值在 include
之后发生了变化,变量 DIR
的扩展发生在使用时。
我在你的 Makefile 中添加了 info
用于演示
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))
输出
$ 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
请注意 MAKEFILE_LIST
的值在 include
之后如何变化以及 DIR
的值如何变化。
解决此问题的一种方法是使用 :=
而不是 =
强制立即扩展 DIR
DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
这样 DIR
的值只计算一次,即使 MAKEFILE_LIST
改变也不会改变。
另一种方法是使用 firstword
而不是 lastword
。
另请注意,test
配方中 DIR
的扩展恰好发生在执行该配方之前。这就是为什么 include
相对于 test
.
发生在哪里并不重要
阅读此处了解更多信息:
- https://www.gnu.org/software/make/manual/html_node/Special-Variables.html
- https://www.gnu.org/software/make/manual/html_node/Flavors.html
- What is the difference between the GNU Makefile variable assignments =, ?=, := and +=?
我不知道如何看待这个 shell
构造来获取 Makefile 的目录。通常来自更高层的 Makefile 包括来自子目录的 Makefile。但是你有你的用例。我不会在这里争论这个问题。我希望我对变量的解释有所帮助。
为了从不同位置调用我的 Makefile 而不会弄乱相对路径,我使用 another answer:
中给出的 Makefile 变量引用路径DIR=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
我知道当我包含其他文件时 MAKEFILE_LIST
不同,但由于我在进行任何包含之前将其值存储在变量中,我很惊讶变量值不同。
示例:
$ tree .
.
├── another_file
└── subdirectory
└── Makefile
$ cat Makefile
DIR=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
test:
@echo $(DIR)
#include $(DIR)/../another_file
$ make
/subdirectory
果然不出所料。但是如果我取消注释 include 行,我会得到
$ make
/
这对我来说没有意义,因为 another_file
仍然包含而没有错误表明 $(DIR)
的值是 /subdirectory
。
注意make目标放在include语句之前,顺序切换时行为不会改变。猜猜这是由于预处理,但它仍然没有向我解释为什么 $(DIR)
似乎有不同的值。
$ make --version
GNU Make 3.81
...
This program built for i386-apple-darwin11.3.0
这是因为 MAKEFILE_LIST
的值在 include
之后发生了变化,变量 DIR
的扩展发生在使用时。
我在你的 Makefile 中添加了 info
用于演示
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))
输出
$ 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
请注意 MAKEFILE_LIST
的值在 include
之后如何变化以及 DIR
的值如何变化。
解决此问题的一种方法是使用 :=
而不是 =
DIR
DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
这样 DIR
的值只计算一次,即使 MAKEFILE_LIST
改变也不会改变。
另一种方法是使用 firstword
而不是 lastword
。
另请注意,test
配方中 DIR
的扩展恰好发生在执行该配方之前。这就是为什么 include
相对于 test
.
阅读此处了解更多信息:
- https://www.gnu.org/software/make/manual/html_node/Special-Variables.html
- https://www.gnu.org/software/make/manual/html_node/Flavors.html
- What is the difference between the GNU Makefile variable assignments =, ?=, := and +=?
我不知道如何看待这个 shell
构造来获取 Makefile 的目录。通常来自更高层的 Makefile 包括来自子目录的 Makefile。但是你有你的用例。我不会在这里争论这个问题。我希望我对变量的解释有所帮助。