Version number comparison inside makefile

Viewed 26827

In a makefile, I'd like to define a variable specifying whether the current redhat-release is greater than 5.3. (This variable will be passed to gcc as a #define)

So far I've come up with:

# Find out which version of Red-Hat we're running
RH_VER_NUM = $(shell /bin/grep -o [0-9].[0-9] /etc/redhat-release)
RH_GT_5_3 = $RH_VER_NUM > '5.3'

What would be the correct way to define RH_GT_5_3?

9 Answers

Building on TrueY's smart use of sort and making it a re-usable Make function:

version_greater_equal = $(shell if printf '%s\n%s\n' '$(2)' '$(1)' | \
    sort -Ct. -k1,1n -k2,2n ; then echo YES; else echo NO; fi )

ifeq (YES,$(call version_greater_equal,${SOME_VERSION},8.2))
...

With the arithmetic capabilities of the GNUmake table toolkit you can write a quite general test - the one thing you need to adapt is the Lisp-like functional style ("function op1,op2,opN"):

include gmtt/gmtt.mk

# Simulate some nasty versioning style:
# X.Y.Z.rN for release versions,
# X.rN-beta.Y.Z for beta versions towards a release
VERSION_NR_REL := $(call glob-match,$(VERSION_NR),*.*.*.r*)
VERSION_NR_BETA := $(call glob-match,$(VERSION_NR),*.r*-beta.*.*)

# glob-match only produces a non-empty result if the match succeeds,
# thus one of the following will be an empty string
$(info Release version: $(VERSION_NR_REL))
$(info Beta version: $(VERSION_NR_BETA))

# we use makes "if" function which sees empty strings as false and everything else as true
BETA_OR_RELEASE := $(if $(VERSION_NR_REL),release,beta)

# react to version numbers on different positions in release and beta
ifeq ($(BETA_OR_RELEASE),beta)
MAJOR_V := $(word 1,$(VERSION_NR_BETA))
MINOR_V := $(word 5,$(VERSION_NR_BETA))
BUGFIX_V := $(word 7,$(VERSION_NR_BETA))
REL_NR := $(word 3,$(VERSION_NR_BETA))
else
MAJOR_V := $(word 1,$(VERSION_NR_REL))
MINOR_V := $(word 3,$(VERSION_NR_REL))
BUGFIX_V := $(word 5,$(VERSION_NR_REL))
REL_NR := $(word 7,$(VERSION_NR_REL))
endif

GT_5_3 := $(if $(or $(call int-gt,$(MAJOR_V),5),\
                    $(and $(call int-eq,$(MAJOR_V),5),\
                          $(call int-gt,$(MINOR_V),3))),\
            yes,no)
$(info Major: $(MAJOR_V), Minor: $(MINOR_V), Bugfix: $(BUGFIX_V), Release: $(REL_NR), greater than 5.3: $(GT_5_3))

Test with a larger version number:

make VERSION_NR=18.r01-beta.3.5

Output:

Release version:
Beta version:  18 .r 01 -beta. 3 . 5
Major: 18, Minor: 3, Bugfix: 5, Release: 01, greater than 5.3:  yes

Test with a version equal to 5.3:

make VERSION_NR=5.3.12.r3

Output:

Release version:  5 . 3 . 12 .r 3
Beta version:
Major: 5, Minor: 3, Bugfix: 12, Release: 3, greater than 5.3: no
Related