'Makefile error trying to use a template to compile multiple programs with similar steps

I am trying to create a makefile that can compile multiple programs. It has a list of programs and will compile each one separately. Every program has pretty much exactly the same template so I tried this solution:

CFLAGS=-O3 -std=c89 -pedantic -Wall -Wextra -Werror

programs=echo cat yes true false cp

all: $(programs)

$(programs): src/[email protected]
    $(CC) $(CFLAGS) -o $@ $^

clean:
    $(RM) $(programs)

install: all
    $(CP) $(programs) /usr/local/bin/

For some reason, this doesn't work. I get the error

make: *** No rule to make target 'src/.c', needed by 'echo'.  Stop.

I'm trying to make this portable so no GNU extensions. POSIX Make if possible.



Solution 1:[1]

Here:

$(programs): src/[email protected]
    ...

You can't use automatic variables like $@ in the prerequisite list that way. The rule gets expanded before a target has been specified, so the variable contains nothing. (You can use it this way but it's a headache.)

Use a static pattern rule instead:

$(programs): %: src/%.c
    $(CC) $(CFLAGS) -o $@ $^

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Beta