uboot版本信息

VERSION = 2006 主版本号

PATCHLEVEL = 03 补丁版本号

SUBLEVEL = 次此版本号
EXTRAVERSION =  附加版本
NAME 
 
 
 

MAKEFLAGS变量

$(MAKE) -C subdir $(MAKE)就是调用“make”命令,-C 指定子目录
export VARIABLE …… //导出变量给子 make 。
unexport VARIABLE…… //不导出变量给子 make。
MAKEFLAGS += -rR --include-dir=$(CURDIR) 上述代码使用“+=”来给变量 MAKEFLAGS 追加了一些值,“-rR”表示禁止使用内置的隐含规则和变量定义,“--include-dir”指明搜索路径,”$(CURDIR)”表示当前目录。
 
 
命令输出
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
 
 
V=1 的话:
KBUILD_VERBOSE=1
quiet= 空 。
Q= 空。
V=0 或者命令行不定义 V 的话:
KBUILD_VERBOSE=0
quiet= quiet_。
Q= @。
 
make V=1  变量V=1
 
静默输出
 
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
 
export quiet Q KBUILD_VERBOSE
 
make -s  选项中的第一个单词
 
 
设置编译结果输出目录
 make O=out 生成的文件和源文件分开, 否则生成的文件在源文件的目录
 
 
代码检查
使用命令“make C=1”使能代码检查,检查那些需要重新编译的文
件。“make C=2”用于检查所有的源码文件
 
 
模块编译
使用命令“make M=dir”即可,旧语法“make
SUBDIRS=dir”也是支持的
 
ifeq ("$(origin M)", "command line")
  KBUILD_EXTMOD := $(M)
endif
 
ifeq ($(KBUILD_SRC),)
# building in the source tree
  srctree := .
else
  ifeq ($(KBUILD_SRC)/,$(dir $(CURDIR)))
    # building in a subdirectory of the source tree
    srctree := ..
  else
    srctree := $(KBUILD_SRC)
  endif
endif
objtree := .
src := $(srctree)
obj := $(objtree)
 
VPATH := $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD))
export srctree objtree VPATH
 
 
获取主机架构和系统
 
HOSTARCH := $(shell uname -m | \
  sed -e s/i.86/x86/ \
    -e s/sun4u/sparc64/ \
    -e s/arm.*/arm/ \
    -e s/sa110/arm/ \
    -e s/ppc64/powerpc/ \
    -e s/ppc/powerpc/ \
    -e s/macppc/powerpc/\
    -e s/sh.*/sh/)
 
HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
  sed -e 's/\(cygwin\).*/cygwin/')
 
export HOSTARCH HOSTOS
 
设置目标架构、交叉编译器和配置文件 
# set default to nothing for native builds
ifeq ($(HOSTARCH),$(ARCH))
  CROSS_COMPILE ?=
endif
 
KCONFIG_CONFIG ?= .config
export KCONFIG_CONFIG
 
调用 scripts/Kbuild.include
scripts/Kbuild.include: ;
include scripts/Kbuild.include
 
交叉编译工具变量设置
# Make variables (CC, etc...)
AS  = $(CROSS_COMPILE)as
# Always use GNU ld
ifneq ($(shell $(CROSS_COMPILE)ld.bfd -v 2> /dev/null),)
  LD = $(CROSS_COMPILE)ld.bfd
else
  LD= $(CROSS_COMPILE)ld
endif
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
LDR = $(CROSS_COMPILE)ldr
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
 
 
导出其他变量
export VERSION PATCHLEVEL SUBLEVEL UBOOTRELEASE UBOOTVERSION
export ARCH CPU BOARD VENDOR SOC CPUDIR BOARDDIR
export CONFIG_SHELL HOSTCC HOSTCFLAGS HOSTLDFLAGS CROSS_COMPILE AS LD CC
export CPP AR NM LDR STRIP OBJCOPY OBJDUMP
export MAKE AWK PERL PYTHON
export HOSTCXX HOSTCXXFLAGS DTC CHECK CHECKFLAGS
 
export KBUILD_CPPFLAGS NOSTDINC_FLAGS UBOOTINCLUDE OBJCOPYFLAGS LDFLAGS
export KBUILD_CFLAGS KBUILD_AFLAGS
 
 
config.mk 配置了ARCH CPU BOARD VENDOR SOC CPUDIR BOARDDIR等
 
