Make支持这种流程吗?

发布于 2024-12-01 12:05:44 字数 876 浏览 0 评论 0原文

想象一下我有这样的情况:

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 中可能吗?

Imagine I have this:

PROJECT1 := /path/to/first
PROJECT2 := /path/to/second
PROJECT3 := /path/to/third

I am doing a find to collect all c,cpp,h files from inside them. I have something like:

PROJECT1_CPP := $(shell find $(PROJECT1) -name "*.cpp" -type "f")
PROJECT1_C := ... ( the same happens for PROJECT2 and PROJECT3 )

Now, I could add targets for each of them like:

project1.lib: $(PROJECT1_OBJS)
  ...

project2.lib: $(PROJECT2_OBJS)
  ...

project3.lib: $(PROJECT3_OBJS)
  ...

The thing with this approach is: there's a lot of repetitive-code ( all the actions for all the builds are almost the same ). I would like to be able to do something more generic, like:

PROJECTS := /path/to/first
PROJECTS += /path/to/second
PROJECTS += /path/to/third

And then somehow iterate through them and build them. Something like this pseudocode:

foreach project in PROJECTS
  gather C/C++ files
  build them
  link them

link everything together

Could you give me any pointers as to where I should start? Is this even possible in Make?

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

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

发布评论

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

评论(3

姐不稀罕 2024-12-08 12:05:44

它可以在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 
lt;

It can be done in GNUMake, I don't know about other varieties.

First we define a macro:

SOURCES = $(shell find $(1) -name "*.cpp" -type "f")

Then we can call it for each project:

PROJECT1_CPP := $(call SOURCES,$(PROJECT1))
PROJECT2_CPP := $(call SOURCES,$(PROJECT2))
PROJECT3_CPP := $(call SOURCES,$(PROJECT3))

Or if there are a lot of them (or we're lazy):

PROJECTS := PROJECT1 PROJECT2 PROJECT3
$(foreach proj,$(PROJECTS),$(eval $(proj)_CPP := $(call SOURCES,$($(proj)))))

Or if we're really lazy:

$(foreach proj,1 2 3,$(eval PROJECT$(proj)_CPP := $(call SOURCES,$(PROJECT$(proj)))))

Now to build them, instead of this:

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)

we change to this:

project1.lib: $(PROJECT1_OBJS)
  do something with $^

project2.lib: $(PROJECT2_OBJS)
  do something with $^

project3.lib: $(PROJECT3_OBJS)
  do something with $^

And then to this:

project1.lib: $(PROJECT1_OBJS)

project2.lib: $(PROJECT2_OBJS)

project3.lib: $(PROJECT3_OBJS)

project1.lib project2.lib project3.lib
  do something with $^

We could even turn that into another $(foreach ... $(eval...)), but let's not go overboard.

EDIT:
You want overboard? Over you go:

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 
lt;
残疾 2024-12-08 12:05:44

您可以在 GNU make 和 eval 中使用宏 (define) 来动态添加规则。这并不容易,但很有效。以下代码假设项目名称为项目所在目录的名称:

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))))

You can use macros (define) in GNU make and eval to add rules on the fly. It is not easy, but it works. The following code assumes that the name of the project is the name of the directory where the project resides:

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))))
寒江雪… 2024-12-08 12:05:44

我会编写一个脚本来为每个项目生成 makefile,对每个项目执行 make,如果一切顺利则删除它们

I'd write a script to generate the makefiles for each project, execute make on each and delete them if all went well

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