18

I am trying to use Makefile to compile a bunch of .cpp files located in src/code/*.cpp, then compile each *.o in build/, and finally generate executable with those in build/ as well.

I have read a couple answers that I tried to work with but have encountered issues I do not understand.

CC = g++
FLAGS = -g -c

SOURCEDIR = /src/code
BUILDDIR = build

EXECUTABLE = DesktopSpecificController
SOURCES = $(wildcard src/code/*.cpp)
OBJECTS = $(patsubst src/code/*.cpp,build/%.o,$(SOURCES))

all: dir $(BUILDDIR)/$(EXECUTABLE)

dir:
    mkdir -p $(BUILDDIR)

$(BUILDDIR)/$(EXECUTABLE): $(OBJECTS)
    $(CC) $^ -o $@

$(OBJECTS): $(BUILDDIR)/%.o : $(SOURCEDIR)/%.cpp
    $(CC) $(FLAGS) $< -o $@

clean:
    rm -f $(BUILDDIR)/*o $(BUILDDIR)/$(EXECUTABLE)

I do get the following error, and I am not sure why:

Makefile:19: target `src/code/main.cpp' doesn't match the target pattern

I also see that when trying to build the EXECUTABLE, it is not using the .o files, so it seems my rule is wrong here.

user1777907
  • 1,355
  • 4
  • 12
  • 28

1 Answers1

20

Your patsubst function is wrong; you can't use shell wildcard characters like *. You want:

OBJECTS = $(patsubst $(SOURCEDIR)/%.cpp,$(BUILDDIR)/%.o,$(SOURCES))

Also you should be using SOURCEDIR and BUILDDIR everywhere, not just in some places (otherwise you'll get inconsistencies). And finally, your SOURCEDIR value is wrong: it should not start with / I expect:

SOURCEDIR = src/code

SOURCES = $(wildcard $(SOURCEDIR)/*.cpp)
MadScientist
  • 92,819
  • 9
  • 109
  • 136
  • 1
    You're welcome. Don't forget SO should be one of your last resorts, _after_ you've tried to work it out yourself. Here are a few makefile debugging hints: first, the `-p` option will print the entire make database out, including all the values of all the variables. Also, in GNU make you can use the `$(info ...)` function to print out information such as variable values. Printing those values would have given you a good clue as to where the problem was. – MadScientist Jun 05 '13 at 02:08
  • 2
    To clarify MadScientist's suggestion, `$(info ...)` can be used as `$(info $(SOURCES))`, for example. It can be inserted immediately after the definition of the variable of interest. – Matthew Walker Dec 09 '13 at 23:56