Rule with empty recipe and empty prequisite and pattern rule - makefile

This is a snippet of the make file:
main.o :
%.o: main.c strlen.h main.h common.h
#echo $^
My question is that since main.o has an empty prerequisite and recipe then why the pattern rule is listing the dependency for main.o? As output shows like :
main.o : main.c strlen.h main.h common.h
Please explain any body help is appreciated!!!!!!!

A rule without a recipe simply adds any provided prerequisites to the given target. In other words, there can be only one rule with a recipe for a given target, but there can be as many rules without recipes for the same target as you like.
This:
foo.o: foo.h
foo.o: bar.h
foo.o:
foo.o: biz.h
foo.o: foo.c
$(CC) -c -o $# $<
is identical, from the point of view of make, to this:
foo.o: foo.c foo.h bar.h biz.h
$(CC) -c -o $# $<

Related

makefile: No rule to make target '%.o'

I have 3 files: Source.cpp 2ndfile.cpp 2ndfile.hpp
And I'm trying to compile them with mingw32-make
makefile that doesn't work:
all: launch.exe
launch.exe: %.o
g++ -o $# $^
%.o: %.cpp
g++ -c $< -std=gnu++11
makefile that works:
all: launch.exe
launch.exe: source.o 2ndfile.o
g++ -o $# $^
source.o: source.cpp
g++ -c source.cpp -std=gnu++11
2ndfile.o: 2ndfile.cpp
g++ -c 2ndfile.cpp -std=gnu++11
My question is: why the first one doesn't work? What's my problem with '%' patterns?
The error I get: mingw32-make: *** No rule to make target '%.o', needed by 'launch.exe'. Stop.
My question is: why the first one doesn't work? What's my problem with '%' patterns?
A pattern rule matches targets to prerequisites via a common element in their names, represented by the % wildcard. You present your own example in the form of this rule:
%.o: %.cpp
g++ -c $< -std=gnu++11
On the other hand, this rule ...
launch.exe: %.o
g++ -o $# $^
... is not a pattern rule, because the target name does not contain a %. There, you seem to be trying to use % in an entirely different sense, analogous to * in a glob pattern. It does not serve that purpose, even in pattern rules. That would give pattern rules a very different (and much less useful) meaning. Instead, in your non-pattern rule, the % is treated as an ordinary character.
There are many ways to write makefiles, but a good, simple model to start from for exploring pattern rules would be a combination of your first and second examples:
all: launch.exe
launch.exe: source.o 2ndfile.o
g++ -o $# $^
%.o: %.cpp
g++ -c $< -std=gnu++11
Substitute % with *.
all: launch.exe
launch.exe: *.o
g++ -o $# $^
*.o: *.cpp
g++ -c $^ -std=gnu++11
EDIT: there's an answer below why this is a bad idea. Here's what works:
all: launch.exe
launch.exe: Source.o 2ndfile.o
g++ -o $# $^
%.o: %.cpp
g++ -c $^ -std=gnu++11

Makefile multiple sources ouputs variable expansion

suppose CC variable is a compiling command and we don't need any additional flags. Simple part of makefile compiling main.c and next.c to main.o and next.o:
all: main.o next.o
%.o : %.c
$(CC) $< -o $#
Now suppose I would like to have output files in variable:
all: $(OBJ)
OBJ = main.o next.o
%.o : %.c
$(CC) $< -o $#
Of course it won't work. I understand why but I can't find solution. Can you help me?

how to expand variables to multiple rules in makefile?

Say that I have two variables in Makefile
CXXFILES = a.cpp b.cpp
OBJFILES = a.o b.o
I would like to write a rule that will expand to
a.cpp : a.o
g++ -o a.o a.cpp
b.cpp : b.o
g++ -o b.o b.cpp
Note that I'm not looking for
%.o : %.cpp
g++ -o $# $<
because I don't want to match all .cpp files -- I only want those files specified by a variable.
Sounds like a job for a Static Pattern Rule:
Here is an example, which compiles each of foo.o and bar.o from the
corresponding .c file:
objects = foo.o bar.o
all: $(objects)
$(objects): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $#

what is mean by "make skips the implicit rule search for phony targets "

I am new to Makefiles and was reading some docs on PHONY targerts. Can some one please explain what is mean by "make skips the implicit rule search for phony targets". If we are declaring a PHONY target as default target, is there any restriction?
It means that if a target is marked as .PHONY, then it must be an explicit rule, i.e. something like
a.o: a.c
$(CC) -o $# -c $<
and not an implicit rule, like a pattern rule or a suffix rule. As an example, consider the following makefile:
.PHONY: a.o
all: a.o b.o
%.o: %.c
$(CC) -o $# -c $<
Invoking make will do the following:
$ make
cc -o b.o -c b.c
$
Note that only b.c was compiled, not a.c.

Makefile: target with pattern does not work

My Makefile looks like this:
BIN = bin
OBJECTS = object1.o \
object2.o \
object3.o
HDR = $(OBJECTS:%.o=%.h) header1.h header2.h
MAIN = main.c
CC = gcc
CFLAGS = -Wall -g -std=c99 -fstack-protector-all
LDFLAGS = -lpthread
$(BIN): $(OBJECTS) $(MAIN)
$(CC) $(CFLAGS) $(LDFLAGS) -o $# $^
%.o: %.c $(HDR)
$(CC) $(CFLAGS) -c $< -o $#
It seems that the %.o: %.c $(HDR) rule is not used. When invoking with option make -r it says that there's no rule to make target object.o. The build of each object file should depend on every header file. What am I missing?
Edit: I should mention that when doing echo $(HDR) than it looks like the variable contains the right values:
object1.h object2.h object3.h header1.h header2.h
In the declaration of HDR, try $(OBJECTS:.o=.h) instead. Or, better yet, use gcc -MM or the like to generate your dependencies instead.
A pattern rule can't have auxilliary dependencies like ${HDR}.
Use:
%.o : %.c
$(CC) $(CFLAGS) -c $< -o $#
${OBJECTS}: ${HDR}
Ok, the given Makefile should work, I had a typo in one of the header file names.
It's a pitty, but make doesn't warn about that. It seems that when a pattern based rule is missing a prerequisite than it's just ignored. The built-in .o creation rule is used instead.
Jonathan Leffler's proposal of ${OBJECTS}: ${HDR} brought that up, because than there's an error regarding "no rule to make target misspelled.h" - I would have expected that from my rule too.
So I can just agree to fluffy, it's better to use auto-generated dependencies instead.

Resources