make xxx_defconfig 过程

version_h := include/generated/version_autogenerated.h
timestamp_h := include/generated/timestamp_autogenerated.h
 
no-dot-config-targets := clean clobber mrproper distclean \
  help %docs check% coccicheck \
  ubootversion backup
 
config-targets := 0
mixed-targets := 0
dot-config := 1
 
ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
  ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),)
    dot-config := 0
  endif
endif
 
ifeq ($(KBUILD_EXTMOD),)
  ifneq ($(filter config %config,$(MAKECMDGOALS)),)
    config-targets := 1
    ifneq ($(words $(MAKECMDGOALS)),1)
      mixed-targets := 1
    endif
  endif
endif 
 
%config: scripts_basic outputmakefile FORCE
  $(Q)$(MAKE) $(build)=scripts/kconfig $@
 
 
 
MAKECMDGOALS 是 make 的一个环境变量,这个变量会保存你所指定的终极目标列表,比如执行“make mx6ull_alientek_emmc_defconfig”
ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)    保留$(MAKECMDGOALS)符合$(no-dot-config-targets)的部分,
这里得到了空,ifneq不成立, dot-config := 1保持不变

 
不单独编译模块则$(KBUILD_EXTMOD)为空, 所以ifeq ($(KBUILD_EXTMOD),)成立
ifneq ($(filter config %config,$(MAKECMDGOALS)),)的%config匹配了make mx6ull_alientek_emmc_defconfig
所以config-targets := 1
 
ifneq ($(words $(MAKECMDGOALS)),1) 多个目标, 这里不成立
 
因此最后有
config-targets = 1
mixed-targets = 0
dot-config = 1
 
make mx6ull_alientek_emmc_defconfig 匹配了目标 %config
%config: scripts_basic outputmakefile FORCE
  $(Q)$(MAKE) $(build)=scripts/kconfig $@
 
其中FORCE没有规则和依赖, 因此FORCE总是新的, 因此$(Q)$(MAKE) $(build)=scripts/kconfig $@总是被执行
PHONY += scripts_basic
PHONY += FORCE  
FORCE:
 
PHONY += scripts_basic
scripts_basic:
  $(Q)$(MAKE) $(build)=scripts/basic
  $(Q)rm -f .tmp_quiet_recordmcount
 
scripts/basic/%: scripts_basic ;
 
变量 build 是在 scripts/Kbuild.include 文件中有定义,定义如下:
build := -f $(srctree)/scripts/Makefile.build obj
即build=-f ./scripts/Makefile.build obj
scripts_basic 展开以后如下
scripts_basic:
  @make -f ./scripts/Makefile.build obj=scripts/basic //也可以没有@,视配置而定
  @rm -f . tmp_quiet_recordmcount //也可以没有@
 
同样 %config展开有
%config: scripts_basic outputmakefile FORCE    
  $(Q)$(MAKE) $(build)=scripts/kconfig $@   =>  @make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig
 
PHONY += outputmakefile
outputmakefile:
ifneq ($(KBUILD_SRC),)
  $(Q)ln -fsn $(srctree) source
  $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \
    $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
endif
 
 这里$(KBUILD_SRC)为空, ifneq ($(KBUILD_SRC),)不成立
 
最终
scripts_basic 目标对应的命令 @make -f ./scripts/Makefile.build obj=scripts/basic

%config 目标对应的命令 @make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig
其中 %config依赖scripts_basic,另外两个outputmakefile, FORCE没有构建命令
 
Makefile.build 脚本分析
 
scripts_basic 目标对应的命令
 
# Modified for U-Boot
prefix := tpl
src := $(patsubst $(prefix)/%,%,$(obj))
ifeq ($(obj),$(src))
prefix := spl
src := $(patsubst $(prefix)/%,%,$(obj))
ifeq ($(obj),$(src))
prefix := .
endif
endif
 
对于@make -f ./scripts/Makefile.build obj=scripts/basic
有src := $(patsubst $(prefix)/%,%,$(obj)) = $(patsubst tpl/%,%, scripts/basic), 其中scripts/basic不符合tpl/%, 没有东西被替换
所以src := scripts/basic    prefix  := .
 

kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
include $(kbuild-file)
 
将 kbuild-dir 展开后为 
$(if $(filter /%, scripts/basic), scripts/basic, ./scripts/basic),
以$(filter /%, scripts/basic)的结果为空, 所以kbuild-dir=./scripts/basic
 
将 kbuild-file 展开后为
$(if $(wildcard ./scripts/basic/Kbuild), ./scripts/basic/Kbuild, ./scripts/basic/Makefile)
因为 scrpts/basic 目录中没有 Kbuild 这个文件,所以 kbuild-file= ./scripts/basic/Makefile
 
最后为 include ./scripts/basic/Makefile
 
 
 
__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
$(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
$(subdir-ym) $(always)
  @:
 
__build 是默认目标,因为命令“@make -f ./scripts/Makefile.build obj=scripts/basic”没有指定目标,所以会使用到默认目标:__build
在顶层 Makefile 中,KBUILD_BUILTIN 为 1,KBUILD_MODULES 为 0,因此展开后目标__build 为:
__build:$(builtin-target) $(lib-target) $(extra-y)) $(subdir-ym) $(always)
  @:
 
只有 always 有效,因此__build 最终为 __build: scripts/basic/fixdep
scripts_basic 目标的作用就是编译出 scripts/basic/fixdep 这个软件
 
%config 目标对应的命令
@make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig
src= scripts/kconfig
kbuild-dir = ./scripts/kconfig
kbuild-file = ./scripts/kconfig/Makefile
include ./scripts/kconfig/Makefile
可以看出,Makefilke.build 会读取 scripts/kconfig/Makefile 中的内容,此文件有如下所示内容
%_defconfig: $(obj)/conf
  $(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
 
 # Added for U-Boot (backward compatibility)
%_config: %_defconfig
  @:
 
$(obj)/conf 为编译出来的主机工具
$(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)最终是@ scripts/kconfig/conf --defconfig=arch/../configs/xxx_defconfig Kconfig
 
最后make xxx_defconfig 执行流程总结
make xxx_defconfig -> 顶层Makefile中的%config
依赖  
  scripts_basic
    make -f ./scripts/Makefile.build obj=scripts/basic  -> 生成 script/basic/fixdep
  outputmakefile
  FORCE
 
命令 make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig 生成  scripts/kconfig/conf 
命令 scripts/kconfig/conf --defconfig=arch/../configs/xxx_defconfig Kconfig 生成 .config
 
 

make 过程
PHONY := _all
_all:
 
PHONY += all
ifeq ($(KBUILD_EXTMOD),)
_all: all
else
_all: modules
endif
 
在主 Makefile 中 all 目标规则如下
all: $(ALL-y)
ifneq ($(CONFIG_SYS_GENERIC_BOARD),y)
  @echo "===================== WARNING ======================"
  @echo "Please convert this board to generic board."
  @echo "Otherwise it will be removed by the end of 2014."
  @echo "See doc/README.generic-board for further information"
  @echo "===================================================="
endif
ifeq ($(CONFIG_DM_I2C_COMPAT),y)
  @echo "===================== WARNING ======================"
  @echo "This board uses CONFIG_DM_I2C_COMPAT. Please remove"
  @echo "(possibly in a subsequent patch in your series)"
  @echo "before sending patches to the mailing list."
  @echo "===================================================="
endif
 
all 目标依赖$(ALL-y),而在顶层 Makefile 中,ALL-y 如下
# Always append ALL so that arch config.mk's can add custom ones
ALL-y += u-boot.srec u-boot.bin u-boot.sym System.map u-boot.cfg binary_size_check
ALL-$(CONFIG_ONENAND_U_BOOT) += u-boot-onenand.bin
 
ifeq ($(CONFIG_SPL_FSL_PBL),y)
  ALL-$(CONFIG_RAMBOOT_PBL) += u-boot-with-spl-pbl.bin
else
  ifneq ($(CONFIG_SECURE_BOOT), y)
     # For Secure Boot The Image needs to be signed and Header must also
    # be included. So The image has to be built explicitly
    ALL-$(CONFIG_RAMBOOT_PBL) += u-boot.pbl
  endif
endif
 
ALL-$(CONFIG_SPL) += spl/u-boot-spl.bin
ALL-$(CONFIG_SPL_FRAMEWORK) += u-boot.img
ALL-$(CONFIG_TPL) += tpl/u-boot-tpl.bin
ALL-$(CONFIG_OF_SEPARATE) += u-boot.dtb
ifeq ($(CONFIG_SPL_FRAMEWORK),y)
  ALL-$(CONFIG_OF_SEPARATE) += u-boot-dtb.img
endif
ALL-$(CONFIG_OF_HOSTFILE) += u-boot.dtb
ifneq ($(CONFIG_SPL_TARGET),)
  ALL-$(CONFIG_SPL) += $(CONFIG_SPL_TARGET:"%"=%)
endif
ALL-$(CONFIG_REMAKE_ELF) += u-boot.elf
ALL-$(CONFIG_EFI_APP) += u-boot-app.efi
ALL-$(CONFIG_EFI_STUB) += u-boot-payload.efi
 
ifneq ($(BUILD_ROM),)
  ALL-$(CONFIG_X86_RESET_VECTOR) += u-boot.rom
endif
 
# enable combined SPL/u-boot/dtb rules for tegra
ifeq ($(CONFIG_TEGRA)$(CONFIG_SPL),yy)
  ALL-y += u-boot-tegra.bin u-boot-nodtb-tegra.bin
  ALL-$(CONFIG_OF_SEPARATE) += u-boot-dtb-tegra.bin
endif
 
# Add optional build target if defined in board/cpu/soc headers
ifneq ($(CONFIG_BUILD_TARGET),)
  ALL-y += $(CONFIG_BUILD_TARGET:"%"=%)
endif
 
ALL-y 包含 u-boot.srec、u-boot.bin、u-boot.sym、System.map、u-boot.cfg 和 binary_size_check 这几个文件。
根据 uboot 的配置情况也可能包含其他的文件,比如:ALL-$(CONFIG_ONENAND_U_BOOT) += u-boot-onenand.bin
 
 
ALL-y 里面有个 u-boot.bin,这个就是我们最终需要的 uboot 二进制可执行文件,所作的所有工作就是为了它。在顶层 Makefile 中找到 u-boot.bin 目标对应的规则
ifeq ($(CONFIG_OF_SEPARATE),y)
u-boot-dtb.bin: u-boot-nodtb.bin dts/dt.dtb FORCE
  $(call if_changed,cat)
 
u-boot.bin: u-boot-dtb.bin FORCE
  $(call if_changed,copy)
else
u-boot.bin: u-boot-nodtb.bin FORCE
  $(call if_changed,copy)
endif
 
if_changed 是 一 个 函 数 , 这 个 函 数 在scripts/Kbuild.include 中有定义,而顶层 Makefile 中会包含 scripts/Kbuild.include 文件
ifneq ($(KBUILD_NOCMDDEP),1)
  arg-check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) $(filter-out $(cmd_$@), $(cmd_$(1))) )
