简体   繁体   English

如何在 Makefile 中为多个目标依赖对编写通用规则

[英]How to write a common rule in Makefile for multiple target dependency pairs

I want to write a single Makefile to compile 3 different C++ files with their own independent targets.我想写一个Makefile来编译 3 个不同的 C++ 文件,它们有自己的独立目标。 All these three files reside in the same directory along with other unused files as well.所有这三个文件以及其他未使用的文件都位于同一目录中。 For example, the directory may contain files a.cpp , b.cpp , c.cpp and d.cpp .例如,该目录可能包含文件a.cppb.cppc.cppd.cpp Out of these four, I want the Makefile to only run the build command for the first three files ie a.cpp , b.cpp and c.cpp .在这四个中,我希望 Makefile 只为前三个文件运行构建命令,即a.cppb.cppc.cpp I'm storing these three files in a variable in the Makefile .我将这三个文件存储在Makefile中的一个变量中。 Similarly, I'm also storing their targets in another variable.同样,我还将他们的目标存储在另一个变量中。 I want make to use a.cpp to compile the target a , b.cpp to compile the target b , and c.cpp to compile the target c .我想make使用a.cpp编译目标a ,使用b.cpp编译目标b ,使用c.cpp编译目标c This is, however, just an example.然而,这只是一个例子。 The real project has hundereds of targets.真正的项目有数百个目标。 Therefore, I do not want to write the rules for each of the targets manually.因此,我不想手动为每个目标编写规则。 Is there a way in which I can tell make to compile each target using it's specific dependency?有没有一种方法可以告诉make使用它的特定依赖项来编译每个目标?

To test out different ways to do this, I created a small test project with four files: the Makefile , aa , bb , and cc .为了测试执行此操作的不同方法,我创建了一个包含四个文件的小型测试项目: Makefileaabbcc Using the Makefile , I want to generate the targets a , b and c .使用Makefile ,我想生成目标abc All these three targets have only one dependency which is their source file.所有这三个目标都只有一个依赖项,即它们的源文件。 For example, a has dependency on aa .例如, a依赖于aa I wrote a test Makefile to do this which is pasted below:我写了一个测试Makefile来执行此操作,粘贴在下面:

TARGETS = a b c                                                                                                                                                
DEPS = aa bb cc

$(TARGETS): $(DEPS)
        @echo $@ $<

This Makefile simply prints out the targets and their dependencies.这个Makefile只是打印出目标及其依赖项。 When I execute this Makefile , I get:当我执行这个Makefile时,我得到:

a aa

However, what I want is the following:但是,我想要的是以下内容:

a aa
b bb
c cc

How can I accomplish this?我怎样才能做到这一点? Note that I need to specifically build the objects which are stored in the variable TARGETS and nothing else.请注意,我需要专门构建存储在变量TARGETS中的对象,仅此而已。

The reason it only builds one target is that make only builds the first target in the makefile by default.它只构建一个目标的原因是默认情况下 make 只构建 makefile 中的第一个目标。 In your example after variables are expanded make sees these rules:在扩展变量后的示例中,make 会看到以下规则:

a b c: aa bb cc
        @echo $@ $<

This is identical (to make) as if you'd written this:这和你写的一样(制作):

a: aa bb cc
        @echo $@ $<
b: aa bb cc
        @echo $@ $<
c: aa bb cc
        @echo $@ $<

Since a is the first target, when you type make it will just build a .由于a是第一个目标,当您键入make时,它只会构建a . If you want make to build ALL the targets, make your first target something that depends on them all, such as:如果你想 make 构建所有目标,让你的第一个目标成为依赖于它们的东西,例如:

TARGETS = a b c                                                                                                                                                
DEPS = aa bb cc

all: $(TARGETS)

$(TARGETS): $(DEPS)
        @echo $@ $<

But of course you can see above that this isn't what you want because each target has ALL the prerequisites so when bb changes, all of a , b , and c are rebuilt.但是当然你可以在上面看到这不是你想要的,因为每个目标都有所有先决条件,所以当bb改变时,所有的abc被重建。

To do this you need to use a pattern rule .为此,您需要使用模式规则 For example if you want to build a from a.cpp you can write your makefile like this:例如,如果你想从a.cpp构建a ,你可以这样写你的 makefile :

TARGETS = a b c                                                                                                                                                
DEPS = aa bb cc

all: $(TARGETS)

%: %.cpp
        @echo $@ $<

If the target name is not derived from the dependency name, you could also do something like this:如果目标名称不是从依赖项名称派生的,您也可以这样做:

TARGETS = a b foo

all:$(TARGETS)                                                                                                                                             

a:aa
b:bb
foo:bar

$(TARGETS):
        @echo $@ $<

.PHONY: all
.PHONY: $(TARGETS)

Note that I declared your TARGETS as PHONY as your recipe does not create files with those names.请注意,我将您的 TARGETS 声明为PHONY ,因为您的食谱不会创建具有这些名称的文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM