Автоматическое копирование зависимостей из других каталогов с помощью make

#makefile #rules #cp

#makefile #Правила #cp

Вопрос:

У меня есть makefile с несколькими целевыми объектами, которые создаются путем копирования файла из-за пределов рабочего каталога.

 a.tex   : $(wildcard /foo/work1/a.tex)
    cp -p

lt; $@

b.tex : $(wildcard /foo/work2/b.tex)
cp -p


lt; $@

Я использую $(wildcard) , потому что иногда я запускаю Make в системах, к которым нет доступа /foo .

Каков наилучший способ избежать повторения cp -p $< $@ команд для каждого правила? Некоторые параметры:

  • Настройка %.tex : %.tex правила. Это работает, но это также относится к целям, которые специально не указаны, поэтому я получаю много предупреждений, таких как make: Circular a.tex <- a.tex dependency dropped.
  • Определение последовательности команд с define помощью . Это кажется бессмысленным, поскольку команда состоит всего из одной строки. Поэтому вместо копирования cp $< $@ в каждое правило я бы определил cp-dep последовательность и скопировал cp-dep в каждое правило.
  • Определение команды как переменной, чтобы я мог сделать a.tex : $(wildcard /foo/work1/a.tex); $(CP-DEP)
  • Дублирование целевых имен в качестве дополнительного правила. a.tex b.tex : ; cp -p $< $@ . Подвержен ошибкам.
  • Просто копирование и вставка. Неуклюжий, но эффективный и простой для понимания.

Ответ №1:

Я не тестировал это, но разве вы не можете просто использовать шаблонное правило без предварительных условий и указать предварительное условие для каждой цели в отдельной строке?

 a.tex: $(wildcard /foo/work1/a.tex)
b.tex: $(wildcard /foo/work2/b.tex)

%.tex:
    cp -p

lt; $@

Кстати. разве функция подстановочных знаков не возвращает пустую строку, когда не находит совпадения, так что $< она тоже пуста? Разве это не вызовет проблемы cp ?

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

1. Это не работает. Правило шаблона ничего не вставляет $< . Когда $(wildcard) возвращается пустая строка, цель воспринимается как актуальная, поэтому ничего не происходит, когда зависимость недоступна в системе.

2. @Michael: Это странно; Я попробовал, и у меня это работает. Вы используете другой make, чем я? Я использую GNU make.

3. @MichaelHoffman: Вы имеете в виду, что $< это пустое, даже если зависимость доступна? И что вы хотите, чтобы Make делал, если зависимость недоступна?

4. @eriktous: Моя ошибка: я попробовал еще раз, и, похоже, это работает. Должно быть, проблема с тестовым кодом, с которым я столкнулся в прошлый раз. Единственное, что мне в этом не нравится, это то, что он будет генерировать %.tex правило для файлов, для которых я явно не определил зависимости, что приводит к запутанным результатам. @Beta: если зависимость недоступна, я не хочу, чтобы Make что-либо делал.

Ответ №2:

Я думаю, что ваш copyrule перебор (и негибкий). Если ваше возражение против решения @eriktous заключается в том, что оно будет применять правило к целевым объектам, для которых вы явно не определили зависимости, это легко исправить с помощью правила статического шаблона:

 a.tex: $(wildcard /foo/work1/a.tex)
b.tex: $(wildcard /foo/work2/b.tex)
blue.tex: $(wildcard /some/other/path/green.tex)

TEXES = a.tex b.tex

$(TEXES): %.tex:
    cp -p

lt; $@

(Если это решит вашу проблему, вы должны принять ответ eriktous — это всего лишь вариант.)

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

1. Приятная особенность этого решения заключается в том, что оно не ограничивается только %.tex файлами. Но это все равно приводит к тому, что мне приходится вводить много шаблонов.

2. @MichaelHoffman: Много шаблонов? Вы сказали, что вам нужно правило только для целевых объектов, для которых вы явно не определили зависимости, поэтому вам нужно ввести зависимости. Это решение также требует, чтобы вы добавили имя нового целевого объекта в TEXES строку. Насколько меньше вы хотите печатать?

Ответ №3:

В итоге я сделал это:

 COPYFILES = /foo/work1/a.tex /foo/work2/b.tex

define copyrule
$(notdir $(1)): $(wildcard $(1))
    cp -p $< $@
endef
$(foreach file,$(COPYFILES),$(eval $(call copyrule,$(file))))
 

Преимущество этого метода в том, что я могу легко добавлять новые файлы с минимальным шаблонным текстом, и я могу легко скопировать часть правила в новый Makefile. Недостатки заключаются в том, что я больше не могу изменять имя файла назначения, а реализация довольно непрозрачна для людей с меньшим опытом работы с makefile.