else  
  arg-check = $(if $(strip $(cmd_$@)),,1)
endif
 
any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^)
 
if_changed = $(if $(strip $(any-prereq) $(arg-check)), \

  @set -e;  \

  $(echo-cmd) $(cmd_$(1));  \
  printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)
 
if_change引用变量太多, 只要知道它从 u-boot-nodtb.bin 生成 u-boot.bin 就行了
 
 
目标 u-boot 依赖于 u-boot_init、u-boot-main 和 u-boot.lds
u-boot-init := $(head-y)
u-boot-main := $(libs-y)
 
head-y := arch/arm/cpu/$(CPU)/start.o
=> head-y := arch/arm/cpu/armv7/start.o

=> u-boot-init= arch/arm/cpu/armv7/start.o
 
620 libs-y += lib/
621 libs-$(HAVE_VENDOR_COMMON_LIB) += board/$(VENDOR)/common/
622 libs-$(CONFIG_OF_EMBED) += dts/
623 libs-y += fs/
624 libs-y += net/
625 libs-y += disk/
626 libs-y += drivers/
627 libs-y += drivers/dma/
628 libs-y += drivers/gpio/
629 libs-y += drivers/i2c/
......
660 libs-y += cmd/
661 libs-y += common/
662 libs-$(CONFIG_API) += api/
663 libs-$(CONFIG_HAS_POST) += post/
664 libs-y += test/
665 libs-y += test/dm/
666 libs-$(CONFIG_UT_ENV) += test/env/
667
668 libs-y += $(if $(BOARDDIR),board/$(BOARDDIR)/)
669
670 libs-y := $(sort $(libs-y))
671
672 u-boot-dirs := $(patsubst %/,%,$(filter %/, $(libs-y))) tools
examples
673
674 u-boot-alldirs := $(sort $(u-boot-dirs)
$(patsubst %/,%,$(filter %/, $(libs-))))
675
676 libs-y := $(patsubst %/, %/built-in.o, $(libs-y))
 
