9

My Makefile:

FULL_VERSION ?= 1.2.3
MINOR_VERSION := $(shell echo "${FULL_VERSION%.*}")

test:
    echo $(MINOR_VERSION)

Running make test gives nothing, I want to get 1.2.

I know I can get it via sed/grep but I'm looking for a more elegant solution, seems there's nothing simpler than bash parameter expansion

2 Answers 2

14

You'd need to first store the value in a shell variable:

MINOR_VERSION := $(shell v='$(FULL_VERSION)'; echo "$${v%.*}")

(assuming $(FULL_VERSION) doesn't contain single quotes)

Now that calls sh, not bash. ${var%pattern} is a standard sh operator (comes from ksh).

If you wanted to use bash-specific operators, you'd need to tell make to call bash instead of sh with

SHELL = bash

Beware however that many systems don't have bash installed by default which would make your Makefile non-portable (but then, some systems don't have GNU make either and you're already using some GNUisms there)).

2
  • Although @uzsolt answer is also great because native, I prefer this one because sometimes it can be a non-semantic versioning, e.g. 1.2 instead of 1.2.3. Anyway, I didn't know that you can use single quotes to pass through Makefile vars
    – chingis
    Aug 27, 2018 at 11:46
  • what if the variable expansion occurs in the shell script? I'm getting "warning: undefined variables" since its not expanding from the Makefile. Jun 10, 2022 at 22:00
5

You can do it with builtin functions (assume you're using GNU make):

VER=1.2.3
MINORVERTMP=$(subst ., ,${VER})
MINORVER=$(word 1,${MINORVERTMP}).$(word 2,${MINORVERTMP})


all:
    @echo ${MINORVER}

If you can use bmake (BSD make) can have more (and maybe simplier) possibilities:

VER=1.2.3

all: test1 test2

test1:
    # simple regular expression-based replace like sed
    @echo $@: ${VER:C,([^\.]*)\.([^\.]*).*,\1.\2,}

test2:
    # replace all dot to spaces (S),
    # print first and second element (:[1..2])
    # with dot separator (ts.)
    @echo $@: ${VER:S,., ,g:[1..2]:ts.}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .