GNU make: получить целевые файлы с расширением (суффиксом) как у зависимых файлов

Имеются некоторые файлы с одинаковым базовым именем, но различающиеся расширением. Например:
foo.ex1
foo.ex2
foo.txt

Требуется, после некоторых операций над каждым зависимым файлом, получить на выходе из Makefile файлы с базовым именем как у цели, но с расширением как у зависимых файлов. Например:
foo.bar.ex1
foo.bar.ex1
foo.bar.txt

С MSFT nmake.exe это делается просто и непринуждённо.
Например, с использованием команд командной оболочки:

foo.bar.txt : foo.???
    ! @<<tmp.bat
for /F "usebackq" %%G in (`dir /b $?`) do (
     for /F "usebackq delims=" %%H in (`type %%G ^|findstr /bvl "Remove me gently"`) \
        do (1>>$(@B)%%~xG echo %%H)
 )
<<

Или это же на PowerShell:

PS = PowerShell.exe
PSFLAGS = -NoLogo -NoProfile -Command

foo.bar.txt : foo.???
    ! @$(PS) $(PSFLAGS) $$ext=(Get-Item $?).Extension; (Get-Content $?) -notmatch 'Remove me gently' \
        ^| Out-File $(@B)$$ext

В общем, в обоих случаях, на выходе получаем такие файлы:
foo.bar.ex1
foo.bar.ex2
foo.bar.txt

Т. е. требуется выполнить некоторые операции над каждым зависимым файлом, и результат сохранить в новом файле. Наименование нового файла формируется из базового имени цели (т. е., в данном случае, foo.bar) и расширения файла зависимости, над которым сейчас выполняется операция.

Подскажите, пожалйста, есть ли что‐то подобное в GNU make?


Ответы (2 шт):

Автор решения: Alexey Ten

UPD: Из каждого файла подходящего под маску foo.??? создаём файл foo.bar.???

# создаём список файлов
FILES := $(patsubst foo.%,foo.bar.%,$(wildcard foo.???))

# объявляем что нам нужно получить все эти файлы
default: $(FILES)

# правила могут быть шаблонными
# объявляем зависимость выходных файлов от входных
foo.bar.%: foo.%
    grep -v 'Remove me gently' $< > $@ || true

Вывод

$ make
grep -v 'Remove me gently' foo.ex1 > foo.bar.ex1 || true
grep -v 'Remove me gently' foo.ex2 > foo.bar.ex2 || true
grep -v 'Remove me gently' foo.txt > foo.bar.txt || true

Я не очень понимаю что вы тут хотите получить. Может что-то такое?

FILES = $(patsubst foo.%,foo.bar.%,$(wildcard foo.???))

default:
    @echo $(FILES)

Выхлоп:

$ ls
foo.ex1  foo.ex2  foo.txt  Makefile
$ make
foo.bar.ex1 foo.bar.ex2 foo.bar.txt
→ Ссылка
Автор решения: HolyBlackCat

Например вот так:

all: $(patsubst foo.%,output/foo.bar.%,$(wildcard foo.*))

output:
        mkdir -p $@

output/foo.bar.%: foo.% | output
        cp $< $@

output здесь нужен чтобы создать отдельную папку и сложить в нее результат. Если вам не нужно, можно убрать.

→ Ссылка