u-boot.lds: $(LDSCRIPT) prepare FORCE
  $(call if_changed_dep,cpp_lds)
 
built-in.o 是怎么生成的,以 drivers/gpio/built-in.o 为例
在drivers/gpio/目录下会有个名为.built-in.o.cmd 的文件
cmd_drivers/gpio/built-in.o := arm-linux-gnueabihf-ld.bfd -r -o drivers/gpio/built-in.o drivers/gpio/mxc_gpio.o
 -r =>  -r –relocateable: 产生可重定向的输出,比如,产生一个输出文件它可再次作为‘ld’的输入,这经常被叫做“部分链接”,当我们需要将几个小的.o 文件链接成为一个.o 文件的时候,需要使用此选项

 
 
最终
arm-linux-gnueabihf-ld.bfd -pie --gc-sections -Bstatic -Ttext 0x87800000 \
-o u-boot -T u-boot.lds \
arch/arm/cpu/armv7/start.o \
--start-group arch/arm/cpu/built-in.o \
arch/arm/cpu/armv7/built-in.o \
arch/arm/imx-common/built-in.o \
arch/arm/lib/built-in.o \
board/freescale/common/built-in.o \
board/freescale/mx6ull_alientek_emmc/built-in.o \
cmd/built-in.o \
common/built-in.o \
disk/built-in.o \
drivers/built-in.o \
drivers/dma/built-in.o \
drivers/gpio/built-in.o \
……
drivers/spi/built-in.o \
drivers/usb/dwc3/built-in.o \
drivers/usb/emul/built-in.o \
drivers/usb/eth/built-in.o \
drivers/usb/gadget/built-in.o \
drivers/usb/gadget/udc/built-in.o \
drivers/usb/host/built-in.o \
drivers/usb/musb-new/built-in.o \
drivers/usb/musb/built-in.o \
drivers/usb/phy/built-in.o \
drivers/usb/ulpi/built-in.o \
fs/built-in.o \
lib/built-in.o \
net/built-in.o \
test/built-in.o \
test/dm/built-in.o \
--end-group arch/arm/lib/eabi_compat.o \
-L /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin/../lib/gcc/arm-linux
gnueabihf/4.9.4 -lgcc -Map u-boot.map
 
arm-linux-gnueabihf-ld.bfd 命令将 arch/arm/cpu/armv7/start.o 和其他众多的 built_in.o 链接在一起,形成 u-boot
 
 
最后的总结
make xxx_defconfig:用于配置 uboot,这个命令最主要的目的就是生成.config 文件
make:用于编译 uboot,这个命令的主要工作就是生成二进制的 u-boot.bin 文件和其他的一些与 uboot 有关的文件,比如 u-boot.imx 等等。
 

