как переписать?
но как теперь это переписать из bash в gmake?
http://stackoverflow.com/questions/7039811/how-do-i-process-extremely-long-lists-of-files-in-a-make-recipe
попробуем заменить for из bash на $(foreach ...) из gmake
переменную можно держать в памяти длинную, если склеивать её средствами gmake, а не средствами bash.
держать её длинную надо между циклами, потому что так сделать проще, чем объяснить, как будет работать один общий цикл
Общая идея такова:
1) взять сразу дедуплицированный список ^@
2) отсортировать его средствами gmake
3) для каждой записи в списке:
3.1) провести замены srcdir и всего такого
3.2) если там есть / то подумать, не надо ли создать директорию
3.3) если директория не такая как предыдущая, то создать её при помощи mkdir -p (сравнение нужно для дедупликации директорий)
3.4) выполнить все прочие проверки и копирования из остатка кода (с ними надо разобраться по-подробнее)
не надо сортировать повторно после замен srcdir, потому что исходный код тоже этого не делает.
в исходном коде сортировка есть только при создании директорий
Проверка на то, с багой sed или без, должна выполняться на стадии configure (хотя вообще сомнительно, что она нужна в наше время)
Возможность вычисления значения переменной склеиванием
https://www.gnu.org/software/make/manual/make.html#Appending
For the append operator, ‘+=’, the right-hand side is considered
immediate if the variable was previously set as a simple variable
(‘:=’ or ‘::=’), and deferred otherwise.
For the shell assignment operator, ‘!=’, the right-hand side is evaluated immediately and handed to the shell.
The result is stored in the variable named on the left, and that variable becomes a simple variable (and will thus be re-evaluated on each reference).
Перенос подготовки списка из bash в gmake
переменные gmake можно пересчитать в другие перемнные вызовом newvar=$(shell echo $(oldvar) | sed ... )
$(shell сама возвращает содержимое stdout (при этом, правда, не проверяются ошибки, а значит и не обрабатываются)
список директорий надо подготавливать средствами gmake
это замедлит работу, потому что на каждый файл надо будет запустить bash и sed (будем надеятся, что исполняемые файлы будут запускаться из кеша диска и это будет быстро)
По причине замедления, такое решение нужно применять не во всех местах, а по мере необходимости.
То есть надо вставялять в autotools проверку на длину переменной
но сделать это будет непросто (в том смысле, что надо будет слова вызывать шелл с какой-нибудь командой вычисления длины),
так как сам makefile не имеет средств для подсчёта длины строки
https://www.gnu.org/software/make/manual/html_node/Text-Functions.html
Вариант вычисления переменной в foreach
srcdirstrip:=$(shell echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`);
topsrcdirstrip:=$(shell echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`);
SUBSTITUTED_DISTFILES:='';
^@
distdir: $(DISTFILES)
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in ${SUBSTITUTED_DISTFILES}; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done