Reputation: 218
Here is my makefile:
SHELL = /bin/sh
CC=g++
CFLAGS=-I.
DEPS = settings.h
OBJ = settings.o tomato.o
EXDIR = $(ROOT_TOMATO)/bin
OBJDIR = $(ROOT_TOMATO)/obj
$(OBJDIR)/%.o: %.cpp $(DEPS)
$(CC) -c -o $@ $<
$(EXDIR)/tomato: $(OBJ)
$(CC) -o $@ $^ $(CFLAGS)
clean:
rm -f a.out *.o
all: tomato
On line 9 and 10, I have attempted to get it to create object files and put them in the OBJDIR
, but it instead places the obj files in the current directory, ROOT_TOMATO/src:
$(OBJDIR)/%.o: %.cpp $(DEPS)
$(CC) -c -o $@ $<
I can't figure out why it is not working. Perhaps there are better ways, but I also like to know why my code doesn't work in this particular case.
As a side note, the makefile is called by another makefile:
#Main makefile for project
#Get root compile directory
ROOT_TOMATO = $(shell pwd)
export ROOT_TOMATO
All:
$(MAKE) -C src
Upvotes: 1
Views: 1401
Reputation: 12514
Make
is a language where ‘keep it simple’ is great advice. It's a language where simple things are simple; hard things look like line-noise.
Remember that Make is a sort of executable build-process documentation – readability is a Good Thing.
I'd rewrite your Makefile as something like
CXX=g++
OBJ=settings.o tomato.o
TARGET=tomato
%.o: %.cpp
$(CXX) -c -o $@ $<
# default target
$(TARGET): $(OBJ)
$(CXX) -o $(TARGET) $(OBJ) $(CFLAGS)
tomato.o: settings.h
settings.o: settings.h
clean:
rm $(TARGET) *.o
That is:
CXX
as the macro for the C++ compiler, and leave CC
for the C compiler – that prompts anyone reading the rules to jump to the right conclusion.%.o: %cpp
rule simple. So, you end up with lots of *.o
files in the current directory - big deal! Put them in your Mercurial/Git ignore file and move on. You can put them into another directory, and @Wintermute shows how to do that, but it needs more punctuation, and doesn't really gain much.$(VAR:sub=result)
constructions. They're useful, but if you use too many of them, the result quickly becomes unreadable.%
rules. Expressing those separately in action-less rules (as with the dependencies for tomato.o
and settings.o
) documents that ‘there's nothing fancy about these modules’ and keeps everything looking cleaner.A complicated makefile which does everything automatically is a great way of procrastinating (take it from me, oh brother...).
Upvotes: 0
Reputation: 44073
Where you say
$(EXDIR)/tomato: $(OBJ)
The prerequisites for $(EXDIR)/tomato
are not $(OBJDIR)/settings.o
and $(OBJDIR)/tomato.o
but just plain settings.o
and tomato.o
, as you defined in OBJ
. Therefore, the pattern rule is not used to build them, and make falls back on implicit rules to build settings.o
and tomato.o
.
You could instead use
$(EXDIR)/tomato: $(OBJ:%=$(OBJDIR)/%)
...or set OBJ
so that it contains these paths from the get-go.
Note that your clean
rule has a similar problem, so having a variable that contains the actual object paths would be sensible. You could use it both in the $(EXDIR)/tomato
prerequisites and in the clean
recipe.
Also note that the default rule for the inner Makefile is not all
but $(EXDIR)/tomato
, because it is the first for a specific target. It's sort of a good thing here; the all
rule would not work as intended because its prerequisite is tomato
, for which there is no rule, rather than $(EXDIR)/tomato
. I suspect you'll want to fix that and move the all
rule to the top at some point, though.
Upvotes: 3