美文网首页
Kernel Makefile

Kernel Makefile

作者: wjundong | 来源:发表于2022-08-25 00:32 被阅读0次

关于 kernel Makefile 中的技巧

MAKECMDGOALS 变量

MAKECMDGOALS 是 make 内置变量, 表示用户输入的目标合集, 例如

default:
    @echo $(MAKECMDGOALS)

demo:
    @echo ok 

执行

$ make default demo
default demo
ok

MAKEFLAGS 变量

MAKEFLAGS 是 make 本身的参数设置项, 通过make --help 可以看到所有可用选项, 当用户执行 make -(options), options 便会传给 MAKEFLAGS, 例如

# 也可以在文件内直接设置
MAKEFLAGS += -r

all:
  @echo $(MAKEFLAGS)

执行

$ make all -s
  sr

MAKEFLAGS 值为 sr, s 是命令行给出, r 是在文件中给出

伪目标

伪目标指不产生实际文件的目标, .PHONY 可用来指明哪些目标是伪目标.
作用1:
作用2: PHONY可以确保源文件(*.c *.h)修改后,对应的目标文件会被重建。倘若缺少了PHONY,可以看到情况会很糟。

PHONY += all
all:
  echo all

PHONY += clean
clean:
  echo clean

.PHONY: $(PHONY)

变量展开

定义一个变量 cmd = xxx, 然后使用 $(cmd) 进行引用, 变量展开后变成字符串再对外层引用进行展开, 直到展开所有引用, 然后执行, 例如:

cmd = echo hello
all:
    $(cmd)

很显然上面会输出 hello, 因为引用 cmd 后, cmd 被展开 --> echo hello, 实际上就相当于执行一次 echo hello, 所以结果是 hello

cmd = echo hello
mycmd = $(shell echo $(cmd))
all:
    $(mycmd)
  1. 先展开内部 $(cmd) --> $(shell echo echo hello)
  2. 再展开 shell 函数部分 --> mycmd = echo hello
  3. 最后展开 $(mycmd) --> echo hello
    所以最后输出是 hello

call 函数

call 函数可以在引用变量时传入参数

cmd =  echo $(1)
all
    $(call cmd,hello)

执行 call 后, cmd 被引用, 而 $(1) 是对第一个参数的引用, 展开有变成 hello, 所以最后展开后变成 echo hello, 输出 hello

  • 组合变量
    利用 call 函数的引用传参特性可以实现对变量的灵活引用
    cmd = $(cmd_$(1))
    cmd_hello = echo hello
    all:
      $(call cmd,hello)
    
    调用 call 函数后, cmd 变量被展开成 --> $(cmd_hello) --> 再展开后变成 echo hello, 于是输出 hello
  • 显示调用命令
    编译时有时需要显示调用的命令详情, 但有时又需要简洁模式. 这就需要能在每一行命令调用时自定义显示内容. 下面的 echo-cmd 正是用于此目的.
    • echo-cmd 会将当前执行的命令按用户自定义的方式进行回显
    • 用户需要定义两个版本命令, 一个是实际命令, 一个是该命令调用时的自定义显示
    • 当 quiet 变量不为空时表示回显的是自定义显示的内容, 当 quiet 为空时, 则回显当前执行的命令详情;
    quiet = quiet_
    
    echo-cmd = echo '  $($(quiet)cmd_$(1))'
    cmd = @$(echo-cmd); $(cmd_$(1))
    
    # 定义两个命令, 一个是实际命令, 一个是该命令调用时的自定义显示
    cmd_hello = echo hello
    quiet_cmd_hello = command runing
    
    all:
      $(call cmd,hello)
    
    cmd = @$(echo-cmd); $(cmd_$(1)) 一行其实是包含了两部分, 前面部分负责回显, 用来给用户提示, 后面部分则是命令执行本身, @ 符号有效的屏蔽了 make 对命令展开后的显示, 最后显示的内容就只要自定义的 echo-cmd 了. 执行后
    • 如果 quiet = quiet_ 则回显提示 command runing, 而后台在默默执行 cmd_hello 即输出 hello
    • 如果 quiet 未定义或为空, 则回显提示 echo hello 即命令本身, 并且命令在后台正确执行, 输出 hello

完整版


# Beautify output
# ---------------------------------------------------------------------------
#
# Normally, we echo the whole command before executing it. By making
# that echo $($(quiet)$(cmd)), we now have the possibility to set
# $(quiet) to choose other forms of output instead, e.g.
#
#         quiet_cmd_cc_o_c = Compiling $(RELDIR)/$@
#         cmd_cc_o_c       = $(CC) $(c_flags) -c -o $@ $<
#
# If $(quiet) is empty, the whole command will be printed.
# If it is set to "quiet_", only the short version will be printed.
# If it is set to "silent_", nothing will be printed at all, since
# the variable $(silent_cmd_cc_o_c) doesn't exist.
#
# A simple variant is to prefix commands with $(Q) - that's useful
# for commands that shall be hidden in non-verbose mode.
#
#   $(Q)ln $@ :<
#
# If KBUILD_VERBOSE equals 0 then the above command will be hidden.
# If KBUILD_VERBOSE equals 1 then the above command is displayed.
# If KBUILD_VERBOSE equals 2 then give the reason why each target is rebuilt.
#
# To put more focus on warnings, be less verbose as default
# Use 'make V=1' to see the full commands

ifeq ("$(origin V)", "command line")
  KBUILD_VERBOSE = $(V)
endif
ifndef KBUILD_VERBOSE
  KBUILD_VERBOSE = 0
endif

ifeq ($(KBUILD_VERBOSE),1)
  quiet =
  Q =
else
  quiet=quiet_
  Q = @
endif

# If the user is running make -s (silent mode), suppress echoing of
# commands

ifneq ($(findstring s,$(filter-out --%,$(MAKEFLAGS))),)
  quiet=silent_
  KBUILD_VERBOSE = 0
endif

export quiet Q KBUILD_VERBOSE

# -----------------------------------------------------
# include 部分

squote  := '

# 转义单引号以在 echo 语句中使用
escsq = $(subst $(squote),'\$(squote)',$1)

# 命令执行时回显
# 如果有自定义回显内容 $(quiet)cmd_$(1), 则执行回显
echo-cmd = $(if $($(quiet)cmd_$(1)),\
    echo '  $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)

# sink stdout for 'make -s'
       redirect :=
 quiet_redirect :=
silent_redirect := exec >/dev/null;

# 执行一个命令
# 通过 $(call cmd, name) 来执行, 它会根据需要将命令回显,同时执行实际命令 cmd_name
cmd = @set -e; $(echo-cmd) $($(quiet)redirect) $(cmd_$(1))

# why - 告诉 User 为何该目标需要进行构建
# 当 V=2 时才显示
ifeq ($(KBUILD_VERBOSE),2)
why = $(if $(0),                        \
            - 'due to something'        \
        )
endif

echo-why = $(call escsq, $(strip $(why)))
# -----------------------------------------------------

# 定义两个命令, 一个是实际命令, 一个是该命令调用时的自定义显示
quiet_cmd_hello = GEN $@
      cmd_hello = echo hello

all: tar1
    $(call cmd,hello)

tar1:
    $(Q)echo "tar1"

相关文章

网友评论

      本文标题:Kernel Makefile

      本文链接:https://www.haomeiwen.com/subject/jjlagrtx.html