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. 1.1 大数据简介-hadoop-最全最完整的保姆级的java大数据学习资料

    目录 1 hadoop-最全最完整的保姆级的java大数据学习资料 1.1 大数据简介 1.1.1 大数据的定义 1.1.2 大数据的特点 1.1.3 大数据的应用场景 1.1.4 大数据的发展趋势及 ...

  2. Spring Boot整合log4j实战(一):排除自带依赖、日志重定向、测试类验证

    〇.参考资料 1.springboot整合log4j全过程详解 https://blog.csdn.net/m0_60845963/article/details/123307232 2.Spring ...

  3. 24V转5V降压芯片,24V转3.3V的稳压芯片,中文规格书

    一般说明PW2312 是一个高频,同步,整流,降压,开关模式转换器内部功率 MOSFET.它提供了一个非常紧凑的解决方案,以实现 1.5A 的峰值输出电流在广泛的输入电源范围内,具有优良的负载和线路调 ...

  4. 【云原生 • DevOps】一文掌握容器管理工具 Rancher

    一.容器管理工具 Rancher 介绍Rancher 是一个开源的企业级全栈化容器部署及管理平台,其实就是一个 Docker 的图形化管理界面.它为容器提供基础架构服务,可以让 CNI 兼容的网络服务 ...

  5. PRIx64:uint64_t类型输出为十六进制格式

    #include <stdio.h> #include <stdint.h> #include <inttypes.h> int main(void) { uint ...

  6. 网络监测工具之Zabbix的搭建与测试方法(一)

    简介 Zabbix是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案,它能监视各种网络参数,保证服务器系统的安全运营:并提供灵活的通知机制以让系统管理员快速定位/解决存在的 ...

  7. [OpenCV实战]8 深度学习目标检测网络YOLOv3的训练

    目录 1 数据集 1.1 下载openImages雪人数据[约1.5小时] 1.2 训练集测试集拆分 2 Darknet 2.1 下载并构建Darknet 2.2 修改代码以定期保存模型文件 2.3 ...

  8. Hadoop详解(04)-Hdfs

    Hadoop详解(04)-Hdfs HDFS概述 HDFS产出背景及定义 背景:随着数据量越来越大,在一个操作系统存不下所有的数据,那么就分配到更多的操作系统管理的磁盘中,但是不方便管理和维护,迫切需 ...

  9. [Leetcode]寻找峰值

    题目 思路 如果常规解法不考虑时间复杂度,直接遍历即可得到峰值,时间复杂度为O(n),题目要求O(logn),因此我们需要使用二分法. 首先考虑题目要求:nums[-1]=nums[n]=-∞,因此在 ...

  10. Flutter帧率监控 | 由浅入深,详解获取帧率的那些事

    前言 做线上帧率监控上报时,少不了需要弄明白如何通过代码获取实时帧率的需求,这篇文章通过图解配合Flutter性能调试工具的方式一步步通俗易懂地让你明白获取帧率的基础知识,以后再也不愁看不懂调试工具上 ...