Список аргументов слишком длинная ошибка с Makefile

  • Настройте виртуальную машину, чтобы разрешить удаленный доступ к дисплею (это нужно сделать только один раз, вы также можете использовать графический интерфейс):

VBoxManage modifyvm "GE Win7 "--vrde on

  • Используйте командную строку для запуска виртуальной машины в автономном режиме:

ssh server VBoxManage startvm" GE Win7 "--type headless

  • Запустите программу просмотра удаленного рабочего стола:

rdesktop server : 3389

Помните, что никакой брандмауэр не блокирует трафик rdp (порт TCP 3389).

1
09.11.2018, 22:55
4 ответа

Как уже объяснил @schily, это не проблема оболочки, и ее нельзя обойти с помощью xargs, цитирования, разделения на дополнительные эхо с помощью ;и т. д. Весь текст из действия make передается как аргумент/с в один execve(2), и он не может быть длиннее, чем максимальный размер, разрешенный операционной системой.

Если вы используете GNU, сделайте (по умолчанию в Linux ), вы можете использовать его функцииfileиforeach:

TEST = $(shell yes foobar | sed 200000q)

/tmp/junk:
        $(file >$@) $(foreach V,$(TEST),$(file >>$@,$V))
        @true

.PHONY: /tmp/junk

Это напечатает все слова из $(TEST), разделенные символами новой строки, в файл с именем $@. Он основан на аналогичном примере из руководства make .

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

Обновление:

Для точного фрагмента вопроса можно сделать что-то вроде этого:

.hgignore :.hgignore_extra
    $(info Making $@)
    $(file >$@.new)
    $(file >>$@.new,# Automatically generated by Make. Edit.hgignore_extra instead.)
    $(shell tail -n 2 $< >>$@.new)
    $(file >>$@.new,)
    $(file >>$@.new,# The following files come from the Makefile.)
    $(file >>$@.new,syntax: glob)
    $(foreach L, $(IGNORE_DIRS) $(CLEAN_FILES) $(CLEAN_DIRS) $(REALCLEAN_FILES), $(file >>$@.new,$L))
    @mv -f $@.new $@
    @chmod a-w $@
.PHONY :.hgignore

Я его немного изменил, поэтому он сначала пишет в .hgignore.new, и если все пойдет хорошо, то только потом перемещать .hgignore.newв .hgignore. Вам придется заменить отступы пробелами на табуляции, потому что этот тупой интерфейс искажает пробелы.

4
27.01.2020, 23:15

См. этот ответ , в частности эту цитату:

one argument must not be longer than MAX_ARG_STRLEN (131072). This might become relevant if you generate a long call like "sh -c 'generated with long arguments'".

С другой стороны, ограничение на общее количество передаваемых аргументов довольно велико, поэтому, может быть, вместо этого просто передавать их как отдельные аргументы, поскольку конечный результат echoбудет таким же?

Это просто удаляет "из исходной команды:

@echo $(IGNORE_DIRS) $(CLEAN_FILES) $(CLEAN_DIRS) $(REALCLEAN_FILES) | tr ' ' '\n' >> $@

Надеемся, что этого достаточно, чтобы удерживать аргументы в пределах количества аргументов (, которое довольно велико )и длины каждого аргумента (, что больше не будет проблемой, поскольку каждый аргумент теперь короткий.)


ОБНОВЛЕНИЕ:Удаление кавычек на самом деле не исправит это полностью, так как makeзапускает каждую команду в оболочке, используя эквивалент sh -c '...', где вся команда становится одним аргументом, поэтому она все равно будет привязан к предельной длине для отдельного аргумента, которая составляет 131 072 байта в Linux на платформе x86.

0
27.01.2020, 23:15

Ур -вопрос в таких случаях: зачем вы вообще это делаете? Похоже, вы пытаетесь создать какой-то файл.ignore, содержащий все файлы, которые предположительно являются либо выходными данными программы, либо глобусами. В первом случае я бы рекомендовал передавать вывод программы непосредственно в tr(, если это строго необходимо, ), а затем в файл без передачи через промежуточную переменную. Если вы используете globs, вы можете использовать очень простой циклfor:

for file in *
do
    echo "$file" >> out.txt
done

(Escape, если необходимо, в вашем Makefile.)

В самых общих чертах:

  • Используйте конвейеры и перенаправления, а не переменные для больших блоков данных. Они очень быстрые (, поскольку их можно обрабатывать так же быстро, как каждая программа в конвейере может обрабатывать ввод ).
  • Используйте xargs, когда это действительно необходимо.
  • Избегайте бесполезных echoс и catс .
0
27.01.2020, 23:15

В UNIX применяется следующее правило:

The following data forms the initial stack of a process:

  • The sum of strlen() of all environment strings + final nul character per string
  • The sum of strlen() of all argument strings + final nul character per string
  • The environment array: n+1 environment strings * sizeof char *
  • The argv array: n+1 argument strings * sizeof char *
  • A few additional numbers

Все эти данные не должны превышать ARG_MAX.

В предыдущей версии UNIX значение для ARG_MAXбыло 10240 или 20480 байт .

SunOS -4.0 (, опубликованная в декабре 1987 г. ), увеличила это ограничение до 1 МБ

Версия Solaris -7.0 (, опубликованная в 1997 году ), представила поддержку 64-разрядных систем и во избежание практически меньшего ограничения на 64-разрядные системы (, вызванного большими envи argvмассивами в качестве результат от большего char *), ARG_MAXбыл увеличен до 2 МБ для 64-битных программ.

Кстати, :Современные ОС, совместимые с POSIX, включают поддержку программы getconf, а getconf ARG_MAXпечатает фактическое значение. В 64-разрядной версии Linux это возвращает 2 МБ , поэтому на первый взгляд кажется, что Linux использует улучшения SunOS....

Теперь давайте посмотрим наmake:

Программа makeвызывает команды из Makefilesчерез:

sh -ce command

где command— это одиночный аргумент , то есть расширенная строка, которую вы видите в строке действия из Makefile.

SunPro Makeввел оптимизацию в начале 1990-х:

  • Если командная строка не содержит метасимволов оболочки, makeсам помечает командную строку и вызывает команду через :execv(), чтобы избежать накладных расходов на вызов оболочки.

Позднее gmakeи smakeприняли эту оптимизацию.

smakeпредставили еще одну оптимизацию в 2012 г.:

  • Если команда оболочки представлена ​​простой командой echo, которая заканчивается на ;, и если следующая командная строка не содержит метасимволов оболочки,echoвстроен в smake, а команда после ;выполняется через execv(), чтобы уменьшить накладные расходы для современных систем сборки, которые обычно используют @для подавления эха команды makeи вместо этого используют упрощенные вызовы echoдля облегчения понимания вывода make(см., например, система Schily Makefile, представленная в феврале 1993 года ).

Ни одно из этих makeправил не применяется к вашей makeкомандной строке, поскольку ваша командная строка содержит метасимволы оболочки. Итак, вся ваша команда вызывается через:

sh -ce command

, где command— это отдельная строка с общим размером, вызванным вашим make-файлом.

Теперь кажется, что ядро ​​Linux не совместимо ни с UNIX, ни с POSIX и налагает дополнительное ограничение, которого никогда не было в UNIX. Это дополнительное ограничение, по-видимому, основано на максимальной длине одной строки.

Если это действительно так, это дисквалифицирует Linux, так как не позволит использовать Linux в более крупных проектах, управляемых make.

Думали ли вы о том, чтобы сообщить об ошибке людям, занимающимся ядром Linux?

3
27.01.2020, 23:15

Теги

Похожие вопросы