GNU Make - Dynamically created variable names

2019-08-14 07:32发布

I have a makefile setup where it accepts a command-line argument that gets parsed at build time to determine which compiler to use, CPULIST.

So, I plan to build via the following command: make all CPULIST="arm x86". I then created some phony rules so that make all loops and effectively does:

make all CPULIST=x86
make all CPULIST=arm

The rules:

.PHONY: all
all:
    @echo "Detected CPULIST:${CPULIST_DETECTED}"
    @echo "CPULIST:${CPULIST}"
    @for cpu in $(CPULIST_DETECTED); do         \
        echo "CPU:$${cpu}";                      \
        variant_$${cpu}=abc;                        \
        echo "variant_$${cpu}: $${variant_x86}"; \
        $(MAKE) build CPULIST=$$cpu;             \
    done
    @true

.PHONY: build
build: sanity_check $(TARGET)
    @true

If this were a bash script, I would use variant_${cpu} to, for example, have it dynamically create variables name and assignments like:

variant_x86=abc;
variant_arm=abc;

It seems I'm not getting the escape sequences correct, at least in GNU make syntax.

Building dependencies file for list_algorithms.o

Detected CPULIST:x86 arm
CPULIST:test arm x86
CPU:x86
/bin/sh: 3: variant_x86=abc: not found
variant_x86:
make[1]: Entering directory `/home/svn/public/lib/libMYLib'
CPULIST:x86

I seem to be having two problems:

  1. My string expansion seems to be something the makefile is trying to execute after expansion
  2. I don't seem to be assigning anything to variant_x86, so the syntax is off.

How do I resolve these two issues?

Thank you.

1条回答
虎瘦雄心在
2楼-- · 2019-08-14 08:07

This has nothing to do with make. What you're trying to do is not legal, as you've written it, in the shell. You can't create "dynamic variable names" in the shell like this:

$ a=foo
$ xxx$a=baz
xxxfoo=baz: command not found

If you want to do this in the shell you have to use eval:

$ a=foo
$ eval xxx$a=baz
$ echo $xxxfoo
baz

So rewrite your make rule:

all:
        @echo "Detected CPULIST:${CPULIST_DETECTED}"
        @echo "CPULIST:${CPULIST}"
        @for cpu in $(CPULIST_DETECTED); do          \
            echo "CPU:$${cpu}";                      \
            eval variant_$${cpu}=abc;                \
            echo "variant_$${cpu}: $${variant_x86}"; \
            $(MAKE) build CPULIST=$$cpu;             \
        done

Also, adding a @true at the end of this recipe has no use.

查看更多
登录 后发表回答