是否支持这种流动?

时间:2011-08-23 14:19:51

标签: makefile

想象一下,我有这个:

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?中是否可行?

3 个答案:

答案 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并在一切顺利的情况下删除它们