фильтрация на выходе оболочки - PullRequest
0 голосов
/ 04 августа 2020

В моем каталоге sr c четыре папки: dir1, dir2, dir3, dir4.

PARSE_MODULES = $$(MODULES=$$(ls -l $1 | grep '^d' | awk '{print $$9}'); echo $$MODULES);
MODULES:=$(call PARSE_MODULES,src)
all:
    @echo $(MODULES)

Следовательно, этот небольшой фрагмент кода выводит

dir1 dir2 dir3 dir4

Теперь , Я добавляю следующие две строки перед правилом all:

X:=dir1 dir3
MODULES:=$(filter-out $(X),$(MODULES))

Результат остается неизменным, т.е. filter-out работает не так, как ожидалось. Однако, если я вручную определяю MODULES, я получаю ожидаемый результат:

MODULES:=dir1 dir2 dir3 dir4
X:=dir1 dir3
MODULES:=$(filter-out $(X),$(MODULES))

Вывод: dir2 dir4

Почему невозможно обработать вывод из awk в фильтре? Есть ли способ сделать это?

Ответы [ 3 ]

4 голосов
/ 04 августа 2020

Ваша проблема в том, что вы отложили расширение содержимого PARSE_MODULES с помощью $$, так что он запускается оболочкой в ​​рецепте, а не make.

Это:

PARSE_MODULES = $$(MODULES=$$(ls -l $1 | grep '^d' | awk '{print $$9}'); echo $$MODULES);
MODULES:=$(call PARSE_MODULES,src)

оставляет переменную MODULES, содержащую этот текст:

$(MODULES=$(ls -l src | grep '^d' | awk '{print $9}'); echo $MODULES);

Затем, когда вы используете $(MODULES) в рецепте, оно расширяется следующим образом:

all:
        @echo $(MODULES=$(ls -l src | grep '^d' | awk '{print $9}'); echo $MODULES);

тогда оболочка выполнит команду внутри $(...) и отобразит результаты.

Когда вы попытаетесь отфильтровать имена вроде dir1 et c. от значения переменной make MODULES ничего не происходит, потому что переменная make MODULES содержит сам сценарий оболочки в виде текста, он не содержит результатов выполнения сценария оболочки.

I ' Я не уверен, почему вы пытаетесь делать что-то таким невероятно запутанным способом, с таким большим количеством экранирований и использованием сложных для понимания сценариев оболочки. Возможно, есть причина, по которой ваша полная среда нуждается в чем-то настолько сложном, но вы можете FAR проще реализовать приведенный выше пример, просто используя некоторые базовые c функции make:

PARSE_MODULES = $(sort $(notdir $(patsubst %/.,%,$(wildcard $1/*/.))))

MODULES := $(call PARSE_MODULES,src)

Теперь PARSE_MODULES расширяется make, а не рецептом, а filter-out et c. будет нормально работать на нем. К тому же это намного проще, чем использовать командную оболочку с помощью grep и awk.

1 голос
/ 04 августа 2020

Незначительное упрощение от версии OP:

# possibly: find -maxdepth 1
PARSE_MODULES = $(shell find $1 -type d -printf "%P\n")
SKIP := dir1 dir3

MODS := $(call PARSE_MODULES,src)
FLTR := $(filter-out $(SKIP), $(MODS))

all:
    @echo MODS: $(MODS)
    @echo SKIP: $(SKIP)
    @echo FLTR: $(FLTR)

Вывод:

MODS: dir1 dir2 dir3 dir4
SKIP: dir1 dir3
FLTR: dir2 dir4
1 голос
/ 04 августа 2020

Насколько я понимаю, список оболочки $(MODULES=$(ls -l src | grep '^d' | awk '{print $9}'); echo $MODULES) оценивается оболочкой при выполнении рецепта all. Слишком поздно. Попробуйте так, может быть:

PARSE_MODULES = $(shell ls -l $1 | grep '^d' | awk '{print $$9}')
MODULES       := $(call PARSE_MODULES,src)

X             := dir1 dir3
MODULES       := $(filter-out $(X),$(MODULES))

all:
    @echo $(MODULES)
...