想象一下,我有这个:
PROJECT1 := /path/to/first
PROJECT2 := /path/to/second
PROJECT3 := /path/to/third
我正在搜索从其中收集所有c,cpp,h
个文件。我有类似的东西:
PROJECT1_CPP := $(shell find $(PROJECT1) -name "*.cpp" -type "f")
PROJECT1_C := ... ( the same happens for PROJECT2 and PROJECT3 )
现在,我可以为每个人添加目标,如:
project1.lib: $(PROJECT1_OBJS)
...
project2.lib: $(PROJECT2_OBJS)
...
project3.lib: $(PROJECT3_OBJS)
...
使用这种方法的是:有很多重复代码(所有构建的所有操作几乎相同)。我希望能够做一些更通用的事情,比如:
PROJECTS := /path/to/first
PROJECTS += /path/to/second
PROJECTS += /path/to/third
然后以某种方式迭代它们并构建它们。像这样的伪代码:
foreach project in PROJECTS
gather C/C++ files
build them
link them
link everything together
你能否指点我应该从哪里开始?这在Make?中是否可行?
答案 0 :(得分:1)
可以在GNUMake中完成,我不了解其他品种。
首先我们定义一个宏:
SOURCES = $(shell find $(1) -name "*.cpp" -type "f")
然后我们可以为每个项目调用它:
PROJECT1_CPP := $(call SOURCES,$(PROJECT1))
PROJECT2_CPP := $(call SOURCES,$(PROJECT2))
PROJECT3_CPP := $(call SOURCES,$(PROJECT3))
或者如果有很多(或者我们很懒):
PROJECTS := PROJECT1 PROJECT2 PROJECT3
$(foreach proj,$(PROJECTS),$(eval $(proj)_CPP := $(call SOURCES,$($(proj)))))
或者,如果我们真的懒惰:
$(foreach proj,1 2 3,$(eval PROJECT$(proj)_CPP := $(call SOURCES,$(PROJECT$(proj)))))
现在构建它们,而不是:
project1.lib: $(PROJECT1_OBJS)
do something with $(PROJECT1_OBJS)
project2.lib: $(PROJECT2_OBJS)
do something with $(PROJECT2_OBJS)
project3.lib: $(PROJECT3_OBJS)
do something with $(PROJECT3_OBJS)
我们改为:
project1.lib: $(PROJECT1_OBJS)
do something with $^
project2.lib: $(PROJECT2_OBJS)
do something with $^
project3.lib: $(PROJECT3_OBJS)
do something with $^
然后到此:
project1.lib: $(PROJECT1_OBJS)
project2.lib: $(PROJECT2_OBJS)
project3.lib: $(PROJECT3_OBJS)
project1.lib project2.lib project3.lib
do something with $^
我们甚至可以将其变成另一个$(foreach ... $(eval...))
,但我们不要过分。
修改:
你想要超越?你走了:
PROJECT1 := /path/to/first
PROJECT2 := /path/to/second
PROJECT3 := /path/to/third
all:
@echo linking $^ somehow
define all_rules
PROJECT$(1)_CPP := $(shell find $(PROJECT$(1)) -name "*.cpp" -type "f")
project$(1).lib: $(PROJECT$(1)_CPP:.cpp=.o)
@echo making $$@ from $$^
all: project$(1).lib
endef
$(foreach proj,1 2 3,$(eval $(call all_rules,$(proj))))
%.o: %.cpp
@echo making $@ from $<
答案 1 :(得分:1)
您可以在GNU make和define
中使用宏(eval
)来动态添加规则。这并不容易,但它确实有效。以下代码假定项目的名称是项目所在目录的名称:
PROJECTS := /path/to/project1 /path/to/project2
all:
# Do all libraries
define def_rules
v=$$(notdir $(1))
$$(v)_CPP := $$(shell find $(1) -name "*.cpp" -type "f")
$$(v)_OBJS := $$(patsubst %.cpp,%.o,$$($$(v)_CPP))
$$(v).lib: $$($$(v)_OBJS)
lib ... $$<
endef
$(foreach pr,$(PROJECTS),$(eval $(call def_rules,$(pr))))
答案 2 :(得分:0)
我会编写一个脚本来为每个项目生成makefile,在每个项目上执行make并在一切顺利的情况下删除它们