'How can I store my .o files in a sepparate folder?

INCDIR=include
SRCDIR=src


SRC = $(wildcard $(SRCDIR)/*.cpp)
DEPS = $(wildcard $(INCDIR)/*.h)
OBJ = $(SRC:.cpp=.o)


CFLAGS = -I$(INCDIR) -Wall -Weffc++ -Wextra -Wsign-conversion
CC=g++


preprocessor: $(OBJ) 
    $(CC) $(OBJ) -o $@ $(CFLAGS)

$(SRCDIR)/%.o: $(SRCDIR)/%.cpp
    $(CC) -c $(CFLAGS) $^ -o $@

clean: 
    rm $(SRCDIR)/*.o preprocessor

This is my current makefile, if I wanted to store my .o files in a sepparate directory, src/obj for example, how would I have to modify it?



Solution 1:[1]

Many ways to do it, but according to your own code, you could do:

INCDIR=include
SRCDIR=src
OBJDIR=obj

SRC= $(wildcard $(SRCDIR)/*.cpp)
DEPS= $(wildcard $(INCDIR)/*.h)
OBJ=$(patsubst %.cpp, $(OBJDIR)/%.o, $(notdir $(SRC)))
    
CFLAGS= -I$(INCDIR) -Wall -Weffc++ -Wextra -Wsign-conversion
CC=g++

$(OBJDIR):
    @if ! [ -d $(@) ]; then\
        echo "==> creating dir: $(@)";\
        mkdir $(@);\
    fi

preprocessor: $(OBJDIR) $(OBJ)
    $(CC) $(OBJ) -o $@ $(CFLAGS)

$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
    $(CC) -c $(CFLAGS) $^ -o $@

clean:
    rm $(OBJDIR)/*.o preprocessor

printobj: $(OBJDIR)
    @echo "$(OBJ)"

will output:

$ gmake preprocessor
g++ -c -Iinclude -Wall -Weffc++ -Wextra -Wsign-conversion src/a.cpp -o obj/a.o
g++ -c -Iinclude -Wall -Weffc++ -Wextra -Wsign-conversion src/b.cpp -o obj/b.o
g++  obj/a.o  obj/b.o -o preprocessor -Iinclude -Wall -Weffc++ -Wextra -Wsign-conversion

NOTE: the target printobj is just here to output what you could expect, the target $(OBJDIR) ensure your directory exist before creating object files.

Solution 2:[2]

The are just a few things to change:

INCDIR := include
SRCDIR := src
OBJDIR := $(SRCDIR)/obj

SRC  := $(wildcard $(SRCDIR)/*.cpp)
DEPS := $(wildcard $(INCDIR)/*.h)
OBJ  := $(patsubst $(SRCDIR)/%.cpp,$(OBJDIR)/%.o,$(SRC))


CFLAGS := -I$(INCDIR) -Wall -Weffc++ -Wextra -Wsign-conversion
CC     := g++

preprocessor: $(OBJ) 
    $(CC) $^ -o $@ $(CFLAGS)

$(OBJDIR)/%.o: $(SRCDIR)/%.cpp | $(OBJDIR)
    $(CC) -c $(CFLAGS) $< -o $@

$(OBJDIR):
    mkdir -p "$@"

clean: 
    rm -f $(OBJ) preprocessor

Note some other minor modifications:

  • the | $(OBJDIR) order-only prerequisite and the $(OBJDIR): rule to ensure the objects directory exists before compiling,
  • := instead of = for all make variable assignments because you don't need recursively expanded variables here,
  • $^ instead of $(OBJ) in the link recipe because using automatic variables in recipes makes them more generic,
  • $< instead of $^ in the compile recipe because you compile only the first prerequisite, not all of them,
  • rm -f $(OBJ) preprocessor instead of rm $(SRCDIR)/*.o preprocessor to remove only the object files of the project and avoid errors if none exists.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Valery S.
Solution 2