NotePublic/Software/Development/OperatingSystem/Linux/Kernel/Modules/Version/内核版本添加字符.md

5.3 KiB
Raw Blame History

内核版本添加字符

之前每次由于git仓库编译出来每次都带有'+', 导致都需要使用git archive单独拉出一个干净的源码出来编译这样一方面要重新编译耗费时间另一方面改动会更麻烦可能要本地来回打patch. 于是分享下面来解决这个问题。

有个简单的办法无论kernel还是uboot都可以在本地仓库的根目录下touch .scmversion空文件然后编译即可, .config中CONFIG_LOCALVERSION_AUTO为No, CONFIG_LOCALVERSION="" 如果不配置Auto可能导致镜像用不了

引子

编译2.6.35.7 kernel版本的时候发现“2.6.35.7“的内核版本编译成功后生成的版本号变成了“2.6.35.7+”为什么后面会多一个加号呢问题出现在linux的版本控制这一块

打开Makefile我们可以在文件的最上面可以发现

VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 35
EXTRAVERSION = .7
NAME = Yokohama

这些就是告诉我们内核版本的版本号,生成出来的版本号理论上不应带+号,但为什么带+号呢

include/config/kernel.release文件是生成的带有版本号的文件该文件由内核顶层Makefile的如下脚本处理

# Store (new) KERNELRELASE string in include/config/kernel.release
include/config/kernel.release: include/config/auto.conf FORCE
        $(Q)rm -f $@
        $(Q)echo "$(KERNELVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))" > $@

使用scripts/setlocalversion工具来生成include/config/kernel.release。“+”号就是在调用这个脚本时添加的。

阅读scripts/setlocalversion文件并查阅资料做如下笔记

为何会添加“+”号

在scripts/setlocalversion文件中有这么一段

# scm version string if not at a tagged commit
if test "$CONFIG_LOCALVERSION_AUTO" = "y"; then
 # full scm version string
 res="$res$(scm_version)"
else
 # apped a plus sign if the repository is not in a clean tagged
 # state and  LOCALVERSION= is not specified
 if test "${LOCALVERSION+set}" != "set"; then
  scm=$(scm_version --short)
  res="$res${scm:++}"
 fi
fi

如果定义了 CONFIG_LOCALVERSION_AUTOCONFIG_LOCALVERSION_AUTO=y

此时会执行第一个if下的脚本。执行res="res(scm_version)"

如果代码属于git管理打了tag则会添加tag相关字符没有打tag则会添加log相加字符例如最新的commit是:commit cdebe039ded3e7fcd00c6e5603a878b14d7e564e则编译之后文件include/config/kernel.release的内容为2.6.35.7-gcdebe03。

如果没有定义 CONFIG_LOCALVERSION_AUTO

此时会执行else下的脚本。

  • 如果没有定义LOCALVERSION版本号后面会添加“+”号执行else里的if下的脚本scm=$(scm_version --short)在函数scm_version --short里如果传入参数short会添加“+”号,
if $short; then
    echo "+"
    return
fi
  • 定义了LOCALVERSION则不会执行else里if所在的脚本从而不会在后面添加“+”号。

  • LOCALVERSION变量可在命令行定义

make LOCALVERSION=.88 include/config/kernel.release

或者添加为环境变量。

如果既不想添加字符,又不想有“+”号不定义CONFIG_LOCALVERSION_AUTO将LOCALVERSION变量定义为空LOCALVERSION=

往版本号里添加字符的方式

在scripts/setlocalversion文件中还有有这么一段

# localversion* files in the build and source directory
res="$(collect_files localversion*)"
if test ! "$srctree" -ef .; then
 res="$res$(collect_files "$srctree"/localversion*)"
fi

# CONFIG_LOCALVERSION and LOCALVERSION (if set)
res="${res}${CONFIG_LOCALVERSION}${LOCALVERSION}"

由此可看出,如果想往版本号里添加字符,有几种方式:

  • 使用LOCALVERSION变量或者在命令行或者添加为环境变量
  • 在linux-2.6.35目录下添加文件localversion文件内容会自动添加到版本号里去。
  • 定义CONFIG_LOCALVERSION变量

如果linux-2.6.35目录下有文件localversion其内容为.33也使用了LOCALVERSION变量也定义了CONFIG_LOCALVERSION=".XYZ"。

make LOCALVERSION=.44 include/config/kernel.release

此时对2.6.35.7的内核include/config/kernel.release的内容为2.6.35.7.33.XYZ.44。

可看到添加的三种字符的顺序文件localversion内容在前然后是CONFIG_LOCALVERSION的值最后是LOCALVERSION的值。

另外关于scripts/setlocalversion文件

  • 在scripts/setlocalversion文件中可用echo "aaa" >&2来输出显示相关信息例如
echo "LOCALVERSION=${LOCALVERSION}" >&2
  • 这个文件里很多地方是跟根据一些git命令来进行判断的例如
if head=`git rev-parse --verify --short HEAD 2>/dev/null`; then

    if [ -z "`git describe --exact-match 2>/dev/null`" ]; then

        if git config --get svn-remote.svn.url >/dev/null; then

            [ -w . ] && git update-index --refresh --unmerged > /dev/null

                if git diff-index --name-only HEAD | grep -v "^scripts/package" \

需要仔细注意:

使用modinfo可查看编译出来的ko文件对应的内核版本号

使用uname或者 cat /proc/version 可在目标系统上查看内核版本号。

可查看kernel编译过程生成的文件 include/generated/utsrelease.h ,确定编译出来的内核的版本号。