如何使用一个makefile构建可执行文件的变体?

时间:2011-01-10 21:01:31

标签: c++ c makefile


我有一组源文件,我需要从中生成多个可执行文件的变体。例如,我需要从同一 main.c app1.elf app2.elf app3.elf >和 comm.c 。每个应用程序之间的区别是节点地址,这是在gcc调用中传递的参数。即:

gcc -DNODE=1 -oapp1.elf main.c 
gcc -DNODE=2 -oapp2.elf main.c 
gcc -DNODE=3 -oapp3.elf main.c 

我们假设我有以下文件:

  • SRC / main.c中
  • 的src / comm.c

当我按原样运行Makefile时:

  

制作all_nodes

仅使用以下输出构建app1.elf:

  

内置app1
  内置app2
  内置app3

FAIL! 输出似乎表明它有效,但它只生成一个可执行文件,即app1.elf。有人想指出我做错了什么吗?

为了进一步解释我的Makefile,我创建了一个 cleanobjs 目标来清除./obj子目录中的对象。这是我尝试使用新的节点地址'make'重建obj文件,但它失败了。我是否以某种不打算使用的方式使用'make'?我知道我也可以创建一个批处理文件来运行make(我已经成功完成了)但是我想知道我做错了什么。我的Makefile如下:

obj/%.o: src/%.c
    gcc -DNODE=$(NODE) -o$@ $<

app.elf : ./obj/main.o ./obj/comm.o
    gcc -oapp$(NODE).elf main.o comm.o

node1 : NODE=1
node1 : cleanobj app.elf
    @echo 'Built app1'

node2 : NODE=2
node2 : cleanobj app.elf
    @echo 'Built app2'

node3 : NODE=3
node3 : cleanobj app.elf
    @echo 'Built app3'

all_nodes : node1 node2 node3

cleanobj :
    rm -rf obj/main.o obj/comm.o

.PHONY : cleanobj

5 个答案:

答案 0 :(得分:6)

您将需要针对不同版本的多个目标。每个目标都需要自己的main.o和comm.o目标,这意味着你需要将它们称为其他东西,否则它们最终会相互混淆。然后你的所有人都应该发挥作用来建立这三个。

答案 1 :(得分:3)

类似的方法:

ifeq ($(NODE),)

all:
    make NODE=1
    make NODE=2
    make NODE=3

cleanobj:
    make NODE=1 cleanobj
    make NODE=2 cleanobj
    make NODE=3 cleanobj

else

OBJS = main.o comm.o
objs = $(patsubst %.o,obj/$(NODE)/%.o,$(OBJS))

app$(NODE).elf: $(objs)
    gcc -o app$(NODE).elf $^
    @echo 'Built app$(NODE)'

obj/$(NODE)/%.o: src/%.c
    gcc -c -DNODE=$(NODE) -o $@ $<

cleanobj :
    rm -rf $(objs)

endif

.PHONY: all cleanobj

答案 2 :(得分:2)

这就是我要做的事情:

SRC     = src/main.c
OBJ     = $(patsubst src%,obj$(VERSION)%,$(patsubst %.c,%.o,$(SRC)))

C_FLAGS = -DNODE=$(VERSION)


all:    app.1 app.2 app.3

#
# For each application just call make with VERSION set correctly    
app.%:  dir.%
    $(MAKE) VERSION=$* app$*.elf

#
# Build each applications objects into a seprate directory
# So we need to make sure the obj directory exists.    
dir.%:
    @- if ! test -e obj$*; then mkdir obj$*; fi

app%.elf:   $(OBJ)
    $(CC) -o$@ $(C_FLAGS) $(OBJ)


obj$(VERSION)/%.o:  src/%.c
    $(CC) -c -o obj$(VERSION)/$*.o $(C_FLAGS) $<

答案 3 :(得分:1)

简单的方法是创建单独的构建目录,并使用VPATH允许您的(大部分未修改的)Makefile在单独的目录中构建原始源。

稍微更难的方法是修改Makefile以重写目标.o和可执行文件在子目录中。例如:

NODE = 1
OBJDIR = obj.node$(NODE)
SRC = main.c comm.o
OBJ = $(SRC:%.c=$(OBJDIR)/%.o)

然后你的目标会在设置NODE的情况下重新调用你的Makefile。

答案 4 :(得分:0)

创建一个批处理文件或shell脚本,可以创建所有三个版本。类似的东西:

make node1
<if needed copy your executable to a different directory>
<clean all objs from make node1>
make node2
<if needed copy your executable to a different directory>
<clean all objs from make node1>
make node3
<if needed copy your executable to a different directory>
<clean all objs from make node1>

all_node构建规则调用此批处理文件或shell脚本。