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

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

makefile crifan 3862浏览 0评论

折腾:

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

期间,感觉此处对于:

<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))
MAKEFILE_LIST_LASTWORD = $(lastword $(MAKEFILE_LIST))
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))

BOOK_NAME := $(CURRENT_DIR_NAME)

OUTPUT_FOLDER_NAME = output
OUTPUT_PATH = $(CURRENT_DIR)/$(OUTPUT_FOLDER_NAME)/$(BOOK_NAME)
DEBUG_PATH = $(CURRENT_DIR)/debug
</code>

需要弄个函数出来,可以实现

传入参数,返回当前文件夹路径和当前文件夹的名字

makefile function

GNU make: Functions

GNU make: Syntax of Functions

GNU make: File Name Functions

GNU make: Call Function

Define your own function in a Makefile (Example)

functions in makefiles? – Stack Overflow

GNU make 5.8 Defining Canned Recipes

How to define global shell functions in a Makefile? – Stack Overflow

makefile – Using Make’s file function – Stack Overflow

接着要去搞清楚:

【已解决】Makefile中如何获得define自定义函数的返回值

结果出错:

【已解决】Makefile自定义函数调用出错:unterminated call to function `notdir’: missing `)’.  Stop

makefile – Defining custom GNU make functions – Stack Overflow

【已解决】Makefile中define自定义函数中打印输出没效果

另外:

makefile专题:函数定义及调用 – 简书

<code>define func1
    @echo "My name is $(0)"
endef
</code>

也可以写成:

$(0)

后记:

GNU make: Call Function

中提到了:

<code>$(call variable,param,param,…)
</code>

获取函数参数,应该写成带括号的:$(1),$(2)

而$(0)代表了函数(variable)本身

makefile MAKEFILE_LIST

GNU make: MAKEFILE_LIST Variable

此处:

<code>  $(info MAKEFILE_LIST is $(MAKEFILE_LIST))
</code>

输出:

MAKEFILE_LIST is  Makefile ../Makefile_common

是对的。

那么再去看看lastword不工作:

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

Makefile 关于realpath的研究 – CSDN博客

抽空可以去利用realpath看看

放在函数外部的,普通的赋值:

<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))
MAKEFILE_LIST_LASTWORD = $(lastword $(MAKEFILE_LIST))
$(info MAKEFILE_LIST_LASTWORD=$(MAKEFILE_LIST_LASTWORD))
# MAKEFILE_PATH := $(abspath $(MAKEFILE_LIST_LASTWORD))
MAKEFILE_LIST_FIRSTWORD = $(firstword $(MAKEFILE_LIST))
$(info MAKEFILE_LIST_FIRSTWORD=$(MAKEFILE_LIST_FIRSTWORD))
MAKEFILE_PATH := $(abspath $(MAKEFILE_LIST_FIRSTWORD))
$(info MAKEFILE_PATH=$(MAKEFILE_PATH))
MAKEFILE_DIR := $(dir $(MAKEFILE_PATH))
$(info MAKEFILE_DIR=$(MAKEFILE_DIR))
MAKEFILE_DIR_PATSUBST := $(patsubst %/,%,$(MAKEFILE_DIR))
$(info MAKEFILE_DIR_PATSUBST=$(MAKEFILE_DIR_PATSUBST))
MAKEFILE_DIR_NOSLASH = $(MAKEFILE_DIR_PATSUBST)
$(info MAKEFILE_DIR_NOSLASH=$(MAKEFILE_DIR_NOSLASH))
CURRENT_DIR_WITH_SLASH = $(MAKEFILE_DIR)
$(info CURRENT_DIR_WITH_SLASH=$(CURRENT_DIR_WITH_SLASH))
CURRENT_DIR = $(MAKEFILE_DIR_NOSLASH)
$(info CURRENT_DIR=$(CURRENT_DIR))
CURRENT_DIR_NAME := $(notdir $(MAKEFILE_DIR_PATSUBST))
$(info CURRENT_DIR_NAME=$(CURRENT_DIR_NAME))
</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
</code>

