虽然现代化的编译过程构建工具已经很流行,但是在某些地方,或者由于历史原因,还是需要使用基本的makefile语法来构建我们的工程。假如我们需要在makefile A中加载makefile B,而makefile B 是在 makefile A中生成的,那么就会遇到重载问题。 下面举一段示例:
objdir = $(GXSRC_PATH)/output
TARGET = appservice
LIBS += -lmongoose -lcjson
SRCS = $(shell find . -iname "*.c" | sed "s/\(\.\/\)\(.*\)/\2/g" | xargs)
OBJS = $(shell find . -iname "*.c" | sed "s%\(\.\/\)\(.*\)%$(objdir)\/\2%g" | sed "s/\.c/\.o/g" | xargs)
all: deps $(TARGET)
DEPS = $(objdir)/deps
deps: $(SRCS)
@echo -e "\033[31m---- generate ----\033[0m";
@echo -e "\033[32mdeps=$(DEPS)\033[0m";
@-mkdir -p $(objdir);
@-rm -f ./deps;
@for a in $(SRCS); do \
b=${objdir}/$$(echo $$a | sed 's/\.c/\.o/'); \
c=$$(dirname $$a); \
if [ $$c != "." ]; then \
d=$(objdir)/$$c; \
if [ ! -d $$d ]; then \
mkdir -p $$d; \
fi; \
fi; \
echo $$b: $$a >> ./deps; \
echo ' @echo -e "compiling \033[032m[$$(CC)]\033[0m": ' $$a >> ./deps; \
echo ' @$$(CC) -c $$(CFLAGS) -o $$@ $$^'>> ./deps; \
done
@-mv ./deps $(DEPS)
-include $(DEPS)
$(TARGET): $(OBJS)
@echo "LDFLAGS:"$(LDFLAGS)
@echo "LIBS:"$(LIBS)
$(LD) $(OBJS) $(LDFLAGS) $(LIBS) -o $@
clean:
rm -rf output;
这个makefile通过自动搜寻目录下的所有.c文件,然后构建一个名为deps的makfile文件,再通过加载这个deps文件实现整个工程的编译。然而这个makefile第一次执行就会报错,第二次执行才能实现编译动作,原因是啥呢? 在makefile执行时首先做的就是加载所有的makefile文件,内建所有的变量、明确规则和隐含规则,并建立所有目标和依赖之间的依赖关系结构链表。因此第一次执行makefile时,deps文件还没生成就被include了,它还是个空文件。 等到第二次执行,其实加载的是第一次执行生成的deps文件。要保证能正确的执行编译动作,就要求我们在deps文件生成时再把它重新加载一次。修改方法也很简单,我们只需要在生成deps文件以后,再执行一次make命令。为了避免 陷入死循环,我们引入一个中间目标 elf,把整个编译过程分解为两步,先通过deps目标构建自动化的编译脚本deps,然后再执行make elf来完成重载和编译。
objdir = $(GXSRC_PATH)/output
TARGET = appservice
LIBS += -lmongoose -lcjson
SRCS = $(shell find . -iname "*.c" | sed "s/\(\.\/\)\(.*\)/\2/g" | xargs)
OBJS = $(shell find . -iname "*.c" | sed "s%\(\.\/\)\(.*\)%$(objdir)\/\2%g" | sed "s/\.c/\.o/g" | xargs)
all: deps
elf: $(TARGET)
DEPS = $(objdir)/deps
deps: $(SRCS)
@echo -e "\033[31m---- generate ----\033[0m";
@echo -e "\033[32mdeps=$(DEPS)\033[0m";
@-mkdir -p $(objdir);
@-rm -f ./deps;
@for a in $(SRCS); do \
b=${objdir}/$$(echo $$a | sed 's/\.c/\.o/'); \
c=$$(dirname $$a); \
if [ $$c != "." ]; then \
d=$(objdir)/$$c; \
if [ ! -d $$d ]; then \
mkdir -p $$d; \
fi; \
fi; \
echo $$b: $$a >> ./deps; \
echo ' @echo -e "compiling \033[032m[$$(CC)]\033[0m": ' $$a >> ./deps; \
echo ' @$$(CC) -c $$(CFLAGS) -o $$@ $$^'>> ./deps; \
done
@-mv ./deps $(DEPS)
make elf
-include $(DEPS)
$(TARGET): $(OBJS)
@echo "LDFLAGS:"$(LDFLAGS)
@echo "LIBS:"$(LIBS)
$(LD) $(OBJS) $(LDFLAGS) $(LIBS) -o $@
clean:
rm -rf output;