kbuild: Clean up and speed up the localversion logic

Now that we run scripts/setlocalversion during every build, it makes
sense to move all the localversion logic there. This cleans up the
toplevel Makefile and also makes sure that the script is called only
once in 'make prepare' (previously, it would be called every time due to
a variable expansion in an ifneq statement). No user-visible change is
intended, unless one runs the setlocalversion script directly.

Reported-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Greg Thelen <gthelen@google.com>
Cc: Nico Schottelius <nico-linuxsetlocalversion@schottelius.org>
Signed-off-by: Michal Marek <mmarek@suse.cz>

+137 -120
+3 -71
Makefile
··· 883 883 $(vmlinux-dirs): prepare scripts 884 884 $(Q)$(MAKE) $(build)=$@ 885 885 886 - # Build the kernel release string 887 - # 888 - # The KERNELRELEASE value built here is stored in the file 889 - # include/config/kernel.release, and is used when executing several 890 - # make targets, such as "make install" or "make modules_install." 891 - # 892 - # The eventual kernel release string consists of the following fields, 893 - # shown in a hierarchical format to show how smaller parts are concatenated 894 - # to form the larger and final value, with values coming from places like 895 - # the Makefile, kernel config options, make command line options and/or 896 - # SCM tag information. 897 - # 898 - # $(KERNELVERSION) 899 - # $(VERSION) eg, 2 900 - # $(PATCHLEVEL) eg, 6 901 - # $(SUBLEVEL) eg, 18 902 - # $(EXTRAVERSION) eg, -rc6 903 - # $(localver-full) 904 - # $(localver) 905 - # localversion* (files without backups, containing '~') 906 - # $(CONFIG_LOCALVERSION) (from kernel config setting) 907 - # $(LOCALVERSION) (from make command line, if provided) 908 - # $(localver-extra) 909 - # $(scm-identifier) (unique SCM tag, if one exists) 910 - # ./scripts/setlocalversion (only with CONFIG_LOCALVERSION_AUTO) 911 - # .scmversion (only with CONFIG_LOCALVERSION_AUTO) 912 - # + (only without CONFIG_LOCALVERSION_AUTO 913 - # and without LOCALVERSION= and 914 - # repository is at non-tagged commit) 915 - # 916 - # For kernels without CONFIG_LOCALVERSION_AUTO compiled from an SCM that has 917 - # been revised beyond a tagged commit, `+' is appended to the version string 918 - # when not overridden by using "make LOCALVERSION=". This indicates that the 919 - # kernel is not a vanilla release version and has been modified. 920 - 921 - pattern = ".*/localversion[^~]*" 922 - string = $(shell cat /dev/null \ 923 - `find $(objtree) $(srctree) -maxdepth 1 -regex $(pattern) | sort -u`) 924 - 925 - localver = $(subst $(space),, $(string) \ 926 - $(patsubst "%",%,$(CONFIG_LOCALVERSION))) 927 - 928 - # scripts/setlocalversion is called to create a unique identifier if the source 929 - # is managed by a known SCM and the repository has been revised since the last 930 - # tagged (release) commit. The format of the identifier is determined by the 931 - # SCM's implementation. 932 - # 933 - # .scmversion is used when generating rpm packages so we do not loose 934 - # the version information from the SCM when we do the build of the kernel 935 - # from the copied source 936 - ifeq ($(wildcard .scmversion),) 937 - scm-identifier = $(shell $(CONFIG_SHELL) \ 938 - $(srctree)/scripts/setlocalversion $(srctree)) 939 - else 940 - scm-identifier = $(shell cat .scmversion 2> /dev/null) 941 - endif 942 - 943 - ifdef CONFIG_LOCALVERSION_AUTO 944 - localver-extra = $(scm-identifier) 945 - else 946 - ifneq ($(scm-identifier),) 947 - ifeq ($(LOCALVERSION),) 948 - localver-extra = + 949 - endif 950 - endif 951 - endif 952 - 953 - localver-full = $(localver)$(LOCALVERSION)$(localver-extra) 954 - 955 886 # Store (new) KERNELRELASE string in include/config/kernel.release 956 - kernelrelease = $(KERNELVERSION)$(localver-full) 887 + localversion = $(shell $(CONFIG_SHELL) \ 888 + $(srctree)/scripts/setlocalversion $(srctree)) 957 889 include/config/kernel.release: include/config/auto.conf FORCE 958 890 $(Q)rm -f $@ 959 - $(Q)echo $(kernelrelease) > $@ 891 + $(Q)echo $(KERNELVERSION)$(localversion) > $@ 960 892 961 893 962 894 # Things we need to do before we recursively start building the kernel
+1 -1
scripts/package/Makefile
··· 44 44 fi 45 45 $(MAKE) clean 46 46 $(PREV) ln -sf $(srctree) $(KERNELPATH) 47 - $(CONFIG_SHELL) $(srctree)/scripts/setlocalversion > $(objtree)/.scmversion 47 + $(CONFIG_SHELL) $(srctree)/scripts/setlocalversion --scm-only > $(objtree)/.scmversion 48 48 $(PREV) tar -cz $(RCS_TAR_IGNORE) -f $(KERNELPATH).tar.gz $(KERNELPATH)/. 49 49 $(PREV) rm $(KERNELPATH) 50 50 rm -f $(objtree)/.scmversion
+133 -48
scripts/setlocalversion
··· 10 10 # 11 11 12 12 usage() { 13 - echo "Usage: $0 [srctree]" >&2 13 + echo "Usage: $0 [--scm-only] [srctree]" >&2 14 14 exit 1 15 15 } 16 16 17 - cd "${1:-.}" || usage 17 + scm_only=false 18 + srctree=. 19 + if test "$1" = "--scm-only"; then 20 + scm_only=true 21 + shift 22 + fi 23 + if test $# -gt 0; then 24 + srctree=$1 25 + shift 26 + fi 27 + if test $# -gt 0 -o ! -d "$srctree"; then 28 + usage 29 + fi 18 30 19 - # Check for git and a git repo. 20 - if head=`git rev-parse --verify --short HEAD 2>/dev/null`; then 31 + scm_version() 32 + { 33 + local short=false 21 34 22 - # If we are at a tagged commit (like "v2.6.30-rc6"), we ignore it, 23 - # because this version is defined in the top level Makefile. 24 - if [ -z "`git describe --exact-match 2>/dev/null`" ]; then 35 + cd "$srctree" 36 + if test -e .scmversion; then 37 + cat "$_" 38 + return 39 + fi 40 + if test "$1" = "--short"; then 41 + short=true 42 + fi 25 43 26 - # If we are past a tagged commit (like "v2.6.30-rc5-302-g72357d5"), 27 - # we pretty print it. 28 - if atag="`git describe 2>/dev/null`"; then 29 - echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}' 44 + # Check for git and a git repo. 45 + if head=`git rev-parse --verify --short HEAD 2>/dev/null`; then 30 46 31 - # If we don't have a tag at all we print -g{commitish}. 32 - else 33 - printf '%s%s' -g $head 47 + # If we are at a tagged commit (like "v2.6.30-rc6"), we ignore 48 + # it, because this version is defined in the top level Makefile. 49 + if [ -z "`git describe --exact-match 2>/dev/null`" ]; then 50 + 51 + # If only the short version is requested, don't bother 52 + # running further git commands 53 + if $short; then 54 + echo "+" 55 + return 56 + fi 57 + # If we are past a tagged commit (like 58 + # "v2.6.30-rc5-302-g72357d5"), we pretty print it. 59 + if atag="`git describe 2>/dev/null`"; then 60 + echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}' 61 + 62 + # If we don't have a tag at all we print -g{commitish}. 63 + else 64 + printf '%s%s' -g $head 65 + fi 34 66 fi 67 + 68 + # Is this git on svn? 69 + if git config --get svn-remote.svn.url >/dev/null; then 70 + printf -- '-svn%s' "`git svn find-rev $head`" 71 + fi 72 + 73 + # Update index only on r/w media 74 + [ -w . ] && git update-index --refresh --unmerged > /dev/null 75 + 76 + # Check for uncommitted changes 77 + if git diff-index --name-only HEAD | grep -v "^scripts/package" \ 78 + | read dummy; then 79 + printf '%s' -dirty 80 + fi 81 + 82 + # All done with git 83 + return 35 84 fi 36 85 37 - # Is this git on svn? 38 - if git config --get svn-remote.svn.url >/dev/null; then 39 - printf -- '-svn%s' "`git svn find-rev $head`" 86 + # Check for mercurial and a mercurial repo. 87 + if hgid=`hg id 2>/dev/null`; then 88 + tag=`printf '%s' "$hgid" | cut -d' ' -f2` 89 + 90 + # Do we have an untagged version? 91 + if [ -z "$tag" -o "$tag" = tip ]; then 92 + id=`printf '%s' "$hgid" | sed 's/[+ ].*//'` 93 + printf '%s%s' -hg "$id" 94 + fi 95 + 96 + # Are there uncommitted changes? 97 + # These are represented by + after the changeset id. 98 + case "$hgid" in 99 + *+|*+\ *) printf '%s' -dirty ;; 100 + esac 101 + 102 + # All done with mercurial 103 + return 40 104 fi 41 105 42 - # Update index only on r/w media 43 - [ -w . ] && git update-index --refresh --unmerged > /dev/null 106 + # Check for svn and a svn repo. 107 + if rev=`svn info 2>/dev/null | grep '^Last Changed Rev'`; then 108 + rev=`echo $rev | awk '{print $NF}'` 109 + printf -- '-svn%s' "$rev" 44 110 45 - # Check for uncommitted changes 46 - if git diff-index --name-only HEAD | grep -v "^scripts/package" \ 47 - | read dummy; then 48 - printf '%s' -dirty 111 + # All done with svn 112 + return 49 113 fi 114 + } 50 115 51 - # All done with git 116 + collect_files() 117 + { 118 + local file res 119 + 120 + for file; do 121 + case "$file" in 122 + *\~*) 123 + continue 124 + ;; 125 + esac 126 + if test -e "$file"; then 127 + res="$res$(cat "$file")" 128 + fi 129 + done 130 + echo "$res" 131 + } 132 + 133 + if $scm_only; then 134 + scm_version 52 135 exit 53 136 fi 54 137 55 - # Check for mercurial and a mercurial repo. 56 - if hgid=`hg id 2>/dev/null`; then 57 - tag=`printf '%s' "$hgid" | cut -d' ' -f2` 138 + if test -e include/config/auto.conf; then 139 + source "$_" 140 + else 141 + echo "Error: kernelrelease not valid - run 'make prepare' to update it" 142 + exit 1 143 + fi 58 144 59 - # Do we have an untagged version? 60 - if [ -z "$tag" -o "$tag" = tip ]; then 61 - id=`printf '%s' "$hgid" | sed 's/[+ ].*//'` 62 - printf '%s%s' -hg "$id" 145 + # localversion* files in the build and source directory 146 + res="$(collect_files localversion*)" 147 + if test ! "$srctree" -ef .; then 148 + res="$res$(collect_files "$srctree"/localversion*)" 149 + fi 150 + 151 + # CONFIG_LOCALVERSION and LOCALVERSION (if set) 152 + res="${res}${CONFIG_LOCALVERSION}${LOCALVERSION}" 153 + 154 + # scm version string if not at a tagged commit 155 + if test "$CONFIG_LOCALVERSION_AUTO" = "y"; then 156 + # full scm version string 157 + res="$res$(scm_version)" 158 + else 159 + # apped a plus sign if the repository is not in a clean tagged 160 + # state and LOCALVERSION= is not specified 161 + if test "${LOCALVERSION+set}" != "set"; then 162 + scm=$(scm_version --short) 163 + res="$res${scm:++}" 63 164 fi 64 - 65 - # Are there uncommitted changes? 66 - # These are represented by + after the changeset id. 67 - case "$hgid" in 68 - *+|*+\ *) printf '%s' -dirty ;; 69 - esac 70 - 71 - # All done with mercurial 72 - exit 73 165 fi 74 166 75 - # Check for svn and a svn repo. 76 - if rev=`svn info 2>/dev/null | grep '^Last Changed Rev'`; then 77 - rev=`echo $rev | awk '{print $NF}'` 78 - printf -- '-svn%s' "$rev" 79 - 80 - # All done with svn 81 - exit 82 - fi 167 + echo "$res"