【发布时间】:2018-11-08 05:58:22
【问题描述】:
我希望将 .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'.。不知何故,我需要让它更年轻,但我不知道如何。
感谢任何帮助。
【问题讨论】:
-
是否构建了相应的
.d文件? (实际名称会有所帮助。) -
如果您将
$(info $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRC)))))添加到您的makefile 中,它会显示所有.d文件吗?如果您查看build/dep/myfile.d文件的内容,您是否看到列出了正确的先决条件?如果您运行make -d build/obj/myfile.o,您是否看到它正在查看您的头文件?仅仅基于这个makefile很难知道问题是什么:你需要调试它。由于您没有从 make 中得到错误,可能是根本找不到您的.d文件,或者.d文件的内容不正确。 -
@MadScientist 我添加了额外的信息。我认为这个错误是在 .h 文件被更改/触摸后重新生成 .d 文件。
-
@Beta 是的,它确实构建了一个相应的 .d 文件。我添加了额外的信息。
标签: makefile dependencies