Установите дерево каталога данных с большим количеством файлов, используя automake

У меня есть каталог данных, который я хотел бы automake для создания целей установки и удаления. По сути, я просто хочу скопировать этот каталог в каталог DATA. Обычно я могу перечислить все файлы по отдельности, например

dist_whatever_DATA=dir/subdir/filea ...

Но проблема возникает, когда моя структура каталогов выглядит так:

*root
 *subdir
  *~10 files
 *subdir
  *~10 files
 *subdir
  *~700 files
 *subdir
 ...
 ~20 subdirs

Я просто не могу перечислить все 1000+ файлов, включенных как часть моего Makefile.am. Это было бы смешно.

Мне также нужно сохранить структуру каталогов. Я должен отметить, что эти данные вообще не генерируются процессом сборки и на самом деле являются в значительной степени короткими аудиозаписями. Поэтому мне не хотелось бы, чтобы automake "проверял", что каждый файл, который я хочу установить, фактически был создан, поскольку они либо есть, либо нет, и какой бы файл там ни был, я знаю, что хочу, чтобы он был установлен, и что бы ни было файла нет, его не следует устанавливать. Я знаю, что это оправдание, используемое в других местах, чтобы не делать подстановочные знаки, но все возможные причины здесь не применимы.

Ответы

Ответ 1

Я обнаружил, что установка сотен файлов по отдельности делает мучительно длинный вызов make install. У меня был аналогичный случай, когда я хотел установить сотни файлов, сохраняя структуру каталогов, и я не хотел менять свой Makefile.am каждый раз, когда файл был добавлен или удален из коллекции.

Я включил архив LZMA в файлы в моем дистрибутиве и сделал такие правила automake как:

GIANTARCHIVE = My_big_archive.tar.lz

dist_pkgdata_DATA = $(GIANTARCHIVE)

install-data-hook:
    cd $(DESTDIR)$(pkgdatadir); \
    cat $(GIANTARCHIVE) | unlzma | $(TAR) --list > uninstall_manifest.txt; \
    cat $(GIANTARCHIVE) | unlzma | $(TAR) --no-same-owner --extract; \
    rm --force $(GIANTARCHIVE); \
    cat uninstall_manifest.txt | sed --expression='s/^\|$$/"/g' | xargs chmod a=rX,u+w

uninstall-local:
    cd $(DESTDIR)$(pkgdatadir); \
    cat uninstall_manifest.txt | sed --expression='s/ /\\ /g' | xargs rm --force; \
    rm --force uninstall_manifest.txt

Таким образом, automake устанавливает My_big_archive.tar.lz в каталог $(pkgdata) и извлекает его там, составляя список всех файлов, которые были в нем, поэтому он может удалить их позже. Это также работает намного быстрее, чем перечисление каждого файла в качестве цели установки, даже если вы должны автогенерировать этот список.

Ответ 2

Я бы использовал script для генерации фрагмента Makefile, в котором перечислены все файлы:

echo 'subdir_files =' > subfiles.mk
find subdir -type f -print | sed 's/^/  /;$q;s/$/ \\/' >> subfiles.mk

а затем включите этот subfiles.mk из основного Makefile.am:

include $(srcdir)/subfiles.mk
nobase_dist_pkgdata_DATA = $(subdir_files)

Вторая опция - EXTRA_DIST = subdir, а затем для написания пользовательских правил install-data-local и uninstall-local.

Проблема заключается в том, что EXTRA_DIST = subdir будет распространять все файлы в subdir/, включая файлы резервных копий, файлы конфигурации (например, из вашего VCS) и другие вещи, которые вы не хотели бы распространять.

Используя script, как описано выше, вы можете фильтровать файлы, которые вы действительно хотите распространять.

Ответ 3

Я бы написал script (либо в виде отдельной оболочки script, либо в Makefile.am), которая запускается как часть install-data-hook.