Makefile - список аргументов слишком длинный, но только в некоторых конфигурациях - PullRequest
0 голосов
/ 06 июня 2018

Я пытаюсь воспроизвести ситуацию, которая происходит только на некоторых машинах.Чтобы воспроизвести его, я создаю каталог с 2000 файлами:

mkdir /tmp/test
cd /tmp/test
for f in $(seq 1 2000); do touch $f.txt; done

Затем я использую следующий Makefile (упрощенный из реального варианта использования):

FILES:=$(shell find . -name '*.txt')

%.done: %.txt
    @echo "done $@"

toolong:
    @$(foreach file,$(sort $(FILES)), \
        if $(MAKE) $(file); \
        then echo "did $(file)" >> $@; \
        else echo "failed $(file)" >> $@; fi; )

Запуск make производитНеудивительно, что ошибка:

make: execvp: /bin/sh: Argument list too long

Этот вопрос представляет решение, которое работает.Однако мне нужно точно понять, почему эта ошибка не возникает на компьютерах моих коллег.Я пробовал следующие вещи:

  • Увеличение предела стека (ulimit -s дает одинаковый результат на обеих машинах, 8192, и увеличение его ничего не меняет);
  • Проверка getconf ARG_MAX (2097152 на обеих машинах);
  • Проверка MAX_ARG_STRLEN (131072 на обеих машинах);
  • Использование другой оболочки (zsh используется на обеих машинах; я также пытался bash, dash и sh, через export SHELL=<shell> make, а также путем замены символической ссылки /bin/sh -> /bin/bash ссылкой на dash).

Наконец, я попытался перекомпилировать Make изисточник, и понял, что даже когда я компилирую ту же версию Make (4.1) в моей тестовой машине Ubuntu, я получаю то же поведение, что и в своей Fedora, то есть ошибка «список аргументов слишком длинный».

make --version показывает только одну разницу между ними:

Версия из пакета apt:

GNU Make 4.1 Создано для x86_64- pc -linux-gnu

Версия, скомпилированная из исходного кода (./configure && make):

GNU Make 4.1 Создано для x86_64- неизвестно -linux-gnu

Я даже пытался скомпилировать make-dfsg , что приводит к идентичным make --version, но результат такой же, как и с моей другой скомпилированной вручную сборкой.

Увеличив количество файлов в Ubuntu, мне удалось определить, что фактические ограничения в размере сгенерированной командыследующие строки:

  • Fedora или Arch Linux (оба с Make 4.2.1) или Ubuntu с вручную скомпилированным Make 4.1: 128 КБ (~ 1200 файлов);
  • Debian Sidили Ubuntu, оба с Make 4.1, установленным из пакета apt: 2 МБ (~ 19300 файлов).

Мне бы очень хотелось понять (1), почему существует это различие, и (2)как я могу скомпилировать Make для получения более высокого предела, чтобы у меня было одинаковое поведение на обеих машинах.

1 Ответ

0 голосов
/ 06 июня 2018

Ваш рецепт расширяется как составная команда оболочки из одной строки (из-за обратной косой черты в конце строки).И эта линия, вероятно, слишком длинная.Вы проверяли, как это выглядит (составная команда оболочки) на всех машинах?Я предлагаю вам обернуть его в $(info...):

toolong:
    @$(info $(foreach file,$(sort $(FILES)), \
        if $(MAKE) $(file); \
        then echo "did $(file)" >> $@; \
        else echo "failed $(file)" >> $@; fi; ))

и посмотреть, совпадает ли вывод на вашем компьютере и на других.Если по какой-то причине у вас больше, это может быть объяснением.В противном случае это должно быть отличие ОС ...

Примечание: у вас может быть одно правило на цель, а не одно правило с огромным рецептом для всех.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...