1

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.

Cloud
  • 18,753
  • 15
  • 79
  • 153

1 Answers1

6

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.

MadScientist
  • 92,819
  • 9
  • 109
  • 136
  • I forgot one thing. How do I update `echo "variant_$${cpu}: $${variant_x86}"` to something like `echo "variant_$${cpu}: $${variant_$${CPU}}"`? – Cloud Jun 19 '14 at 21:51
  • 1
    You have to use `eval` again: at a shell prompt it would be: `eval echo variant_\${cpu}: \${variant_${cpu}}` so in a makefile you'd double the dollar signs, like: `eval echo variant_\$${cpu}: \$${variant_$${cpu}}`. Basically the way to write makefile recipes is: get the command to work at the shell prompt first, _THEN_ put it in your makefile recipe and double the dollar signs. – MadScientist Jun 19 '14 at 22:02
  • Thank you. One last thing: How do I know when to use `$$` as opposed to `\$$`? – Cloud Jun 19 '14 at 22:05
  • You use `$$` to escape what would normally be a `$` in the shell. The `\$` construct is for quoting a variable expansion so eval doesn't expand it the first pass and the shell expands it on the second pass. – Etan Reisner Jun 19 '14 at 22:41
  • If you're interested, I have a related, but separate, makefile question here: http://stackoverflow.com/questions/2373081/assign-a-makefile-variable-value-to-a-bash-command-result – Cloud Jun 19 '14 at 23:11
  • Etan is right, but I explained this in my comment above: _FIRST_ get it working from a shell prompt. You'll need to use the backslash there as I show above. Once it's working at the shell prompt, _THEN_ put it into a make recipe, and double all the dollar signs. Regarding the other question, that was asked and answered over 4 years ago... are you sure you didn't add the wrong link? – MadScientist Jun 19 '14 at 23:55
  • @MadScientist I tried the answer provided in the link I referenced, but I still get an empty result assigned to the variable. – Cloud Jun 20 '14 at 01:39
  • The question is about setting a _make_ variable to the result of a `shell` function. You're trying to use the `shell` function inside a recipe and set a _shell_ variable to the result. They're entirely different things, as I discussed in your other question. – MadScientist Jun 20 '14 at 02:48