在makefile中使用特定于目标的变量

时间:2011-11-15 17:04:58

标签: makefile gnu-make

我有以下makefile:

OUTPUTDIR = build

all: v12target v13target
v12target: INTDIR = v12
v12target: DoV12.avrcommontargets
v13target: INTDIR = v13
v13target: DoV13.avrcommontargets

%.avrcommontargets: $(OUTPUTDIR)/%.elf
    @true

$(OUTPUTDIR)/%.elf: $(OUTPUTDIR)/$(INTDIR)/main.o
    @echo TODO build ELF file from object file: destination $@, source $^
    @echo Compiled elf file for $(INTDIR) > $@

$(OUTPUTDIR)/$(INTDIR)/%.o: %.c
    @echo TODO call GCC to compile C file: destination $@, source $<
    @echo Compiled object file for $<, revision $(INTDIR) > $@

$(shell rm -rf $(OUTPUTDIR))
$(shell mkdir -p $(OUTPUTDIR)/v12 2> /dev/null) $(shell mkdir -p $(OUTPUTDIR)/v13 2> /dev/null)

.SECONDARY:

这个想法是有几种不同的代码配置需要从相同的源代码编译。 “all”目标依赖于v12target和v13 target,它为该特定构建设置了许多变量。它还依赖于“avrcommontargets”模式,该模式定义了如何实际进行编译。然后avrcommontargets依赖于ELF文件,而ELF文件又取决于从C源代码构建的目标文件。

每个编译的C文件都会生成一个目标文件(* .o)。由于每个配置(v12,v13等)都会产生不同的输出,因此需要多次构建C文件,并将输出放在不同的子目录中。例如,“build / v12 / main.o”,“build / v13 / main.o”等。

示例输出:

TODO call GCC to compile C file: destination build//main.o, source main.c
TODO build ELF file from object file: destination build/DoV12.elf, source build//main.o
TODO build ELF file from object file: destination build/DoV13.elf, source build//main.o

问题是目标文件没有进入正确的子目录。例如,“build // main.o”而不是“build / v12 / main.o”。然后,这会阻止正确重建main.o以生成main.o的v13版本。

我猜测问题是$(INTDIR)是一个目标特定变量,也许这不能用于我为%.elf和%.o定义的模式目标。

正确的输出是:

TODO call GCC to compile C file: destination build/v12/main.o, source main.c
TODO build ELF file from object file: destination build/DoV12.elf, source build/v12/main.o
TODO call GCC to compile C file: destination build/v13/main.o, source main.c
TODO build ELF file from object file: destination build/DoV13.elf, source build/v13/main.o

我需要做些什么来调整这个makefile以便生成正确的输出?

1 个答案:

答案 0 :(得分:1)

您从输出中重定向了“编译的精灵文件”行,如下所示:

Compiled elf file for v13

虽然特定于目标的变量替换在一般情况下起作用,但它似乎是在选择目标之后完成的 - 这是公平的,因为否则将很难实现。

您可以使用$(foreach)$(eval)为每个目标生成一条规则。但是,我想再次指出您在这里重新设计了树构建。最好的选择是继续使用autotools。第二个最好的方法是使你的树外构建逻辑完整,每个目标使用一个构建树,一个小的configure sh脚本在Makefile中插入编译标志。

阐述第二个解决方案:

让常规make在子目录中运行,每个目标一个。在主makefile中有一个开关,用于控制子make的执行。您的主Makefile如下所示:

TARGETS = v12 v13

CFLAGS_v12 = -foo
CFLAGS_v13 = -bar

ifeq ($(TARGET),)
all :
    mkdir --parents $(TARGETS)
    $(foreach t,$(TARGETS),SRCDIR=.. CFLAGS="$(CFLAGS_$t)" TARGET=$t $(MAKE) -C $t -f ../Makefile &&) true
clean :
    rm -rf $(TARGETS)
else
all : main.elf
endif

%.elf : %.o
    echo "Linking $@ from $< with $(CFLAGS)"

%.o : $(SRCDIR)/%.c
    echo "Compiling $@ from $< with $(CFLAGS)"

.PHONY : all
相关问题