makefile, compile list of sources stuck on first file - c

I have a very extrange problem.
I'm working with makefile and Eclipse to compile a program for an AVR microcontroller. The basic idea is to create a project handled by a makefile, and everything works well if I only have one (1) source file, but if I add more than one source file, just the first file is compiled as many time as objects (.o files) I want to create.
I think is better with the example below:
This is a snipet of my makefile:
PROJ_DIR = /home/namontoy/workspace-AVR/exampleBitCloudMakefile
SDK_ROOT = /opt/cross/avr
LIST_PATH = $(CONFIG_NAME)/List
EXE_PATH = $(CONFIG_NAME)/Exe
OBJ_PATH = $(CONFIG_NAME)/Obj
# Create list of sources and list objects
SRCS := $(shell find . -type f -name '*.c')
OBJECTS := $(SRCS:.c=.o)
# Second for to create list of sources and objects
#SOURCES=$(wildcard $(SRCS)/*.c)
#OBJECTS_AUX=$(patsubst %.c, %.o, $(SOURCES))
#OBJECTS = $(subst $(PROJ_DIR),$(OBJ_PATH), $(OBJECTS_AUX))
directories:
#echo
#echo $(MSG_MKDIR) $#
#"mkdir" -p $(LIST_PATH)
#"mkdir" -p $(EXE_PATH)
#"mkdir" -p $(OBJ_PATH)
# Compile: create object files from C source files.
$(OBJECTS) : $(SRCS) directories
#echo
#echo $(MSG_BUILDING) $< # print message of begining build
#echo srcs: $(SRCS) # print list of sources
#echo objects: $(OBJECTS) # print list of objects
#echo '$$< is "$<"' # print file to be compiled
#echo '$$# is "$#"' # print name of object file
$(CC) $(CFLAGS) $< -o $#
#echo $(MSG_FINISH_BUILDING) $< # print message of finished build
On the terminal, make prints:
Building file: dummyFile.c
srcs: ./dummyFile.c ./LearningInterrupt_Main.c
objects: ./dummyFile.o ./LearningInterrupt_Main.o
$< is "dummyFile.c"
$# is "dummyFile.o"
avr-gcc -g -c -O1 -std=gnu99 -Wall -mmcu=atmega328p -fshort-enums -funsigned-char -funsigned-bitfields -fpack-struct -Wstrict-prototypes -Wa,-adhlns=dummyFile.lst -I/opt/cross/avr/avr/include -I/opt/cross/avr/lib/gcc/avr/4.8.3/include -I/opt/cross/avr/lib/gcc/avr/4.8.3/include-fixed -I/home/namontoy/workspace-AVR/exampleBitCloudMakefile/headers -I/home/namontoy/workspace-AVR/exampleBitCloudMakefile/ dummyFile.c -o dummyFile.o
Finished building: dummyFile.c
Building file: dummyFile.c
srcs: ./dummyFile.c ./LearningInterrupt_Main.c
objects: ./dummyFile.o ./LearningInterrupt_Main.o
$< is "dummyFile.c"
$# is "LearningInterrupt_Main.o"
avr-gcc -g -c -O1 -std=gnu99 -Wall -mmcu=atmega328p -fshort-enums -funsigned-char -funsigned-bitfields -fpack-struct -Wstrict-prototypes -Wa,-adhlns=dummyFile.lst -I/opt/cross/avr/avr/include -I/opt/cross/avr/lib/gcc/avr/4.8.3/include -I/opt/cross/avr/lib/gcc/avr/4.8.3/include-fixed -I/home/namontoy/workspace-AVR/exampleBitCloudMakefile/headers -I/home/namontoy/workspace-AVR/exampleBitCloudMakefile/ dummyFile.c -o LearningInterrupt_Main.o
Finished building: dummyFile.c
So, as you can see, make read all sources files and objects, but when the second object file is going to be created, make didn't run over the list of sources, it stucks on the first source file.
Any ideas or suggestions?
Thanks in advance,
namontoy.

