linux核心版本本地版本號的檢查

vc66vcc發表於2016-10-19
在一次編譯kernel版本的時候我突然發現,“2.6.35.7“的核心版本編譯成功後生成的版本號變成了“2.6.35.7+”,百思不得其解為什麼後面會多一個加號。一步一步的查詢,我發現了問題所在,原來問題出現在linux的版本控制這一塊。
開啟Makefile我們可以在檔案的最上面可以發現
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 35
EXTRAVERSION = .7
NAME = Yokohama
這些就是告訴我們核心版本的版本號,生成出來的版本號理論上不應帶+號,但為什麼帶+號呢。繼續往下看。
在編譯成功後,我發現在kernel.release這個檔案是生成的帶有版本號的檔案,開啟後發現還是帶+號,這肯定是生成這一個檔案的指令碼有問題所導致,繼續查詢,在主Makefile裡面發現了生成kernel.release檔案的指令碼
# 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))" > $@這個指令碼是從根目錄呼叫了setlocalversion的指令碼來生成版本號,並輸出到kernel.release中的。開啟setlocalversion發現這個檔案為bash的指令碼。檔案頭說明告訴我們這是一個增加本地版本號的指令碼,那個+號可能就是通過這個指令碼增加的本地版本號。
#!/bin/sh
#
# This scripts adds local version information from the version
# control systems git, mercurial (hg) and subversion (svn).
#
# If something goes wrong, send a mail the kernel build mailinglist
# (see MAINTAINERS) and CC Nico Schottelius
.
#
通過閱讀指令碼,發現在指令碼最後呼叫了一段程式
# 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_AUTO = y 這段程式會通過scm_version函式配置本地版本號。如果不為y,則會增加一個+號。我們目前的程式碼中CONFIG_LOCALVERSION_AUTO是沒有開啟的,應該開啟,接受linux的版本檢查。原來如此,加號是這樣加上去的。如果不想破壞這段程式碼,該如何去掉加號呢?那只有研究scm_version函式了。函式中有一段如下函式
        # Check for git and a git repo.
        if head=`git rev-parse --verify --short HEAD 2>/dev/null`; then                # If we are at a tagged commit (like "v2.6.30-rc6"), we ignore
                # it, because this version is defined in the top level Makefile.
                if [ -z "`git describe --exact-match 2>/dev/null`" ]; then                        # If only the short version is requested, don't bother
                        # running further git commands
                        if $short; then
                                echo "+"
                                return
                        fi
                        # If we are past a tagged commit (like
                        # "v2.6.30-rc5-302-g72357d5"), we pretty print it.
                        if atag="`git describe 2>/dev/null`"; then
                                echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'                        # If we don't have a tag at all we print -g{commitish}.
                        else
                                printf '%s%s' -g $head
                        fi
                fi                # Is this git on svn?
                if git config --get svn-remote.svn.url >/dev/null; then
                        printf -- '-svn%s' "`git svn find-rev $head`"
                fi                # Update index only on r/w media
                [ -w . ] && git update-index --refresh --unmerged > /dev/null                # Check for uncommitted changes
                if git diff-index --name-only HEAD | grep -v "^scripts/package" \
                    | read dummy; then
                        printf '%s' -dirty
                fi                # All done with git
                return
        fi
他用bash判斷語句來判斷git rev-parse --verify --short 來判斷當前是否是git版本庫管理,並輸出一個短的版本庫HEAD revision的短編碼,如果存在則繼續走。因為我的核心是在git版本庫中的,因此肯定走這個地方。
接下來的程式碼 -z是判斷字串是否是0,是0則輸出真。關鍵在git describe --exact-match的執行結果。這一句是描述出tag的標識。如果沒有tag就為空,那麼整個if語句就為真,就會執行下去,下面的echo “+”,這就會在版本號中輸出一個+號。
如果我們在版本庫中,git tag -a -m "v0.1" v0.1 後,我們在執行git describe --exact-match這一句,發現輸出的是我們的tag標識。那if語句就不成裡了,就不會echo “+”了。
但是問題又出現了,我發現,這樣弄好後,版本號中出現了“2.6.35。7-dirty”,為什麼呢?繼續看上面的程式碼,printf -dirty的地方進行了git diff的檢查,也就是說我有修改過的,沒有上傳的檔案。到此基本上原因全部查明,我把檔案進行上傳後,重新make prepare後,生成額kernel.release果然正確了。
結論,linux對版本的管理相當嚴格,這也就讓我們在進行程式碼管理中必須嚴格要求自己,比如發版本前,先檢查是否還有修改為上傳的檔案,然後要在git版本庫中打一個tag。

相關文章