1

I am new in makefle, I had need array in makefile then I found that I can achieve that having variable that their items separated with spaces, and then iterating over it. Now I want something like map(key,value) pair to store values with keys. Question: can I have that in makefile ? Thanks in advance..

ant_dev
  • 653
  • 8
  • 16
  • 1
    By chance did you get a chance to look at this thread? [Dictionaries/Maps/Lookup Tables in Makefiles](https://stackoverflow.com/questions/40919502/dictionaries-maps-lookup-tables-in-makefiles) – vijay v May 25 '20 at 15:46
  • Thanks, I have viewed that post, it is no helpful in my situation. I do not need many variables I need one long variable from that I get get value passing it's key. – ant_dev May 25 '20 at 15:50

2 Answers2

5

You can use token pasting for that:

VAR_FOO_KEY := FOO_VAL
VAR_BAR_KEY := BAR_VAL

#example lookup:
KEY := FOO_KEY
LOOKUP_VAL := $(VAR_$(KEY))
HardcoreHenry
  • 5,909
  • 2
  • 19
  • 44
1

Make a file named KV.mk with the following function definitions:

# KV(3 args): in a dictionary directory record a key value pair in a file
# KV(2 args): in a dictionary directory recover value associated with a key
# KV(1 arg ): remove a dictionary directory
# KV(0 arg ): remove all dictionary directories
define KV
    $(if $4,$(error K0123.mk: args>3 forbidden),      \
    $(if $3,mkdir -p $1.key; echo "$3" > $1.key/$2,   \
    $(if $2,`cat $1.key/$2`,                          \
    $(if $1,rm -fr $1.key/*,                          \
            rm -fr *.key                              \
    ))))
endef

Then make a client Makefile with the following contents:

include KV.mk

all: hello.cpp hello

.PHONY: hello.cpp
hello.cpp:
    @echo '#include <iostream>' > $@
    @echo 'int main(int argc, char** argv)' >> $@
    @echo '{ std::cout << "hello" << std::endl; return 0; }' >> $@

hello: hello.cpp
    @$(call KV,$@)
    @$(call KV,$@,compiler,g++)
    @$(call KV,$@,compiler) -o hello hello.cpp
    @./$@

clean:
    @rm -f hello.cpp hello
    @$(call KV)

Copy these two files into an empty directory and run "make".

This method offers much liberty in having multiple dictionaries with multiple key/value pairs per dictionary. One dictionary may be used for the entire Makefile. Another dictionary may be used for all rules having common needs. Individual dictionaries may be used for each rule.

Simplifying one more step, here is a shell script encapsulating the KV idea.

#!/bin/bash

usage() {
    cat <<USAGE
KV(1) -- syre(tm) user command

NAME
    KV - key value store management for Makefile

SYNOPSIS
    (1) KV [--help]
    (2) KV [--clear]
    (3) KV [OPTION]... {key}
    (4) KV [OPTION]... {key}={value}

1: display usage (this text)
2: clear all dictionaries (make clean)
3: print value associated with key
4: store key value pair in the dictionary and key file
USAGE

    if [ "" != "$1" ] ; then echo "KV error: $1"; fi

    exit 0
}

if [ $1 = "--help" ] ; then usage;
elif [ $1 = "--clear" ] ; then rm -fr *.key;
else
    case $# in
        3) mkdir -p $1.key; echo "$3" > $1.key/$2;;
        2) cat $1.key/$2;;
        1) rm -fr $1.key;;
        *) usage "KV error: 1, 2, or 3 args required";;
    esac
fi

and here is the same Makefile showing that simplification.

all: hello.cpp hello

.PHONY: hello.cpp
hello.cpp:
    @echo '#include <iostream>' > $@
    @echo 'int main(int argc, char** argv)' >> $@
    @echo '{ std::cout << "hello" << std::endl; return 0; }' >> $@

hello: hello.cpp
    @./KV $@
    @./KV $@ compiler g++
    @`./KV $@ compiler` -o hello hello.cpp
    @./$@

clean:
    @rm -f hello.cpp hello
    @./KV --clear
jlettvin
  • 1,113
  • 7
  • 13