输出都是:

<code>➜  youdao_note_summary git:(master) ✗ make
MAKEFILE_LIST_LASTWORD=../Makefile_common
MAKEFILE_LIST_FIRSTWORD=Makefile
MAKEFILE_PATH=/Users/crifan/GitBook/Library/Import/youdao_note_summary/Makefile
MAKEFILE_DIR=/Users/crifan/GitBook/Library/Import/youdao_note_summary/
MAKEFILE_DIR_PATSUBST=/Users/crifan/GitBook/Library/Import/youdao_note_summary
MAKEFILE_DIR_NOSLASH=/Users/crifan/GitBook/Library/Import/youdao_note_summary
CURRENT_DIR_WITH_SLASH=/Users/crifan/GitBook/Library/Import/youdao_note_summary/
CURRENT_DIR=/Users/crifan/GitBook/Library/Import/youdao_note_summary
CURRENT_DIR_NAME=youdao_note_summary
nothing
</code>

接着继续弄:

【已解决】Makefile中如何获得define自定义函数的返回值

【总结】

最后用:

<code>define getCurrentDirAndDirName
$(eval MAKEFILE_LIST_LASTWORD = $(lastword $(MAKEFILE_LIST)))
$(eval MAKEFILE_LIST_FIRSTWORD = $(firstword $(MAKEFILE_LIST)))
$(eval MAKEFILE_PATH := $(abspath $(MAKEFILE_LIST_FIRSTWORD)))
$(eval MAKEFILE_DIR := $(dir $(MAKEFILE_PATH)))
$(eval MAKEFILE_DIR_PATSUBST := $(patsubst %/,%,$(MAKEFILE_DIR)))
$(eval MAKEFILE_DIR_NOSLASH = $(MAKEFILE_DIR_PATSUBST))
$(eval CURRENT_DIR_WITH_SLASH = $(MAKEFILE_DIR))
$(eval CURRENT_DIR = $(MAKEFILE_DIR_NOSLASH))
$(eval CURRENT_DIR_NAME := $(notdir $(MAKEFILE_DIR_PATSUBST)))

$(info CURRENT_DIR=$(CURRENT_DIR))
endef

$(eval $(call getCurrentDirAndDirName))
</code>

输出:

<code>CURRENT_DIR=/Users/crifan/GitBook/Library/Import/youdao_note_summary
</code>

此处已经搞清楚如何获取define的函数返回值了,需要的话,再去参考:

【已解决】Makefile中如何获得define自定义函数的返回值

去加上。

【后记】

makefile 自定义函数

makefile自定义函数 – CSDN博客

Makefile学习(6) – – ITeye博客

关于makefile中自定义函数:

语法:

<code>define userDefinedFunctionName
用户自定义函数体
endef
</code>

其中:

  • 用户自定义函数体:行首不需要加Tab

调用函数:

<code>$(call userDefinedFunctionName, arg1, arg2, arg3)
</code>

函数体内获取传入的参数:

<code>$(1),$(2),$(3)
</code>

其中:

$(0):表示函数(名称)本身

想要获取返回值:

<code>define userDefinedFunctionName
xxx
xxxx $(1) xxxx
xxxx $(2) xxxx
someOtherValue
$(3) = $$(someOtherValue)
endef
</code>

调用:

<code>$(call userDefinedFunctionName, arg1, arg2, returnValue1)
</code>

然后returnValue1即可获得对应的someOtherValue的值了。

【后记2】

GNU make: Top

-》

GNU make: Quick Reference

-》

GNU make: Multi-Line

才是解释了define的,多行的,用户自定义的函数

但是注意到:

此处,我们所说的,用户自定义函数user-defined function,对于makefile来说,叫做:

Defining Multi-Line Variables 定义多行变量

-》对应着:

用户 自己定义的变量,一般都是单行的变量

此处,变量是多行的时候,才会去用到define+endef

具体支持两类用途,详见:

不过看到说是:

