Adding additional dependencies for all files with a given extension - makefile

Let's say I am using the implicit rule to build an .o file from a .c file.
If I want to add a specific additional dependency for one particular .o file, it is as easy as adding a rule without a recipe:
file.o : header.h
This makes file.o depend on header.h in addition to file.c.
What if I want to do that for all .o files? The following doesn't work:
%.o : header.h

For this to make sense, header.h must a header that is (and has to be) included by every .c file
and is hence a prerequisite of every .o file. If that is your situation you
need to write your own pattern rule, like:
%.o: %.c header.h
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
But the usual approach to managing header file dependencies is Auto-Dependency Generation
Later
My goal was to avoid duplicating the existing implicit rule (the recipe part) for $(CC) compilation. Is that possible?
You have to define a new pattern rule that adds header.h to the %.c prerequisite,
and has the appropriate recipe. In fact I ought
to have advised you also to cancel the builtin pattern rule:
%.o: %.c
%.o: %.c header.h
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#

Related

Does the target .SUFFIX have any meaning in a Makefile?

In a Makefile I encountered:
.SUFFIX: .c
Is that a misspelling of .SUFFIXES: .c, because I can't find anything about .SUFFIX only. Does this do anything at all?
If the Makefile only uses pattern rules, do I even need that hanging around in the Makefile at all?
Assuming you are using GNU make, unless there is really a user target named .SUFFIX, this is probably a misspelling of .SUFFIXES: .c. And if there is no recipe you can safely remove it: without a recipe it's useless.
If it was .SUFFIXES: .c and if it had a recipe it would redefine the implicit rules for:
%: %.c
<recipe>
which is:
LINK.c = $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
%: %.c
$(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $#

Rebuilding object files when a header changes

I have the following rules in my Makefile:
%.o: $(HFILES)
%.o: %.c
$(CC) $(CFLAGS) $*.c
where HFILES contains all headers of my project.
The Problem is that this does not rebuild the object files when a header changes as intended. Why does the first line not add the headers to the prerequisites of the object files?
Because that's not how pattern rules work. The documentation for pattern rules says that when you create a pattern rule with no recipe that cancels the pattern rule (that is, deletes it).
Since your first line is creating a pattern rule with a target %.o and prerequisites $(HFILES) but no recipe, that line simply cancels a pattern rule (which doesn't exist anyway).
You can write:
%.o: %.c $(HFILES)
$(CC) $(CFLAGS) -c -o $# $<
(you shouldn't put the -c flag in your CFLAGS variable).
Be aware that, of course, this means that if ANY header file in HFILES changes, ALL .o files that use this pattern will be rebuilt.

Makefile decoupled dependencies

With the following makefile snippet:
main: main.o f1.o f2.o
$(CC) $(CFLAGS) -o program main.o f1.o f2.o
main.o: main.cc
$(CC) $(CFLAGS) -c main.cc
f1.o: f1.cc
$(CC) $(CFLAGS) -c f1.cc
f2.o: f2.cc
$(CC) $(CFLAGS) -c f2.cc
If I just change one file, only that file get recompiled when I rerun make, as desired. However, I'm having a hard time generalizing this without having to list each file individually. When I try something like:
$(OBJECTS): $(SOURCES)
$(CC) $(CFLAGS) -o $# -c $(patsubst %.o,%.cc,$#)
It builds each object file individually, but each object file depends on ALL my sources, so a change in any one file causing a full recompile. What's a good way to accomplish this?
Basically,
you do have to list each .o file's dependencies individually.
For example, each .o is likely to depend on a different bunch of headers.
Taking your f1.o, you need something like:
f1.o: include/i.h
f1.o: another.h dir/and-another.h
f1.o: f1.cc
$(CC) $(CFLAGS) -c f1.cc
(you can have as many dependency lines for a target as you like).
Maintaining that list is a nightmare.
Broken dependency lists render your Makefile worse than useless—you might as well use a batch file.
All is not lost!
If you are tidy,
you can get the compiler to do it automatically,
and pretty much for free.
Makes your Makefile tidier to boot.
Win Win.
As Ismail Badawi commented, pattern rules provide a nice solution. They are a type of implicit rule for make. Basically, implicit rules are automatic recipes based off the file extension. For example, make knows how to convert .c files into .o files implicitly. By default make will run the following recipe for .c files (see the rule catalogue):
$(CC) $(CPPFLAGS) $(CFLAGS) -c
You can modify the process either by setting the variables CC, CPPFLAGS, and CFLAGS, or by defining a pattern rule:
%.o: %.c
$(CC) $(CFLAGS) -c $<
The "$<" above matches the name of the first prerequisite, which will be the .c file in this example. See Beta's comment and automatic variables.

Why doesn't this make file work?

CC=g++
CFLAGS=-Wall -ggdb
OBJDIR=Objects
SRCDIR=Source
HDIR=Headers
OBJ=$(patsubst %,$(OBJDIR)/%,main.o vector.o obstacle.o \
person.o simulation.o map.o wall.o room.o )
all: CrowdSim
CrowdSim: $(OBJ)
$(CC) $(CFLAGS) -o $# $^
$(OBJDIR)/%.o: $(SRCDIR)/%.cc $(HDIR)/%.h
$(CC) $(CFLAGS) -c -o $# $<
clean:
rm -rf Objects/*.o Source/*.o
When attempting to make, I receive the error: "No rule to make target 'Objects/main.o' needed by 'CrowdSim'. Note: this is my first attempt at a makefile, and I'm following the example here.
Additional information: All my .cc files are stored in Source, all my .h files are in Headers, and I want to put all my .o files in Objects.
A rule like this:
$(OBJDIR)/%.o: $(SRCDIR)/%.cc $(HDIR)/%.h
requires both the prerequisites to exist. If either one does not exist, then the rule doesn't match and make will ignore it and look for another rule. In this case there is no other rule, so make fails.
If you don't always have both a .cc and .h file for every .o file, then you cannot write your rule like this.
Instead, you'll have to write the pattern rule like this:
$(OBJDIR)/%.o: $(SRCDIR)/%.cc
$(CC) $(CFLAGS) -c -o $# $<
Then you'll have to declare the header files separately, like this:
$(OBJDIR)/vector.o: $(HDIR)/vector.h
etc. for any headers. You might consider implementing a method to automatically manage dependencies, such as this one.
By the way, CC and CFLAGS are for C compilers. You have C++ code here. By convention in makefiles you should use CXX and CXXFLAGS for C++ compilers.

Makefile pattern rules

Is it possible to write pattern rule like:
%.o: %.c %.h
<some action>
so it accepts not one but any number of headers, because I have:
main.o: main.c $(HEADERS)
so it doesen't fit to standard implicit rule, because of many .h files that main.c depends on, so is it possible to make an implicit rule, that would accept such input, or should I just write
$(CC) $(CFLAGS) $(DEFINE_OPT) $(INCLUDE) -c $<
explicitly?
You can write:
%.o: %.c $(HEADERS)
However, in general, you probably don't want all source files to be dependent on all header files. You should look into auto-generating the prerequisite lists; the Make manual talks about this a bit: http://www.gnu.org/software/make/manual/make.html#Automatic-Prerequisites.
In GNUMake you can write
main.o: $(HEADERS)
and the built-in implicit rule will work. If you want to handle dependencies automatically, Advanced Auto-Dependency Generation is superior to the one in the GNUMake manual.

Resources