Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to evaluate once a makefile conditional variable?

I'm trying to use the same value to all tasks, but the variable are evaluating for every task. How to avoid it?

Version: GNU Make 4.1

Makefile content:

SHELL = /bin/bash -ex
BUILD_TIMESTAMP ?= $(shell date '+%Y%m%d%H%M%S')
VERSION ?= 1.2-${BUILD_TIMESTAMP}

t1:
    echo ${VERSION}
    sleep 1

t2:
    echo ${VERSION}
    sleep 1

Output:

$ make t1 t2
date +%Y%m%d%H%M%S
echo 1.2-20170803143838
+ echo 1.2-20170803143838
1.2-20170803143838
sleep 1
+ sleep 1
+ date +%Y%m%d%H%M%S
echo 1.2-20170803143839
+ echo 1.2-20170803143839
1.2-20170803143839
sleep 1
+ sleep 1
like image 854
Gabriel Luis Avatar asked Oct 18 '25 13:10

Gabriel Luis


2 Answers

The ?= in GNU make is equivalent to a = that's only done when the variable was undefined before. As you may know, = sets a recursively expanded variable, that is, its value is only expanded when the variable itself is expanded.

What you want instead is a simply expanded variable, its content is only expanded once and directly assigned to it. For more info on the difference, see The Two Flavors of Variables. You get a simply expanded variable by assigning it with :=.

You have two options to solve your immediate problem:

  1. Make BUILD_TIMESTAMP a simply expanded variable by reassigning it:

    BUILD_TIMESTAMP ?= $(shell date '+%Y%m%d%H%M%S')
    BUILD_TIMESTAMP := ${BUILD_TIMESTAMP}
    
    VERSION ?= 1.2-${BUILD_TIMESTAMP}
    
  2. Do the logic for only assigning when the variable was undefined yourself:

    ifeq ($(origin BUILD_TIMESTAMP), undefined)
    BUILD_TIMESTAMP := $(shell date '+%Y%m%d%H%M%S')
    endif
    
    VERSION ?= 1.2-${BUILD_TIMESTAMP}
    

Just add the following statements to your code after corresponding ?= assignments:

BUILD_TIMESTAMP := $(BUILD_TIMESTAMP)
VERSION := $(VERSION)
like image 39
Alexey Semenyuk Avatar answered Oct 21 '25 03:10

Alexey Semenyuk