折腾:
期间,之前可以正常工作的代码:
<code>MAKEFILE_LIST_LASTWORD = $(lastword $(MAKEFILE_LIST)) $(info MAKEFILE_LIST_LASTWORD=$(MAKEFILE_LIST_LASTWORD)) MAKEFILE_PATH := $(abspath $(MAKEFILE_LIST_LASTWORD)) $(info MAKEFILE_PATH=$(MAKEFILE_PATH)) MAKEFILE_DIR := $(dir $(MAKEFILE_PATH)) $(info MAKEFILE_DIR=$(MAKEFILE_DIR)) </code>
输出:
<code>MAKEFILE_LIST_LASTWORD=Makefile MAKEFILE_PATH=/Users/crifan/GitBook/Library/Import/selenium_summary/Makefile MAKEFILE_DIR=/Users/crifan/GitBook/Library/Import/selenium_summary/ </code>
但是在提取公共部分,include进来后:
结果就不工作了:
/Users/crifan/GitBook/Library/Import/Makefile_common
<code># get current folder name # support call makefile from anywhere, not only from current path of makefile located # MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) # CURRENT_DIR_WITH_SLASH := $(notdir $(patsubst %/,%,$(MAKEFILE_DIR)) define getCurrentDirAndDirName $(info MAKEFILE_LIST=$(MAKEFILE_LIST)) MAKEFILE_LIST_LASTWORD := $(lastword $(MAKEFILE_LIST)) $(info MAKEFILE_LIST_LASTWORD=$(MAKEFILE_LIST_LASTWORD)) MAKEFILE_PATH := $(abspath $(MAKEFILE_LIST_LASTWORD)) MAKEFILE_DIR := $(dir $(MAKEFILE_PATH)) MAKEFILE_DIR_PATSUBST := $(patsubst %/,%,$(MAKEFILE_DIR)) MAKEFILE_DIR_NOSLASH = $(MAKEFILE_DIR_PATSUBST) CURRENT_DIR_WITH_SLASH = $(MAKEFILE_DIR) CURRENT_DIR = $(MAKEFILE_DIR_NOSLASH) CURRENT_DIR_NAME := $(notdir $(MAKEFILE_DIR_PATSUBST)) $1 := $(CURRENT_DIR_NAME) $2 := $(CURRENT_DIR) endef </code>
debug_makefile:
$(eval $(call getCurrentDirAndDirName, CURRENT_DIR_NAME, CURRENT_DIR))
输出:
<code>➜ youdao_note_summary git:(master) ✗ make MAKEFILE_LIST= Makefile ../Makefile_common MAKEFILE_LIST_LASTWORD= make: Nothing to be done for `debug_makefile'. </code>
接着继续去搞清楚:
此处:
<code>define getCurrentDirAndDirName MAKEFILE_LIST_LASTWORD = $(lastword $(MAKEFILE_LIST)) $(info {MAKEFILE_LIST}=${MAKEFILE_LIST}) $(info (MAKEFILE_LIST)=$(MAKEFILE_LIST)) $(info MAKEFILE_LIST_LASTWORD=${MAKEFILE_LIST_LASTWORD}) </code>
中的MAKEFILE_LIST_LASTWORD是空:
<code>{MAKEFILE_LIST}= Makefile ../Makefile_common (MAKEFILE_LIST)= Makefile ../Makefile_common MAKEFILE_LIST_LASTWORD= </code>
lastword
makefile lastword not work
“$(lastword names…)
The argument names is regarded as a series of names, separated by whitespace. The value is the last name in the series.
For example,
$(lastword foo bar)
produces the result ‘bar’. Although $(lastword text) is the same as $(word $(words text),text), the lastword function was added for its simplicity and better performance.
“
感觉难道是:
<code>Makefile ../Makefile_common </code>
没法提取last的word?
去试试:
https://www.gnu.org/software/make/manual/html_node/Text-Functions.html
“$(firstword names…)
The argument names is regarded as a series of names, separated by whitespace. The value is the first name in the series. The rest of the names are ignored.
For example,
$(firstword foo bar)
produces the result ‘foo’. Although $(firstword text) is the same as $(word 1,text), the firstword function is retained for its simplicity.
”
<code>MAKEFILE_LIST_FIRSTWORD := $(firstword $(MAKEFILE_LIST)) $(info MAKEFILE_LIST_FIRSTWORD=$(MAKEFILE_LIST_FIRSTWORD)) </code>
结果:
<code>MAKEFILE_LIST= Makefile ../Makefile_common MAKEFILE_LIST_FIRSTWORD= MAKEFILE_LIST_LASTWORD= </code>
都是空的
测试看看:
<code>testFileList = aa ../bb $(info first=$(firstword $(testFileList))) $(info last=$(lastword $(testFileList))) </code>
结果都是空:
<code>first= last= </code>
换个正常的:
<code>testFileList = aa bb $(info first=$(firstword $(testFileList))) $(info last=$(lastword $(testFileList))) </code>
输出:
<code>first= last= </code>
参考:
https://stackoverflow.com/questions/35678904/gnu-make-builtin-functions-not-working
去试试:
<code>testFileList = aa bb first=$(firstword $(testFileList)) last=$(lastword $(testFileList)) $(info first=$(first)) $(info last=$(last)) </code>
结果:还是空
makefile – make subst not working as I want it to be – Stack Overflow
makefile firstword not work
mac makefile firstword not work
makefile pathing issues on OSX – Stack Overflow
How to retrieve the first word of the output of a command in bash? – Stack Overflow
然后试了试之前同样代码:
<code>MAKEFILE_LIST_LASTWORD = $(lastword $(MAKEFILE_LIST)) $(info MAKEFILE_LIST_LASTWORD=$(MAKEFILE_LIST_LASTWORD)) MAKEFILE_PATH := $(abspath $(MAKEFILE_LIST_LASTWORD)) $(info MAKEFILE_PATH=$(MAKEFILE_PATH)) MAKEFILE_DIR := $(dir $(MAKEFILE_PATH)) $(info MAKEFILE_DIR=$(MAKEFILE_DIR)) MAKEFILE_DIR_PATSUBST := $(patsubst %/,%,$(MAKEFILE_DIR)) MAKEFILE_DIR_NOSLASH = $(MAKEFILE_DIR_PATSUBST) CURRENT_DIR_WITH_SLASH = $(MAKEFILE_DIR) CURRENT_DIR = $(MAKEFILE_DIR_NOSLASH) CURRENT_DIR_NAME := $(notdir $(MAKEFILE_DIR_PATSUBST)) debug_makefile: @echo nothing </code>
结果输出:
<code>➜ youdao_note_summary git:(master) ✗ make MAKEFILE_LIST_LASTWORD=../Makefile_common MAKEFILE_PATH=/Users/crifan/GitBook/Library/Import/Makefile_common MAKEFILE_DIR=/Users/crifan/GitBook/Library/Import/ nothing # </code>
-》说明正常情况下:lastword是工作的
-〉但是在define的函数中,lastword就不工作了。
再去试试:
<code>define getCurrentDirAndDirName MAKEFILE_LIST_LASTWORD = $(lastword $(MAKEFILE_LIST)) $(info MAKEFILE_LIST_LASTWORD=$(MAKEFILE_LIST_LASTWORD)) MAKEFILE_PATH := $(abspath $(MAKEFILE_LIST_LASTWORD)) $(info MAKEFILE_PATH=$(MAKEFILE_PATH)) MAKEFILE_DIR := $(dir $(MAKEFILE_PATH)) $(info MAKEFILE_DIR=$(MAKEFILE_DIR)) MAKEFILE_DIR_PATSUBST := $(patsubst %/,%,$(MAKEFILE_DIR)) MAKEFILE_DIR_NOSLASH = $(MAKEFILE_DIR_PATSUBST) CURRENT_DIR_WITH_SLASH = $(MAKEFILE_DIR) CURRENT_DIR = $(MAKEFILE_DIR_NOSLASH) CURRENT_DIR_NAME := $(notdir $(MAKEFILE_DIR_PATSUBST)) endef </code>
debug_makefile:
$(eval $(call getCurrentDirAndDirName, CURRENT_DIR_NAME, CURRENT_DIR))
@echo nothing
结果:
<code>➜ youdao_note_summary git:(master) ✗ make MAKEFILE_LIST_LASTWORD= MAKEFILE_PATH= MAKEFILE_DIR= nothing </code>
果然是。
那需要去搞清楚:
8.2 Functions for String Substitution and Analysis
中的firstword,lastword,放到define中后,为何不工作
makefile String Substitution and Analysis function not work inside define
难道是:
makefile – Defining custom GNU make functions – Stack Overflow
中的:
<code>define dep2 $(eval makefile_list_$1 := $(MAKEFILE_LIST)); $(eval -include $1.mk); $(eval MAKEFILE_LIST := $(makefile_list_$1)); endef </code>
要去加上eval才能赋值给变量?
<code>define getCurrentDirAndDirName $(eval MAKEFILE_LIST_LASTWORD = $(lastword $(MAKEFILE_LIST))) # MAKEFILE_LIST_LASTWORD = $(lastword $(MAKEFILE_LIST)) $(info MAKEFILE_LIST_LASTWORD=$(MAKEFILE_LIST_LASTWORD)) </code>
结果:
果然是:
<code>➜ youdao_note_summary git:(master) ✗ make MAKEFILE_LIST_LASTWORD=../Makefile_common </code>
此处mac中的make是3.81
<code>➜ youdao_note_summary git:(master) ✗ make --version GNU Make 3.81 Copyright (C) 2006 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. This program built for i386-apple-darwin11.3.0 </code>
看来问题转换为:
defin中自定义函数中的变量赋值,必须要用:
$(eval someVariable=xxx)
makefile custom function set variable value
makefile set variable value inside custom function
Define your own function in a Makefile (Example)
The Basics of GNU Make | CMCrossroads
Variables inside makefile function are not expanded correctly? – Stack Overflow
好像说是用 $$(xxx)
也可以?
去试试
<code>define getCurrentDirAndDirName # $(eval MAKEFILE_LIST_LASTWORD = $(lastword $(MAKEFILE_LIST))) MAKEFILE_LIST_LASTWORD = $(lastword $(MAKEFILE_LIST)) $(info MAKEFILE_LIST_LASTWORD=$$(MAKEFILE_LIST_LASTWORD)) # $(info MAKEFILE_LIST_LASTWORD=$(MAKEFILE_LIST_LASTWORD)) </code>
结果:
<code>➜ youdao_note_summary git:(master) ✗ make MAKEFILE_LIST_LASTWORD=$(MAKEFILE_LIST_LASTWORD) MAKEFILE_LIST_LASTWORD=../Makefile_common </code>
不对。
makefile – Define make variable at rule execution time – Stack Overflow
Makefile Optimization: $(eval) and macro caching | CMCrossroads
makefile variable value inside define function
Defining variables within a makefile macro (define) – Stack Overflow
makefile – Can’t assign variable inside recipe – Stack Overflow
然后就可以继续调试了.
【总结】
对于Makefile来说,关于define的自定义函数的中的变量的赋值,不是普通的:
<code>someVariable = xxxe </code>
而必须是:
<code>$(eval someVariable = xxx) </code>
比如:
<code>define getCurrentDirAndDirName $(eval MAKEFILE_LIST_LASTWORD = $(lastword $(MAKEFILE_LIST))) # MAKEFILE_LIST_LASTWORD = $(lastword $(MAKEFILE_LIST)) $(info MAKEFILE_LIST_LASTWORD=$(MAKEFILE_LIST_LASTWORD)) # MAKEFILE_PATH := $(abspath $(MAKEFILE_LIST_LASTWORD)) $(eval MAKEFILE_LIST_FIRSTWORD = $(firstword $(MAKEFILE_LIST))) $(info MAKEFILE_LIST_FIRSTWORD=$(MAKEFILE_LIST_FIRSTWORD)) $(eval MAKEFILE_PATH := $(abspath $(MAKEFILE_LIST_FIRSTWORD))) $(info MAKEFILE_PATH=$(MAKEFILE_PATH)) $(eval MAKEFILE_DIR := $(dir $(MAKEFILE_PATH))) $(info MAKEFILE_DIR=$(MAKEFILE_DIR)) $(eval MAKEFILE_DIR_PATSUBST := $(patsubst %/,%,$(MAKEFILE_DIR))) $(info MAKEFILE_DIR_PATSUBST=$(MAKEFILE_DIR_PATSUBST)) $(eval MAKEFILE_DIR_NOSLASH = $(MAKEFILE_DIR_PATSUBST)) $(info MAKEFILE_DIR_NOSLASH=$(MAKEFILE_DIR_NOSLASH)) $(eval CURRENT_DIR_WITH_SLASH = $(MAKEFILE_DIR)) $(info CURRENT_DIR_WITH_SLASH=$(CURRENT_DIR_WITH_SLASH)) $(eval CURRENT_DIR = $(MAKEFILE_DIR_NOSLASH)) $(info CURRENT_DIR=$(CURRENT_DIR)) $(eval CURRENT_DIR_NAME := $(notdir $(MAKEFILE_DIR_PATSUBST))) $(info CURRENT_DIR_NAME=$(CURRENT_DIR_NAME)) endef debug_makefile: $(eval $(call getCurrentDirAndDirName) @echo nothing </code>
而为何非要用eval,不知道。
觉得挺诡异的,没有找到官网的标准解释。
另外,不能写成:
<code>$$(xxx) </code>
否则只会输出普通的字符串:
<code>$(xxx) </code>
后记:
并没有解释,在define的自定义函数中,为何要用eval才能赋值