Makefile recursive method issue - makefile

Below is my code structure with Makefile and source codes
work
├── code
| |
| └── main.h and test.h files here
│ └── main.c and test.c files here
| └── subdir.mk
|
├── _build/
└── Makefile here
Makefile looks like below
all : ../code/target_file
../code/target_file : ../code/main.o ../code/test.o
#echo Building ...
#echo Linking files ...
gcc -Llib ../code/main.o ../code/test.o -lm -o ../code/target_file
.PHONY:subdir
../code/main.o ../code/test.o:subdir;
subdir:
#echo Building object files ...
cd ../code && $(MAKE) -f subdir.mk
clean:
rm -rv ../code/*.o ../code/*.exe
subdir.mk code is
main.o : main.c main.h test.h
#echo Building main.c ...
gcc -Werror -Wall -c main.c -o main.o
test.o : test.c test.h
#echo Building test.c ...
gcc -Werror -Wall -c test.c -o test.o
I am trying to use recursive make as per the tutorials and suggestions in the forum.
The error I am getting is
Building object files ...
cd ../code && make -f subdir.mk
make[1]: Entering directory '/f/My_Work/C/VSC/makefile_test/Recursive/test_mulltiple_2020_09_19/code'
Building main.c ...
gcc -Werror -Wall -c main.c -o main.o
make[1]: Leaving directory '/f/My_Work/C/VSC/makefile_test/Recursive/test_mulltiple_2020_09_19/code'
Building ...
Linking files ...
gcc -Llib ../code/main.o ../code/test.o -lm -o ../code/target_file
____________________________________________________________
gcc.exe: error: ../code/test.o: No such file or directory |
|
make: *** [Makefile:7: ../code/target_file] Error 1 |
____________________________________________________________|
main.o is generated but test.o didn't.
Any suggestions for removing the error?

Your subdir.mk file lists two targets. Make will always build either the target(s) you give on the command line, or else the first target in the makefile if you don't specify.
So you either have to create an initial target in your subdir.mk like this:
all: main.o test.o
so that it will build both, or else tell the recursive make invocation you want to build them both:
subdir:
#echo Building object files ...
cd ../code && $(MAKE) -f subdir.mk test.o main.o

Related

MAKEFILE header file error when try to generate dependency file

Code structure
work
├── code
| |
| ├──inc/
| | └── main.h
| |
| └── main.c
├── _Build/
│ └── Makefile
Below is the Makefile code
WORKSPACE = ..
DIR_CODE = $(WORKSPACE)/code
DIR_BIN = $(WORKSPACE)/bin
DIR_OBJ = $(WORKSPACE)/obj
C_SRC_WITH_PATH = $(shell find $(DIR_CODE) -iname *.c)
C_SRC_ONLY_PATH = $(patsubst %/,%,$(sort $(dir $(C_SRC_WITH_PATH))))
TARGET = $(DIR_BIN)/application
.PHONY : all run clean
all : $(TARGET)
$(TARGET) : ../obj/main.o | $(DIR_BIN) ../deps
gcc $^ -o $#
../obj/main.o : ../code/main.c ../deps | $(DIR_OBJ)
gcc -c -o $# $< -MMD -MP -MF ../deps/main.d
$(DIR_BIN) $(DIR_OBJ) ../deps :
mkdir -p $#
run :
$(TARGET)
clean :
rm -rf $(DIR_BIN) $(DIR_OBJ) ../deps
-include ../deps/main.d
I am getting below error
gcc -c -o ../obj/main.o ../code/main.c -MMD -MF ../deps/main.d
../code/main.c:2:10: fatal error: main.h: No such file or directory
2 | #include "main.h"
| ^~~~~~~~
compilation terminated.
make: *** [Makefile:26: ../obj/main.o] Error 1
Although I am trying to generate the dependency file in the makefile, the file main.d is not generated and getting error for main.h file which is included in main.c file.
Any guidance is deeply appreciated.
This doesn't have anything to do with .d files etc. The compiler can't find your header file, because you haven't add the correct directory to the compile line. If your headers live in ../code/inc then you have to add this to your compile line, else how can the compiler find them?
Since you're not using any make variables to hold the compiler or flags, you'll have to add it directly to your recipe:
../obj/main.o : ../code/main.c ../deps | $(DIR_OBJ)
gcc -I../code/inc -c -o $# $< -MMD -MP -MF ../deps/main.d
There are a lot of weird things about this makefile but at least this will solve your compile error.

Makefile non-recursive method issues

I am trying to build using Makefile below code structure using non-recursive method as per the guidance I received in
link description
work
├── code
| |
| └── main.h and test.h files here
│ └── main.c and test.c files here
| └── subdir.mk
|
├── _Build/
│ └── Makefile here
Below is the Makefile
-include ../code/subdir.mk
all : target_file
target_file : ../code/main.o ../code/test.o
#echo Building ...
#echo Linking files ...
gcc -Llib ../code/main.o ../code/test.o -lm -o target_file
clean:
rm -rv ../code/*.o
Below is the subdir.mk file
../code/test.o : ../code/test.c ../code/test.h
#echo Building test.c ...
gcc -Werror -Wall -c ../code/test.c -o ../code/test.o
../code/main.o : ../code/main.c ../code/main.h ../code/test.h
#echo Building main.c ...
gcc -Werror -Wall -c ../code/main.c -o ../code/main.o
The output I am getting while running make command is below
Building test.c ...
gcc -Werror -Wall -c ../code/test.c -o ../code/test.o
There is no error I am getting nor main.o is getting generated. Also in Makefile the linking command is not executed.
That's likely because make by default builds the first target it encounters. Since you include the subdir.mk before your all : target_file line, the first target named in subdir.mk is built, and nothing else. Solution: place the subdir.mk inclusion last, e.g. near the end.

Makefile compiles all the files everytime

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.

Makefile Errors: make all command

This is the makefile:
all: main
main: main.o sum/sum.o sum/add/add.o utils/utils.o
gcc -Wall main.o sum/sum.o sum/add/add.o utils/utils.o -o main
main.o: main.c utils/utils.h sum/sum.h
gcc -Wall -c main.c
sum/sum.o: sum/sum.c sum/sum.h add/add.h
gcc -Wall -c sum/sum.c
sum/add/add.o: sum/add/add.c add.h
gcc -Wall -c sum/add/add.c
utils/utils.o: utils/utils.c
gcc -Wall -c utils/utils.c
clean:
rm -f main main.o sum/sum.o sum/add/add.o utils/utils.o *~
When I run make all in bash, I get errors like:
-make: *** No rule to make target `add.h', needed by `sum/sum.o'. Stop.
-make: *** No rule to make target `sum.c', needed by `sum/sum.o'. Stop.
And I have a directory where everything is:
.:
main.c main.o Makefile sum utils
./sum:
add sum.c sum.h
./sum/add:
add.c add.h
./utils:
utils.c utils.h
Where did I go wrong?

Makefile - move object files

After a bit of searching, I've managed to throw together the following Makefile:
CC = gcc
CFLAGS = -c -Wall
LDFLAGS =
SOURCEFILES = main.c
SOURCES = src/$(SOURCEFILES)
OBJECTS = $(SOURCES:.c=.o)
EXECUTABLE = netsim
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.c.o:
$(CC) $(CFLAGS) $< -o $#
clean:
rm -rf netsim $(OBJECTS)
I would like to be able to move my object files into another directory, but have been struggling with getting that to work. What am I missing?
The trick is to not move your objects.
You should build it and use it from where they are built.
For example you have the following directory structure:
$ tree .
├── Makefile
├── include
│   └── common_head.h
├── obj
└── src
├── foo.c
└── main.c
Manual execution:
$ gcc -o ./obj/foo.o -c ./src/foo.c -I ./include # Build Object #
$ gcc -o ./obj/main.o -c ./src/main.c -I ./include
$ gcc -o exe ./obj/foo.o ./obj/main.o # Build Executable #
Makefile to simulate the above
C_FLAGS := -g -Wall -Wextra
CC := gcc
RM := rm
LINKFLAGS := -lanylibrary
.PHONY: $(TARGET)
.PHONY: 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)
So when you do a Make
$ make -B
[CC] src/foo.c
[CC] src/main.c
[INFO] Creating Binary Executable [exe]
To see a dry-run use make -n
$ make clean ; make -n
g++ -g -Wall -Wextra -o obj/foo.o -c src/foo.c -I ./include
g++ -g -Wall -Wextra -o obj/main.o -c src/main.c -I ./include
g++ -o exe obj/foo.o obj/main.o -lanylibrary
So after building your directory structure should look like this.
$ tree .
├── Makefile
├── exe
├── include
│   └── common_head.h
├── obj
│   ├── foo.o
│   └── main.o
└── src
├── foo.c
└── main.c
So from my previous answer.
You don't have to use any PHONY move and also no objects are recreated unnecessarily.
Something like this?
SOURCES = src/main.c
OBJECTS = obj/main.o
...
obj/%.o: src/%.c
$(CC) $(CFLAGS) $< -o $#
Once that's working, you can add further tricks, like this:
OBJECTS = $(patsubst src/%.c, obj/%.o, $(SOURCES)

Resources