最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【已解决】Makefile中define的自定义函数中的lastword不工作

makefile crifan 4439浏览 0评论

折腾:

【已解决】Makefile中实现自己的函数并调用

期间,之前可以正常工作的代码:

<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进来后:

【已解决】提取Gitbook中Makefile公共部分

结果就不工作了:

/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

GNU make: Text Functions

$(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

GNU make: Value 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

GNU make: Eval Function

然后就可以继续调试了.

【总结】

对于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>

后记:

GNU make: Eval Function

并没有解释,在define的自定义函数中,为何要用eval才能赋值

转载请注明:在路上 » 【已解决】Makefile中define的自定义函数中的lastword不工作

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
83 queries in 0.182 seconds, using 22.20MB memory