我想将.h文件作为给定.o文件的依赖项包括在内。我遵循these instructions,并将其调整为我的Makefile。但是,当我执行touch myhfile.h
时,不会重建对应的.o文件。在我看来,依赖项是正确的,并包含在Makefile中。只是无法弄清楚为什么它不起作用。任何帮助表示赞赏。 Makefile包含在下面
ROOT=.
BUILDDIR=$(ROOT)/build
LIBDIR=$(BUILDDIR)/lib
OBJDIR=$(BUILDDIR)/obj
INCLUDEDIR=$(BUILDDIR)/include
DEPDIR=$(BUILDDIR)/dep
LIB=mylib
XCOMPILE=arm-linux-gnueabihf-
CC=$(XCOMPILE)gcc
AR=$(XCOMPILE)ar
DEPFLAGS+=\
-MT $@ \
-MMD \
-MP \
-MF \
$(DEPDIR)/$*.Td
CFLAGS+=\
-Wall \
-Wextra \
-Werror \
-pedantic \
-std=gnu11 \
-fPIC
CPPFLAGS+=\
$(INCLUDE)
SRCDIRS+=\
$(ROOT)/../3rdparty/log/src \
$(ROOT)/LTC2947/src \
$(ROOT)/i2c/src \
$(ROOT)/spi/src \
$(ROOT)/sensors/src \
$(ROOT)/telegraf/src \
$(ROOT)/uart-packet/src \
$(ROOT)/STCN75/src \
$(ROOT)/utils/src
DEPDIRS+=\
$(SRCDIRS) \
$(ROOT)/addresses-ports/src
VPATH+=\
$(SRCDIRS)
SRC+=$(shell find $(SRCDIRS) -type f -name "*\.c")
DEP+=$(shell find $(DEPDIRS) -type f -name "*\.h")
OBJ=$(patsubst %.c, $(OBJDIR)/%.o, $(notdir $(SRC)))
INCLUDE=$(addprefix -I,$(sort $(dir $(DEP))))
POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d && touch $@
release: CFLAGS+=-O3
release: all
debug: CFLAGS+=-ggdb
debug: CPPFLAGS+=-DDEBUG
debug: all
all: lib include
lib: $(LIBDIR)/$(LIB).a $(LIBDIR)/$(LIB).so
include: $(INCLUDEDIR)
$(LIBDIR)/$(LIB).a: $(OBJ) | $(LIBDIR)
$(AR) rcs $@ $^
$(LIBDIR)/$(LIB).so: $(OBJ) | $(LIBDIR)
$(CC) $(CPPFLAGS) $(CFLAGS) -shared $(LDFLAGS) -lc $^ -o $@
$(INCLUDEDIR): $(DEP)
if [[ ! -d $@ ]]; then mkdir -p $@; fi
cp $^ $@
touch $@
%.o: %.c
$(OBJDIR)/%.o: %.c $(DEPDIR)/%.d | $(DEPDIR) $(OBJDIR)
$(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
$(POSTCOMPILE)
$(DEPDIR):
mkdir -p $@
$(LIBDIR):
mkdir -p $@
$(OBJDIR):
mkdir -p $@
.PHONY: clean
clean:
rm -rf $(BUILDDIR)
$(DEPDIR)/%.d: ;
.PRECIOUS: $(DEPDIR)/%.d
include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRC))))
编辑
$(info $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRC)))))
产生了一个空字符串。 $(info $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRC))))
生成了正确的依赖项列表
./build/dep/./../3rdparty/log/src/log.d ./build/dep/./uart-packet/src/uart_packet.d ./build/dep/./utils/src/utils.d ./build/dep/./telegraf/src/telegraf.d ./build/dep/./i2c/src/myproject_i2c.d ./build/dep/./spi/src/myproject_spi.d ./build/dep/./LTC2947/src/LTC2947.d ./build/dep/./sensors/src/sensors.d ./build/dep/./STCN75/src/STCN75.d
所以我删除了$(wildcard ...) function
但是那不能解决问题。
为了测试它,我决定运行:
1. make clean
2. make
3. touch telegraf/src/telegraf.h
4. make build/obj/telegraf.d
5. make build/obj/telegraf.Td
6. make build/obj/telegraf.o
步骤1-3工作正常。但是步骤4-6无效。
步骤4产生以下结果:
make: *** No rule to make target 'buid/dep/telegraf.d'. Stop.
步骤5产生以下结果: make:***没有将目标设为“ buid / dep / telegraf.Td”的规则。停止。
第6步根本没有重建目标。
在第2步之后,我查看了build / dep / telegraf.d,这是我所拥有的:
$ cat build/dep/telegraf.d
build/obj/telegraf.o: telegraf/src/telegraf.c ../3rdparty/log/src/log.h \
telegraf/src/telegraf.h utils/src/utils.h
../3rdparty/log/src/log.h:
telegraf/src/telegraf.h:
utils/src/utils.h:
在我看来,依赖关系是正确生成的。
我还尝试运行make -d build/obj/telegraf.o
。不幸的是,我不能为此发布整个输出(stackoverflow不允许它,消息变得很大)。但是,这是输出的结尾。 (对于感兴趣的人,可以看到完整的输出here)
No need to remake target 'telegraf.c'; using VPATH name './telegraf/src/telegraf.c'.
Considering target file 'build/dep/telegraf.d'.
Looking for an implicit rule for 'build/dep/telegraf.d'.
Trying pattern rule with stem 'telegraf'.
Found an implicit rule for 'build/dep/telegraf.d'.
Finished prerequisites of target file 'build/dep/telegraf.d'.
No need to remake target 'build/dep/telegraf.d'.
Considering target file 'build/dep'.
Finished prerequisites of target file 'build/dep'.
No need to remake target 'build/dep'.
Considering target file 'build/obj'.
Finished prerequisites of target file 'build/obj'.
No need to remake target 'build/obj'.
Finished prerequisites of target file 'build/obj/telegraf.o'.
Prerequisite './telegraf/src/telegraf.c' is older than target 'build/obj/telegraf.o'.
Prerequisite 'build/dep/telegraf.d' is older than target 'build/obj/telegraf.o'.
Prerequisite 'build/dep' is order-only for target 'build/obj/telegraf.o'.
Prerequisite 'build/obj' is order-only for target 'build/obj/telegraf.o'.
No need to remake target 'build/obj/telegraf.o'.
make: 'build/obj/telegraf.o' is up to date.
看来这是问题,Prerequisite 'build/dep/telegraf.d' is older than target 'build/obj/telegraf.o'.
。我需要以某种方式使它更年轻,但是我不确定如何。
感谢您的帮助。
答案 0 :(得分:1)
不幸的是,您在这里跑错了方向:)。
您不应该删除$(wildcard ...)
;需要/想要的。
它返回空字符串的事实是您遇到的 THE 问题,而不仅仅是删除它,您需要弄清楚原因并修复它。您的.d
文件看起来像./build/dep/./../3rdparty/log/src/log.d
的事实是问题所在……这不是您要创建的.d
文件的路径。您正在创建类似./build/dep/log.d
问题是这样的:您正在使用此规则在配方中创建.d
个文件:
POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d && touch $@
在这里,$*
是文件的茎,因此对于./build/obj/log.o
,$*
的值为log
。因此,您正在创建./build/dep/log.d
。
但是在包含行中将SRC
变量转换为.d
文件时,可以使用basename
函数。这只是去除路径的后缀,不会删除目录。因此,如果您的源文件是./../3rdparty/log/src/log.c
,则basename
会产生./../3rdparty/log/src/log
,并且您的通配符匹配错误的内容。
您需要像这样计算包含行的通配符:
include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(notdir $(basename $(SRC)))))
也添加notdir
以剥离路径,这将为您提供所需的依赖文件:./build/dep/log.d
等。