huangcm
2025-09-01 53d8e046ac1bf2ebe94f671983e3d3be059df91a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
###
# build: Generic definitions
#
#  Lots of this code have been borrowed or heavily inspired from parts
#  of kbuild code, which is not credited, but mostly developed by:
#
#  Copyright (C) Sam Ravnborg <sam@mars.ravnborg.org>, 2015
#  Copyright (C) Linus Torvalds <torvalds@linux-foundation.org>, 2015
#
 
###
# Convenient variables
comma   := ,
squote  := '
pound   := \#
 
###
# Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o
dot-target = $(dir $@).$(notdir $@)
 
###
# filename of target with directory and extension stripped
basetarget = $(basename $(notdir $@))
 
###
# The temporary file to save gcc -MD generated dependencies must not
# contain a comma
depfile = $(subst $(comma),_,$(dot-target).d)
 
###
# Check if both arguments has same arguments. Result is empty string if equal.
arg-check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
                    $(filter-out $(cmd_$@),   $(cmd_$(1))) )
 
###
# Escape single quote for use in echo statements
escsq = $(subst $(squote),'\$(squote)',$1)
 
# Echo command
# Short version is used, if $(quiet) equals `quiet_', otherwise full one.
echo-cmd = $(if $($(quiet)cmd_$(1)),\
           echo '  $(call escsq,$($(quiet)cmd_$(1)))';)
 
###
# Replace >$< with >$$< to preserve $ when reloading the .cmd file
# (needed for make)
# Replace >#< with >$(pound)< to avoid starting a comment in the .cmd file
# (needed for make)
# Replace >'< with >'\''< to be able to enclose the whole string in '...'
# (needed for the shell)
make-cmd = $(call escsq,$(subst $(pound),$$(pound),$(subst $$,$$$$,$(cmd_$(1)))))
 
###
# Find any prerequisites that is newer than target or that does not exist.
# PHONY targets skipped in both cases.
any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^)
 
###
# Copy dependency data into .cmd file
#  - gcc -M dependency info
#  - command line to create object 'cmd_object :='
dep-cmd = $(if $(wildcard $(fixdep)),                                           \
           $(fixdep) $(depfile) $@ '$(make-cmd)' > $(dot-target).tmp;           \
           rm -f $(depfile);                                                    \
           mv -f $(dot-target).tmp $(dot-target).cmd,                           \
           printf '$(pound) cannot find fixdep (%s)\n' $(fixdep) > $(dot-target).cmd; \
           printf '$(pound) using basic dep data\n\n' >> $(dot-target).cmd;           \
           cat $(depfile) >> $(dot-target).cmd;                                 \
           printf '\n%s\n' 'cmd_$@ := $(make-cmd)' >> $(dot-target).cmd)
 
###
# if_changed_dep  - execute command if any prerequisite is newer than
#                   target, or command line has changed and update
#                   dependencies in the cmd file
if_changed_dep = $(if $(strip $(any-prereq) $(arg-check)),         \
                  @set -e;                                         \
                  $(echo-cmd) $(cmd_$(1)) && $(dep-cmd))
 
# if_changed      - execute command if any prerequisite is newer than
#                   target, or command line has changed
if_changed = $(if $(strip $(any-prereq) $(arg-check)),                   \
              @set -e;                                                   \
              $(echo-cmd) $(cmd_$(1));                                   \
              printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)
 
###
# C flags to be used in rule definitions, includes:
# - depfile generation
# - global $(CFLAGS)
# - per target C flags
# - per object C flags
# - BUILD_STR macro to allow '-D"$(variable)"' constructs
c_flags_1 = -Wp,-MD,$(depfile) -Wp,-MT,$@ $(CFLAGS) -I$(dir $@) -D"BUILD_STR(s)=\#s" -D"KBUILD_NAME=BUILD_STR($(basetarget))" $(CFLAGS_$(basetarget).o) $(CFLAGS_$(obj))
c_flags_2 = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(c_flags_1))
c_flags   = $(filter-out $(CFLAGS_REMOVE_$(obj)), $(c_flags_2))
cxx_flags = -Wp,-MD,$(depfile) -Wp,-MT,$@ $(CXXFLAGS) -I$(dir $@) -D"BUILD_STR(s)=\#s" $(CXXFLAGS_$(basetarget).o) $(CXXFLAGS_$(obj))
 
###
## HOSTCC C flags
 
host_c_flags = -Wp,-MD,$(depfile) -Wp,-MT,$@ $(CHOSTFLAGS) -D"BUILD_STR(s)=\#s" $(CHOSTFLAGS_$(basetarget).o) $(CHOSTFLAGS_$(obj))
 
###
# Easy method for doing a status message
       kecho := echo
 quiet_kecho := :
silent_kecho := :
kecho := $($(quiet)kecho)
 
###
# filechk is used to check if the content of a generated file is updated.
# Sample usage:
# define filechk_sample
#    echo $KERNELRELEASE
# endef
# version.h : Makefile
#    $(call filechk,sample)
# The rule defined shall write to stdout the content of the new file.
# The existing file will be compared with the new one.
# - If no file exist it is created
# - If the content differ the new file is used
# - If they are equal no change, and no timestamp update
# - stdin is piped in from the first prerequisite ($<) so one has
#   to specify a valid file as first prerequisite (often the kbuild file)
define filechk
   $(Q)set -e;                \
   $(kecho) '  CHK     $@';        \
   mkdir -p $(dir $@);            \
   $(filechk_$(1)) < $< > $@.tmp;        \
   if [ -r $@ ] && cmp -s $@ $@.tmp; then    \
       rm -f $@.tmp;            \
   else                    \
       $(kecho) '  UPD     $@';    \
       mv -f $@.tmp $@;        \
   fi
endef