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

在makefile中使用特定于目标的变量,makefile,gnu-make,Makefile,Gnu Make,我有以下生成文件: OUTPUTDIR = build all: v12target v13target v12target: INTDIR = v12 v12target: DoV12.avrcommontargets v13target: INTDIR = v13 v13target: DoV13.avrcommontargets %.avrcommontargets: $(OUTPUTDIR)/%.elf @true $(OUTPUTDIR)/%.elf: $(OUTPUTD

我有以下生成文件:

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:
问题是对象文件没有进入正确的子目录。例如,“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,以便它生成正确的输出?

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

Compiled elf file for v13
虽然目标特定变量替换通常是有效的,但它似乎是在选择目标之后进行的——这是足够公平的,因为否则很难实现

您可以使用
$(foreach)
$(eval)
为每个目标生成一条规则。然而,我想再次指出,您正在对树构建进行重新设计。最好的选择是继续使用自动工具。第二个最好的方法是完成树外构建逻辑,并为每个目标使用一个构建树,使用一个小的configure sh脚本在Makefile中插入编译标志

阐述第二种解决办法:

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

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
TARGETS=v12 v13
CFLAGS_v12=-foo
CFLAGS_v13=-bar
ifeq($(目标),)
全部:
mkdir--父对象$(目标)
$(foreach t,$(TARGETS),SRCDIR=…CFLAGS=“$(CFLAGS_$t)”TARGET=$t$(MAKE)-C$t-f../Makefile&&)true
清洁:
rm-rf$(目标)
其他的
全部:main.elf
恩迪夫
%.elf:%.o
echo“将$@从$<链接到$(CFLAGS)”
%.o:$(SRCDIR)/%.c
echo“使用$(CFLAGS)从$<编译$@”
冒牌货:全部

感谢您的回复。。。具体地说,我有这个AVMtudio 5调用的MaMe文件,还有VisualC++(MaFixFraseProject类型)。AVR Studio 5要求您在外部生成文件中键入路径。VC++要求我为不同的构建类型键入“makeall”、“makeclean”等命令。我的观点是,我需要从某种makefile中启动所有内容,其中“makeall”将构建每个配置。我不清楚我怎么能用自动工具做到这一点…-诚然,这可能是因为我不太了解它。另一个考虑因素是,我试图将自己限制在WinAVR()中包含的实用程序中,我认为它不包括自动工具。我不确定尝试为这个小项目构建一个兼容的autotools是否值得每一个想要构建它的开发人员的麻烦-我们在产品的其他任何地方都不使用autotools或GNU make。@JamesJohnston:很公平,是时候重新发明轮子了时间:-)。使用AVR Studio中的makefile的示例:(选中复选框并键入“Makefile”)我的VisualC++项目可能会如何查找:----不知道如何使用AutoToo工具,并用一个命令来构建所有这些目标。有人认为,我应该在AVR Studio和VisualC++中为每个构建配置创建单独的配置。其他Visual Studio项目中的单个Visual Studio配置。具体而言,此生成脚本编译各种硬件版本的固件。例如,我希望所有版本/配置的编译输出包含在安装程序的单个配置中。(这样,当用户安装产品时,所有固件版本都可用…)
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