Поддерживает ли Make этот вид потока? - PullRequest
0 голосов
/ 23 августа 2011

Представьте, что у меня есть это:

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 ]

1 голос
/ 23 августа 2011

Это можно сделать в 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 голос
/ 23 августа 2011

Вы можете использовать макросы (define) в GNU make и 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))))
0 голосов
/ 23 августа 2011

Я бы написал скрипт для генерации make-файлов для каждого проекта, выполнял make для каждого и удалял их, если все прошло нормально

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...