Here:
$(OBJECTS) : $(SRCS) directories
...
$(CC) $(CFLAGS) $< -o $#
You make every object depend on all sources. And the automatic variable $< takes the first prerequisite, which will be the first source file in the list, no matter what you're trying to build.
Try a pattern rule:
%.o : %.c directories
#echo compiling $< to produce $#
$(CC) $(CFLAGS) $< -o $#

Solved by :
%.o: %.f90
$(FC) $< $(INC) $(LIB) $(FLAGS) -o $(addprefix $(BINDIR)/, $(notdir $#))

Related

How can I improve this Makefile to optimize the usage of the SRC and BIN folders?

This is my first attempt at making a Makefile after having gone through several tutorials and the gnu make manual. The Makefile works and creates the .o, .a and .exe files in the BIN folder. However, I have have added src\ and bin\ prefixes to all files. I know there must be a better way of addressing folder issues while using Makefiles. Only problem is, I am unable to figure it out after hours of editing and trying out different things, based on the tutorials. I find GNU make manual too overwhelming at this stage of my learning curve.
I am using MinGW GCC toolchain on Windows 7. I have copied mingw32-make.exe to make.exe for the purpose of trying out the tutorials and exampples I have been going through.
I would really appreciate any help on the subject. Thank you.
My Makefile is as follows:
CC = gcc
CFLAGS = -O3 -Wall -c
BIN = bin/
LDFLAGS = -L$(BIN) -lmyLib
all: test.exe
test.exe: test.o libmyLib.a
gcc bin\test.o -o bin\test.exe $(LDFLAGS)
test.o: src\test.c src\myLib.h
$(CC) $(CFLAGS) -o bin\test.o src\test.c
libmyLib.a: myLib.o
ar rcs bin\libmyLib.a bin\myLib.o
myLib.o: src\test.c src\myLib.h
$(CC) $(CFLAGS) -o bin\myLib.o src\myLib.c
clean:
del bin\*.* /Q
First, there are some issues with your Makefile, even if it apparently works. When you write:
myLib.o: src\test.c src\myLib.h
$(CC) $(CFLAGS) -o bin\myLib.o src\myLib.c
you are lying to make:
You tell it that the result of the rule is myLib.o while it is bin\myLib.o, that is, a different file.
You tell make that myLib.o depends on src\test.c while it in fact depends on src\myLib.c.
Same with your other rules as in:
libmyLib.a: myLib.o
ar rcs bin\libmyLib.a bin\myLib.o
You tell make that the rule shall be executed if myLib.o is newer than libmyLib.a while the real prerequisite is bin\myLib.o and the real target is bin\libmyLib.a.
By doing so you totally prevent make from doing what it is supposed to do: decide if a recipe must be executed or not, depending on the last modification times of target files and prerequisite files. Give it a try: run make twice and you'll see that it uselessly redoes what it did already. Never, never lie to make.
Second, you can improve your Makefile by using several advanced features like automatic ($#, $<, $^), standard (LDLIBS, AR, ARFLAGS) and regular (BIN, SRC) make variables. Here is an example of what you could try, after fixing the above mentioned issues and better using variables (plus adding the missing -I gcc option, and declaring all and clean as phony because these targets are not real files and we do not want to lie to make):
BIN = bin
SRC = src
CC = gcc
CFLAGS = -O3 -Wall -c -I$(SRC)
LDFLAGS = -L$(BIN)
LDLIBS = -lmyLib
AR = ar
ARFLAGS = rcs
.PHONY: all clean
all: $(BIN)/test.exe
$(BIN)/test.exe: $(BIN)/test.o $(BIN)/libmyLib.a
$(CC) $< -o $# $(LDFLAGS) $(LDLIBS)
$(BIN)/test.o: $(SRC)/test.c $(SRC)/myLib.h
$(CC) $(CFLAGS) -o $# $<
$(BIN)/libmyLib.a: $(BIN)/myLib.o
$(AR) $(ARFLAGS) $# $^
$(BIN)/myLib.o: $(SRC)/myLib.c $(SRC)/myLib.h
$(CC) $(CFLAGS) -o $# $<
clean:
del $(BIN)\*.* /Q
Now, all non-phony targets and prerequisites are regular files, the ones that are really involved in the rules. Again, give it a try and you'll see that make rebuilds only what is out of date and thus needs to be rebuilt.
If you want to get rid of the $(SRC)/ prefix you can use the vpath directive that tells make where to look for source files (I insist on source, many people try to use it for target files, this is not what it is intended for):
vpath %.h $(SRC)
vpath %.c $(SRC)
And then:
$(BIN)/test.o: test.c myLib.h
$(CC) $(CFLAGS) -o $# $<
$(BIN)/myLib.o: myLib.c myLib.h
$(CC) $(CFLAGS) -o $# $<
Note: you could also use the VPATH variable instead of the vpath directive.
Pattern rules are used to factor similar rules, like, for instance, your compilation rules that differ only by the names of the source file and object file:
$(BIN)/%.o: %.c myLib.h
$(CC) $(CFLAGS) -o $# $<
All in all:
BIN = bin
SRC = src
CC = gcc
CFLAGS = -O3 -Wall -c -I$(SRC)
LDFLAGS = -L$(BIN)
LDLIBS = -lmyLib
AR = ar
ARFLAGS = rcs
vpath %.h $(SRC)
vpath %.c $(SRC)
.PHONY: all clean
all: $(BIN)/test.exe
$(BIN)/test.exe: $(BIN)/test.o $(BIN)/libmyLib.a
$(CC) $< -o $# $(LDFLAGS) $(LDLIBS)
$(BIN)/%.o: %.c myLib.h
$(CC) $(CFLAGS) -o $# $<
$(BIN)/libmyLib.a: $(BIN)/myLib.o
$(AR) $(ARFLAGS) $# $^
clean:
del $(BIN)\*.* /Q
Finally, if you really want to avoid the $(BIN)/ prefix in your rules you will have to move to the $(BIN) directory and call make from there. You can leave the Makefile in the main directory and use the -f ../Makefile option, if you wish.
But of course this is less convenient that just typing make [goals] from the main directory. There are ways to let make test from where it has been called, and if it is not from the build directory, re-call itself with the -C and -f options such that it does its job from the build directory. But it is probably a bit too complicated if you are new to make.
If you are however interested have a look at this post that covers this topic (and more). If we simplify as much as possible what the post suggests and specialize it for your case, the final Makefile could be something like:
# here starts the black magic that makes it possible
.SUFFIXES:
BIN := bin
SRC := src
ifneq ($(notdir $(CURDIR)),$(BIN))
.PHONY: $(BIN) clean
$(BIN):
#$(MAKE) --no-print-directory -C $# -f ../Makefile SRC=$(CURDIR)/$(SRC) $(MAKECMDGOALS)
Makefile: ;
% :: $(BIN) ; :
clean:
del $(BIN)\*.* /Q
else
# here ends the black magic that makes it possible
# here starts the Makefile you would really like to write
CC := gcc
CFLAGS := -O3 -Wall -c -I$(SRC)
LDFLAGS := -L.
LDLIBS := -lmyLib
AR := ar
ARFLAGS := rcs
vpath %.h $(SRC)
vpath %.c $(SRC)
.PHONY: all
all: test.exe
test.exe: test.o libmyLib.a
$(CC) $< -o $# $(LDFLAGS) $(LDLIBS)
%.o: %.c myLib.h
$(CC) $(CFLAGS) -o $# $<
libmyLib.a: myLib.o
$(AR) $(ARFLAGS) $# $^
# here ends the Makefile you would really like to write
# a last bit of black magic
endif
The Makefile you would really like to write is what you would write if your source files and target files were all in the source directory. No prefixes any more; vpath takes care of the $(SRC)/ prefix and $(BIN)/ is useless because when this part of the Makefile is used we are already inside $(BIN).
Note: I know nothing about Windows and its various command line interfaces so there are probably some things to adapt (backslashes instead of slashes for instance).

Make file that compiles gcc and puts the objects in a separate folder

I am trying to create a make file that will work accordingly
OBJECT_DIRECTORY := out/obj
C_SOURCE_FILES = (Path and files fetched from different make files)
CFLAGS += -mcpu=$(CPU) -mthumb -mabi=aapcs -mfloat-abi=soft
CFLAGS += -Wall -Werror
CFLAGS += -D$(DEVICE) -std=gnu99
$(OBJECT_DIRECTORY)/%.o: %.c
$(CC) $(C_SOURCE_FILES) $(CFLAGS) -c -o $# $<
I verified that the C_SOURCE_FILES variable actually contains the c source files. This since I am able to compile using this:
$(OBJECT_DIRECTORY)/%.o:
$(CC) $(C_SOURCE_FILES) $(CFLAGS) -c
Problem with that is that the object files are not placed in the folder where I need them for the linking.
By the way, I am executing the make file from the Eclipse C/C++ IDE
I would be extremely happy if someone could help me solve this problem.
Try this:
$(OBJECT_DIRECTORY)/%.o: %.c
$(CC) $(CFLAGS) -c -o $# $<
You don't need the C_SOURCE_FILES variable here. This recipe will create out/obj/{file}.o for every file called {file}.c.
You don't show it, but the dependency list for the executable being created from the object files must explicitly call out each object file.
I solved the problem, I think... By creating a list of target files to be used in the compilation.
# Create the object file names needed for the target. Make needs these file names as target for the compilation
TEMP := $(notdir $(C_SOURCE_FILES:.c=.o))
C_OBJECT_FILES := $(addprefix $(OBJECT_DIRECTORY)/, $(TEMP:.c=.o) )
TEMP_1 := $(notdir $(ASSEMBLER_SOURCE_FILES:.s=.o))
ASSEMBLER_OBJECT_FILES := $(addprefix $(OBJECT_DIRECTORY)/,$(TEMP_1:.s=.o) )
# Tells make to compile all the files in the C_OBJECTS_VARIABLE
all: $(C_OBJECT_FILES)
# Do the compilation of the c files and place the object files in the out/obj folder
$(C_OBJECT_FILES): $(C_SOURCE_FILES)
$(CC) $(CFLAGS) -M $< -MF "$(#:.o=.d)" -MT $#
$(CC) $(CFLAGS) -c -o $# $<
# Tells make to compile all the files in the ASSEMBLER_OBJECTS_VARIABLE
all: $(ASSEMBLER_OBJECT_FILES)
# Do the compilation of the assembler files and place the object files in the out/obj folder
$(ASSEMBLER_OBJECT_FILES): $(ASSEMBLER_SOURCE_FILES)
$(CC) $(ASMFLAGS) -c -o $# $<
This works well and consistently. Issue I have now is that the rule for linking is not executed at all...
## Link C and assembler objects to an .out file
$(BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out: $(C_OBJECT_FILES) $(ASSEMBLER_OBJECT_FILES) $(LIBRARIES)
$(CC) $(LDFLAGS) -o $(BINARY_DIRECTORY)/$(OUTPUT_FILENAME).out
I am wondering if it has anything to do with "all:"
Found the solution to that problem as well. I created a couple of new rules to make sure that the linking is getting executed. Now the make file works well.

Make implicit rules with GCC: Redirecting *.o

I am trying to get make to do the following with an implicit rule:
obj/lsabase.o : inc/lsabase.h lsabase.c
cc -c lsabase.c && mv lsabase.o obj
I searched for ways to redirect the output of "cc -c .." with compiler options, but didn't find any here.
Also the implicit rule defined for compiling from source to object only lets you use $(CPPFLAGS) and $(CFLAGS).
Does anybody know how to trick make into using this (mv lsabase.o obj) in an implicit rule, so I can put all *.o files in a seperate directory?
obj/lsabase.o : inc/lsabase.h lsabase.c
cc -I"inc" -c lsabase.c -o obj/lsabase.o
I would
avoid doing the mv manually but rather telling gcc to put in the obj dir
let gcc handle the dependencies (by creating .d files)
and here is what I usually do when all my .c files are in a subdir and I want to compile all of them in a parallel dir obj (that I can easily remove):
default: my_code
#add subdirs
DIRS := $(shell find src -type d)
#add include directives for subdirs
CFLAGS += $(DIRS:%=-I%)
#collect all c files
SRCS := $(shell find src/* -name \*.c)
OBJS := $(addprefix obj/, $(SRCS:.c=.o))
DEPS := $(addprefix obj/, $(SRCS:.c=.d))
# this generates a dependency file for every .c
obj/%.d: %.c
# mkdir -p "$(#D)"
# echo "Checking dependencies for $<"
# create and modify dependecy file .d to take into account the location obj (sed magical)
# gcc $(CFLAGS) -MM $< 2>/dev/null | sed -e "s#\(^.*\)\.o:#obj/$(shell dirname $<)/\1.d obj/$(shell dirname $<)/\1.o:#" > $#
#this compiles
obj/%.o : %.c
gcc $(CFLAGS) -c $< -o $#
#this creates the executable
my_code: $(OBJS)
gcc $(OBJS) -o $# $(LDFLAGS)
# this does the magic
-include $(DEPS)
clean:
rm -rf obj
If you're new to Make, this might seem difficult, but it's really powerful once you get through.
you can write the makefile rule this way:
obj/lsabase.o : lsabase.c inc/lsabase.h
<tab>cc $(CFLAGS) -c $< -o $# -Iinc/.
where, in the actual makefile, the <tab> would be replaced with an actual tab character
Notice the *.c file is first in the list of dependencies, so can use the $< shortcut
You mentioned wanting to do this for all the object files..
obj/$.o : %.c inc/%.h
<tab>cc $(CFLAGS) -c $< -o $# -Iinc/.
However, that may not be the most flexible. For maximum flexibility, suggest adding a rule to generate and include dependency files named *.d. Then using:
obj/$.o : %.c %.d
<tab>cc $(CFLAGS) -c $< -o $# -Iinc/.

Compiling a list of files with many directories

i've been banging my head over this issue today.
I have many c files in many directories. They all need to be compiled and linked to a library.
Here is a hypothetical layout of the files:
main_dir/
thing1/
thing1.c
thing2/
thing2.c
thing3/
thing3.c
MakeFile
I have a makefile that "finds" these files and generates the necessary objects, however, the same c file is always used as the input.
This is what the Makefile looks like (the contents of each file are a function each that uses puts()):
C=gcc
CFLAGS=-Wall -g
OBJDIR=obj
SRC=$(shell find src/ -type f -name "*.c")
SRC_DIRS=$(shell find src/ -type f -name "*.c" -exec dirname {} \; | uniq)
OBJS=$(SRC:%.c=${OBJDIR}/%.o)
$(OBJS) : $(SRC)
#echo Compiling : $<
$(C) -c $(CFLAGS) -o $# $<
clean:
rm -fv $(OBJS) thingy.a
folders:
$(call build_dirs)
all: folders $(OBJS)
ar -r -o thingy.a $(OBJS)
define build_dirs
for dir in $(SRC_DIRS); do \
mkdir -pv $(OBJDIR)/$$dir; \
done
endef
The output from making:
for dir in src/thing1 src/thing2 src/thing3; do mkdir -pv obj/$dir; done
Compiling : src/thing1/thing1.c
gcc -c -Wall -g -o obj/src/thing1/thing1.o src/thing1/thing1.c
Compiling : src/thing1/thing1.c
gcc -c -Wall -g -o obj/src/thing2/thing2.o src/thing1/thing1.c
Compiling : src/thing1/thing1.c
gcc -c -Wall -g -o obj/src/thing3/thing3.o src/thing1/thing1.c
ar -r -o thingy.a obj/src/thing1/thing1.o obj/src/thing2/thing2.o obj/src/thing3/thing3.o
ar: creating thingy.a
I'm very certain the problem is my use of $(SRC) in
$(OBJS) : $(SRC)
However, I just don't know what to do.
Anybody with MakeFu that could help?
Your $(OBJS) seems to be setup correctly, therefore the following should work (instead of $(OBJ) : $(SRC) target):
$(OBJDIR)/%.o : %.c
#echo Compiling : $<
$(C) -c $(CFLAGS) -o $# $<
You're right about the $(OBJS) rule being the problem.
Look at the variables: (SRC) is src/thing1/thing1.c src/thing2/thing2.c src/thing3/thing3.c, and $(OBJS) is obj/src/thing1/thing1.o obj/src/thing2/thing2.o obj/src/thing3/thing3.o. (Are you sure you want a src directory in obj/?) Now suppose you want to build obj/src/thing2/thing2.o using this rule:
$(OBJS) : $(SRC)
#echo Compiling : $<
$(C) -c $(CFLAGS) -o $# $<
The prerequisite field ($(SRC)) expands to "src/thing1/thing1.c src/thing2/thing2.c src/thing3/thing3.c", so $< expands to "src/thing1/thing1.c". Obviously what you want in this case is "src/thing2/thing2.c", so that's what the prerequisite field should be. What you need is something like a pattern rule or static pattern rule. The trick is that you don't know the paths ahead of time, and Make doesn't handle patterns well, so we have to be deft:
$(OBJS) : $(OBJDIR)/%.o : %.c
#echo Compiling : $<
$(C) -c $(CFLAGS) -o $# $<

How can I create a Makefile for C projects with SRC, OBJ, and BIN subdirectories?

A few months ago, I came up with the following generic Makefile for school assignments:
# ------------------------------------------------
# Generic Makefile
#
# Author: yanick.rochon#gmail.com
# Date : 2010-11-05
#
# Changelog :
# 0.01 - first version
# ------------------------------------------------
# project name (generate executable with this name)
TARGET = projectname
CC = gcc -std=c99 -c
# compiling flags here
CFLAGS = -Wall -I.
LINKER = gcc -o
# linking flags here
LFLAGS = -Wall
SOURCES := $(wildcard *.c)
INCLUDES := $(wildcard *.h)
OBJECTS := $(SOURCES:.c=*.o)
rm = rm -f
$(TARGET): obj
#$(LINKER) $(TARGET) $(LFLAGS) $(OBJECTS)
#echo "Linking complete!"
obj: $(SOURCES) $(INCLUDES)
#$(CC) $(CFLAGS) $(SOURCES)
#echo "Compilation complete!"
clean:
#$(rm) $(TARGET) $(OBJECTS)
#echo "Cleanup complete!"
This will basically compile every .c and .h file to generate .o files and the executable projectname all in the same folder.
Now, I'd like to push this a little. How can I write a Makefile to compile a C project with the following directory structure?
./
./Makefile
./src/*.c;*.h
./obj/*.o
./bin/<executable>
In other words, I'd like to have a Makefile that compiles C sources from ./src/ into ./obj/ and then link everything to create the executable in ./bin/.
I've tried to read different Makefiles, but I simply can't make them work for the project structure above; instead, the project fails to compile with all sorts of errors. Sure, I could use full blown IDE (Monodevelop, Anjuta, etc.), but I honestly prefer to stick with gEdit and the good ol' terminal.
Is there a guru who can give me a working solution, or clear information about how this can be done? Thank you!
** UPDATE (v4) **
The final solution :
# ------------------------------------------------
# Generic Makefile
#
# Author: yanick.rochon#gmail.com
# Date : 2011-08-10
#
# Changelog :
# 2010-11-05 - first version
# 2011-08-10 - added structure : sources, objects, binaries
# thanks to http://stackoverflow.com/users/128940/beta
# 2017-04-24 - changed order of linker params
# ------------------------------------------------
# project name (generate executable with this name)
TARGET = projectname
CC = gcc
# compiling flags here
CFLAGS = -std=c99 -Wall -I.
LINKER = gcc
# linking flags here
LFLAGS = -Wall -I. -lm
# change these to proper directories where each file should be
SRCDIR = src
OBJDIR = obj
BINDIR = bin
SOURCES := $(wildcard $(SRCDIR)/*.c)
INCLUDES := $(wildcard $(SRCDIR)/*.h)
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
rm = rm -f
$(BINDIR)/$(TARGET): $(OBJECTS)
#$(LINKER) $(OBJECTS) $(LFLAGS) -o $#
#echo "Linking complete!"
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
#$(CC) $(CFLAGS) -c $< -o $#
#echo "Compiled "$<" successfully!"
.PHONY: clean
clean:
#$(rm) $(OBJECTS)
#echo "Cleanup complete!"
.PHONY: remove
remove: clean
#$(rm) $(BINDIR)/$(TARGET)
#echo "Executable removed!"
First, your $(OBJECTS) rule is problematic, because:
it's kind of indiscriminate, making all sources prerequisites of every object,
it often uses the wrong source (as you discovered with file1.o and file2.o)
it tries to build executables instead of stopping at objects, and
the name of the target (foo.o) is not what the rule will actually produce (obj/foo.o).
I suggest the following:
OBJECTS := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
$(CC) $(CFLAGS) -c $< -o $#
#echo "Compiled "$<" successfully!"
The $(TARGET) rule has the same problem that the target name does not actually describe what the rule builds. For that reason, if you type make several times, Make will rebuild the target each time, even though there is no reason to. A small change fixes that:
$(BINDIR)/$(TARGET): $(OBJECTS)
$(LINKER) $# $(LFLAGS) $(OBJECTS)
#echo "Linking complete!"
Once that's all in order, you might consider more sophisticated dependency handling; if you modify one of the header files, this makefile will not know which objects/executables must be rebuilt. But that can wait for another day.
EDIT:
Sorry, I omitted part of the $(OBJECTS) rule above; I've corrected it. (I wish I could use "strike" inside a code sample.)
You can add the -I flag to the compiler flags (CFLAGS) to indicate where the compiler should look for source files , and the -o flag to indicate where the binary should be left:
CFLAGS = -Wall -I./src
TARGETPATH = ./bin
$(TARGET): obj
#$(LINKER) $(TARGETPATH)/$(TARGET) $(LFLAGS) $(OBJECTS)
#echo "Linking complete!"
In order to drop the object files into the obj directory, use the -o option when compiling. Also, look at the $# and $< automatic variables.
For example, consider this simple Makefile
CFLAGS= -g -Wall -O3
OBJDIR= ./obj
SRCS=$(wildcard *.c)
OBJS=$(SRCS:.c=.o )
all:$(OBJS)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $(OBJDIR)/$#
Update>
By looking at your makefile, I realize you are using the -o flag. Good. Continue using it, but add a target directory variable to indicate where the output file should be written.
I have stopped writing makefiles these days, if your intention is to learn go ahead, else you have good makefile generator that comes with eclipse CDT. If you want some maintainability / multiple project support with in your build tree, have a look at the following -
https://github.com/dmoulding/boilermake I found this pretty good..!

Resources