MAKEFILE header file error when try to generate dependency file - makefile

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.

Related

Makefile recursive method issue

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

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 dependency error after using flags $(#:.o=.d)

I have created a Makefile for the below code structure
work
├── code
| |
| ├──inc/
| | └── main.h and test.h files here
| |
| ├──src/
│ └── main.c and test.c files here
├── _Build/
│ └── Makefile here
Here is the Makefile
# All path are referenced with the directory path of Makefile
# Directory Path for workspace
WORKSPACE = ..
# Directory path for code
PATH_DIR_CODE = $(WORKSPACE)/code
# Directory path for c source files
PATH_DIR_C_SOURCES = $(PATH_DIR_CODE)/src
# Directory path for c header files
DIR_PATH_C_HEADERS = $(PATH_DIR_CODE)/inc
# Directory path for obj files
DIR_PATH_OBJ = $(WORKSPACE)/obj
# Directory path for executables
DIR_PATH_BIN = $(WORKSPACE)/bin
# Executable name declaration
FILE_PATH_EXE = $(DIR_PATH_BIN)/main
# Command mkdir
MKDIR = mkdir
FILE_PATH_C_HEADER = $(shell find $(PATH_DIR_CODE) -name *.h)
DIR_PATH_C_HEADER = $(patsubst %/,%,$(sort $(dir $(FILE_PATH_C_HEADER))))
FILE_PATH_C_SRC = $(shell find $(PATH_DIR_CODE) -name *.c)
DIR_PATH_C_SRC = $(patsubst %/,%,$(sort $(dir $(FILE_PATH_C_SRC))))
INC_FILE_C_HEADER = $(addprefix -I, $(DIR_PATH_C_HEADER))
FILE_PATH_OBJ = $(patsubst $(DIR_PATH_C_SRC)/%.c, $(DIR_PATH_OBJ)/%.o, $(FILE_PATH_C_SRC))
CC = gcc
CFLAGS = -Werror -Wall
CDEPS = -MMD -MP -MF $(#:.o=.d)
LDFLAGS = -Llib
LDLIBS = -lm
MKDIR = mkdir
-include $(FILE_PATH_OBJ:.o=.d)
all : $(FILE_PATH_EXE)
.PHONY : all
$(FILE_PATH_EXE) : $(FILE_PATH_OBJ) | $(DIR_PATH_BIN)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(DIR_PATH_OBJ)/%.o : $(DIR_PATH_C_SRC)/%.c | $(DIR_PATH_OBJ)
$(CC) $(CFLAGS) -c $< $(CDEPS) -o $#
$(DIR_PATH_BIN) $(DIR_PATH_OBJ):
$(MKDIR) -p $#
clean :
$(RM) -rv $(DIR_PATH_BIN) $(DIR_PATH_OBJ)
Based on tutorial for dependencies I have used the flags
CDEPS = -MMD -MP -MF $(#:.o=.d)
and
-include $(FILE_PATH_OBJ:.o=.d)
still I am getting the following error
mkdir -p ../obj
gcc -Werror -Wall -c ../code/src/main.c -MMD -MP -MF ../obj/main.d -o ../obj/main.o
../code/src/main.c:4:10: fatal error: test.h: No such file or directory
#include "test.h"
^~~~~~~~
compilation terminated.
make: *** [Makefile:56: ../obj/main.o] Error 1
To remove this error what should be included in the Makefile?
Dependencies should be removed by this logic or some other logic should be used?
You are conflating two different things.
The .d files tell make where to look for prerequisites of the target. In this case the target is an object file (.o) and the prerequisite is a header file, but to make they're just "targets" and "prerequisites". Make is not restricted to just compiling C programs: it can do essentially any task where changing some files means that some other files need to be updated: compiling programs (not just C programs) is one common use but it can build documentation, web sites, run tests, etc. Make does its job by running commands, just as you would do it yourself from the command line (except make never forgets to add an option and doesn't make typos). It doesn't really know anything about "compilers" and "linkers", internally.
The error you are getting is from the compiler (or to be pedantic, the preprocessor), not make, and the compiler has to be told where to look for the header files it needs to include. Those are two completely different things and require different operations: the compiler requires that you provide the directories to search using the -I command line option.
I suppose it might be nice if the compiler could parse make's .d files and figure out where to look for headers, but it can't. You have to specify the flags yourself.
In your situation it's even more clear: you are actually using the compiler to generate the .d files! So there's a chicken-and-egg problem: if the compiler could get the paths from the .d files, but the .d files are being created from the compiler, then where do the paths come from in the first place?

Using suffix rules in Makefile

Suppose there are a.c, b.c, c.c, tt/at.c, tt/bt.c, fff/af.c, fff/bf.c. So I make Makefile like this:
OBJS=a.o b.o c.o
SRCS=$(OBJS:.o=.cc)
OBJS_TT=at.o bt.o
SRCS_TT=tt/at.c tt/bt.c
OBJS_FFF=af.o bf.o
SRCS_FFF=fff/af.c fff/bf.c
TARGET=test
.cc.o:
gcc -c $<
$(OBJS_TT):
gcc -c $(SRCS_TT)
$(OBJS_FFF):
gcc -c $(SRCS_FFF)
all:
gcc -o $(TARGET) $(OBJS) $(OBJS_TT) $(OBJS_FFF)
If C files in tt directory are added, I have to add file name in SRCS_TT & OBJS_TT.
Is there a way to improve make file?
How do I do all c files (including files in directory) using suffix rules ?
One common solution when source files reside in different directories is to build an isomorphic directory structure in the build directory. This way you can have multiple sources with the same file name (e.g. util.cc) but in different directories and the object files won't collide because they get built into different directories.
A working example that creates an isomorphic build directory structure also with auto-generated header dependencies:
build_dir := build
all : ${build_dir}/test
.SECONDEXPANSION:
.SECONDARY:
test_srcs := a.cc b.cc x/c.cc y/d.cc
${build_dir}/test : ${test_srcs:%.cc=${build_dir}/%.o} | ${build_dir}/
g++ -o $# ${LDFLAGS} ${LDLIBS} $^
# Include the auto-generated dependencies.
-include ${test_srcs:%.cc=${build_dir}/%.d}
# Compile and generate dependency files.
${build_dir}/%.o : %.cc | $$(dir $$#)
g++ -o $# -c -MD -MP ${CPPFLAGS} ${CXXFLAGS} $<
# Directory build rules. while loop to handle races on mkdir during parallel builds.
${build_dir}/%/ : | ${build_dir}/
while ! mkdir -p $#; do true; done
# Build root directory rule.
${build_dir}/ :
mkdir -p $#
# Don't try to rebuild these, these are generated when compiling.
${build_dir}/%.d : ;
clean :
rm -rf ${build_dir}
.PHONY : all clean
Usage example:
$ mkdir x y
$ touch b.cc x/c.cc y/d.cc
$ echo "int main() {}" > a.cc
$ make
mkdir -p build/
g++ -o build/a.o -c -MD -MP a.cc
g++ -o build/b.o -c -MD -MP b.cc
while ! mkdir -p build/x/; do true; done
g++ -o build/x/c.o -c -MD -MP x/c.cc
while ! mkdir -p build/y/; do true; done
g++ -o build/y/d.o -c -MD -MP y/d.cc
g++ -o build/test build/a.o build/b.o build/x/c.o build/y/d.o
$ tree build/
build/
├── a.d
├── a.o
├── b.d
├── b.o
├── test
├── x
│   ├── c.d
│   └── c.o
└── y
├── d.d
└── d.o
2 directories, 9 files
$ make
make: Nothing to be done for 'all'.
$ make clean
rm -rf build

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