Linux - Extraktion der Kernelversion
-
Ich habe hier einen Hardware-Treiber mit Patchfunktion, der die Kernelversion aus
include/linux/version.h bzw. include/generated/uapi/linux/version.h
ermittelt. Diese Dateien existieren aber erst nachdem wenigstens make prepare gelaufen ist. Ich möchte das make-File des Treibers gerne so anpassen, dass der Patch auch ohne irgendwelche vorherigen Build-Schritte im Linuxtree aufgespielt werden kann. Gibt es eine offizielle Methode, die Version zu bestimmen?Der entsprechende Teil des make-Files sieht gegenwärtig so aus.
VERSION_H := $(shell sh -c " \ if test -f $(KERNELDIR)/include/linux/version.h; then \ echo $(KERNELDIR)/include/linux/version.h; \ elif test -f $(KERNELDIR)/include/generated/uapi/linux/version.h; then \ echo $(KERNELDIR)/include/generated/uapi/linux/version.h; \ fi") MAJOR := $(shell expr `grep LINUX_VERSION_CODE $(VERSION_H) | cut -d\ -f3` / 65536 % 65536) MINOR := $(shell expr `grep LINUX_VERSION_CODE $(VERSION_H) | cut -d\ -f3` / 256 % 256) KERNEL_VER := $(MAJOR).$(MINOR)
und falls die Dateien nicht existieren, ist VERSION_H leer und grep benutzt die Standardeingabe, was nicht optimal ist.
-
version.h wird nach dem Makefile so generiert:
define filechk_version.h (echo \#define LINUX_VERSION_CODE $(shell \ expr $(VERSION) \* 65536 + 0$(PATCHLEVEL) \* 256 + 0$(SUBLEVEL)); \ echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))';) endef
Und die relevante Information sollte mit
# Read KERNELRELEASE from include/config/kernel.release (if it exists) KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null) KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION) export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
auch dem Modul-Makefile zur Verfügung stehen.
D.h. wenn ich das richtig überflogen habe, müsste dein gezeigter Code eine umständliche Schreibweise für
MAJOR := $(VERSION) MINOR := $(PATCHLEVEL) KERNEL_VER := $(MAJOR).$(MINOR)
sein. Je nachdem, wofür KERNEL_VER verwendet wird, würde ich sogar nur
KERNEL_VER := $(KERNELVERSION)
schreiben.
-
include/config existiert auch nicht nach einem make mrproper
Allerdings beginnt bei mir $(KERNELDIR)/Makefile mitVERSION = 3 PATCHLEVEL = 11 SUBLEVEL = 2
Der Installer des Treibers (für eine RAID-Karte) soll sowohl mit einem vollständigen Linux-Sourcetree zurecht kommen (zwecks Integration), als auch, wenn nur mit den notwendigen Header vorhanden sind (z.B. mit LiveCD) um ein Modul bauen und installieren zu können. In letzterem Fall dürfte das Makefile nicht existieren.
Ich verwende jetzt
VERSION_H := $(shell sh -c " \ if test -f $(KERNELDIR)/include/linux/version.h; then \ echo $(KERNELDIR)/include/linux/version.h; \ elif test -f $(KERNELDIR)/include/generated/uapi/linux/version.h; then \ echo $(KERNELDIR)/include/generated/uapi/linux/version.h; \ fi") ifneq ($(VERSION_H),) MAJOR := $(shell expr `grep LINUX_VERSION_CODE $(VERSION_H) | cut -d\ -f3` / 65536 % 65536) MINOR := $(shell expr `grep LINUX_VERSION_CODE $(VERSION_H) | cut -d\ -f3` / 256 % 256) else ifneq ($(strip $(wildcard $(KERNELDIR)/Makefile)),) MAJOR := $(shell expr `grep "^VERSION =" $(KERNELDIR)/Makefile | cut -d\ -f3`) MINOR := $(shell expr `grep "^PATCHLEVEL =" $(KERNELDIR)/Makefile | cut -d\ -f3`) else $(error Cannot find kernel version. Check $(KERNELDIR)/include/linux/version.h.) endif endif KERNEL_VER := $(MAJOR).$(MINOR)
was soweit zu funktionieren scheint.
-
Wenn du das aus der Kernel-Makefile ziehen willst und Zeit nicht so kritisch ist (also du ne Extrasekunde hast), geht "make kernelversion" bzw. "$(shell make -f $(KERNELDIR)/Makefile kernelversion)".