U-Boot top layer Makefile analysis I

The top-level Makefile is the Makefile file in the root directory of uboot.

1. Version number

VERSION = 2016
PATCHLEVEL = 03
SUBLEVEL =
EXTRAVERSION =
NAME =

VERSION is the major VERSION number, PATCHLEVEL is the patch VERSION number, and SUBLEVEL is the minor VERSION number

2. Recursive call to makefile

In Makefile, use the "make" command to execute other makefile files, which are generally makefile files in subdirectories.

MAKEFLAGS += -rR --include-dir=$(CURDIR)

# Avoid funny character set dependencies
unexport LC_ALL
LC_COLLATE=C
LC_NUMERIC=C
export LC_COLLATE LC_NUMERIC

# Avoid interference with shell env settings
unexport GREP_OPTIONS

The above code uses "+ =" to append some values to the variable MAKEFLAGS, "- rR" means that the built-in implicit rules and variable definitions are prohibited, "– include dir" indicates the search path, and "$(CURDIR)" indicates the current directory.
"export" exports the variables to be passed to the child make.
The "unexport" declaration does not export variables passed to child makefile s.

3. Command output

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

The default compilation of uboot does not display complete commands in the terminal, which are short commands. In the above code, first use ifeq to judge whether "$(origin V)" and "command line" are equal. The function origin in Makefile is used here. Unlike other functions, origin does not operate on the value of variables. Origin is used to tell you where variables come from. The syntax is:
$(origin < variable>)

Variable is the name of the variable, and the return value of the origin function is the source of the variable, so $(origin V) is the source of the variable v. If the variable V is defined on the command line, its source is "command line", so "$(origin V)" and "command line" are equal. When the two are equal, the variable kbuild_ Verbose is equal to the value of V. for example, if you enter "V=1" on the command line, KBUILD_VERBOSE=1. If you do not enter V on the command line, KBUILD_VERBOSE=0.
Variables quiet and Q are used in Makefile to control whether complete commands are output at the terminal during compilation. There are many commands in the top-level Makefile as follows:
$ (Q) $(MAKE) $(build)=tools
If V=0, the above command expansion is "@ make $(build)=tools". When making is executed, the command will be output on the terminal by default, but adding "@" before the command will not output the command on the terminal. When V=1, Q is empty. The above command is "make $(build)=tools". Therefore, during the execution of make, the command will be completely output on the terminal.

4. Silent output

If V=0 is set or V is not defined in the command line, it will be displayed in the terminal when compiling uboot
Short commands, but there will still be command output. Sometimes we don't need to output commands when compiling uboot. At this time, we can use the silent output function of uboot. Silent output can be achieved by using "make -s" during compilation. The corresponding code in the top-level Makefile is as follows:

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

ifneq ($(filter 4.%,$(MAKE_VERSION)),)	# make-4
ifneq ($(filter %s ,$(firstword x$(MAKEFLAGS))),)
  quiet=silent_
endif
else					# make-3.8x
ifneq ($(filter s% -s%,$(MAKEFLAGS)),)
  quiet=silent_
endif
endif

export quiet Q KBUILD_VERBOSE

First, judge whether the version number of the compiler currently in use is 4 x. Judge whether $(filter 4.%, $(make_version)) and "" (empty) are equal. If not, it is true and execute the statements inside. In other words, if $(filter4.%, $(make_version)) is not empty, the condition is true. Here, the filter function in Makefile is used, which is a filter function. The function format is as follows:
$ (filter <pattern...>, )
The filter function means that the words in the text string are filtered in the pattern mode, and only the words conforming to the pattern are retained. There can be multiple patterns. The return value of the function is a string that matches the pattern. Therefore, $(filter 4.%, $(MAKE_VERSION)) means to find the characters matching "4.%" in the string "MAKE_VERSION" (% is a wildcard),
MAKE_VERSION is the version number of the make tool
Judgment statement if $(filter% s, $(firstword x $(makeflags))) is not empty
True, the variable quiet is equal to "silent_". The function filter is also used here to filter out words matching "% s" in $(firstword x $(makeflags)). When you get to the function firstword, the function firstword is to get the first word. The function format is as follows:
$(firstword )
The firstword function is used to retrieve the first word in the text string. The return value of the function is the obtained word. When compiling with "make -s", the "- s" is passed to Makefile as part of the MAKEFLAGS variable.

5. Set the output directory of compilation results

uboot can output the compiled target file to a separate directory. When making, use "O" to specify the output directory. For example, "make O=out" sets the target file to be output to the out directory. This is to separate the source file from the compiled file. Of course, the o parameter can not be specified. If not specified, the source file and the compiled file are in the same directory. Generally, we do not specify the o parameter.

# kbuild supports saving output files in a separate directory.
# To locate output files in a separate directory two syntaxes are supported.
# In both cases the working directory must be the root of the kernel src.
# 1) O=
# Use "make O=dir/to/store/output/files/"
#
# 2) Set KBUILD_OUTPUT
# Set the environment variable KBUILD_OUTPUT to point to the directory
# where the output files shall be placed.
# export KBUILD_OUTPUT=dir/to/store/output/files/
# make
#
# The O= assignment takes precedence over the KBUILD_OUTPUT environment
# variable.

# KBUILD_SRC is set on invocation of make in OBJ directory
# KBUILD_SRC is not intended to be used by the regular user (for now)
ifeq ($(KBUILD_SRC),)

# OK, Make called in directory where kernel src resides
# Do we want to locate output files in a separate directory?
ifeq ("$(origin O)", "command line")
  KBUILD_OUTPUT := $(O)
endif

# That's our default target when none is given on the command line
PHONY := _all
_all:

# Cancel implicit rules on top Makefile
$(CURDIR)/Makefile Makefile: ;

ifneq ($(KBUILD_OUTPUT),)
# Invoke a second make in the output directory, passing relevant variables
# check that the output directory actually exists
saved-output := $(KBUILD_OUTPUT)
KBUILD_OUTPUT := $(shell mkdir -p $(KBUILD_OUTPUT) && cd $(KBUILD_OUTPUT) \
								&& /bin/pwd)
$(if $(KBUILD_OUTPUT),, \
     $(error failed to create output directory "$(saved-output)"))

PHONY += $(MAKECMDGOALS) sub-make

$(filter-out _all sub-make $(CURDIR)/Makefile, $(MAKECMDGOALS)) _all: sub-make
	@:

sub-make: FORCE
	$(Q)$(MAKE) -C $(KBUILD_OUTPUT) KBUILD_SRC=$(CURDIR) \
	-f $(CURDIR)/Makefile $(filter-out _all sub-make,$(MAKECMDGOALS))

# Leave processing to above invocation of make
skip-makefile := 1
endif # ifneq ($(KBUILD_OUTPUT),)
endif # ifeq ($(KBUILD_SRC),)

First, judge whether "O" comes from the command line. If it comes from the command line, the condition is true, KBUILD_OUTPUT is $(O), so the variable KBUILD_OUTPUT is the output directory.
Then judge kbuild_ Whether output is empty.
Then call mkdir command to create KBUILD_OUTPUT directory, and assign the absolute path after successful creation to KBUILD_OUTPUT. At this point, the output directory specified through O exists.

Keywords: uboot

Added by sac0o01 on Sun, 19 Dec 2021 00:34:27 +0200