Tinchu
Tinchu

Reputation: 99

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?

Upvotes: 0

Views: 166

Answers (1)

MadScientist
MadScientist

Reputation: 100906

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?

Upvotes: 1

Related Questions