Обработка нескольких файлов, сгенерированных из одного ввода - PullRequest
0 голосов
/ 02 марта 2019

У меня есть файл данных, который обрабатывается скриптом для создания нескольких выходных файлов.Каждый из этих выходных файлов затем обрабатывается дальше.Какие файлы создаются, зависит от содержимого входного файла, поэтому я не могу перечислить их явно.Я не могу понять, как обращаться к различным файлам, которые генерируются в make-файле.

В настоящее время у меня есть что-то вроде этого:

final.out: *.out2
  merge_files final.out $(sort $^)

%.out2: %.out1
  convert_files $?

%.out1: data.in
  extract_data data.in

Это не с No rule to make target '*.out2', needed by 'final.out',Я предполагаю, что это потому, что файлы .out2 еще не существуют, и поэтому подстановочное выражение не заменяется так, как мне бы хотелось.Я пытался использовать функцию подстановки, но это не помогло, потому что список предварительных условий оказывается пустым.

Любые указатели будут очень благодарны.

Ответы [ 2 ]

0 голосов
/ 02 марта 2019

К сожалению, в вашем вопросе отсутствуют некоторые детали. Я бы сразу спросил, если какой-нибудь разработчик ПО предоставит этот make-файл для проверки:

  • предоставляет ли extract_files список файлов?
  • convert_files конвертирует один файл или несколько?Пример показывает, что он преобразует несколько.
    • тогда я должен подвергнуть сомнению решение разбить извлечение, преобразование и объединение в отдельные правила, так как параллельная сборка вам все равно не поможет

Следующееэто подход, который я бы выбрал.Я собираюсь использовать tar-файл в качестве примера для входного файла, который приводит к нескольким выходным файлам

  • создать фрагмент make-файла для отсортированного списка файлов
    • использовать tar опция v для печати файлов во время их извлечения
    • преобразование каждой строки в присваивание переменной make-файла
  • включает фрагмент для определения $(DATA_FILES)
    • если фрагмент должен быть восстановлен, make будет перезапущен после того, как он его сгенерировал
  • использовать правило статического шаблона для преобразования
  • использовать список преобразованных файлов какзависимость для конечной цели
.PHONY: all
all: final.out

# extract files and created sorted list of files in $(DATA_FILES)
Makefile.data_files: data.tar
    set -o pipefail; tar xvf $< | sort | sed 's/^/DATA_FILES += /' >$@

DATA_FILES :=
include Makefile.data_files

CONVERTED_FILES := $(DATA_FILES:%.out1=%.out2)

$(CONVERTED_FILES): %.out2: %.out1
    convert_files $< >$@

final.out: $(CONVERTED_FILES)
    merge_files final.out $^

ОБНОВЛЕНИЕ , если extract_data не предоставляет список файлов, вы можете изменить мой пример следующим образом.Но, конечно, это зависит от того, что в вашем каталоге нет других файлов, которые соответствуют *.out1.

# extract files and created sorted list of files in $(DATA_FILES)
Makefile.data_files: data.in
    set -o pipefail;   \
    extract_data $< && \
    (ls *.out1 | sort | sed 's/^/DATA_FILES += /') >$@
0 голосов
/ 02 марта 2019

РЕДАКТИРОВАТЬ : исправлен список предпосылок во втором проходе.

Вы, очевидно, не можете вычислить список промежуточных файлов перед запуском команды extract_data.В этом случае решение состоит в том, чтобы запустить make дважды.Первый раз для генерации файлов *.out1 и второй раз для завершения работы.Вы можете использовать пустой фиктивный файл, чтобы указать, будет ли команда extract_data выполняться снова или нет:

ifeq ($(FIRST_PASS_DONE),)
final.out: .dummy
    $(MAKE) FIRST_PASS_DONE=yes

.dummy: data.in
    extract_data $<
else
OUT1 := $(wildcard *.out1)
OUT2 := $(patsubst %.out1,%.out2,$(OUT1))

final.out: $(OUT2)
    merge_files $@ $(sort $^)

%.out2: %.out1
    convert_files $?
endif
...