2013-05-02 3 views
0

Позвольте мне сначала быстро написать Makefile как витрина:Один дочерний процесс за цикл в make?

#!/bin/make -f 

folders := $(shell find -mindepth 1 -maxdepth 1 -type d -print) 

make_dir: 
    @mkdir -p "test0" 

pwd_test: 
    @cd "test0" && pwd 
    @pwd 

pwd_all: 
    @for f in $(folders); do \ 
     cd "$${f}" && pwd; \ 
     pwd; \ 
     cd ..; \ 
    done 

Сначала делают make make_dir, а затем увидеть различные результаты:

➜ so make pwd_test 
/data/cache/tmp/so/test0 
/data/cache/tmp/so 
➜ so make pwd_all 
/data/cache/tmp/so/test0 
/data/cache/tmp/so/test0 

Вы видите, что в течение цикла необходимо сделать cd .. , По-видимому, теперь нет никакого дочернего процесса для команды cd X && pwd, в то время как это нормально. Является ли это поведение специфичным для создания или специфики моей оболочки?

+0

Короткий ответ (спасибо ниже): ** для цикла ** является частью оболочки, которую вы используете. Так что make не имеет понятия о ** для циклов **. –

ответ

1

Создайте новый процесс для каждой команды в правиле. Поскольку цикл for является одной командой, вы получаете только один процесс.

Взгляните на Recipe Execution

Edit:

Каждая строка в файле управления получает его собственный подоболочку. Команды, которые имеют \, говорят, что следующая строка должна быть частью текущей строки.

Причины для петли получить свою собственную подоболочку потому, что делает увидеть линию как

@for f in $(folders); do cd "$${f}" && pwd; pwd; cd ..; done 

Безумных учёные объясняет это довольно хорошо. Любая команда, которую вы можете ввести в свою оболочку в одной строке, будет выполнена make в одной подоболочке или в процессе.

Если вы запустите это в KSH, KSH будет принят for f in $(folders); do cd "$${f}" && pwd; pwd; cd ..; done и было бы работать в этой одной подоболочки. Если у ksh не было цикла for, то это , вероятно, было бы ошибкой и make, если бы команда вернула некоторый код ошибки.


Объяснение pwd_test

pwd_test: 
    @cd "test0" && pwd 
    @pwd 

@cd "test0" && pwd рассматривается как одна строка так подоболочка обновляет свой текущий рабочий каталог, а затем выводит то, что текущий рабочий является.

@pwd На этой линии марки порождает новый подоболочку, который содержит старый работающий каталог (или каталог марка называлась форма) и pwd печатает этот каталог .

+1

Иными словами, если вы вырезаете и вставляете эту команду, включая обратную косую черту в вашу оболочку, вы получите то же поведение, что видите с помощью make. Make принимает каждую логическую строку рецепта и отправляет его в оболочку. То, что оболочка делает с ней, не имеет понятия. Он просто ждет завершения оболочки и смотрит на код выхода. – MadScientist

+0

поэтому ** для цикла ** является самой командой оболочки, если бы не было ** для цикла **, определенного для данной оболочки (скажем, облегченной версии оболочки Korn ksd) ** make ** (запустить в этой оболочке) не будет реализовывать ** для цикла **? –

+0

Думаю, я понимаю. Make не нужно использовать for-loops!Макияж способ делать вещи, это именно путем определения целей: 'pwd_make_all: $ (папки) .PHONY: $ (папки) $ (папки): \t @cd $ @ && pwd' –

Смежные вопросы