在 makefile 中,如何对变量中的每个文件名执行命令?

发布于 2024-08-08 03:45:28 字数 759 浏览 3 评论 0原文

我知道我做错了,但我不知道如何组织这个 makefile。我定义了我的 util 源文件,并使用一些函数来定义它们的 .o 文件:

UTIL_SRC = utils/src/foo.cpp utils/src/bar.cpp utils/src/baz.cpp

UTIL_OBJS = $(patsubst utils/src/%.cpp,utils/obj/%.o,$(UTIL_SRC))

这是我使用这些文件的目标:

lib : lib/libutils.a

lib/libutils.a : $(UTIL_OBJS)
    rm -f lib/libutils.a
    ar -c -q lib/libutils.a $(UTIL_OBJS)

然后,当我得到编译这些婴儿的规则时,我很乐意有一个命令可以迭代每个 UTIL_OBJS 文件和每个 UTIL_SRC 文件。相反,我诉诸于这种怪物,这违背了将它们存储在变量中的目的。

$(UTIL_OBJS) : $(UTIL_SRC)
    g++ $(UTIL_FLAGS) utils/src/foo.cpp -o utils/obj/foo.o
    g++ $(UTIL_FLAGS) utils/src/bar.cpp -o utils/obj/bar.o
    g++ $(UTIL_FLAGS) utils/src/baz.cpp -o utils/obj/baz.o

我可以将其压缩为一行吗?如何?谢谢,伟大的人们!

I know I am doing it wrong, but I can't figure out how to organize this makefile. I define my util source files, and use some functions to define the .o files from them here:

UTIL_SRC = utils/src/foo.cpp utils/src/bar.cpp utils/src/baz.cpp

UTIL_OBJS = $(patsubst utils/src/%.cpp,utils/obj/%.o,$(UTIL_SRC))

This is the target that I use these files for:

lib : lib/libutils.a

lib/libutils.a : $(UTIL_OBJS)
    rm -f lib/libutils.a
    ar -c -q lib/libutils.a $(UTIL_OBJS)

Then, when I get to the rule to compile these babies, I would love to just have one command that would iterate through each UTIL_OBJS file and each UTIL_SRC file. Instead I have resorted to this monstrosity, which defeats the purpose of storing them in variables.

$(UTIL_OBJS) : $(UTIL_SRC)
    g++ $(UTIL_FLAGS) utils/src/foo.cpp -o utils/obj/foo.o
    g++ $(UTIL_FLAGS) utils/src/bar.cpp -o utils/obj/bar.o
    g++ $(UTIL_FLAGS) utils/src/baz.cpp -o utils/obj/baz.o

Can I condense this down to one line? How? Thanks, great ones!

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

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

发布评论

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

评论(2

魔法唧唧 2024-08-15 03:45:28

使用隐含规则通常更容易。有很多预定义的,您只需要指定变量即可。

CXX=g++
CXXFLAGS=$(UTIL_FLAGS)

然后您需要定义一个可执行文件,如下所示

myutil: $(UTIL_OBJS)

由于您没有将对象存储在同一目录中,因此您还需要指定一个新的隐式规则(否则,我们现在就完成了)。

utils/obj/%.o: utils/obj/%.cpp

% 是一个模式匹配,它将匹配左侧和右侧相同的文本,因此此规则将使 foo.o 脱离 foo.cpp。
尝试一下是否可以在没有命令的情况下工作(它可能从另一个规则中获取了该命令,我不确定),否则让它说:

utils/obj/%.o: utils/obj/%.cpp
    $(CXX) $(CXXFLAGS) -o $@ $^

$@ 是规则的目标(例如 foo.o),而 $^ 是所有文件都在右侧。
我是凭空写下这个的,无法测试它,所以请让我知道结果如何..:)

为了使它更加优雅,你可以包含一个依赖文件

include .depend

如果你正在运行GNU make,如果找不到 .depend 文件,它会尝试创建它(使用老式 make,您需要先自己创建它,但如果您想管理它,它可以只是一个虚拟文件)通过 makefile)

.depend: $(UTIL_SRC)
    $(CXX) -MM -o $@ $^

依赖文件将包含每个 .cpp 文件的行,告诉 make 它需要哪些头文件,这将允许 make 在您更改某些内容时重新编译必要的文件。但这对解决您原来的问题没有帮助,只是认为它可能会派上用场。

编辑:
作为对您的编辑的回应。您也可以删除用于创建 .a 文件的命令,这也已经作为隐式规则可用。虽然不太清楚它具体是如何工作的,但没有使用过它。我确实知道 make 在处理 .a(rchive?) 文件时有很多怪癖。

It's usually easier to work with implicit rules. There are a lot of predefined ones, where you'll only need to specify variables.

CXX=g++
CXXFLAGS=$(UTIL_FLAGS)

Then you need to define an executable, like this

myutil: $(UTIL_OBJS)

Since you're not storing your objects in the same directory, you'll need to specify a new implicit rule as well though (otherwise, we'd be done now).

utils/obj/%.o: utils/obj/%.cpp

% is a pattern-match, it'll match the same text on both left and right side, so this rule will make foo.o out of foo.cpp.
Try if that'll work without the command (it might have grabbed that from another rule, I'm not sure), otherwise let it say:

utils/obj/%.o: utils/obj/%.cpp
    $(CXX) $(CXXFLAGS) -o $@ $^

$@ is the target of the rule (e.g. foo.o), and $^ is all files on the right hand side.
I'm writing this off the top of my head, without the possibility to test it, so please let me know how it turned out.. :)

To make it even more elegant, you can include a dependency file

include .depend

If you're running GNU make, it'll try to make the .depend file if it can't find it (with old school make, you need to create it yourself first, it can be just a dummy though, if you'd like to manage it through the makefile)

.depend: $(UTIL_SRC)
    $(CXX) -MM -o $@ $^

The dependency file will contain lines for each .cpp file, telling make what header files it needs, which will allow make to recompile the necessary files when you change something. This doesn't help with your original question though, just thought it might come in handy.

EDIT:
As a response to your edit. You could probably drop the commands for creating the .a-file as well, that too is already available as an implicit rule. Not sure exactly how it works though, haven't used it much. I do know that there are a bunch of quirks in make for dealing with .a(rchive?)-files.

成熟稳重的好男人 2024-08-15 03:45:28

我想你可以使用这个:

$(UTIL_OBJS) : $(UTIL_SRC)
    g++ $(UTIL_FLAGS) $(@ : .o = .cpp)  -o $@ 

再次,我不太确定......特别是关于 $(@ : .cpp = .o) 部分

I think you could use this:

$(UTIL_OBJS) : $(UTIL_SRC)
    g++ $(UTIL_FLAGS) $(@ : .o = .cpp)  -o $@ 

again, I'm not quite sure... especialy about the $(@ : .cpp = .o) part

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