Makefile compiles all the files everytime - gcc

My Makefile compiles all the files everytime I run it though the files have not been changed. I know that this question has been asked several times but none of the provided solutions seem to work for me. I am new to Makefile and most of the times I do not understand the jargon used in the solution. Also, I want to save all the generated .o files under the folder 'obj'
Here is my folder structure
project (-)
gen (-)
display (-)
.c and .h files
logic (-)
.c and .h files
lib (-)
include (-)
.h files
.lib files
man (-)
.c and .h files
obj (-)
want to save all the .o files here
I am running this on Windows OS using MinGW
Here is my Makefile:
ALL: demo
SRCS:= filename1.o filename2.o filename3.o filename4.o and so on till filename27.o
demo: display.o logic.o man.o
gcc $(SRCS) -lglut32 -loglx -lopengl32 -Llib -o demo
display.o:
gcc -Igen/display -Igen/logic -Iman -Ilib/include gen/display/*.c -lglut32 -loglx -lopengl32 -Llib -c
logic.o:
gcc -Igen/display -Igen/logic -Iman -Ilib/include gen/logic/*.c -lglut32 -loglx -lopengl32 -Llib -c
man.o:
gcc -Igen/display -Igen/logic -Iman -Ilib/include man/*.c -lglut32 -loglx -lopengl32 -Llib -c
clean:
#echo "Cleaning up.."
-rm -rf *.o
-rm *.exe
NOTE: glut and oglx files are present in the lib folder. Display.o, lib.o and man.o do not have corresponding .c files. They are just folder names with many c files in them.
I understand this could be the problem. As there are no display.o, logic.o and man.o files created, MAKE complies the rule associated with it eveytime. SO how do I tell it to check for the actual .o filename1.o, filename2.o etc for the timestamp and recompile ONLY if they are older than the corresponding c files and h files maybe even the lib files they depend on.
I tried the following to create dependencies and avoid compiling of files everytime. But this did not help.
%.d: %.c
#set -e; rm -f $#; \
$(CC) -M $(CFLAGS) $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$

At a basic level, make is looking for lines like:
target: dependency
command
If target does not exist, it calls the rule for dependency and then runs command. If target does exist, it tests if dependency is newer or does not exist. If so, it calls the rule for dependency and then runs command. Otherwise, it stops.
Significantly, the rule for dependency will only be called if (a) dependency doesn't exist, or (b) dependency is newer than target.
In the question, assume we run make demo. Then make looks for the line that begins demo: and notices it declares dependencies. So it looks at each dependency in turn to see if they require action. It first discovers display.o. It notices that display.o: does not exist, so it runs the associated rule. It does the same for the other *.o.
To avoid the *.o rules always being run because no associated file exists, you could rewrite like:
ALL: demo
SRCS:= filename1.o filename2.o filename3.o filename4.o and so on till filename27.o
demo: display.ts logic.ts man.ts
gcc $(SRCS) -lglut32 -loglx -lopengl32 -Llib -o demo
display.ts: gen/display/*.c
gcc -Igen/display -Igen/logic -Iman -Ilib/include gen/display/*.c -lglut32 -loglx -lopengl32 -Llib -c
echo . > display.ts
logic.ts: gen/logic/*.c
gcc -Igen/display -Igen/logic -Iman -Ilib/include gen/logic/*.c -lglut32 -loglx -lopengl32 -Llib -c
echo . > logic.ts
man.ts: man/*.c
gcc -Igen/display -Igen/logic -Iman -Ilib/include man/*.c -lglut32 -loglx -lopengl32 -Llib -c
echo . > man.ts
clean:
#echo "Cleaning up.."
-rm -rf *.o *.ts
-rm *.exe

Problem is that your binary object targets (like display.o) do not actually match files produced by their rules. If you tell make it needs to make target display.o, it (normally, except for phony targets, but those always rerun) expect the corresponding file to be produced by the rule's recipe and it can track if the target needs to be remade. If no such file is produces, this target always evaluates as outdated and needing remaking.
A bit of a silly example of this would be the following tree:
.
├── Makefile
├── main.c
└── test
└── file.c
and Makefile:
main: test.o main.o
$(CC) -o main *.o
test.o:
$(CC) $(CFLAGX) -c test/*.c
There is no test.o file and target needs to be remade... the rule runs, produces file.o (again). Since this target was remade and is prerequisite of main... everything always gets remade.
Now with this small modification:
main: test.o main.o
$(CC) -o main *.o
test.o:
$(CC) $(CFLAGX) -o $# -c test/*.c
test.o target indeed produces test.o file and the rule needs no remaking if test.c does not change... and with test.o unchanged and main.c perhaps as well, we get:
$ make
make: 'main' is up to date.
It still is not entirely correct as it really should read:
main: test.o main.o
$(CC) -o main $+
test.o: test/*.c
$(CC) $(CFLAGX) -o $# -c $^
Where I declare depend prerequisites of test.o and reference both them and the target by automatic variable in the rule's recipe. And Same goes for prerequisites for linking. Of course in this simple example I could just rely on implicit pattern rules and do this:
main: test/file.o main.c
test/file.o: test/*.c
What does this mean for your makefile? When you compile your object files, have a look what do they actually produce and match your target to that or (with -o $# for instance) tell them to produce exactly the file matching your target.
I've extended the silly example a bit and there are now two files in test/:
.
├── Makefile
├── main.c
└── test
├── file.c
└── other.c
And the Makefile can look something like this:
main: obj/file.o obj/other.o main.c
obj/%.o: test/%.c
mkdir -p obj
$(CC) $(CFLAGS) -c -o $# $^
It now stores object files in obj/ and make still understand what needs what and can track changes. Of course your setup is more complex and will require more rules, perhaps also divining actual sources or intermediate targets from the directory tree and define few variables to work with that information, e.g.:
OBJS := $(patsubst test/%.c,obj/%.o,$(wildcard test/*.c))
main: $(OBJS) main.c
obj/%.o: test/%.c
mkdir -p obj
$(CC) $(CFLAGS) -c -o $# $^
But the principles remain the same.

Related

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.

Makefile - a command in a command?

I have an embarrassingly simple makefile question but I can't google it due to lack of knowledge - I don't know the words for things I don't know.
Basically, I want to run the makefile in the current directory, look into the ./SRC directory for source files and when everything is finished, move the object files into the ./OBJ directory.
Makefile:
move_obj:
mv -f -t ./OBJ_DIR ./$(OBJ_FILES)
file.o: other_file.h
$(CC) $(CFLAGS) $(CPPFLAGS) -c file.c
move_obj
I want to call "move_obj" after compiling the source files but since I don't know what
result: dependency
evaluation
actually represents (and all makefile introduction guides I've found state "This is what a makefile looks like, off you go then"), I don't know why this isn't working. I assume I need some evaluate command or need to define a function or...?
Thanks for any help in advance.
You can do this by creating another rule for example move, like below
all: $(EXECUTABLE) move
$(EXECUTABLE): $(OBJECTFILES)
$(CC) -o $# $<
$(OBJECTFILES): $(SOURCEFILES)
$(CC) $(CFLAGS) -c -o $# -I $(INCLUDE_PATH) $<
# Move the .o to Object directory #
move:
$(MV) $(OBJECTFILES) $(OBJECT_PATH)
But by doing the above, you will defeat the purpose of the Makefile.
Since your rule is dependent on .o, Make will look for .o in current directory and not find it (because you've moved it) and thus rebuild.
To avoid this, you should output it to ./obj directory and use it from there.
Something like
gcc -g -Wall -o obj/foo.o -c src/foo.c -I ./include
gcc -g -Wall -o obj/main.o -c src/main.c -I ./include
gcc -o exe obj/foo.o obj/main.o -lanylibrary
Below is the makefile doing the same.
C_FLAGS := -g -Wall -Wextra
CC := gcc
RM := rm
LINKFLAGS := -lanylibrary
.PHONY: $(TARGET) clean
VPATH:= ./src/ ./obj/ ./include/
# Path for .c , .h and .o Files
SRC_PATH := ./src/
OBJ_PATH := ./obj/
INC_PATH := -I ./include
# Executable Name
TARGET := exe
# Files to compile
OBJ1 := foo.o \
main.o
OBJ := $(patsubst %,$(OBJ_PATH)%,$(OBJ1))
# Build .o first
$(OBJ_PATH)%.o: $(SRC_PATH)%.c
#echo [CC] $<
#$(CC) $(C_FLAGS) -o $# -c $< $(INC_PATH)
# Build final Binary
$(TARGET): $(OBJ)
#echo [INFO] Creating Binary Executable [$(TARGET)]
#$(CC) -o $# $^ $(LINKFLAGS)
# Clean all the object files and the binary
clean:
#echo "[Cleaning]"
#$(RM) -rfv $(OBJ_PATH)*
#$(RM) -rfv $(TARGET)
Refer to this answer for a better understanding
EDIT:
You can also output your executable to directory, add the following changes to your Makefile.
Ensure that the bin directory is created beforehand, and not deleted by clean.
# Path for .c , .h and .o Files, and ./bin directory
BIN_PATH := ./bin
# Executable Name
TARGET := $(BIN_PATH)/exe
# Clean all the object files and the binary
clean:
#echo "[Cleaning]"
#$(RM) -rfv $(OBJ_PATH)*
#$(RM) -fv $(TARGET)
If you want to build a target(move_obj) after another(file.o), add the move_obj to the dependency list of file.o so that the commands under the move_obj will be executed.
So your Makefile should be:
file.o: other_file.h move_obj
$(CC) $(CFLAGS) $(CPPFLAGS) -c file.c
move_obj:
mv -f -t ./OBJ_DIR ./$(OBJ_FILES)
As Colonel Thirty Two mentioned in the comment section, instead of compiling and then move, you can build the object files in the required directory
file.o: other_file.h
$(CC) $(CFLAGS) $(CPPFLAGS) -c file.c -o ./$(OBJ_FILES)/$#
This is flawed in various ways.
result normally is an actual file that should be present after the recipe is executed. If the file is already there and is not older than any of its dependencies, make does nothing. So instead of creating a file somewhere and then moving it around with another rule, make sure the rule creates it where it should FINALLY be. Otherwise make can never check whether it has to rebuild it (and always will). In this case, use the -o flag of the compiler to directly create it where it should be (e.g. -o $(OBJ_DIR)/file.o)
dependency should list ALL files that are needed to build the result, so make really rebuilds it if ANY of these files changed. In your case, at least file.c is missing from the dependency list
In order to place files in a directory, you should make sure it exists. you could do it like this:
$(OBJ_DIR):
mkdir -p $(OBJ_DIR)
$(OBJ_DIR)/file.o: $(OBJ_DIR) file.c other_file.h
$(CC) $(CFLAGS) $(CPPFLAGS) -c file.c -o $(OBJ_DIR)/file.o
Your move_obj recipe, although not suitable in this case, would be a PHONY target, meaning it does not create a file. If you need such rules, mark them accordingly by mentioning them as dependency of the special target .PHONY:
.PHONY: move_obj
The reason for this is that you could (by accident) have a file named move_obj in your working directory. In that case, make would decide there's nothing to do for move_obj, and this is not what you want. Marking it as phony tells make that this rule does not create its target and the recipe must be executed no matter what.
All in all, your question comes down to misunderstanding a Makefile as kind of a script. It is not. It's a declarative file that tells make what has to be done in order to build files (your evaluation block) and when this needs to be done (your dependency block). It's better not to try to misuse a Makefile as a script.

Simple makefile with directory for object files.

I have written very simple makefile and I can not figure out why it works incorrectly. I wanted to put .o files in different directory.
Unfortunately my .o files are not created in ./obj/Debug but they are in current working directory the same directory where makefile is. Should those directories be created before invoking make? I can't locate my error.
SHELL = /bin/sh
.SUFFIXES:
.SUFFIXES: .c .o
CC := gcc # compiler type
CFLAGS = -Wall
Version := Debug
oPath = obj/$(Version)
app: header1.o main.o
$(CC) -Wall -o -v app $(oPath)/main.o $(oPath)/header1.o
$(oPath)/%.o: %.c header1.h
$(CC) $(CFLAGS) -c $< -o $#
I have also tried:
$(oPath)/%.o: %.c header1.h
$(CC) $(CFLAGS) -c $< -o $(oPath)/$#
but with no success.
The line
app: header1.o main.o
tells make that app depends on header1.o and main.o in the current working directory, so it uses the implicit rules to build them, whereupon they appear in that directory. To fix this, use
app: $(oPath)/header1.o $(oPath)/main.o
make will then use your pattern rule to build $(oPath)/header1.o and $(oPath)/main.o before running the recipie for app.

The makefile creates the object files in the src directory rather than objects folder

Thanks!, I have updated my makefile now. And the .o are created in the src directory.
here is the makefile and output. The makefile throws the error because all the .o are created in the src folders. I don't know why? I am new to Makefile so kindly please bear with my silly questions.
# This is the Vpath; as my source directory is in the src folder - all the .c files
#folder structure
#Gif_Utility
#-->src/*.c
#-->include/*.h
VPATH = src:include:objects
CFLAGS = -I ./include -g -Wall -DDEBUG
OBJS =./objects
# Look at the CFLAGS here; it has -DDEBUG because in my code, I have #ifdef DEBUG
# Look at the CFLAGS here; -Wall : To generate all the compiler warnings.
# include is required as my compilation depends on the .h files.
# The LD flags to link the shared objects
#LDFLAGS=
#in my mini-project, I am using maths library, Thus, I have lm.
# lc to link my main function with crt1.o
#what is the compiler, am I using.
#This is a good practice since I can modify these flags when cross-compiling.
cc= gcc
#PATH for the LIBS
#This might be useful while cross-compiling.
LIBS= -lm -lc
target: $(patsubst %.c,%.o,$(wildcard ./src/*.c))
#echo "making target"
#mkdir -p ./objects
$(cc) $(patsubst ./src/%.c,./objects/%.o,$(wildcard ./src/*.c)) $(LIBS) -o gif
./objects/%.o: ./src/%.c
#echo "making objects now"
$(cc) $(CFLAGS) $(LDFLAGS) -c $< -o $#
#It is always better to write a PHONY rule for a rules like clean.
#It may happen that in source sandbox, you have a clean file. This may invoke the clean file.
#In order to prevent invoking a clean file during make clean; We give this general rule as PHONY
#PHONY tells the MAKEFILE that there is a rule clean, not a file called clean.
#Generally use PHONY for all, install, clean, distclean,
.PHONY: clean
clean:
#echo "cleaning everything"
#rm -f *.o
#rm -f gif
#echo "clearning .o from src"
#rm -f ./src/*.o
#rm -f ./objects/*.o
$make target
cc -I ./include -g -Wall -DDEBUG -c -o src/sysm.o src/sysm.c
cc -I ./include -g -Wall -DDEBUG -c -o src/x86_main.o src/x86_main.c
src/x86_main.c:11:9: warning: second argument of ‘main’ should be ‘char **’ [-Wmain]
src/x86_main.c: In function ‘main’:
src/x86_main.c:16:9: warning: implicit declaration of function ‘display_init’ [-Wimplicit-function-declaration]
src/x86_main.c:19:9: warning: implicit declaration of function ‘Gif_Read’ [-Wimplicit-function-declaration]
making target
gcc ./objects/gif_display.o ./objects/gif_lzw.o ./objects/gif_read.o ./objects/sysm.o ./objects/x86_main.o -lm -lc -o gif
gcc: error: ./objects/gif_display.o: No such file or directory
gcc: error: ./objects/gif_lzw.o: No such file or directory
gcc: error: ./objects/gif_read.o: No such file or directory
gcc: error: ./objects/sysm.o: No such file or directory
gcc: error: ./objects/x86_main.o: No such file or directory
make: *** [target] Error
You need to fix your patsubst to change the directory part of the filenames as well as the suffixes:
$(patsubst ./src/%.c,./objects/%.o,$(wildcard ./src/*.c))
You have other issues in your makefile too, e.g. this target has the wrong prerequisite:
./objects/%.o: %.c
The source file should be something like ./src/%.c
And the rule for that target is wrong, it outputs to ./objects/$# which would expand to something like ./objects/./objects/x86_main.o

Makefiles: Get .cpp from one directory and put the compiled .o in another directory

I'm working on a cross-platform 2D engine for mobile devices (Windows Mobile 6 and Android). My Windows version is pretty much ready, but I still need to make sure the same functionality is available on Android.
What I want is one Makefile in the root of the project and several Makefile's for the project itself and the test applications.
Makefile
---Engine
------Makefile
------src
------bin
------intermediate
---Tests
------TestOne
---------Makefile
---------src
---------bin
---------intermediate
------TestTwo
---------Makefile
---------src
---------bin
---------intermediate
I'm basing my attempts on the following Makefile:
include ../makeinclude
PROGS = test1
SOURCES = $(wildcard *.cpp)
# first compile main.o and start.o, then compile the rest
OBJECTS = main.o start.o $(SOURCES:.cpp=.o)
all: $(PROGS)
clean:
rm -f *.o src
test1: $(OBJECTS)
$(LD) --entry=_start --dynamic-linker system/bin/linker -nostdlib -rpath system/lib -rpath $(LIBS) -L $(LIBS) -lm -lc -lui -lGLESv1_CM $^ -o ../$#
acpy ../$(PROGS)
.cpp.o:
$(CC) $(CFLAGS) -I $(GLES_INCLUDES) -c $*.cpp $(CLIBS)
However, I'm not very good with these things. What I want is for it to take the .cpp's that are in the src folder, compile them to .o and put them in the intermediate folder and, finally, compile the .o's to the compiled exe and put it in the bin folder.
I've managed to get clean to work like this:
cd intermediate && rm -f *.o
However, I can't get it to retrieve the .cpp's, compile them and put them in the intermediate folder.
I've looked at several other Makefiles, but none do the things I want to do.
Any help is appreciated.
There's more than one way to do this, but the simplest is to run in TestOne, making Intermediate/foo.o out of Src/foo.cpp and test1 out of Intermediate/foo.o, like this:
# This makefile resides in TestOne, and should be run from there.
include makeinclude # Adjust the path to makeinclude, if need be.
PROG = bin/test1
SOURCES = $(wildcard Src/*.cpp)
# Since main.cpp and start.cpp should be in Src/ with the rest of
# the source code, there's no need to single them out
OBJECTS = $(patsubst Src/%.cpp,Intermediate/%.o,$(SOURCES))
all: $(PROG)
clean:
rm -f Intermediate/*.o bin/*
$(PROG): $(OBJECTS)
$(LD) $(BLAH_BLAH_BLAH) $^ -o ../$#
$(OBJECTS): Intermediate/%.o : Src/%.cpp
$(CC) $(CFLAGS) -I $(GLES_INCLUDES) -c $&lt $(CLIBS) -o $#

Resources