<code>define two-lines =
echo foo
echo $(bar)
endef
</code>
  • 函数名后面带=等于号

  • 函数内部每行后面加上;分号

    • two-lines = echo foo; echo $(bar)

总体上感觉:

和此处我们所说的,用户自定义函数,语法上貌似不是完全一样

我们所说的用户自定义函数,不用等于号和分号的

然后看了:

https://www.gnu.org/software/make/manual/html_node/Multi_002dLine.html#Multi_002dLine

-》

https://www.gnu.org/software/make/manual/html_node/Flavors.html#Flavors

以为用

:=

或许可以实现赋值?

试了:

<code>define getCurrentDirAndDirName
MAKEFILE_LIST_LASTWORD := $(lastword $(MAKEFILE_LIST))
$(info MAKEFILE_LIST_LASTWORD with := $(MAKEFILE_LIST_LASTWORD))
$(eval MAKEFILE_LIST_LASTWORD = $(lastword $(MAKEFILE_LIST)))
$(info MAKEFILE_LIST_LASTWORD with eval = $(MAKEFILE_LIST_LASTWORD))
$(eval MAKEFILE_LIST_FIRSTWORD = $(firstword $(MAKEFILE_LIST)))
</code>

并没有输出我要的效果:

<code>MAKEFILE_LIST_LASTWORD with :=
MAKEFILE_LIST_LASTWORD with eval = ../Makefile_common
</code>

:=的值,还是空的。

试试:

<code>define getCurrentDirAndDirName
MAKEFILE_LIST_LASTWORD := $(lastword $(MAKEFILE_LIST));
$(info MAKEFILE_LIST_LASTWORD with ; and := $(MAKEFILE_LIST_LASTWORD))
$(eval MAKEFILE_LIST_LASTWORD = $(lastword $(MAKEFILE_LIST)))
$(info MAKEFILE_LIST_LASTWORD with eval = $(MAKEFILE_LIST_LASTWORD))
</code>

结果:

还是空:

<code>MAKEFILE_LIST_LASTWORD with ; and :=
</code>

GNU make: Canned Recipes

<code>define getCurrentDirAndDirName =
MAKEFILE_LIST_LASTWORD := $(lastword $(MAKEFILE_LIST));
$(info MAKEFILE_LIST_LASTWORD with ; and := $(MAKEFILE_LIST_LASTWORD))
$(eval MAKEFILE_LIST_LASTWORD = $(lastword $(MAKEFILE_LIST)))
$(info MAKEFILE_LIST_LASTWORD with eval = $(MAKEFILE_LIST_LASTWORD))
…

$(info CURRENT_DIR=$(CURRENT_DIR))
endef

$(eval $(call getCurrentDirAndDirName))
</code>

结果:

info的信息,就完全不输出了

-》看来

define xxx

define xxx =

还是不一样的。

而对于:

https://www.gnu.org/software/make/manual/html_node/Quick-Reference.html#Quick-Reference

中的

<code>define variable
define variable =
define variable :=
define variable ::=
define variable +=
define variable ?=
</code>

的深层次含义,需要后续再研究了。

makefile define function

Metaprogramming Make VI — The eval Function | GNU make

Makefile Tutorial by Example

5.7

You can make a list of commands like so:

define sweet

echo “hello”

echo “target:” $@

echo “prereqs:” $<

endef

.PHONY: all

all: one

        $(sweet)

  # Append @ here to append @ to all the commands in sweet: @$(sweet)

one:

        touch one

clean:

        rm -f one

6.8

“define” is actually just a multiline variable defintion. It has nothing with being a function.  

Note here that it’s a bit different than having a semi-colon between commands, because each is run

in a seperate shell, as expected.

one = export blah=”I was set!”; echo $$blah

define two

export blah=set

echo $$blah

endef

.PHONY: all

all:

        @echo “This prints I was set:”

        @$(one)

        @echo “This does not:”

        @$(two)

GNU make – How to Use Variables

转载请注明:在路上 » 【已解决】Makefile中实现自己的函数并调用

发表我的评论
取消评论

表情

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

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