Как использовать цикл for в рецепте make - PullRequest
8 голосов
/ 06 января 2012

Я хотел бы использовать цикл, чтобы найти некоторые файлы и переименовать их:

  for i in `find $@  -name *_cu.*`;do mv $i "$(echo $i|sed s/_cu//)"
  done

Это работает в оболочке.Но как я могу сделать это в рецепте makefile?

Ответы [ 2 ]

29 голосов
/ 06 января 2012

При добавлении нетривиальных фрагментов оболочки в рецепты изготовления нужно знать две основные вещи:

  1. Команды в рецепте (конечно!) Выполняются по одной за раз, где команда означает «строку с префиксом табуляции в рецепте», возможно, распределенную по нескольким строкам make-файла с обратной косой чертой.

    Таким образом, ваш фрагмент оболочки должен быть записан в одну (возможно, обратную косую черту) строку. Более того, он эффективно представляется оболочке в виде одной строки (обратные косые черты - не простые переводы строк, поэтому они не используются оболочкой в ​​качестве разделителей команд), поэтому должны быть синтаксически правильными как таковые.

  2. Переменные оболочки и переменные make представлены знаками доллара ($@, $i), поэтому вам необходимо скрыть переменные оболочки от make, записав их как $$i. (Точнее, любой знак доллара, который вы хотите видеть в оболочке, должен быть экранирован от make, написав его как $$.)

Обычно в сценарии оболочки вы пишете отдельные команды в отдельных строках, но здесь вы фактически получаете только одну строку, поэтому вместо них необходимо разделять отдельные команды оболочки точкой с запятой. Собирая все это вместе для вашего примера, получаем:

foo: bar
    for i in `find $@  -name *_cu.*`; do mv $$i "$$(echo $$i|sed s/_cu//)"; done

или эквивалентно:

foo: bar
    for i in `find $@  -name *_cu.*`; do      \
        mv $$i "$$(echo $$i|sed s/_cu//)";    \
    done

Обратите внимание, что последняя, ​​даже если она разложена на несколько строк, требует одинакового аккуратного использования точек с запятой, чтобы оболочка была счастливой.

1 голос
/ 27 декабря 2016

Я нашел это полезным, пытаясь использовать циклы for для создания нескольких файлов:

PROGRAMS = foo bar other

.PHONY all
all: $(PROGRAMS)
$(PROGRAMS):
    gcc -o $@ $@.c

Он скомпилирует foo.c, bar.c, other.c в foor bar другие исполняемые файлы

...