I have common code (e.g. hello.cpp) that is used by multiple executables. I'm using a single Makefile to build it all:
EXE=app1.out app2.out
SRC=hello.cpp
OBJ=$(SRC:.cpp=.o)
SRC_MAIN=app1.cpp app2.cpp
OBJ_MAIN=$(SRC_MAIN:.cpp=.o)
all: $(EXE)
app1.out: app1.o $(OBJ)
g++ $< $(OBJ) -o $@
app2.out: app2.o $(OBJ)
g++ $< $(OBJ) -o $@
.cpp.o:
g++ -c $< -o $@
clean:
rm -f $(EXE) $(OBJ) $(OBJ_MAIN)
I'm not very happy about having a separate target for each executable -- the targets are essentially the same. Is there any way to do this with one target for all executables? I was hoping that something like this would work:
EXE=app1.out app2.out
SRC=hello.cpp
OBJ=$(SRC:.cpp=.o)
SRC_MAIN=app1.cpp app2.cpp
OBJ_MAIN=$(SRC_MAIN:.cpp=.o)
all: $(EXE)
.o.out: $(OBJ)
g++ $< $(OBJ) -o $@
.cpp.o:
g++ -c $< -o $@
clean:
rm -f $(EXE) $(OBJ) $(OBJ_MAIN)
But I get a linking error:
misha@misha-desktop:~/cpp/stack$ make -f Makefile2
g++ -c app1.cpp -o app1.o
g++ app1.o hello.o -o app1.out
g++: hello.o: No such file or directory
make: *** [app1.out] Error 1
rm app1.o
For some reason it tries to build app1.out without building its dependency hello.o. Can anyone explain why this doesn't work, and suggest something that does?
Here's the rest of the dummy code, just in case.
app1.cpp:
#include "hello.h"
int
main(void)
{
print_hello();
}
app2.cpp:
#include "hello.h"
int
main(void)
{
for (int i = 0; i < 4; ++i)
print_hello();
return 0;
}
hello.cpp:
#include "hello.h"
#include <stdio.h>
void
print_hello()
{
printf("hello world!\n");
}
hello.h:
#ifndef HELLO_H
#define HELLO_H
void
print_hello();
#endif
The problem appears to be that you are using old-style suffix rules. From the make info:
Suffix rules cannot have any prerequisites of their own. If they have any, they are treated as normal files with funny names, not as suffix rules. Thus, the rule:
.c.o: foo.h $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<tells how to make the file '.c.o' from the prerequisite file 'foo.h', and is not at all like the pattern rule:
%.o: %.c foo.h $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<which tells how to make '.o' files from '.c' files, and makes all '.o' files using this pattern rule also depend on 'foo.h'.
The solution is to use new-style pattern rules:
%.out: %.o $(OBJ)
g++ $< $(OBJ) -o $@
%.o: %.cpp
g++ -c $< -o $@
(Also note that you don't need to define a .cpp to .o rule; make has a sensible default.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With