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

发布于 2024-10-11 22:32:47 字数 1329 浏览 2 评论 0原文


我有一组源文件,需要从中生成可执行文件的多个变体。例如,我需要从同一个 ma​​in.c 生成 app1.elfapp2.elfapp3.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 时:

创建所有节点

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

构建应用程序1
构建应用程序2
构建应用程序3

失败! 输出似乎表明它有效,但它只生成一个可执行文件,即 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

I have one set of source files from which I need to generate multiple variants of an executable. For example I need to generate app1.elf, app2.elf, app3.elf from the same main.c and comm.c. The difference between each of the apps is a node address, a parameter that is passed down in the invocation of gcc. i.e.:

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

Let's assume that I have the following files:

  • src/main.c
  • src/comm.c

When I run the Makefile as so:

make all_nodes

make only builds app1.elf with the following output:

Built app1
Built app2
Built app3

FAIL!
The output seems to suggest that it worked, however it only generates one executable, namely app1.elf. Anybody care to point out what I'm doing wrong?

To further explain my Makefile, I've created a cleanobjs target to clean out the objects in the ./obj subdirectory. This is my attempt at having 'make' rebuild the obj files with the new node address, but it fails. Am I using 'make' in a way it wasn't intended to be used? I know I can also create a batch file to run make (something I've done sucessfully) but I'd like to know what I'm doing wrong. My Makefile is below:

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

软的没边 2024-10-18 22:32:47

您将需要针对不同版本的多个目标。每个目标也需要自己的 main.o 和 comm.o 目标,这意味着您需要将它们称为其他名称,否则它们最终会相互混淆。然后你的一切应该可以构建所有三个。

You're going to need multiple targets for the different versions. Each target is going to need its own main.o and comm.o targets as well, meaning you need to call them something else or they'll end up confusing with each other. Then your all should function to build all three.

满栀 2024-10-18 22:32:47

这就是我要做的:

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) 
lt;

This is what I would do:

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) 
lt;
海之角 2024-10-18 22:32:47

类似的方法:

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 $@ 
lt;

cleanobj :
    rm -rf $(objs)

endif

.PHONY: all cleanobj

a similar approach:

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 $@ 
lt;

cleanobj :
    rm -rf $(objs)

endif

.PHONY: all cleanobj
陌伤ぢ 2024-10-18 22:32:47

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

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

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

然后你的目标重新调用你的Makefile并设置NODE

The easy way is to make separate build directories and use VPATH to allow your (mostly unmodified) Makefile to build the original sources in the separate directory.

The slightly harder way is to modify your Makefile to rewrite target .o and executable files to be in a subdirectory. For example:

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

Then your targets re-invoke your Makefile with NODE set.

甜尕妞 2024-10-18 22:32:47

创建可以创建所有三个版本的批处理文件或 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 脚本。

create a batch file or shell script which can create all three builds. Something like:

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>

Call this batch file or shell script for all_node build rule.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文