最近写代码想Makefile同时支持交叉编译器和主机编译器,所以要把不同编译器生成的目标文件放到不同的目录中。首先想到的是目录里要保留原来的源文件目录结构,这样就可以用隐式规则或静态规则推导出源文件,否则根本无法得到依赖关系。最后用了
隐式规则扣出源文件路径才勉强可用,照这个思路花了点时间写了个测试例子,准备把现有需要交叉编译的程序都转到这种模式:
ifdef HOST
objdir:=obj_$(word 1, $(subst -, ,$(HOST)))
else
objdir:=obj
endif
SRC_DIR:=. src
CFILES:=$(shell find $(SRC_DIR) -maxdepth 1 -name "*.c")
OBJS:=$(addprefix $(objdir)/,$(CFILES:%.c=%.o))
OBJDIRS:=$(addprefix $(objdir)/, $(SRC_DIR))
TARGET=main
all:$(OBJDIRS) $(TARGET)
$(TARGET):$(OBJS)
gcc -o $@ $(OBJS)
$(objdir)/%.o:%.c
gcc -c $< -o $@
$(OBJDIRS):
@mkdir -p $@
clean:
-rm -r -f $(objdir) $(TARGET)
.PHONY: clean all
还有就是查资料时发现了这个东东(order-only prerequisites),可惜没法用在我这里,因为用隐式规则我没法弄出目录依赖-_-!!!,下一步是把所有*.d文件也搞进目录中去。
gnu make的两种依赖关系(Prerequisites):
-
正常依赖(normal prerequisites)
1)检查和重建依赖
2)如果依赖更新,则要重建目标
-
顺序依赖(order-only prerequisites)
1)检查和重建依赖
顺序依赖不会影响最终的目标的重建,这个适合与在makefile里建目录,因为目录作为目标有一个特性是目录里的文件改了,目录就更新了,导致一系列不必要的重建,用顺序依赖方式的话,就不回影响最终的目标了
Gnu make手册上给了个例子:
OBJDIR := objdir
OBJS := $(addprefix $(OBJDIR)/,foo.o bar.o baz.o)
$(OBJDIR)/%.o : %.c
$(COMPILE.c) $(OUTPUT_OPTION) $<
all: $(OBJS)
$(OBJS): | $(OBJDIR)
$(OBJDIR):
mkdir $(OBJDIR)
http://www.gnu.org/software/make/manual/html_node/Prerequisite-Types.html http://cm.techwell.com/articles/weekly/making-directories-gnu-make