linux内核uname中的编译时间如何自动更新的?

帅得不敢出门
博客专家认证
2015-05-26 10:44:30
uname -a
Linux jyxtec 3.16.7-21-desktop #1 SMP PREEMPT Tue Apr 14 07:11:37 UTC 2015 (93c1539) x86_64 x86_64 x86_64 GNU/Linux
Tue Apr 14 07:11:37 UTC 2015 这个时间找到是在在include/generated/compile.h中定义的宏,而这个.h文件是由scripts/mkcompile_h脚本生成的(脚本在init/Makefile中调用)。
但是没看出它是如何保证只有在内核改变的情况下才更新这个时间(内核不改变则每次编译时间不变)

我的目的是想做个在源码改变情况下,会自动更新版本号的功能。求指教。
...全文
1037 9 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
nswcfd 2015-05-28
  • 打赏
  • 举报
回复
相关步骤,由根目录下的Makefile定义 参考以下makefile变量的定义

vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o $(kallsyms.o) FORCE
	...
	$(call if_changed_rule,vmlinux__)
	...
if_changed_rule在scripts/Kbuild.include里定义,利用make的$?发现更新的依赖文件,有关有更新,执行命令。 即,如果vmlinux的依赖部分发生了变化(也就是说,【有源代码的变化】),则执行rule_vmlinux__
	
define rule_vmlinux__:
    ...
    $(if $(CONFIG_KALLSYMS),,+$(call cmd,vmlinux_version))
    $(call cmd,vmlinux__)
	...
endef
分别调用cmd_vmlinux_version和cmd_vmlinux__

quiet_cmd_vmlinux_version = GEN     .version
      cmd_vmlinux_version = set -e;                     \
        if [ ! -r .version ]; then                      \
          rm -f .version;                               \
          echo 1 >.version;                             \
        else                                            \
          mv .version .old_version;                     \
          expr 0$$(cat .old_version) + 1 >.version;     \
        fi;                                             \
        $(MAKE) $(build)=init
更新.version文件,重新make object=init,如前所述,这会导致更新compile.h,【包含新的时间戳】 进而重新生成init/build-in.o(含version.o) cmd_vmlinux__ 重新链接,显示LD vmlinux,就不再上代码了。 这样,vmlinux的uname -r就是更新之后的了。
nswcfd 2015-05-28
  • 打赏
  • 举报
回复
相关步骤,由根目录下的Makefile定义 参考以下makefile变量的定义 quiet_cmd_vmlinux_version:对应 GEN .version 更新version文件; 执行make -f scripts/Makefile.build obj=init 更新inclue/linux/compile.h 重新编译init/version.o ....
nswcfd 2015-05-28
  • 打赏
  • 举报
回复
mkcompile不保证源代码不变,它只检查基本的配置例如SMP、PREEMPT、gcc版本等是否改变。 检查源代码变不变是make完成的事情(根据依赖关系定义和文件时间戳)。 在编译好vmlinux的基础上(version #5),修改了一个源文件,重新make vmlinux(变成version #6),发现过程是这样的
  CHK     include/linux/version.h
  CHK     include/linux/utsrelease.h
  SYMLINK include/asm -> include/asm-x86
  CALL    scripts/checksyscalls.sh
  CHK     include/linux/compile.h		<------- 这时候还是version #5,因为只CHK,没有UPD
  LD      vmlinux.o						<------- 生成vmlinux.o,应该不包含version.o
  MODPOST vmlinux.o
  GEN     .version						<-------- 更新版本号(#5->#6)
  CHK     include/linux/compile.h		<-------- 重新执行mkcompile_h
  UPD     include/linux/compile.h		<-------- 由于版本号更新,更新linux/compile.h文件
  CC      init/version.o				<-------- 生成新的version.o
  LD      init/built-in.o			    <-------- 以下是最后的链接过程
  LD      .tmp_vmlinux1
  KSYM    .tmp_kallsyms1.S
  AS      .tmp_kallsyms1.o
  LD      .tmp_vmlinux2
  KSYM    .tmp_kallsyms2.S
  AS      .tmp_kallsyms2.o
  LD      .tmp_vmlinux3
  KSYM    .tmp_kallsyms3.S
  AS      .tmp_kallsyms3.o
  CHK     include/linux/version.h
make[2]: “scripts/unifdef”是最新的。
  LD      vmlinux
  SYSMAP  System.map
  SYSMAP  .tmp_System.map 

帅得不敢出门 2015-05-28
  • 打赏
  • 举报
回复
引用 5 楼 nswcfd 的回复:
这里的逻辑是: 1)在makefile里指定一个FORCE依赖,导致每次都执行mkcompile_h这个脚本; 2)mkcompile每次生成一个临时文件(.tmpcompile),然后跟compile.h进行比较(使用cmp -s),只有产生变化的时候,才去真正替换compile.h; 3)makefile了,version.o依赖于compile.h,当compile.h修改了,才真正重新编译。 # Only replace the real compile.h if the new one is different, # in order to preserve the timestamp and avoid unnecessary # recompilations. # We don't consider the file changed if only the date/time changed. # A kernel config change will increase the generation number, thus # causing compile.h to be updated (including date/time) due to the # changed comment in the # first line.
你有点提到点子上了, 你说的我也知道,关键是mkcompile每次生成一个临时文件(.tmpcompile)这个临时文件如何保证 在源码不改变的情况下会与compile.h一致,所以又绕回我提的问题了。
nswcfd 2015-05-27
  • 打赏
  • 举报
回复
这里的逻辑是: 1)在makefile里指定一个FORCE依赖,导致每次都执行mkcompile_h这个脚本; 2)mkcompile每次生成一个临时文件(.tmpcompile),然后跟compile.h进行比较(使用cmp -s),只有产生变化的时候,才去真正替换compile.h; 3)makefile了,version.o依赖于compile.h,当compile.h修改了,才真正重新编译。 # Only replace the real compile.h if the new one is different, # in order to preserve the timestamp and avoid unnecessary # recompilations. # We don't consider the file changed if only the date/time changed. # A kernel config change will increase the generation number, thus # causing compile.h to be updated (including date/time) due to the # changed comment in the # first line.
nswcfd 2015-05-27
  • 打赏
  • 举报
回复
script/mkcomple_h在init/Makefle中被引用
$(obj)/version.o: include/linux/compile.h

# compile.h changes depending on hostname, generation number, etc,
# so we regenerate it always.
# mkcompile_h will make sure to only update the
# actual file if its content has changed.

       chk_compile.h = :
 quiet_chk_compile.h = echo '  CHK     $@'
silent_chk_compile.h = :
include/linux/compile.h: FORCE
        @$($(quiet)chk_compile.h)
        $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkcompile_h $@ \
        "$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CONFIG_PREEMPT)" "$(CC) $(KBUILD_CFLAGS)"
~
帅得不敢出门 2015-05-27
  • 打赏
  • 举报
回复
要的是编译的时候如果发现有新修改就自动加版本号(或者是写当前时间)。 linux kernel不知道是怎么实现的。
iasky 2015-05-26
  • 打赏
  • 举报
回复
我记得原来老内核,在config后,可以修改.config文件中的版本号的。搞个脚本来修改
zhxianbin 2015-05-26
  • 打赏
  • 举报
回复
版主的分数别人大啊! 没研究过,说说我的猜想:是因为不改变,就不会重新编译吧?

4,465

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 内核源代码研究区
社区管理员
  • 内核源代码研究区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