0

I have a file structure for a project like this:

Project Folder
|
->source
    |
    -->main.cpp
    -->frac.hpp
    -->frac.cpp
-> obj
    |Empty for now, but will store the .o files

Here is my makefile:

CC = g++
CFLAGS = --std=c++11 -Wall
LFLAGS = --std=c++11
SRC = source
OBJ = obj

all: frac

frac: $(OBJ)/main.o $(OBJ)/frac.o
    g++ $(LFLAGS) -o frac $(OBJ)/main.o $(OBJ)/frac.o

$(OBJ)/main.o: $(SRC)/main.cpp $(SRC)/frac.hpp
    g++ $(CFLAGS) -c $(SRC)/main.cpp

$(OBJ)/frac.o: $(SRC)/frac.cpp $(SRC)/frac.hpp
    g++ $(CFLAGS) -c $(SRC)/frac.cpp

Now, when I run the command make frac

I get these errors:

g++ --std=c++11 -o frac obj/main.o obj/frac.o
g++: error: obj/main.o: No such file or directory
g++: error: obj/frac.o: No such file or directory
g++: fatal error: no input files
compilation terminated.
make: *** [frac] Error 4

Now the strange part about this to me is that after these errors, it still generates main.o and frac.o in the current directory. I then have to do mv *.o obj to move them all into the obj directory. I can then run make frac and this time it works and generates the executable. I understand that make is trying to use linking files that don't exist, so how can I get them generated with the first run of the command?

Thank you!

EDIT: I've looked at this thread How to place object files in separate subdirectory But I am unclear on how to implement that solution. I can't just copy paste that directly into my makefile, and his is structured differently than mine

1 Answers1

3

The target name ($(OBJ)/main.o) tells Make what to expect, but it doesn't tell the compiler what to build. The -o flag will tell g++ where to put the file it builds. So change these:

$(OBJ)/main.o: $(SRC)/main.cpp $(SRC)/frac.hpp
    g++ $(CFLAGS) -c $(SRC)/main.cpp

$(OBJ)/frac.o: $(SRC)/frac.cpp $(SRC)/frac.hpp
    g++ $(CFLAGS) -c $(SRC)/frac.cpp

to these:

$(OBJ)/main.o: $(SRC)/main.cpp $(SRC)/frac.hpp
    g++ $(CFLAGS) -o $@ -c $(SRC)/main.cpp

$(OBJ)/frac.o: $(SRC)/frac.cpp $(SRC)/frac.hpp
    g++ $(CFLAGS) -o $@ -c $(SRC)/frac.cpp

Then you can use another automatic variable to simplify these rules:

$(OBJ)/main.o: $(SRC)/main.cpp $(SRC)/frac.hpp
    g++ $(CFLAGS) -o $@ -c $<

$(OBJ)/frac.o: $(SRC)/frac.cpp $(SRC)/frac.hpp
    g++ $(CFLAGS) -o $@ -c $<

And then, if you want, since these rules are very similar, you can combine them into a static pattern rule:

$(OBJ)/main.o $(OBJ)/frac.o: $(OBJ)/%.o: $(SRC)/%.cpp $(SRC)/frac.hpp
    g++ $(CFLAGS) -o $@ -c $<
Beta
  • 96,650
  • 16
  • 149
  • 150