tike64
tike64

Reputation: 21

Makefile: How to write a pattern rule with prerequisite without suffix

In embedded projects you typically convert an ELF output from gcc into a raw binary form with objcopy. I tried to write a pattern rule for that: %.bin: % (executable output from gcc doesn't have a suffix, at least on Linux). This fails with make: *** No rule to make target ...

Here is a complete test case:

test.c:

int main(int argc, char *argv[]) {
    return 0;
}

Makefile:

%.bin: %
    objcopy -O binary $< $@

This works by saying make test test.bin, that is, by explicitly asking it to build test executable first. It does not work by saying make test.bin. Somehow in that case make does not realize it can make prerequisite with a built in rule.

I know I can fix this by writing the rule as test.bin: test but I'd like to know, why this pattern rule does not work and can I make it work somehow.

Furthermore, I think the obvious and practical ways to make it work breaks the nice and elegant built in rule system. It could be rescued if I could put an option into e.g. LDFLAGS to make linker output the executable with some suffix e.g. .elf (do I still have to rewrite the built in rule for linking? Oh well...).

I admit, this is purely academic problem born in pedantic mind.

Upvotes: 2

Views: 586

Answers (3)

tike64
tike64

Reputation: 21

My example works when running make like this: make test test.bin because, IIUC, test is built first and then the prerequisite is already there for building test.bin. Exploiting that, I modified the Makefile like this:

all: $(subst .bin, , $(filter %.bin, $(MAKECMDGOALS))) $(MAKECMDGOALS)

%.bin: %
    objcopy -O binary $< $@

Now I can run make test.bin and make builds first test and then test.bin. Or I can run make foo bar.bin and make tries to build foo, bar and bar.bin. This is the closest thing I can come up with. On the positive side is that the Makefile does not have to reference explicitly any file names and no built in rules are rewritten.

Upvotes: 0

HardcoreHenry
HardcoreHenry

Reputation: 6387

Your idea is correct, but you hit a caveat of make -- make will not chain pure % targets with other implicit rules --

https://www.gnu.org/software/make/manual/html_node/Chained-Rules.html#Chained-Rules

... for performance reasons make will not consider non-terminal match-anything rules (i.e., ‘%:’) when searching for a rule to build a prerequisite of an implicit rule (see Match-Anything Rules).

Upvotes: 2

Altaf
Altaf

Reputation: 3086

You can generate an executable output with a suffix in gcc by passing the output -o option with the name and extension. Example:

# Give your elf file name
ELF_FILE= test.elf 

$(ELF_FILE): $(OBJ_FILES)
    echo "Creating elf file"
    gcc.exe -o $(ELF_FILE) $(OBJ_FILES)

%.bin: %.elf
    objcopy -O binary $< $@

Upvotes: 1

Related Questions