在 GNU make 的
Makefile
中,依赖项的生成和使用如下。这是我在 mad-scientist.net 找到的一种方法,效果非常好(有关完整的 Makefile,请参阅此问题的结尾):
1。指定模块:
MODULES := main bar
2。添加疯狂科学家的魔法:
DEPDIR := .deps
DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.d
$(DEPDIR): ; @mkdir -p $@
DEPFILES := $(SRCS:%.c=$(DEPDIR)/%.d)
$(DEPFILES):
include $(wildcard $(DEPFILES))
3.在对象和可执行文件的规则中使用
DEPDIR
和 DEPFLAGS
:
main.x: $(OBJS)
gcc $(OBJS) -o $@ -lm
%.obj: %.c
%.obj: %.c $(DEPDIR)/%.d | $(DEPDIR)
gcc -c $< -O2 -o $@ $(DEPFLAGS)
现在我遇到的情况是,某些文件是自动生成的(从示例中的其他位置复制),例如从
bar.c
生成的 orig-bar.c
;与 bar.h
类似。这是使用静态模式规则完成的:
GEN_SRC := bar.c bar.h
$(GEN_SRC): % : orig-%
cp $< $@
加上这一点,依赖项不完整,我由于不存在的文件而导致构建失败,例如
make
尝试在生成 main.obj
之前构建 bar.h
,但 main.c
包含该标头。
我可以手动添加所有依赖项,例如
bar.obj: bar.h
和 main.obj: bar.h
,但我想避免这种情况并使用自动依赖项生成。
问题:有没有办法让规则按正确的顺序应用,例如在编译
bar.h
之前生成main.c
?
> head main.c orig-bar.[ch]
==> main.c <==
#include <stdio.h>
#include "bar.h"
int main (void)
{
printf ("Hallo main.\n");
return 0;
}
==> orig-bar.c <==
#include "bar.h"
==> orig-bar.h <==
/* empty */
.SECONDARY: # Don't auto-delete intermediate files.
MODULES := main bar
all: main.x
.PHONY: all clean clean-all
###########################################################################
# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/
SRCS := $(MODULES:%=%.c)
OBJS := $(SRCS:%.c=%.obj)
DEPDIR := .deps
DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.d
$(DEPDIR): ; @mkdir -p $@
DEPFILES := $(SRCS:%.c=$(DEPDIR)/%.d)
$(DEPFILES):
include $(wildcard $(DEPFILES))
#############################################################
# Auto-generate some files.
GEN_SRC := bar.c bar.h
$(GEN_SRC): % : orig-%
cp $< $@
#############################################################
EXTRA_DEP = Makefile
main.x: $(OBJS) $(EXTRA_DEP)
gcc $(OBJS) -o $@ -lm
%.obj: %.c
%.obj: %.c $(EXTRA_DEP) $(DEPDIR)/%.d | $(DEPDIR)
gcc -c $< -O2 -o $@ $(DEPFLAGS)
###########################################################
clean:
rm -f $(wildcard *.x $(OBJS))
clean-all: clean
rm -rf $(DEPDIR) $(wildcard $(GEN_SRC))
是的,这很不幸。 这与自动生成
version.h
时遇到的问题相同。
稍微次优的版本是在编译 any源之前生成
version.h
(或者在您的情况下生成任何标头)。
草图:
auto-gen-headers := $(filter-out %.c,${GEN_SRC})
${OBJS}: | ${auto-gen-headers}