ILD

escape of # in GNU Make
作者:Yuan Jianpeng 邮箱:yuanjp89@163.com
发布时间:2021-4-4 站点:Inside Linux Development

在ubuntu 20上编译busybox的时候,编译过一次后,再次编译仍然会重新编译。


于是开始debug,首先查看Makefile,可以单独编译一个目录:

    $ make applets


其recipe是:make -f /work/staging/source/busybox-1.31.1/scripts/Makefile.build obj=applets


查看scripts/Makefile.build,发现其和内核是一套东西,里面有一个编译.o的规则:

1
2
3
%.o: %.c FORCE
        $(call cmd,force_checksrc)
        $(call if_changed_rule,cc_o_c)


if_changed_rule,定义在scripts/Kbuild.include:

1
2
3
4
if_changed_rule = $(if $(strip $(filter-out $(PHONY),$?)            \
                        $(call arg-check, $(cmd_$(1)), $(cmd_$@)) ),\
                        @set -e; \
                        $(rule_$(1)))


$? 是所有比目标新的依赖。如果有就执行rule_cc_o_c,还有一个检查arg-check,$@是目标的名字,它比较两个变量是否相同,cmd_cc_o_c,cmd_applets/applets.o。


rule_cc_o_c的定义如下:

1
2
3
4
5
6
7
8
define rule_cc_o_c
        $(call echo-cmd,checksrc) $(cmd_checksrc)                         \
        $(call echo-cmd,cc_o_c) $(cmd_cc_o_c);                            \
        $(cmd_modversions)                                                \
        scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' > $(@D)/.$(@F).tmp;  \
        rm -f $(depfile);                                                 \
        mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd
endef



这个定义不仅生成依赖文件,还生成.applets.o.cmd,看一下这个文件的内容:

1
2
3
4
5
6
7
8
9
10
11
cmd_applets/applets.o := /home/yuan/toolchain/crosstool-ipq4018/bin/arm-linux-gnueabihf-gcc -Wp,-MD,applets/.applets.o.d  -std=gnu99 -Iinclude -Ilibbb -Iinclude2 -I/work/staging/source/busybox-1.31.1/include -I/work/staging/source/busybox-1.31.1/libbb -include include/autoconf.h -D_GNU_SOURCE -DNDEBUG -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D"BB_VER=KBUILD_STR(1.31.1)" -I/work/staging/source/busybox-1.31.1/applets -Iapplets -Wall -Wshadow -Wwrite-strings -Wundef -Wstrict-prototypes -Wunused -Wunused-parameter -Wunused-function -Wunused-value -Wmissing-prototypes -Wmissing-declarations -Wno-format-security -Wdeclaration-after-statement -Wold-style-definition -fno-builtin-strlen -finline-limit=0 -fomit-frame-pointer -ffunction-sections -fdata-sections -fno-guess-branch-probability -funsigned-char -static-libgcc -falign-functions=1 -falign-jumps=1 -falign-labels=1 -falign-loops=1 -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-builtin-printf -Os  -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(applets)"  -D"KBUILD_MODNAME=KBUILD_STR(applets)" -c -o applets/applets.o /work/staging/source/busybox-1.31.1/applets/applets.c
 
deps_applets/applets.o := \
  /work/staging/source/busybox-1.31.1/applets/applets.c \
    $(wildcard include/config/build/libbusybox.h) \
  /home/yuan/toolchain/crosstool-ipq4018/arm-linux-gnueabihf/sysroot/usr/include/stdc-predef.h \
  /work/staging/source/busybox-1.31.1/include/busybox.h \
    $(wildcard include/config/feature/prefer/applets.h) \
    $(wildcard include/config/feature/sh/standalone.h) \
    $(wildcard include/config/feature/sh/nofork.h) \
    $(wildcard include/config/feature/suid.h) \


可以看到不仅依赖变了,如果编译.o的命令变了,比如CFLAGS变了,那么也会重新编译.o,这是内核编译的逻辑。


那么打印出cmd_cc_o_c,cmd_applets/applets.o两个变量,发现后者少了#之后的内容。这样就明朗了,在.cmd文件中,内容是完整的,但是在老的ubuntu上是可以编译的,其Make版本是4.1,而ubuntu 20上的版本是4.3

$ make --version
GNU Make 4.3
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

rule_cc_o_c,调用scripts/Kbuild.include中的make-cmd来转义cc_o_c,其定义如下:

make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1)))))


核心就是替换#为\#,在变量的定义中,是需要转义的。在老的Make中,函数中的#需要转移,但是新的不需要转义。写一个测试Makefile:

1
2
3
4
5
6
cmd_a := "12\#34"
make-cmd = $(subst \#,\\\#,$(cmd_a))
 
$(info $(value make-cmd))
 
all: ;


在Make 4.3中输出为:

$(subst \#,\\\#,$(cmd_a))

可以看到是把\#,替换为\\\#,就出问题了。


在Make 4.1中的输出为:

$(subst #,\#,$(cmd_a))


网上有类似的问题:

http://savannah.gnu.org/bugs/?20513


Copyright © linuxdev.cc 2017-2024. Some Rights Reserved.