Повторяющиеся каталоги и условия в makefiles

#makefile #gnu-make

#makefile #gnu-make

Вопрос:

У меня есть структура репозитория, в которой зависимости могут быть либо svn: external’d либо в этом репозитории, либо в супер-репозитории, в котором есть svn: external’d этот. Внешние файлы имеют глубину всего в один уровень, и поэтому, если мой репозиторий экстернализируется супер-репозиторием, мне нужно иметь возможность определять, где найти зависимость на более высоком уровне, и копировать все соответствующие данные. Если зависимость действительно найдена в моем собственном репозитории, то мне нужно ее создать.

У меня возникли проблемы с созданием моего рецепта makefile для этого. Вот что у меня есть на данный момент:

 DEPENDENCIES = dep1 dep2
ROOTDIR = .

deps : 
    for dep in $(DEPENDENCIES); do 
        if [ -e $(ROOTDIR)/ext/$dep ]; then 
            depdir = $(ROOTDIR)/ext/$dep; 
            $(MAKE) -C $depdir; 
        elif [ -e $(ROOTDIR)/../$dep ]; then 
            depdir = $(ROOTDIR)/../$dep; 
        else 
            $(error Could not find dependency: $dep) 
        fi 
        cp $depdir/bin/* $(ROOTDIR)/bin; 
        cp $depdir/lib/* $(ROOTDIR)/lib; 
        cp $depdir/inc/$dep $(ROOTDIR)/inc/$dep; 
    done
 

Первая проблема — строка $(ошибка). Я хотел бы иметь возможность выдавать ошибку, но это явно не подпадает под действие инструкций условия bash. Это вывод:

 $ make deps
makefile:108: *** Could not find dependency: $dep.  Stop.
 

Если я закомментирую это утверждение else, то у меня все еще возникают проблемы

 $ make deps
for dep in dep1 dep2; do 
        if [ -e ./ext/$dep ]; then 
/bin/sh: -c: line 2: syntax error: unexpected end of file
make: *** [makefile:106: deps] Error 1
 

Может ли кто-нибудь дать несколько советов о том, как это сделать? Я использую GNU make как в средах cygwin, так и в Linux.

Редактировать: я бы действительно предпочел, чтобы это было как можно ближе к make (и как можно меньше содержимого оболочки). Я думаю, что я немного приблизился, но все равно нужно повторить это для каждого элемента в $(ЗАВИСИМОСТИ).

 DEPENDENCIES = foo bar
ROOTDIR = .
EXTDIR = $(ROOTDIR)/ext
BINDIR = $(ROOTDIR)/bin
INCDIR = $(ROOTDIR)/inc

# Need a foreach DEP in $(DEPENDENCIES) here
ifneq("$(wildcard $(EXTDIR)/$(DEP))","")  
DEPDIR = $(EXTDIR)/$(DEP)
BUILDDEP = $(MAKE) -C $(DEPDIR)/build
else ifneq("$(wildcard $(ROOTDIR)../$(dep))", "") 
DEPDIR = $(ROOTDIR)/../$(dep)
else
$(error Could not find dependency: $(DEP))
endif 

$(DEPDIR) :
    $(BUILDDEP)
    cp $(DEPDIR)/bin/* $(BINDIR)
    cp $(DEPDIR)/inc/$(DEP)/* $(INCDIR)/$(DEP)
 

Правка2:
Я думаю, что я приближаюсь. Следующее больше похоже на то, что я хочу, но у него все еще есть проблемы:
1) Я не знаю, как вызывать каждый рецепт
2) Он не выдает ошибку, если не находит все зависимости
3) Это не позволяет мне диктовать порядок сборки
4) Это не позволяет мне фильтровать, чтобы использовать только папки, перечисленные в зависимостях (он выполняет все папки)

 ifneq "$(wildcard $(EXTDIR)/%/build)" ""  
$(EXTDIR)/%:
    $(MAKE) -C $(EXTDIR)/%/build
    cp $(EXTDIR)/%/bin/* $(BINDIR)
    cp $(EXTDIR)/%/int/*.a $(INTDIR)
    cp $(EXTDIR)/%/inc/%/* $(INCDIR)/%
endif

ifneq "$(wildcard $(ROOTDIR)/../%/build)" ""
DEPDIR = $(ROOTDIR)/..
$(DEPDIR)/%: 
    cp $(DEPDIR)/%/bin/* $(BINDIR)
    cp $(DEPDIR)/%/int/*.a $(INTDIR)
    cp $(DEPDIR)/%/inc/%/* $(INCDIR)/%
endif
 

Правка3
После того, как мне сказали, что я пытаюсь решить слишком много проблем сразу, я свел это к следующему:

 DEPENDENCIES = dep1 dep2 dep3

for each DEP in $(DEPENDENCIES)

$(DEP) : 
    $(MAKE) -C ../ext/$(DEP)
 

Как я могу создать рецепт ($ (DEP) ) для каждого элемента в $(ЗАВИСИМОСТИ)?

Комментарии:

1. Вы пишете сценарий оболочки, а не Makefile: там нет правил. Превратите это в сценарий оболочки!

2. Вы пытаетесь решить слишком много проблем одновременно. Попробуйте сделать это из командной строки (т. Е. Без Make), и если у вас возникнут проблемы с частью этого, уменьшите эту проблему до ее сути (например, как мне выдать ошибку в bash?), И если вы не можете решить эту проблему, спросите об этом здесь .

3. Мне легко сделать это из командной строки. Однако я бы предпочел использовать make, чтобы: А) эта структура могла быть обобщена и легко настроена для использования другими разработчиками Б) я не застрял на g и Linux. Мы также хотели бы разрабатывать в Windows с помощью MinGW, и поэтому Bash для меня не подходит.

4. Ваше решение также является параллельным безопасным. Передайте -j5 (скажем) в make и make , чтобы гарантировать, что ваши процессоры будут заняты во всех подразделах. Неплохо. Одно замечание: вы, вероятно, хотите добавить .PHONY: ${DEPENDENCIES} , чтобы пометить их как символические цели, иначе это будет неправильно, если кто-то создаст файл с именем ../ext/dep2 (скажем).

Ответ №1:

Решена. Это решает проблему, описанную выше:

 DEPENDENCIES = dep1 dep2 dep3
$(DEPENDENCIES) : 
    $(MAKE) -C ../ext/$@
 

Ответ очень прост. Хотел бы я знать достаточно об этом, чтобы задать более понятный вопрос.