uboot之顶层Makefile的更多相关文章

  1. UBOOT编译--- UBOOT顶层Makefile中目标_all和all的关系及背景(四)

    @ 目录 1. 前言 2. 概述 3. 老版本UBOOT(背景) 4. 新版本UBOOT 5. 参考 1. 前言 UBOOT版本:uboot2018.03,开发板myimx8mmek240. 2. 概 ...

  2. uboot 顶层makefile细节分析

    uboot的源文件众多,学习庞然大物首先找到脊椎--顶层的makfile,逐一破解.但是,uboot的makefile同样是一个庞然大物,所以也要找到它的主线.倘若过分专注部分细节,很难做到把握全局, ...

  3. TQ210 —— S5PV210 uboot顶层Makefile分析

    转自:http://blog.csdn.net/wqx521/article/details/52469759 # (C) Copyright 2000-2008 # Wolfgang Denk, D ...

  4. 内核顶层Makefile相关3

    http://www.groad.net/bbs/simple/?f104.html 伪目标 .PHONY是一个特殊工作目标(special target),它用来指定一个假想的工作目标,也就是说它后 ...

  5. 内核顶层Makefile相关4

    http://www.groad.net/bbs/simple/?f104.html make 的递归执行与 MAKEFLAGS 变量 make 的递归调用是指:在 Makefile 中使用 make ...

  6. u-boot顶层Makefile分析

    1.u-boot制作命令 make forlinx_nand_ram256_config: make all; 2.顶层mkconfig分析,参考 U-BOOT顶层目录mkconfig分析 mkcon ...

  7. UBOOT编译--- UBOOT的顶层config.mk(五)

    1. 前言 UBOOT版本:uboot2018.03,开发板myimx8mmek240. 2. 概述 此文件包含在 ./Makefile 和 spl/Makefile 中. 清理状态以避免添加两次相同 ...

  8. Uboot 2014.07 makefile分析 - 其他Cortex系列

    uboot的官网可以通过谷歌搜索得到,显示结果第一个链接就是. 官网:: http://www.denx.de/wiki/U-Boot ftp下载: ftp://ftp.denx.de/pub/u-b ...

  9. u-boot中的Makefile

    在windos下,pc机上电之后,BIOS会初始化硬件配置,为内核传递参数,引导操作系统启动,并且识别C盘.D盘.等整个操作系统启动起来之后,才可以运行应用程序比如QQ.QQ音影.同理,在嵌入式Lin ...

  10. 内核顶层Makefile相关1

    http://www.groad.net/bbs/simple/?f104.htm $(Q) 变量 内核 Makefile 文件 238 行到 259 行的注释中知道,$(Q) 变量的作用是决定是否在 ...

随机推荐

  1. 前端学习 Nginx

    前端学习 nginx 本篇主要讲解 nginx 常用命令.基础概念(正向/反向代理.负载均衡.动静分离.高可用).配置文件结构,并通过简单的实验来体验反向代理和负载均衡,最后说一下 nginx 原理. ...

  2. 关于mysql远程连接失败的问题解决

    解决办法 mysql 数据库user表配置密码 mysql 数据库user表配置plugin字段为mysql_native_password mysql 数据库user表host字段更改为% mysq ...

  3. 8.一个项目实战(下载CSDN博客文章)

    专栏地址 ʅ(‾◡◝)ʃ 前言 要写一个下载器,首先要实现一个接口函数,而这个函数可以对请求的数据进行处理也就是爬虫,其次才是写图形化界面 接口的实现 其实CSDN的浏览器页面的接口很复杂,是直接通过 ...

  4. python-面向过程与函数式

    面向过程与函数式 面向过程 "面向过程"核心是"过程"二字,"过程"指的是解决问题的步骤,即先干什么再干什么......,基于面向过程开发程 ...

  5. day 19 分组查询 & having和where区别

    day19 分组查询group by having用法 用于分组关键字(group by)后面 用于对分组之后的结果集进行筛选 having关键字后面可以使用聚合函数 having和where的区别 ...

  6. Kafka教程(三):原理及存储

    一.思维导图 1.实时更新连接 https://www.mubucm.com/doc/1GRE2U7qYuj 2.思维导图图片 二.具体内容   8.系统架构   架构推导   拓扑结构   多对多 ...

  7. 【每日一题】【回溯】2021年12月29日-93. 复原 IP 地址

    有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔. 例如:"0.1.2.201" 和 "192.1 ...

  8. 使用mysqldump备份与还原的mysql数据库

    使用mysqldump备份与还原的mysql数据库 一.mysqldump命令介绍 1.mysqldump -help 查看命令介绍: mysqldump --help 2.mysqldump登录选项 ...

  9. Bootstrap响应式相关

    bootstrap响应式布局实现原理:百分比布局+媒体查询  | 栅格系统 bootstrap和vue响应式布局的区别: 1. bootstrap 栅格系统,简,缺少组件 2. vue 速度快,组件多 ...

  10. 详解redis网络IO模型

    前言 "redis是单线程的" 这句话我们耳熟能详.但它有一定的前提,redis整个服务不可能只用到一个线程完成所有工作,它还有持久化.key过期删除.集群管理等其它模块,redi ...