0

我想使用单个 makefile 编译具有多个源文件的多个应用程序。
所有来源都在一个目录中。

应用程序/src/
app1_file1.cpp
app1_file2.cpp
app1_main.cpp
app2_file1.cpp
app2_file2.cpp
app2_main.cpp

应用程序/Makefile

生成文件

APPS:= app1_main app2_main  
app1_main_SOURCES:= app1_file1.cpp app1_file2.cpp app1_main.cpp
app2_main_SOURCES:= app2_file1.cpp app2_file2.cpp app2_main.cpp

default: app1_main app2_main

%: $(foreach $CPP_FILE,$(%_SOURCES),$(patsubst %.cpp,%.o,$(CPP_FILE)))
     gcc ....
%.o: src/%.cpp
     gcc ...

问题

我希望将 $(%_SOURCES) 替换为“app1_main_SOURCES,app2_main_SOURCES”。但这似乎并没有发生在上面的代码中。有人可以建议使用 % 的正确方法将其替换为我想要的变量名。

谢谢

4

2 回答 2

0

foreach 在 make 解析 makefile 时发生。当您的规则运行时,它已经完成了很长时间。

此外,您不希望$foreach 的第一个参数中的 (即您想要的$(foreach CPP_FILE,...,... $(CPP_FILE) ...))。

我可能会做类似(未经测试)的事情:

$(foreach APP,$(APPS),$(APP): $(addprefix src/,$($(APP)_SOURCES:.cpp=.o)))

%:
        gcc ...
%.o: src/%.cpp
        gcc ...

也就是说,使用 for 循环建立应用程序及其目标文件之间的先决关系,然后让 % 规则处理目标 -> 规则映射。

于 2013-07-31T02:06:05.517 回答
0

有几种方法可以做到这一点。首先让我们让它工作。

编写对象列表就像编写列表一样容易,并且可以节省我们以后的工作:

app1_main_OBJECTS:= app1_file1.o app1_file2.o app1_main.o
app2_main_OBJECTS:= app2_file1.o app2_file2.o app2_main.o

default: app1_main app2_main

app1_main: $(app1_main_OBJECTS)
app2_main: $(app2_main_OBJECTS)

app%_main:
    gcc $^ -o $@

如果有许多应用程序,那么该应用程序规则列表是多余且乏味的。我们可以减少它:

define rule_template
$(1): $$($(1)_OBJECTS)
endef

$(foreach app,app1_main app2_main,$(eval $(call rule_template,$(app))))

或者,如果您的 Make 版本支持SECONDEXPANSION,则更简单:

.SECONDEXPANSION:                
app1_main app2_main: $$($$@_OBJECTS)

您可以通过定义应用列表来进一步简化事情:

APPS := app1_main app2_main

...但是这个答案越来越长。

于 2013-07-31T02:34:21.060 回答