简体   繁体   中英

apply the patches based on openwrt package version

In openwrt, as we known, usually the patches for a certain package should be put in package/[pkg]/patches and it will be applied in Makefile via $(Build/Patch). Example:

  • package/test/0001-1.0.1.8.fix-A.patch

  • package/test/0002-1.0.1.8.fix-B.patch

When the package update to a new version, the patches sometimes also need to be updated. Example:

  • package/test/0001-1.0.1.9.fix-A.patch
  • package/test/0002-1.0.1.9.fix-B.patch

OR

  • package/test/0001-1.0.2.0.fix-A.patch
  • package/test/0002-1.0.2.0.fix-B.patch

For a single certain package version, this works well. The only thing is to update the package version and patches manually.

For a certion reason the old patch can not be applied and submit to package source when pacakge upgrade. So they have to be maintained via patches.

What I am doing is that, if the Makefile could automatically find the right patches based on the package version. I choose to put all these patches in "package/test/file/patches/" directory base on package verion, such as:

  • package/test/file/patches/1.0.1.8/0001-v1.0.1.8.fix-A.patch
  • package/test/file/patches/1.0.1.8/0002-1.0.1.8.fix-B.patch
  • package/test/file/patches/1.0.1.9/0001-1.0.1.9.fix-A.patch
  • package/test/file/patches/1.0.1.9/0002-1.0.1.9.fix-B.patch
  • package/test/file/patches/1.0.2.0/0001-1.0.2.0.fix-A.patch
  • package/test/file/patches/1.0.2.0/0002-1.0.2.0.fix-B.patch

In the Makefile, the right patches should be copied to "package/test/patches/" directory first in "define Build/Prepare" section, before $(Build/Patch).

Match rule: (I don't know how to insert a table here, I put an image instead...)

match the latest version

So, in this way, all the patches can be stored in the "pacakge/test" directory and they will be auto matched and applied when building.

The question is, how can I achieve to find out the right match ? Since it's a little complex to compare and match the version, especially in Makefile rather than in shell script.

Actually I found some interesting script to do part of this, such as:

how-to-compare-two-strings-in-dot-separated-version-format-in-bash

While I don't exactly understand which version number you want to compare to which patch or the other way around, the following snippet will give you an idea how solve the task with GNUmake programming with the help of the GNUmake table toolkit which was designed for such problems:

include gmtt/gmtt.mk

# Helper function which converts a list of numbers into a decimal
# number with 3 digits per original version place:
vers-to-num = $(call lpad,$(word 1,$1),3,0)$(call lpad,$(word 3,$1),3,0)$(call lpad,$(word 5,$1),3,0)$(call lpad,$(word 7,$1),3,0)

VERSION := 1.1.1.4
VERS_LIST := $(call glob-match,$(word 1,$(VERSION)),*.*.*.*)
$(info VERS_LIST = $(VERS_LIST))

VERS_NUM := $(call vers-to-num,$(VERS_LIST))
$(info $(VERS_NUM))


PATCH := 1.0.2.0


# Patch to version relation:
# Table with 3 columns: patch-nr | first applicable version | last applicable version
# In case there is only one version it has to go into both columns (no empty cells!)
define PATCH_TO_VER :=
3
1.0.1.8   1.0.1.8   1.0.1.8
1.0.1.9   1.0.1.9   1.0.1.9
1.0.2.0   1.0.2.0   1.1.1.3
1.1.1.4   1.1.1.4   1.1.3.9
endef

VA_VB := $(call select,2 3,$(PATCH_TO_VER),$$(call str-eq,$(PATCH),$$1))
$(info VA_VB = $(VA_VB))

VA_LIST := $(call glob-match,$(word 1,$(VA_VB)),*.*.*.*)
VA_NUM := $(call vers-to-num,$(VA_LIST))
$(info $(VA_NUM))

VB_LIST := $(call glob-match,$(word 2,$(VA_VB)),*.*.*.*)
VB_NUM := $(call vers-to-num,$(VB_LIST))
$(info $(VB_NUM))

# Instead of comparing each version digit against upper and lower
# allowed value (the if-else tree for this gets hellish, try it
# yourself) we use gmtt's numeric range capability of at least 64
# digits to compare versions :
COMPARE_RESULT := $(if $(call int-ge,$(VERS_NUM),$(VA_NUM)),$(if $(call int-le,$(VERS_NUM),$(VB_NUM)),yes))

$(info patch version in range (empty=no): <$(COMPARE_RESULT)>)
                                                                                                                                                                                                                                             

Output:

VERS_LIST =  1 . 1 . 1 . 4
001001001004
VA_VB = 1.0.2.0 1.1.1.3
001000002000
001001001003
patch version in range (empty=no): <>
make: *** No targets.  Stop.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM