Includes not found in a makefile - makefile

I have been working on this makefile for quite some time now and I can't find the solution to my problem. Here is the makefile:
# Compiler:
CPPFLAGS = $(OPT_FLAGS) $(DEBUG_FLAGS) $(STANDARD_FLAGS) \
$(WARN_AS_ERRORS_FLAGS)
# Source files, headers, etc.:
OBJ_DIR = $(CX_BUILD_ROOT)/tests/unit
OUT_DIR = $(CX_BUILD_ROOT)/tests/unit
INCLUDES = -I$(CX_SRC_ROOT)/cXbase/publicAPI
LIBINCLUDES = -L$(CX_BUILD_ROOT)/connectx/libs
VPATH = tests
SRCS = cxUnitTests.cpp\
test_Player.cpp\
test_Name.cpp\
test_Game.cpp\
test_GameBoard.cpp\
test_Disc.cpp\
test_Color.cpp\
test_AsciiColorCode.cpp\
OBJS = test_Player.o\
test_Name.o\
test_Game.o\
test_GameBoard.o\
test_Disc.o\
test_Color.o\
test_AsciiColorCode.o\
LIBS = -lgtest\
-lgtest_main\
-lpthread\
-lcXbase
# Product:
MAIN = cxUnitTests.out
all: make_dir $(MAIN)
$(MAIN): $(OBJS)
#echo Invoquing GCC...
$(CPPC) $(LIBINCLUDES) -o $(OUT_DIR)/$(MAIN) $(OBJS) $(LIBS)
#echo $(MAIN) has been compiled and linked!
$(OBJ_DIR)/%.o: %.cpp
#echo Invoquing GCC...
$(CPPC) $(CPPFLAGS) $(INCLUDES) -c $< -o $#
#echo Object files created!
make_dir:
mkdir -p $(OBJ_DIR)
mkdir -p $(OUT_DIR)
clean:
#echo Removing object files...
$(RM) $(OBJ_DIR)/*.o
#echo Object files removed!
mrproper: clean
#echo Cleaning project...
$(RM) $(OUT_DIR)/$(MAIN)
#echo Project cleaned!
depend: $(SRCS)
#echo Finding dependencies...
makedepend $(INCLUDES) $^
#echo Dependencies found!
All values in the "Source files, headers, etc" section are defined in other makefiles from which this makefile is invoked with the $(MAKE) -C option They can all be #echoed and the resultant values are good. When I run make, I get:
g++ -g3 -std=c++0x -pedantic-errors -Wall -Wextra -Werror -Wconversion -c -o test_Player.o tests/test_Player.cpp
and
tests/test_Player.cpp:36:30: fatal error: publicAPI/Player.h: No such file or directory
It seems that make cannot access the content of the INCLUDES variable for some reason. I use Gnu-make.
Can you see what is wrong?
Regards

Make is using its built-in rule for compiling C++ files because your pattern rule $(OBJ_DIR)/%.o: %.cpp doesn't match your list of objects. By coincidence you've used one of the variables that the built-in recipe uses (CPPFLAGS), but make makes no use of INCLUDES.
One way to fix it would be to put something like the following after your list of objects
OBJS := $(addprefix $(OBJ_DIR)/,$(OBJS))

I finally found the problem. In fact, there were two:
The INCLUDES variable should have been set to
$(CX_SRC_ROOT)/cXbase instead of $(CX_SRC_ROOT)/cXbase/publicAPI
since, like the error message shows, the include file for Player
is looked for in publicAPI/Player.h so publicAPI was there
twice, but didn't show twice in the #echo.
My object list should have been in the form: $(OBJ_DIR)/objectFile.o.

Related

Makefile ignoring included rules

I'm trying to create a makefile for a very basic c++ program. I'm trying to implement the automatic generation of dependencies by running g++ with the -M flag, storing this output in a .d file, and then including those .d files in my main makefile. The makefile content is below
CC=g++
CPPFLAGS=-Wall -Wextra -g -std=c++11
SOURCEDIR=src
SOURCES = $(wildcard $(SOURCEDIR)/*.cpp)
BUILDDIR=build
OBJDIR=$(BUILDDIR)/objs
OBJS=$(SOURCES:$(SOURCEDIR)/%.cpp=$(OBJDIR)/%.o)
DEP_FILES = $(OBJS:.o=.d)
OUTFILE=hello.out
$(OUTFILE) : $(OBJS)
$(CC) -o $# $^ $(CPPFLAGS)
include $(DEP_FILES)
$(OBJDIR)/%.d : $(SOURCEDIR)/%.cpp
$(CC) $(CPPFLAGS) $< -MM -MT $(#:.d=.o) > $#
$(DEP_FILES) : | $(OBJDIR)
$(OBJS): | $(OBJDIR)
$(OBJDIR):
mkdir -p $(OBJDIR)
.PHONY: clean
clean:
rm -f $(BUILDDIR) -r
rm -f *~
rm -f $(OUTFILE)
When I run make, the directory build/objs/ is generated and a .d file is generated with rules in it. Here's main.d file:
build/objs/main.o: src/main.cpp src/main.h
And here's the myfunc.d file:
build/objs/myfunc.o: src/myfunc.cpp src/main.h
Here's the issue
Since I'm calling include on these .d files, I'd expect the .o files which they specify to then be created, and then the main outfile to be created as the main rule. However, make creates the .d files, and then skips directly to the main compilation step without creating any .o files:
g++ -o hello.out build/objs/myfunc.o build/objs/main.o -Wall -Wextra -g -std=c++11
This fails with the following error, since the .o files are never created:
g++: error: build/objs/myfunc.o: No such file or directory
g++: error: build/objs/main.o: No such file or directory
g++: fatal error: no input files
How can I use this makefile to generate the .o files necessary for g++? Thank you for any help in advance!
I saw you got your makefile working but I just wanted to add a few things you might want to consider for future projects. I recommend using the vpath variable rather than specifying $(OBJDIR)/%.o in your makefile recipes. I actually read somewhere that it's not "cannon" to build object files in a separate directory, but in the cursory search I conducted before posting, I couldn't find the document.
That being said, I wrote a makefile that does what you wanted; it builds the output folder, generates the dependencies, and compiles the program. I specifically included the $(COMPILE.cpp) definition so you could see what it's composed of. $(CC) is specifically the C compiler, and $(CFLAGS) is specifically flags for the C compiler. They're just variables, obviously, so you can change them like you did and it will work fine, but the main think to keep in mind is that whoever uses your programs will expect to be able to configure the compilation as they see fit. This means they will set the $(CXX) and $(CXXFLAGS) expecting to set the C++ compiler and flags. $(CPPFLAGS) stands for C/C++ Preprocessor flags.
It's not the cleanest makefile, and if I was to change something, I would just compile the object files in place and save myself that headache. That cuts down on unnecessary make hacking, but for the purposes of answering your question, here it is. Anyways I hope this helps you somewhat, let me know if you have any questions.
Oh yea, I almost forgot; notice I changed your make clean script. I used $(RM) instead of simply rm -f. When you use utilities in your makefiles, you want to use them as variables. Again, this is to allow your users as much freedom and flexibility as possible when they're compiling your program.
vpath %.cpp src
vpath %.hpp include
vpath %.o build/objs
vpath %.d build/objs
.SUFFIXES:
.SUFFIXES: .cpp .hpp .o .d
SRCDIR = src
INCLUDESDIR = include
BUILDDIR = build
OBJDIR = $(BUILDDIR)/objs
SRCS = $(wildcard $(SRCDIR)/*.cpp)
OBJS = $(patsubst %.cpp, %.o, $(notdir $(SRCS)))
DEP_FILES = $(patsubst %.o, %.d, $(OBJS))
INCLUDE_DIRS = -I $(INCLUDESDIR)
CXX = g++
CPPFLAGS =
CXXFLAGS = -Wall -Wextra -g -std=c++11
PROGRAM = hello.out
COMPILE.cpp = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDE_DIRS) $(TARGET_ARCH)
all: $(PROGRAM)
$(PROGRAM): %: $(OBJS)
$(LINK.cpp) $(INCLUDE_DIRS) $(addprefix $(OBJDIR)/, $^) $(LOADLIBES) $(LDLIBS) -o $#
%.o: %.cpp
$(COMPILE.cpp) -c -o $(OBJDIR)/$# $<
%.d: %.cpp
mkdir -p $(OBJDIR)
$(COMPILE.cpp) $^ -MM -MT $(addprefix $(OBJDIR)/, $(#:.d=.o)) > $(OBJDIR)/$#
include $(DEP_FILES)
.PHONY: clean
clean:
#echo $(RM)
$(RM) $(BUILDDIR) -r
$(RM) *~
$(RM) $(PROGRAM)
For anyone having a similar issue, here's the correct solution is in the comments. Here for convenience: The included .d files generate dependencies but not a recipe for making the .o files, and since I'm putting things in various directories the default rule doesn't work here, so the .o files aren't created. The solution was to add in the following rule to my main makefile.
$(OBJDIR)/%.o :
$(CC) -c -o $# $< $(CPPFLAGS)
Thanks Matt and Renaud for your answers!

Evolving a Makefile From Flat Directory Structure to Sub-Directory Structure

SEE UPDATES BELOW
Research Done: I'm finding learning how to evolve Makefiles from one situation to another is difficult. There are a ton of questions and answers out there but few of them actually show how a Makefile can evolve as your project changes. They also all seem to use various different techniques and idioms of Makefiles so translating between one question and another can be tricky when you are learning Makefiles for the first time, as I am.
Problem: My problem is that I have a project that started at as a flat directory structure but then is migrating to a structure with sub-directories. What I can't do is get my Makefile to along for the ride.
First I'll show what I created that works and then I show how I want it to evolve and how that doesn't work.
Flat Directory Structure, Working Makefile
I have project directory that has all my C files and one header file plus my Makefile:
project
Makefile
c8_asm.c
c8_dasm.c
c8_terp.c
chip8.h
Here is my Makefile (which works just fine):
CC = gcc
CFLAGS += -c -Wall -std=c99
CFLAGS += -D_POSIX_C_SOURCE=200809L
LDLIBS += -lm
# Targets
all: c8_dasm c8_asm c8_terp
c8_dasm: c8_dasm.o
$(CC) $(LDLIBS) c8_dasm.o -o $#
c8_asm: c8_asm.o
$(CC) $(LDLIBS) c8_asm.o -o $#
c8_terp: c8_terp.o
$(CC) $(LDLIBS) c8_terp.o -o $#
# Using implicit rules for updating an '.o' file from a correspondingly
# named '.c' file.
c8_dasm.o: chip8.h
c8_asm.o: chip8.h
c8_terp.o: chip8.h
.PHONY: clean
clean:
rm c8_dasm c8_asm c8_terp c8_dasm.o c8_asm.o c8_terp.o
I get all my .o files and my executables are created in the project directory.
Evolving The Project
But what I wanted to do is have my sources files (all .c and .h) in a src directory. I wanted to build into an obj directory and have the executables go in a bin directory. So my project would look like this:
project
src
c8_asm.c
c8_dasm.c
c8_terp.c
chip8.h
Makefile
Sub-Directory Structure, Makefile NOT Working
To accommodate the above, I changed my Makefile accordingly:
CC = gcc
CFLAGS += -c -Wall -std=c99
CFLAGS += -D_POSIX_C_SOURCE=200809L
LDLIBS += -lm
SRC_DIR = src
OBJ_DIR = obj
BIN_DIR = bin
SOURCES := $(wildcard $(SRC_DIR)/*.c)
OBJECTS := $(SOURCES:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
MKDIR_P ?= mkdir -p
# Targets
all: $(BIN_DIR)/c8_dasm $(BIN_DIR)/c8_asm $(BIN_DIR)/c8_terp
$(BIN_DIR)/c8_dasm: $(OBJ_DIR)/c8_dasm.o
$(CC) $(LDLIBS) $(OBJ_DIR)/c8_dasm.o -o $#
$(BIN_DIR)/c8_asm: $(OBJ_DIR)/c8_asm.o
$(CC) $(LDLIBS) $(OBJ_DIR)/c8_asm.o -o $#
$(BIN_DIR)/c8_terp: $(OBJ_DIR)/c8_terp.o
$(MKDIR_P) $(dir $#)
$(CC) $(LDLIBS) $(OBJ_DIR)/c8_terp.o -o $#
$(OBJECTS): $(OBJ_DIR)/%.o : $(SRC_DIR)/%.c
$(MKDIR_P) $(dir $#)
$(CC) $< -o $(OBJ_DIR)/$#
# Using implicit rules for updating an '.o' file from a correspondingly
# named '.c' file.
$(OBJ_DIR)/c8_dasm.o: $(SRC_DIR)/chip8.h
$(OBJ_DIR)/c8_asm.o: $(SRC_DIR)/chip8.h
$(OBJ_DIR)/c8_terp.o: $(SRC_DIR)/chip8.h
.PHONY: clean
clean:
rm -r $(BUILD_DIR)
rm $(OBJECTS)
Upon running this I get the following:
mkdir -p obj/obj/
gcc src/c8_dasm.c -o obj/c8_dasm.o
gcc -lm obj/c8_dasm.o -o bin/c8_dasm
ld: can't link with a main executable file 'obj/c8_dasm.o' for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [bin/c8_dasm] Error 1
I wanted to stop here and get some assistance because I fear I'm making this Makefile for complicated than it need be and I'm trying to avoid getting into bad habits.
I'm hoping to hear opinions about what I'm not conceptualizing correctly here.
FIRST UPDATE
I managed to take it bit by bit and get it mostly working. Here is what I ended up with:
CC = gcc
CFLAGS += -c -Wall -std=c99
CFLAGS += -D_POSIX_C_SOURCE=200809L
LDLIBS += -lm
# Directories.
SRC_DIR = src
BIN_DIR = bin
$(shell mkdir -p $(BIN_DIR))
# Patterns for files.
SOURCES := $(wildcard $(SRC_DIR)/*.c)
OBJECTS := $(SOURCES:$(SRC_DIR)/%.c=$(SRC_DIR)/%.o)
EXECUTABLES := c8_dasm c8_asm c8_terp
# Targets
all: $(EXECUTABLES)
c8_dasm: $(SRC_DIR)/c8_dasm.o
$(CC) $^ $(LDLIBS) -o $(BIN_DIR)/$#
#echo "C8 Disassembler Built"
c8_asm: $(SRC_DIR)/c8_asm.o
$(CC) $^ $(LDLIBS) -o $(BIN_DIR)/$#
#echo "C8 Assembler Built"
c8_terp: $(SRC_DIR)/c8_terp.o
$(CC) $^ $(LDLIBS) -o $(BIN_DIR)/$#
#echo "C8 Interpreter Built"
# Using implicit rules for updating an '.o' file from a correspondingly
# named '.c' file.
c8_dasm.o: $(SRC_DIR)/chip8.h
c8_asm.o: $(SRC_DIR)/chip8.h
c8_terp.o: $(SRC_DIR)/chip8.h
.PHONY: clean
clean:
rm $(OBJECTS)
rm -r $(BIN_DIR)
Of course, as I'm finding with Make this leads to other obscure problems. For example doing this:
make
make clean
works fine. Meaning all files are generated and the files are cleaned, including the bin directory.
However, if I do this:
make c8_dasm
make clean
This builds fine. But the clean fails to delete the bin directory (although it does delete the object files). This happens regardless of what individual executable I try to build.
No amount of searching is helping me find out why that is.
SECOND UPDATE
I found that problem was solved as well. It just required using the "-f" for the rm statements in the clean target.
THIRD UPDATE
To get the object file directory part working, I tried (from this: path include and src directory makefile) to construct my Makefile as follows:
CC = gcc
CFLAGS += -c -Wall -std=c99
CFLAGS += -D_POSIX_C_SOURCE=200809L
LDLIBS += -lm
SRC_DIR = src
OBJ_DIR = obj
BIN_DIR = bin
$(shell mkdir -p $(BIN_DIR))
$(shell mkdir -p $(OBJ_DIR))
SOURCES := $(wildcard $(SRC_DIR)/*.c)
OBJECTS := $(SOURCES:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
EXECUTABLES := c8_dasm c8_asm c8_terp
all: $(EXECUTABLES)
c8_dasm: $(SRC_DIR)/c8_dasm.o
$(CC) $^ $(LDLIBS) -o $(BIN_DIR)/$#
#echo "C8 Disassembler Built"
c8_asm: $(SRC_DIR)/c8_asm.o
$(CC) $^ $(LDLIBS) -o $(BIN_DIR)/$#
#echo "C8 Assembler Built"
c8_terp: $(SRC_DIR)/c8_terp.o
$(CC) $^ $(LDLIBS) -o $(BIN_DIR)/$#
#echo "C8 Interpreter Built"
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $(CFLAGS) -c $< -o $(BIN_DIR)/$#
.PHONY: clean
clean:
rm -rf $(BIN_DIR)
rm -f $(OBJECTS)
I was able to condense the original three lines using chip8.h into one target but I have no way to know if that's correct. It compiles at least. I also changed the OBJECTS line to reflect the new OBJ_DIR I created.
However, this doesn't put the object files in the right place. It still puts them in the src directory rather than the obj directory.
This is why it makes sense to not do anything complicated with Makefiles. Just put the actual directory names in your commands. Never rely on wildcards.
People using C and C++ and using Makefiles spend too much time trying to get those to work rather than just actually getting things done. That's why you see so many of the questions that you see and why the answers vary so much.
In your specific case, your targets don't always have to contain the directory and that's part of the problem. The rules getting generated don't have an actual target in your file because of the directories you are prepending to everything. You have to think in terms of what is getting generated by each target: meaning, the output. So if c8_dasm is getting output, that's your target. The directory has nothing to do with that. So you need to remove all of your directory substitutions where they aren't needed.
But before doing that, ask yourself this: if your first solution was working, why change it? It's better to not even do directories when you're using Make. Just have everything in the same directory as you started off with. You can even see that this allows your Makefile to be much cleaner.
I believe I may have figured this out. Below is my Makefile. It seems to do what I want. It does the following:
Compiles all object files into the obj directory.
Compiles and links so that executables are generated in the bin directory.
Recognizes if any .c files are changed and recompiles accordingly.
Recognizes if the .h file is changed and recompiles all C files that reference it.
This seems to satisfy all the criteria but I can't tell if I've painted myself into some corner that I can't see yet.
CC = gcc
CFLAGS += -c -Wall -std=c99
CFLAGS += -D_POSIX_C_SOURCE=200809L
LDLIBS += -lm
SRC_DIR = src
OBJ_DIR = obj
BIN_DIR = bin
$(shell mkdir -p $(BIN_DIR))
$(shell mkdir -p $(OBJ_DIR))
SOURCES := $(wildcard $(SRC_DIR)/*.c)
OBJECTS := $(SOURCES:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
EXECUTABLES := c8_dasm c8_asm c8_terp
all: $(EXECUTABLES)
c8_dasm: $(OBJ_DIR)/c8_dasm.o
$(CC) $^ $(LDLIBS) -o $(BIN_DIR)/$#
#echo "C8 Disassembler Built"
c8_asm: $(OBJ_DIR)/c8_asm.o
$(CC) $^ $(LDLIBS) -o $(BIN_DIR)/$#
#echo "C8 Assembler Built"
c8_terp: $(OBJ_DIR)/c8_terp.o
$(CC) $^ $(LDLIBS) -o $(BIN_DIR)/$#
#echo "C8 Interpreter Built"
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(SRC_DIR)/chip8.h
$(CC) $(CFLAGS) -c $< -o $#
.PHONY: clean
clean:
rm -rf $(BIN_DIR)
rm -rf $(OBJ_DIR)
Stackoverflow is whining about too many comments, so I'll make this another "answer." After our back-and-forth to my original comment, your last comment is correct. That's what I wanted you to see.
Understand that you can't use Make to do what you want to do exactly.
So here's really the answer: You can't create multiple executables AND with only some of the object files applying to each one AND while using a directory structure. Make is in no way capable of handling that.
Right now you're trying to use Make in a way that it wasn't intended for which is why you're running into so many problems. If you keep playing around you're going to run into is a series of errors that say "duplicate symbol" because you will be compiling each of your files multiple times for each executable, assuming you follow most of the advice you'll find.
Check out this How can I create a Makefile for C projects with SRC, OBJ, and BIN subdirectories? to see what I mean. That one works because all object files are being used to create a single executable. But as you've stated, that's not going to be the case for you. And that's what Make can't handle. That's why you're not finding an answer to that.
And while your chip8.h file is now not going to cause problems in terms of allowing you to compile, your Makefile with that third update would not recognize when the chip8.h file itself has changed. You would have to change a .c file to force a recompile so that changes to your .h were recognized. So you either have to stick with your second update or use something other than Make.

No rule to make target *, needed by *

I can't get what's wrong with my makefile:
DIST_PATH = ../dist/libs
BUILD_PATH = ../build
MKDIR_P = mkdir -p
.PHONY: all
SHELL = /bin/sh
CC = gcc
FLAGS = -std=gnu99
CFLAGS = -fPIC -pedantic -Wall -Werror
LDFLAGS = -shared
LOG_SRCS = $(shell echo log/*.c)
LOG_HEADERS = $(shell echo log/*.h)
LOG_OBJS = $(addprefix $(BUILD_PATH)/, $(notdir $(LOG_SRCS:.c=.o)))
LOG_TARGET = $(DIST_PATH)/liblog.so
all: dirs $(LOG_TARGET)
dirs :
$(MKDIR_P) $(DIST_PATH)
$(MKDIR_P) $(BUILD_PATH)
$(LOG_TARGET) : $(LOG_OBJS)
$(CC) $(FLAGS) $(CFLAGS) -o $# $(LDFLAGS)
I need to build a shared library from sources in log/ folder to ../dist/libs and put obj file in ../build but I am getting the error:
make: *** No rule to make target '../build/log.o', needed by '../dist/libs/liblog.so'. Stop.
P.S. I know there are many similar questions but I couldn't get from these questions how to resolve my problem.
The problem is that the source and object files are supposed to be placed in different directories, and there's no implicit rule for that.
You need to add a rule for how to translate a source file to an object file:
$(BUILD_PATH)/%.o: log/%.c
Now make knows how to create the object files from the source files.
There's another problem though:
$(LOG_TARGET) : $(LOG_OBJS)
$(CC) $(FLAGS) $(CFLAGS) -o $# $(LDFLAGS)
The command doesn't list any input files, you need to add all the object files to be linked:
$(LOG_TARGET) : $(LOG_OBJS)
$(CC) $(FLAGS) $(CFLAGS) -o $# $^ $(LDFLAGS)
# ^^
# List of all "prerequisites" (object files) to be linked

Makefile not executing to the end

I have the following makefile but it just executes the 1st command where it builds me the .o files and not the .so files. What am I doing wrong?
Thanks,
SHELL = /bin/sh
CC = gcc
CFLAGS = -g -Wall
LDFLAGS = -shared
TARGET = Stepper.so
SOURCES = $(shell echo ./*.c)
HEADERS = $(shell echo ./*.h)
OBJECTS = $(SOURCES:.c=.o)
LIBS = liblua523.a
PREFIX = $(DESTDIR)/usr/local
BINDIR = $(PREFIX)/bin
$(OBJECTS): $(SOURCES) $(HEADERS)
$(CC) $(CFLAGS) -c $(SOURCES) -o $(OBJECTS)
$(TARGET): $(OBJECTS)
$(CC) $(LDFLAGS) -o $(TARGET) $(OBJECTS) $(LIBS)
clean:
rm $(OBJECTS)
Unless you specify a different target on the command line, make always builds the first real target found in the makefile. In this case, the first real target is the first object file, so that's all that's built.
This is why you typically see makefiles with a first target of all or similar, which just depends on the various other targets you want built during a standard invocation of "make" with no arguments.
However, your makefile is really not right, in a number of ways. The fact that it's running it all means you actually only have one source file. As soon as you have >1 it will fail.
This:
SOURCES = $(shell echo ./*.c)
is not very efficient; you should use wildcard here:
SOURCES = $(wildcard ./*.c)
This rule:
$(OBJECTS): $(SOURCES) $(HEADERS)
$(CC) $(CFLAGS) -c $(SOURCES) -o $(OBJECTS)
Tells make, "for every object file, if any source file or any header file has changed, recompile it". Basically, it means that if you change ANYTHING in the directory, EVERYTHING will rebuild. If you want that you might as well write a shell script and not bother with make at all.
Further, the compiler will fail when you have >1 source file, as it will try to run:
gcc -g -Wall -c foo.c bar.c -o foo.o bar.o
which is not right.
You don't need to define this rule at all; make has a built-in rule which knows how to build an object file from a source file. Just replace it with this:
$(OBJECTS): $(HEADERS)
(no recipe) so make knows that the objects depend on the headers as well as the source. Note this is not ideal since all objects rebuild if any header changes but it's fine for a simple program.

Makefile - Generate Targets from Sources

I'm trying to build a growing number of .cpp files with the use of make. They all reside in a subdirectory src/. I want to compile each file into it's own executable, residing in bin/.
This is what I have tried so far, but it doesn't work, and since I'm new to make, all the Patterns, Variables etc. make it difficult to pinpoint what gets expanded into what and so on.
CXX = g++
CXXFLAGS = -Wall -Wextra -pedantic
SRC = $(wildcard src/*.cpp)
BIN = $(patsubst src/%.cpp,bin/%,$(SRC))
all: $(BIN)
%: scr/%.cpp
$(CXX) $(CXXFLAGS) $< -o $#
Also, is there a way to show just the contents of BIN for example to allow me to see what is going on?
This is what your final expansion looks like
file: scr/bin/file.cpp
Why not do this?
BIN = $(patsubst src/%.cpp,%,$(SRC))
all: $(addprefix bin/, $(BIN))
bin/% : src/%
$(GCC) $(FLAGS) $< -o $#
I think that works?
As for showing the contents of BIN
all: $(addprefix bin/, $(BIN))
#echo $(BIN)

Resources