Andna
Andna

Reputation: 6689

Strange make implicit rule

I have written a small makefile for a few simple C programs that compiles them and then tests their execution time:

CC = gcc
CFLAGS = -Wall
PTEST = /usr/bin/time -f "%Us"
ARCH=-march=native
OPTIMIZATION=
NOPTIMIZATION=

%comp : %.c
    $(CC) $(CFLAGS) $(NOPTIMIZATION) -o $* $<
    $(CC) $(CFLAGS) $(OPTIMIZATION) -o $*_opt $<
    $(CC) $(CFLAGS) $(NOPTIMIZATION) $(ARCH) -o $*_arch $<
    $(CC) $(CFLAGS) $(OPTIMIZATION) $(ARCH) -o $*_opt_arch $<

%test:  
    @echo ---$<---  
    @echo Bez optymalizacji, bez podowania architektury
    @$(PTEST) ./$*
    @echo Bez optymalizacji, uwzgledniana architektura
    @$(PTEST) ./$*_arch
    @echo Opcja $(OPTIMIZATION), bez podawania architektury
    @$(PTEST) ./$*_opt
    @echo Opcja $(OPTIMIZATION), uwzgledniania architektura
    @$(PTEST) ./$*_opt_arch

loop%:OPTIMIZATION=-O2
logic%:OPTIMIZATION=-O1
math%:OPTIMIZATION=-O1 -ffast-math
recursive%:OPTIMIZATION=-O2 -foptimize-sibling-calls
recursive%:NOPTIMIZATION=-O2 -fno-optimize-sibling-calls

#all: loopcomp logiccomp mathcomp recursivecomp looptest logictest mathtest  recursivetest 

loop:loopcomp looptest

clean:
    rm -rf loop loop_opt loop_arch loop_opt_arch \
    logic logic_opt logic_arch logic_opt_arch \
    math math_opt math_arch math_opt_arch \
    recursive recursive_opt recursive_arch recursive_opt_arch

When I type make loop it compiles and tests them but then it invokes strange implicit rule that does this:

gcc -Wall    loop.c loopcomp looptest   -o loop
gcc: error: loopcomp: No such file or directory
gcc: error: looptest: No such file or directory

I know that this is make implicit rule because when I invoke make -r loop everything goes OK. I can't figure it out: which built-in implicit rule is make trying to invoke and how can I override it, preferably without adding -r option when invoking make? If it is possible, I would like to override it or somehow diasable make implicit rules inside makefile.

Upvotes: 0

Views: 543

Answers (2)

MadScientist
MadScientist

Reputation: 100781

If you don't want to create a file called "loop" and you just want to be able to say "make loop" as a way to bundle up other targets (like "make all") then you should declare "loop" to be phony and make won't search for implicit rules:

.PHONY: loop
loop: loopcomp looptest

If you don't want to do that but want to ensure that a given target doesn't undergo implicit rule search, then you should declare an explicit rule for it. A simple way to do that is add a do-nothing recipe, like this:

loop: loopcomp looptest
        @:

(the ":" command is the shell's "do-nothing" command).

Upvotes: 1

Jonathan Leffler
Jonathan Leffler

Reputation: 753465

Your default target in the makefile is:

loop:  loopcomp looptest

This tells make that to build loop, it must first ensure that loopcomp and looptest are up to date, and then it must find a way to build loop. Since there is a file loop.c, it invokes its default %.c: rule to build loop:

gcc -Wall    loop.c loopcomp looptest   -o loop

This includes the two files (programs) you told it that loop depends on.

While you have a loop.c, I think you're likely to run into this problem.

There does not seem to be a way to say in the makefile "do not use any built-in rules". If there was, you'd expect it to be a 'Special Built-in Target Name' (§4.8 of the GNU Make manual for version 3.82), such as .DEFAULT.

Your only remaining hope is that declaring .PHONY: loop might suppress this. Otherwise, rewrite the default target rule as:

check-loop: loopcomp looptest

This is a mind-boggling makefile. Porting that to anything other than GNU make will not be trivial.

Upvotes: 1

Related Questions