2011-11-15 60 views
2

使用靶特异性变量I具有以下生成文件:在生成文件

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 [email protected], source $^ 
    @echo Compiled elf file for $(INTDIR) > [email protected] 

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

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

.SECONDARY: 

的想法是,有需要被从相同的源代码编译几个不同的代码构造。 “全部”目标取决于v12target和v13目标,它为该特定版本设置了许多变量。它也依赖于一个“avrcommontargets”模式,它定义了如何实际编译。 avrcommontargets则取决于ELF文件,而ELF文件又取决于从C源代码构建的目标文件。

每个编译的C文件都会生成一个目标文件(* .o)。由于每个配置(v12,v13等)都会导致不同的输出,因此需要将C文件多次构建,并将输出置于不同的子目录中。例如, “构建/ V12/main.o”, “构建/ 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 

什么我需要做调整此生成的文件,以便它产生正确的输出?

回答

1

您重定向从输出的“编译的ELF文件”的线条,看起来像:

Compiled elf file for v13 

虽然具体的目标变量替换一般的工作,现在看来,这是目标的选择后进行 - 这是公平的,因为否则将很难实施。

您可以使用$(foreach)$(eval)为每个目标生成一个规则。不过,我想再次指出,您正在重新设计树木构建。最好的选择是继续使用自动工具。第二个最好的做法是完成树外构建逻辑,并为每个目标使用一个构建树,并使用一个小的configure sh脚本将编译标志插入到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 [email protected] from $< with $(CFLAGS)" 

%.o : $(SRCDIR)/%.c 
    echo "Compiling [email protected] from $< with $(CFLAGS)" 

.PHONY : all 
+0

感谢您的答复...具体而言,我在此生成的文件调用了AVR Studio 5,也VISUAL C++(生成文件项目类型)。 AVR Studio 5要求您输入到外部生成文件的路径。 VC++要求我为不同的构建类型输入“make all”,“make clean”等命令。我的观点是我需要从某种类型的makefile中启动所有的东西,其中“make all”将构建每个配置。我不清楚我如何用autotools做到这一点...... - 不可否认,这可能是因为我不太了解它。 –

+0

另一个考虑是我试图限制自己使用包含在WinAVR中的工具(http://winavr.sourceforge.net/),我不认为它包含autotools。我不确定试图为这个小项目构建一个兼容的autotools对每个想要构建它的开发者来说都是值得的麻烦 - 我们不会在我们产品的其他任何地方使用autotools或GNU make。 –

+0

@詹姆斯约翰斯顿:足够公平,时间轮重新发明时间:-)。 – thiton