Для меня это работает одинаково (повторяется один раз) независимо от того, есть символическая ссылка или нет. Но из содержимого кажется, что вас интересует только создание списка файлов, поэтому существование файла на самом деле не требуется. Если вы опустите зависимость, вы можете сгенерировать список файлов, даже не извлекая файлы.
Для фактического списка файлов запишите слишком большую ошибку командной строки из-за того, что сгенерированная команда представляет собой одну строку с несколькими вызовами подоболочки , что может быть слишком длинным для командной строки:
$ make FL1 --trace
...
Makefile:24: update target 'c_proj1.f' due to: design1/c_files/a.c design1/c_files/b.c design1/c_files/c.c design1/c_files/d.c design1/c_files/e.c design1/c_files/f.c
( rm -f c_proj1.f )
( touch c_proj1.f )
`echo ./design1/c_files/a.c >> c_proj1.f` `echo ./design1/c_files/b.c >> c_proj1.f` `echo ./design1/c_files/c.c >> c_proj1.f` `echo ./design1/c_files/d.c >> c_proj1.f` `echo ./design1/c_files/e.c >> c_proj1.f` `echo ./design1/c_files/f.c >> c_proj1.f`
Эта часть может быть решена с помощью функции $(file)
(если вы используете GNU make 4.1 +):
.PHONY: $(FILE_LIST1)
$(FILE_LIST1):
$(file >$@)
$(foreach file,$(DESIGN_FILES1),$(file >>$@,$(file)))
Если используется более старая версия make, это можно сделать с помощью обычных команд, вам просто нужно генерировать символ новой строки после каждого echo
, чтобы он работал как отдельная команда. Единственная сложность заключается в том, что это должно выполняться как специально созданная переменная:
# Note double empty lines below
define newline
endef
.PHONY: $(FILE_LIST2)
$(FILE_LIST2):
rm -f $@
$(foreach file,$(DESIGN_FILES2),echo $(file) >> $@$(newline))
Результат теперь генерируется в отдельных вызовах оболочки, что должно избегать ограничения длины команды:
$ make FL2
rm -f c_proj2.f
echo ./design2/c_files/a.c >> c_proj2.f
echo ./design2/c_files/b.c >> c_proj2.f
echo ./design2/c_files/c.c >> c_proj2.f
echo ./design2/c_files/d.c >> c_proj2.f
echo ./design2/c_files/e.c >> c_proj2.f
echo ./design2/c_files/f.c >> c_proj2.f
РЕДАКТИРОВАТЬ:
Мне удалось воспроизвести вашу многократную итерацию извлечения. Ваш файл tgz
на самом деле не содержит файлов, которые вы утверждаете для извлечения, поэтому файлы отсутствуют при попытке извлечения первого файла, а извлечение продолжается для следующего файла (который также отсутствует). Об этом также свидетельствует вывод tar
, в котором говорится:
design1/
design1/c_files
вместо:
design1/
design1/c_files
design1/c_files/a.c
design1/c_files/b.c
design1/c_files/c.c
design1/c_files/d.c
design1/c_files/e.c
design1/c_files/f.c
Ваш tgz
содержит только символическую ссылку каталога и извлекает только символическую ссылку. Если целевые файлы не существуют в целевом расположении, он будет пытаться повторно извлечь для каждого файла.
EDIT2:
Когда фактические файлы не включены в файл tgz
, но доступны по символической ссылке, есть вероятность, что они старше, чем сам файл tgz
. В такой ситуации make
проверяет временную метку файла через символическую ссылку и обнаруживает, что ее необходимо переделать, но файл фактически не переделывается (поскольку он не включен в tgz
). Эта проверка выполняется для каждого отдельного файла, поэтому для каждого файла извлекается архив:
$ make FL1 -d
...
Finished prerequisites of target file 'design1/c_files/a.c'.
Prerequisite 'design1.tgz' is newer than target 'design1/c_files/a.c'.
Must remake target 'design1/c_files/a.c'.
tar zxvfmhC design1.tgz .
Putting child 0x7fffe11ae730 (design1/c_files/a.c) PID 6286 on the chain.
Live child 0x7fffe11ae730 (design1/c_files/a.c) PID 6286
design1/
design1/c_files
Reaping winning child 0x7fffe11ae730 PID 6286
Removing child 0x7fffe11ae730 PID 6286 from chain.
Successfully remade target file 'design1/c_files/a.c'.
Considering target file 'design1/c_files/b.c'.
Pruning file 'design1.tgz'.
Finished prerequisites of target file 'design1/c_files/b.c'.
Prerequisite 'design1.tgz' is newer than target 'design1/c_files/b.c'.
Must remake target 'design1/c_files/b.c'.
tar zxvfmhC design1.tgz .
...
В общем, извлечение архива таким способом в любом случае ненадежно (образ работает параллельно с -j
), поэтому было бы лучше использовать целевое правило группы , чтобы явно указать, что это правило генерирует все файлы одновременно:
$(DESIGN_FILES1) &: $(DESIGN_TAR_FILE1)
tar zxvfmhC $(DESIGN_TAR_FILE1) $(DESIGN_EXTRACT_DIR)
Однако это новая функция, представленная в GNU make 4.3, поэтому, чтобы он работал с предыдущими версиями, мы могли бы использовать фальшивую цель, которая используется только для синхронизации, например:
$(DESIGN_FILES1): extract-$(DESIGN_TAR_FILE1)
.PHONY: extract-$(DESIGN_TAR_FILE1)
extract-$(DESIGN_TAR_FILE1):
tar zxvfmhC $(DESIGN_TAR_FILE1) $(DESIGN_EXTRACT_DIR)
Вывод:
$ make FL1
tar zxvfmhC design1.tgz .
design1/
design1/c_files
Обратите внимание, что архив теперь извлекается только один раз.