8

I have one version file verfile which contains below version string
V1.1.2

And in Makefile I intend to read this version string, So I wrote Makefile as follows,

filepath        :=      $(PWD)
versionfile     :=      $(filepath)/verfile

all:
        cat $(versionfile)
        version=$(shell cat $(versionfile))
        echo "version=$(version)"

Now when I run the make file I get following ouput

cat /home/ubuntu/ankur/verfile
v1.1.2
version=v1.1.2
echo "version="
version=

So I am not able to store version string in the variable and use it later, I am not sure what am I doing wrong?

Any suggestion/pointer ?

After reading answer from "Didier Trosset" I changed my makefile as follows,

filepath        :=      $(PWD)
versionfile     :=      $(filepath)/verfile
myversion       :=      ""

all:

ifeq ($(wildcard $(versionfile)),)
all:
        echo "File not present"
else
all: myversion = $(shell cat $(versionfile))
endif
all:
        echo "myversion = $(myversion)"

and below is output for the

echo "myversion = v1.1.2"
myversion = v1.1.2
ART
  • 1,509
  • 3
  • 29
  • 47

2 Answers2

14

You have two problems. First to have bash (and not make) expand the variable you need to use $$version (or $${version}). By this Make first translates $$ into just $ and then bash will see $version (or ${version}). Secondly each line in the rule will be executed as a separate command, so in order to let them interact via environmental variables you have to put them into a common subshell, enclosing with paranthesis.

filepath        :=      $(PWD)
versionfile     :=      $(filepath)/verfile

all:
    cat $(versionfile)
    (version=$(shell cat $(versionfile)); echo "version=$$version")
hlovdal
  • 26,565
  • 10
  • 94
  • 165
7

I usually prefer to have this version string in a make variable.

Therefore, I'd rather use the following that keeps variables into variables, and rules/target/commands in rules/target/commands.

filepath        :=      $(PWD)
versionfile     :=      $(filepath)/verfile
version         :=      $(shell cat $(versionfile))

info:
        echo "version=$(version)"

Note that here, version is a real make variable. (As opposed to a bash variable existing only in a lingle rule line of the target.)


If you need some commands to create the versionfile then it'd be better to create this file on its own target

filepath        :=      $(PWD)
versionfile     :=      $(filepath)/verfile

all: versionfile
        echo "version=$(version)"

all: version = $(shell cat $(versionfile))

versionfile:
        # Create your version file here

Note that you cannot use the := anymore for the target variable: it would read the file at Makefile reading instead of when used, i.e. after versionfile target has been created.

Didier Trosset
  • 36,376
  • 13
  • 83
  • 122
  • 1
    But the problem is, I can use that version file only after running other commands as part of target ? can we set Makefile variable in the target `info` in your Makefile? – ART Apr 05 '16 at 07:31
  • 1
    @AnkurTank Yes, this is possible. It's named target variables in GNU make. If you want to go this way, I'd suggest to create a target `versionfile`, with your actual building target depending on it, as in the answer edit. – Didier Trosset Apr 05 '16 at 07:44
  • @"Didier Trosset" Thank you for help, I have updated my aswer in question. Let me know ifyou see any improvment in that. Basic steps required were, 1. Check if version file present, 2. extract & store that version from the file. 3. Write & use version varible later. – ART Apr 05 '16 at 09:40