Makefile is executing wrong command

I am using the following makefile for my project:

IDIR    =       -I/a/include
CC      =       gcc
CEFLAGS =       -fverbose-asm -masm=intel
WFLAGS  =       -Wall -Wextra
LDIR    =       -L/a/lib.Linux
LIBS    =       -lpthread -lpopt
OLVL    =       -O3

b.exe: b.o c.o
    $(CC) $(DBG) -o $@ $^ $(WFLAGS) $(IDIR) $(LDIR) $(LIBS)

%.o: %.s
    $(CC) -c $(DBG) $< $(AFLAGS) $(WFLAGS)

%.s: %.c %.h
    $(CC) -S $(DBG) $< $(OLVL) $(CEFLAGS) $(IDIR) $(WFLAGS)

.PHONY: debug
    $(eval DBG=-g)

.PHONY: clean
    rm *.o
    rm *.s


Based on this, I expect to generate an assmebly file as a first step. However, when I run this I get

$make b.exe 
gcc    -c -o b.o b.c


It seems to me that make is skipping my rule for creating bo and running the default rule instead. I am wondering why and how to fix this?

I am using GNU Make 3.80 and gcc 3.4.6.


source to share

1 answer

Rules you define in your makefile take precedence over built-in rules, but "one-step" rules (which can directly output from existing input) trump "multi-step" rule chains (which create output from an existing input via an intermediate file). even if the multi-step chain is user-defined and one step rule is embedded.

In your case, you have defined a template chaining:

bar.c -> bar.s -> bar.o


But this is more than a built-in rule to create bar.o

from bar.c


bar.c -> bar.o


In fact, GNU make's implementation is such that multi-step rule chains are not even considered until all the rules of the one-step pattern have been checked. Of course, since there is a one-stage rule that matches your example, GNU uses this and never bothers about multi-stage chains.

As you have found, you can work around this by using -r

the command line to disable all built-in rules. You can also add an override to your make file for a specific built-in rule that is causing you problems. It will literally look like this:

%.o: %.c


That is, just override the built-in rule with no commands.



All Articles