1

Before anyone marks this as a duplicate, let me say that I have looked at these questions to no avail:

Makefiles: Get .cpp from one directory and put the compiled .o in another directory
Can I compile all .cpp files in src/ to .o's in obj/, then link to binary in ./?
Makefile, find sources in src directory tree and compile to .o in build file
C++ Makefile. .o in different subdirectories
Makefile: Compiling from directory to another directory

No matter which of these solutions I try, I am unable to get this rule to build correctly:

$(OBJ_DIR)/$(OBJ): $(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
    $(CC) $(CPPFLAGS) -o $@ $<

Here is the full makefile:

CPPFLAGS = -c -Wall -g \
        -I/usr/include/glib-2.0 \
        -I/usr/lib/x86_64-linux-gnu/glib-2.0/include \
        -I/user/include/gdk-pixbux-2.0 \
        -Iinclude
LFLAGS = -Wall -g
LIB = -lnotify
SRC_DIR = src
INCL_DIR = include
OBJ_DIR = build
TARGET_DIR = bin
SRC := $(subst $(SRC_DIR)/,,$(wildcard src/*.cpp))
INCL := $(subst $(INCL_DIR)/,,$(wildcard include/*.hpp))
OBJ := $(SRC:.cpp=.o)
TARGET = reminders
CC = g++

.PHONY: clean

$(TARGET_DIR)/$(TARGET): $(OBJ_DIR)/$(OBJ)
        $(CC) $(LFLAGS) -o $@ $^ $(LIB) 
        @echo Build successful

$(OBJ_DIR)/$(OBJ): $(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
        $(CC) $(CPPFLAGS) -o $@ $< 

clean:
        rm -rf *.o build/* bin/* *~

In my project folder I have a src, bin, and build folder Within my project folder is main.cpp, reminder.hpp, and controller.cpp. This is what I get when I run make:

Makefile:24: target 'main.o' doesn't match the target pattern
g++ -c -Wall -g -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/user/include/gdk-pixbux-2.0 -Iinclude -o mai
g++: fatal error: no input files
compilation terminated.
Makefile:25: recipe for target 'main.o' failed
make: *** [main.o] Error 1
shell returned 2
jww
  • 97,681
  • 90
  • 411
  • 885
Gabe
  • 59
  • 1
  • 9

1 Answers1

3

I advise you to learn the habit of testing... well... everything.

Suppose your source directory contains

blue.cpp main.cpp red.cpp

Now in your makefile, try this:

$(info $(OBJ_DIR)/$(OBJ))

This produces:

obj/blue.o main.o red.o

Ack! Now you know why your rule fails. You can't add prefixes that way. The pattern is $(OBJ_DIR)/%.o, but the target main.o doesn't match the pattern.

Try this:

SRC := $(wildcard $(SRC_DIR)/*.cpp) # src/blue.cpp ...
OBJ := $(patsubst $(SRC_DIR)/%.cpp, $(OBJ_DIR)/%.o, $(SRC)) # obj/blue.o ...

$(TARGET_DIR)/$(TARGET): $(OBJ)
    $(CC) $(LFLAGS) -o $@ $^ $(LIB) 
    @echo Build successful

$(OBJ): $(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
    $(CC) $(CPPFLAGS) -o $@ $< 
Beta
  • 96,650
  • 16
  • 149
  • 150