1. 前言

 UBOOT版本:uboot2018.03,开发板myimx8mmek240。

2. 概述

在编译uboot的过程中,有两个特别的依赖version_h 和 timestamp_h,它们定义在顶层Makefile中(这里只讲解编译直接在源目录的情况,即srctree 为空),如下:

# 顶层Makefile

version_h := include/generated/version_autogenerated.h
timestamp_h := include/generated/timestamp_autogenerated.h ...... $(version_h): include/config/uboot.release FORCE
$(call filechk,version.h) $(timestamp_h): $(srctree)/Makefile FORCE
$(call filechk,timestamp.h)

3. 目标$(version_h)

# 顶层Makefile
$(version_h): include/config/uboot.release FORCE
$(call filechk,version.h)

3.1 $(version_h)依赖分析

3.1.1 依赖include/config/uboot.release

使用scripts/setlocalversion工具来生成include/config/uboot.release,只是一个版本号,不需要特别关注,参见LINUX 内核编译 LOCALVERSION 配置(分析内核版本号自动添加的"+"号)

# 顶层Makefile
# Store (new) UBOOTRELEASE string in include/config/uboot.release
include/config/uboot.release: include/config/auto.conf FORCE
$(call filechk,uboot.release)

include/config/uboot.release定义在顶层Makefile中,该目标又依赖于include/config/auto.conf(参见UBOOT编译--- include/config/auto.conf、 include/config/auto.conf.cmd、 include/generated/autoconf.h (二)) 和 FORCE。

接下来我们看规则$(call filechk,uboot.release):

#note:scripts/Kbuild.include
###
# 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

上述代码中:

  • ‘$@’ :目标include/config/uboot.release ;
  • ‘$(1)’ :第一个参数uboot.release;
  • ‘$ <’ :第一个依赖include/config/auto.conf ;
  • ‘filechk_$(1)’ :filechk_uboot.release;

filechk_uboot.release定义在顶层Makefile中:

#note:顶层Makefile
# Read UBOOTRELEASE from include/config/uboot.release (if it exists)
UBOOTRELEASE = $(shell cat include/config/uboot.release 2> /dev/null)
UBOOTVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION) ...... define filechk_uboot.release
echo "$(UBOOTVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))"
endef

全部展开,具体编译命令如下:

set -e; : '  CHK     include/config/uboot.release'; mkdir -p include/config/;   echo "2018.03$(/bin/sh ./scripts/setlocalversion .)" < include/config/auto.conf > include/config/uboot.release.tmp; if [ -r include/config/uboot.release ] && cmp -s include/config/uboot.release include/config/uboot.release.tmp; then rm -f include/config/uboot.release.tmp; else : '  UPD     include/config/uboot.release'; mv -f include/config/uboot.release.tmp include/config/uboot.release; fi

最终产生的include/config/uboot.release内容如下:

3.1.2 依赖FORCE

参见UBOOT编译--- make xxx_deconfig过程详解(一) 4.3小节 - 依赖 FORCE

3.2 $(version_h)规则分析

接下来我们看规则$(call filechk,version.h):

#note:scripts/Kbuild.include
###
# 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

上述代码中:

  • ‘$@’ :目标include/generated/version_autogenerated.h;
  • ‘$(1)’ :第一个参数version.h;
  • ‘$ <’ :第一个依赖include/config/uboot.release;
  • ‘filechk_$(1)’ :filechk_version.h;

filechk_version.h定义在顶层Makefile中:

#note:顶层Makefile
define filechk_version.h
(echo \#define PLAIN_VERSION \"$(UBOOTRELEASE)\"; \
echo \#define U_BOOT_VERSION \"U-Boot \" PLAIN_VERSION; \
echo \#define CC_VERSION_STRING \"$$(LC_ALL=C $(CC) --version | head -n 1)\"; \
echo \#define LD_VERSION_STRING \"$$(LC_ALL=C $(LD) --version | head -n 1)\"; )
endef

这上面主要时输出uboot版本和编译器版本。整个命令的流程如下:

(1)打印 ' CHK include/generated/version_autogenerated.h';

(2)创建include/generated/目录;

(3)输出指定信息到include/generated/version_autogenerated.h中;

(4)如果include/generated/version_autogenerated.h 文件存在,且与include/generated/version_autogenerated.h.tmp相同,则直接删除include/generated/version_autogenerated.h.tmp;

(5)如果4不成立,打印' UPD include/generated/version_autogenerated.h',并把include/generated/version_autogenerated.h.tmp更名为include/generated/version_autogenerated.h。

使用cmp命令比较include/generated/version_autogenerated.h include/generated/version_autogenerated.h.tmp两个文件(Linux中的cmp命令用于比较两个文件的不同,若发现两个文件有不同支出,则会标出来第一处不同的位置和列数编号;s或--quiet或--silent: 不显示错误信息)

全部展开,具体编译命令如下:

set -e; : '  CHK     include/generated/version_autogenerated.h'; mkdir -p include/generated/;   (echo \#define PLAIN_VERSION \"2018.03""\"; echo \#define U_BOOT_VERSION \"U-Boot \" PLAIN_VERSION; echo \#define CC_VERSION_STRING \"$(LC_ALL=C /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc --version | head -n 1)\"; echo \#define LD_VERSION_STRING \"$(LC_ALL=C /home/h/my-work/03_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-ld.bfd --version | head -n 1)\"; ) < include/config/uboot.release > include/generated/version_autogenerated.h.tmp; if [ -r include/generated/version_autogenerated.h ] && cmp -s include/generated/version_autogenerated.h include/generated/version_autogenerated.h.tmp; then rm -f include/generated/version_autogenerated.h.tmp; else : '  UPD     include/generated/version_autogenerated.h'; mv -f include/generated/version_autogenerated.h.tmp include/generated/version_autogenerated.h; fi

include/generated/version_autogenerated.h内容如下:

4. 目标$(timestamp_h)

# 顶层Makefile
$(timestamp_h): $(srctree)/Makefile FORCE
$(call filechk,timestamp.h)

4.1 $(timestamp_h)依赖分析

目标 timestamp_h依赖$(srctree)/Makefile 和FORCE。假设直接在源目录编译,顶层Makefile存在,依赖FORCE见UBOOT编译--- make xxx_deconfig过程详解(一) 4.3小节 - 依赖 FORCE

4.2 $(timestamp_h)规则分析

接下来我们看规则$(call filechk,timestamp.h):

#note:scripts/Kbuild.include
###
# 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

上述代码中:

  • ‘$@’ :目标timestamp_h (include/generated/timestamp_autogenerated.h);
  • ‘$(1)’ :第一个参数timestamp.h;
  • ‘$ <’ :第一个依赖$(srctree)/Makefile ;
  • ‘filechk_$(1)’ :filechk_timestamp.h;

filechk_timestamp.h定义在顶层Makefile中:

#note:顶层Makefile
define filechk_timestamp.h
(if test -n "$${SOURCE_DATE_EPOCH}"; then \
SOURCE_DATE="@$${SOURCE_DATE_EPOCH}"; \
DATE=""; \
for date in gdate date.gnu date; do \
$${date} -u -d "$${SOURCE_DATE}" >/dev/null 2>&1 && DATE="$${date}"; \
done; \
if test -n "$${DATE}"; then \
LC_ALL=C $${DATE} -u -d "$${SOURCE_DATE}" +'#define U_BOOT_DATE "%b %d %C%y"'; \
LC_ALL=C $${DATE} -u -d "$${SOURCE_DATE}" +'#define U_BOOT_TIME "%T"'; \
LC_ALL=C $${DATE} -u -d "$${SOURCE_DATE}" +'#define U_BOOT_TZ "%z"'; \
LC_ALL=C $${DATE} -u -d "$${SOURCE_DATE}" +'#define U_BOOT_DMI_DATE "%m/%d/%Y"'; \
LC_ALL=C $${DATE} -u -d "$${SOURCE_DATE}" +'#define U_BOOT_BUILD_DATE 0x%Y%m%d'; \
else \
return 42; \
fi; \
else \
LC_ALL=C date +'#define U_BOOT_DATE "%b %d %C%y"'; \
LC_ALL=C date +'#define U_BOOT_TIME "%T"'; \
LC_ALL=C date +'#define U_BOOT_TZ "%z"'; \
LC_ALL=C date +'#define U_BOOT_DMI_DATE "%m/%d/%Y"'; \
LC_ALL=C date +'#define U_BOOT_BUILD_DATE 0x%Y%m%d'; \
fi)
endef

这上面首先判断在环境变量中是否定义了 SOURCE_DATE_EPOCH ,有则使用 SOURCE_DATE_EPOCH 生成时间戳,没有则使用当前时间。有些编译环境会设置,这个目前我所了解的作用是保证uboot二进制一致性会用到(有机会我们后面会针对镜像二进制一致性单独写一篇)。LC_ALL=C 是为了去除所有本地化的设置,让命令能正确执行。date命令的功能是显示和设置系统日期和时间,使用规则可以参见:linux date命令。在我所使用的的平台暂时没有定义,因此走else分支。整个命令的流程如下:

(1)打印 ' CHK include/generated/timestamp_autogenerated.h';

(2)创建include/generated/目录;

(3)通过date命令,定义几个宏定义,并输出到include/generated/timestamp_autogenerated.h.tmp中;

(4)如果include/generated/timestamp_autogenerated.h 文件存在,且与include/generated/timestamp_autogenerated.h.tmp相同,则直接删除include/generated/timestamp_autogenerated.h.tmp;

(5)如果4不成立,打印' UPD include/generated/timestamp_autogenerated.h',并把include/generated/timestamp_autogenerated.h.tmp更名为include/generated/timestamp_autogenerated.h。

使用cmp命令比较include/generated/timestamp_autogenerated.h include/generated/timestamp_autogenerated.h.tmp两个文件(Linux中的cmp命令用于比较两个文件的不同,若发现两个文件有不同支出,则会标出来第一处不同的位置和列数编号;s或--quiet或--silent: 不显示错误信息)

全部展开,具体编译命令如下:

set -e; : '  CHK     include/generated/timestamp_autogenerated.h'; mkdir -p include/generated/;         (if test -n "${SOURCE_DATE_EPOCH}"; then SOURCE_DATE="@${SOURCE_DATE_EPOCH}"; DATE=""; for date in gdate date.gnu date; do ${date} -u -d "${SOURCE_DATE}" >/dev/null 2>&1 && DATE="${date}"; done; if test -n "${DATE}"; then LC_ALL=C ${DATE} -u -d "${SOURCE_DATE}" +'#define U_BOOT_DATE "%b %d %C%y"'; LC_ALL=C ${DATE} -u -d "${SOURCE_DATE}" +'#define U_BOOT_TIME "%T"'; LC_ALL=C ${DATE} -u -d "${SOURCE_DATE}" +'#efine U_BOOT_TZ "%z"'; LC_ALL=C ${DATE} -u -d "${SOURCE_DATE}" +'#define U_BOOT_DMI_DATE "%m/%d/%Y"'; LC_ALL=C ${DATE} -u -d "${SOURCE_DATE}" +'#define U_BOOT_BUILD_DATE 0x%Y%m%d'; else return 42; fi; else LC_ALL=C date +'#define U_BOOT_DATE "%b %d %C%y"'; LC_ALL=C date +'#define U_BOOT_TIME "%T"'; LC_ALL=C date +'#define U_BOOT_TZ "%z"'; LC_ALL=C date +'#define U_BOOT_DMI_DATE "%m/%d/%Y"'; LC_ALL=C date +'#define U_BOOT_BUILD_DATE 0x%Y%m%d'; fi) < Makefile > include/generated/timestamp_autogenerated.h.tmp; if [ -r include/generated/timestamp_autogenerated.h ] && cmp -s include/generated/timestamp_autogenerated.h include/generated/timestamp_autogenerated.h.tmp; then rm -f include/generated/timestamp_autogenerated.h.tmp; else : '  UPD     include/generated/timestamp_autogenerated.h'; mv -f include/generated/timestamp_autogenerated.h.tmp include/generated/timestamp_autogenerated.h; fi

include/generated/timestamp_autogenerated.h内容如下:

UBOOT编译--- UBOOT的$(version_h) $(timestamp_h)(七)的更多相关文章

  1. uboot编译: uboot编译配置和编译过程

    jz2440: 韦东山Linux视频第1期_裸板_UBoot_文件系统_驱动初步\第09课第2节 u-boot分析之Makefile结构分析.WMV <嵌入式linux完全开发手册> 15 ...

  2. Hi3516开发笔记(四):Hi3516虚拟机编译uboot、kernel、roofts和userdata以及分区表

    若该文为原创文章,转载请注明原文出处本文章博客地址:https://hpzwl.blog.csdn.net/article/details/121572767红胖子(红模仿)的博文大全:开发技术集合( ...

  3. 嵌入式Linux驱动学习之路(四)u-boot编译分析

    u-boot编译分析 在配置完成后,执行make开始编译.这里打开Makefile. 首先在目标all前有一句话首先检查是否有include/config.mk文件来判断是否成功配置过. ifeq ( ...

  4. U-Boot编译过程解析

    解压u-boot-2010.03.tar.bz2就可以得到全部U-Boot源程序.在顶层目录下有29个子目录,分别存放和管理不同的源程序.这些目录中所要存放的文件有其规则,可以分为3类. ● 与处理器 ...

  5. hi3531 SDK 编译 uboot, 改动PHY地址, 改动 uboot 參数 .

    一,编译uboot SDK文档写得比較清楚了,写一下须要注意的地方吧. 1. 之前用SDK里和别人给的已经编译好的uboot,使用fastboot工具都刷不到板子上.最后自己用SDK里uboot源代码 ...

  6. 编译u-boot命令和u-boot常用命令

    一.编译u-boot命令 1.配置开发板 #make TQ2440_config 2.编译 #make all 3.交叉编译器是crosstools_3.4.5_softfloat” 使用4.3.3版 ...

  7. 编译uboot提示libasm-offsets.c10 error bad value (armv5)解决方法

    编译uboot-2016.09提示如下错误: lib/asm-offsets.c:1:0: error: bad value (armv5) for -march= switch 解决方法: 1.在命 ...

  8. 编译Uboot时提示error while loading shared libraries: libz.so.1: cannot open shared object file: No such file or directory

    在Ubuntu14.04 64位系统中已经安装了libc6:i386的库,编译Uboot时提示error while loading shared libraries: libz.so.1: cann ...

  9. hi3531 SDK 编译 uboot, 修改PHY地址, 修改 uboot 参数 .

    一,编译uboot SDK文档写得比较清楚了,写一下需要注意的地方吧. 1. 之前用SDK里和别人给的已经编译好的uboot,使用fastboot工具都刷不到板子上.最后自己用SDK里uboot源码编 ...

  10. [uboot] (第四章)uboot流程——uboot编译流程

    http://blog.csdn.net/ooonebook/article/details/53000893 以下例子都以project X项目tiny210(s5pv210平台,armv7架构)为 ...

随机推荐

  1. KFS邮件自动告警-数据比对-数据修复配置方法

    一.告警机制 用户可以通过配置告警机制,在比对完成和节点报错时接收到邮件告警. 告警机制共包含3个方面: 1. 告警配置 2. 用户订阅 3. 告警历史 KFS邮箱分两个部分,一个是接收告警信息的邮箱 ...

  2. Spark 读Hive并写入HBase

    package com.grady import org.apache.hadoop.hbase.HBaseConfiguration import org.apache.hadoop.hbase.c ...

  3. 引擎之旅 Chapter.1 高分辨率时钟

    目录 游戏中的时间线 真实时间线 游戏时间线 全局时钟的实现方式 我们如何理解时间.在现实生活中,时间就是一个有方向的直线.从一个无穷远到另一个无穷远.用数学去抽象地思考,它就是一个从无穷小到无穷大的 ...

  4. 开源即时通讯GGTalk 8.0发布,增加Linux客户端,支持在统信UOS、银河麒麟上运行!

    GGTalk在2021年推出7.0后,经过一年多时间的开发,终于推出8.0版本,实现了Linux客户端. 这几年,信创国产化的势头越来越猛,政府事企业单位都在逐步转向使用国产OS.国产CPU.国产数据 ...

  5. 数据仓库与hive

    数据仓库与hive hive--数据仓库建模工具之一 一.数据库.数据仓库 1.1 数据库 关系数据库本质上是一个二元关系,说的简单一些,就是一个二维表格,对普通人来说,最简单的理解就是一个Excel ...

  6. Elasticsearch:同步 MongoDB 数据到 Elasticsearch

    转载自:https://elasticstack.blog.csdn.net/article/details/114639152 MongoDB 是一个基于分布式文件存储的数据库.由 C++ 语言编写 ...

  7. SpringBoot 常用读取配置文件的 3 种方法!

    我们在SpringBoot框架进行项目开发中该如何优雅的读取配置呢?或者说对于一些List或者Map应该如何配置呢? 本篇主要解决如下几个问题: 1.Spring Boot有哪些常用的读取配置文件方式 ...

  8. 《吐血整理》高级系列教程-吃透Fiddler抓包教程(26)-Fiddler如何抓取Android7.0以上的Https包-上篇

    1.简介 众所周知,假如设备是android 7.0+的系统同时应用设置targetSdkVersion >= 24的话,那么应用默认是不信任安装的Fiddler用户证书的,所以你就没法抓到应用 ...

  9. SpringBoot的starter到底是什么?

    前言 我们都知道,Spring的功能非常强大,但也有些弊端.比如:我们需要手动去配置大量的参数,没有默认值,需要我们管理大量的jar包和它们的依赖. 为了提升Spring项目的开发效率,简化一些配置, ...

  10. css自定义会话框

    效果图图下: HTML代码: <div style="background-color: transparent; border: 1px #DDDDDD solid; width: ...