Makefile 使用标志$(@:.o=.d)后生成文件依赖项错误
我已经为下面的代码结构创建了一个MakefileMakefile 使用标志$(@:.o=.d)后生成文件依赖项错误,makefile,gnu-make,Makefile,Gnu Make,我已经为下面的代码结构创建了一个Makefile work ├── code | | | ├──inc/ | | └── main.h and test.h files here | | | ├──src/ │ └── main.c and test.c files here ├── _Build/ │ └── Makefile here 这是生成文件 # All path are referenced with the d
work
├── code
| |
| ├──inc/
| | └── main.h and test.h files here
| |
| ├──src/
│ └── main.c and test.c files here
├── _Build/
│ └── Makefile here
这是生成文件
# 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)
及
我仍然得到以下错误
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
要删除此错误,Makefile中应该包含什么
依赖项应该通过此逻辑删除,或者应该使用其他一些逻辑?您将两个不同的东西混为一谈
.d
文件告诉make在哪里查找目标的先决条件。在本例中,目标是一个对象文件(.o
),前提条件是一个头文件,但要使它们只是“目标”和“前提条件”。Make不仅限于编译C程序:它基本上可以执行任何任务,其中更改某些文件意味着需要更新某些其他文件:编译程序(不仅仅是C程序)是一种常见用途,但它可以生成文档、网站、运行测试等。Make通过运行命令来完成其工作,就像您自己在命令行中所做的那样(make永远不会忘记添加选项,也不会出现拼写错误)。在内部,它对“编译器”和“链接器”一无所知
您得到的错误来自编译器(或者是学究,预处理器),而不是make,并且必须告诉编译器在哪里查找需要包含的头文件。这是两件完全不同的事情,需要不同的操作:编译器要求您使用-I
命令行选项提供要搜索的目录
我想,如果编译器能够解析make的.d
文件并找出在哪里查找头,那就太好了,但它不能。您必须自己指定标志
在您的情况下,更清楚的是:您实际上是在使用编译器生成
.d
文件!因此存在一个鸡和蛋的问题:如果编译器可以从.d
文件中获取路径,但是.d
文件是从编译器中创建的,那么路径首先从何而来?看起来像是CFLAGS
需要-I../code/inc
@Milag在这种情况下,如果包含头文件文件夹,则不需要依赖关系逻辑。那么如何在不指定包含头文件文件夹的情况下删除依赖关系呢?如果我给出了include文件夹的详细信息,那么编译器就不需要.d文件。我不知道“删除依赖项”是什么意思。没有必要不是真的。我已经在上面解释了为什么您需要.d
文件(用于了解文件何时过期)和-I
选项(用于编译器查找头文件)。它们用于不同的程序(make vs compiler),用于不同的目的,您不能没有它们中的任何一个。如果所有源文件和头文件都在同一个文件夹中,则不需要include-I标志。这并不总是正确的。详细信息取决于您的编译器,但通常
语法中包含的标题不在工作目录中查找,它们只在-I
目录中查找。但是,如果您使用的是“…”
包含,则大多数编译器(当然是GCC)将自动查找与正在编译的源文件相同的文件。但是,这与您的情况无关,因为您已经清楚地指出头文件与源文件不在同一目录中;您有code/src/main.c
但是code/inc/test.h
。您必须添加-I
,编译器才能找到test.h
。我不理解.d在这里的用法。如果使用-I标志并且指定了include目录,那么.d文件的意义是什么?
-include $(FILE_PATH_OBJ:.o=.d)
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