Makefile and computed variable names

2019-09-01 14:33发布

问题:

I got the following Makefile with several compilers, and I would like to invoke them in a loop through the variable cc:

cc_x64=x86_64-linux-gnu-gcc
cc_mips=mips-linux-gnu-gcc

all:
    for arch in "x64" "mips" ; do\
    cc="cc_$$arch";\
    $($(cc)) some_file -o some_bin

By $($(cc)), I am trying to substitute $(cc) with cc_xxx, and in turn, substitute it with the actual command I am trying to execute. This is called a computed variable name in GNU Make's documentation: https://www.gnu.org/software/make/manual/html_node/Computed-Names.html

For some reason, I cannot get this to work. What am I missing ?

回答1:

If I felt compelled to use a loop, I'd do it like this:

COMPS = x86_64-linux-gnu-gcc mips-linux-gnu-gcc

all:
    for comp in $(COMPS); do\
  $$comp some_file -o some_bin; \
  done


回答2:

You can't cross shell/make boundaries like that. You are trying, in the shell context, to create and evaluate a make variable on-the-fly. That can't work.

You either need to do all the work in make or in the shell. Export those make variables to the shell and then something like this should work:

all:
    for arch in x64 mips; do\
     cc=cc_$$arch;\
     ${!cc} some_file -o some_bin.$$arch;\
    done

But it would probably be better to do this in a more make idiomatic way.

Which would look something more like this (untested):

all: $(addprefix some_file.,x86 mips)

some_file.%: some_file
        $(cc_$(*)) $^ -o $@


回答3:

Your question is "What am I missing?" The answer is, you don't realize, that a Makefile works differently than a shell script. You are trying put a shell script on a Makefile. It is like you trying to put a saddle on a cow. Both you and the cow will be unhappy with the result.

The way you are trying to do it, you don't need Make. Just use the shell script you have there under "all:" and forget about Make. Why try to put a saddle on a cow?

If you do want to learn how to use Make, then please read more carefully the Make manual, and especially study the examples given there. Then you will understand the difference between shell scripts and Makefiles, and everything will be clearer.

I will show you how to do what you want, in the correct way that Makefiles are designed to work. But please, do study the manual more carefully.

RESULTS := $(addprefix some_bin., x86_64 mips)

.PHONY: all
all: $(RESULTS)
$(RESULTS): some_file Makefile
    $(patsubst .%,%-linux-gnu-gcc,$(suffix $@)) $< -o $@