首页 > 解决方案 > 根据 openwrt 包版本应用补丁

问题描述

我们知道,在openwrt中,通常某个包的补丁应该放在package/[pkg]/patches中,它会通过$(Build/Patch)应用到Makefile中。例子:

当包更新到新版本时,补丁有时也需要更新。例子:

或者

对于单个特定的包版本,这很好用。唯一的事情是手动更新软件包版本和补丁。

由于某种原因,旧补丁无法在升级包时应用并提交到包源。所以它们必须通过补丁来维护。

我正在做的是,如果 Makefile 可以根据包版本自动找到正确的补丁。我选择将所有这些补丁放在基于包版本的“package/test/file/patches/”目录中,例如:

在 Makefile 中,应首先将正确的补丁复制到“define Build/Prepare”部分中的“package/test/patches/”目录中,在 $(Build/Patch) 之前。

匹配规则:(这里不知道怎么插入表格,我放了一张图片代替...)

匹配最新版本

因此,通过这种方式,所有补丁都可以存储在“pacakge/test”目录中,并在构建时自动匹配和应用。

问题是,我怎样才能找到正确的匹配?因为比较和匹配版本有点复杂,尤其是在Makefile中而不是在 shell 脚本中。

其实我找到了一些有趣的脚本来做这部分,比如:</p>

如何在 bash 中比较两个字符串中的点分隔版本格式

标签: bashmakefilepackagegnu-makeopenwrt

解决方案


虽然我不完全了解您想要将哪个版本号与哪个补丁或其他方式进行比较,但以下代码片段将让您了解如何借助专为此类设计的 GNUmake 表工具包GNUmake通过编程解决任务问题:

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)>)
                                                                                                                                                                                                                                             

输出:

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.

推荐阅读