OpenWrt uboot 编译时间戳问题
背景
在uboot 启动过程中会有如下打印:
U-Boot SPL 2017.11 (Aug 16 2018 - 07:51:15)
DRAM: 128 MiB
Trying to boot from MMC1U-Boot 2017.11 (Aug 16 2018 - 07:51:15 +0000) Allwinner Technology
通常我们需要通过编译时间来区分uboot 版本。在使用OpenWrt 编译时uboot 时发现上面的时间戳并不会变。造成版本不易区分问题。
要解决这问题需要清楚:
- 编译时间戳是如何生成的?
uboot 编译时间戳是如何生成的?
在uboot 的Makefile 中有如下定义
# The SOURCE_DATE_EPOCH mechanism requires a date that behaves like GNU date.
# The BSD date on the other hand behaves different and would produce errors
# with the misused '-d' switch. Respect that and search a working date with
# well known pre- and suffixes for the GNU variant of date.
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 生成时间戳,没有则使用当前时间。
在OpenWrt 的编译环境中,是会定义 SOURCE_DATE_EPOCH 的,位于openwrt/include/toplevel.mk
ifeq ($(SDK),1)
include $(TOPDIR)/include/version.mk
else
REVISION:=$(shell $(TOPDIR)/scripts/getver.sh)
SOURCE_DATE_EPOCH:=$(shell $(TOPDIR)/scripts/get_source_date_epoch.sh)
endif
其使用 $(TOPDIR)/scripts/get_source_date_epoch.sh 来获取时间戳,scripts/get_source_date_epoch.sh 内容如下:
#!/usr/bin/env bash
export LANG=C
export LC_ALL=C
[ -n "$TOPDIR" ] && cd $TOPDIR
try_version() {
[ -f version.date ] || return 1
SOURCE_DATE_EPOCH="$(cat version.date)"
[ -n "$SOURCE_DATE_EPOCH" ]
}
try_git() {
[ -e .git ] || return 1
SOURCE_DATE_EPOCH="$(git log -1 --format=format:%ct)"
[ -n "$SOURCE_DATE_EPOCH" ]
}
try_hg() {
[ -d .hg ] || return 1
SOURCE_DATE_EPOCH="$(hg log --template '{date}' -l 1 | cut -d. -f1)"
[ -n "$SOURCE_DATE_EPOCH" ]
}
try_mtime() {
perl -e 'print((stat $ARGV[0])[9])' "$0"
[ -n "$SOURCE_DATE_EPOCH" ]
}
try_version || try_git || try_hg || try_mtime || SOURCE_DATE_EPOCH=""
echo "$SOURCE_DATE_EPOCH"
其首先从 version.date 文件中读取时间戳,失败的话尝试使用git ,hg ,mtime 时间戳。
而我当前环境是存在 version.date 文件的
openwrt$ cat version.date
1534405875
这就难怪每次编译uboot 时间戳都是一样的了( Aug 16 2018 - 07:51:15)。
解决:
#!/usr/bin/env bash
export LANG=C
export LC_ALL=C
[ -n "$TOPDIR" ] && cd $TOPDIR
try_date_now(){
SOURCE_DATE_EPOCH="$(date +%s)"
}
...
try_date_now ||try_version || try_git || try_hg || try_mtime || SOURCE_DATE_EPOCH=""
echo "$SOURCE_DATE_EPOCH"