Обходной путь для ошибки GNU Make 3.80 eval

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

Я столкнулся с известной ошибкой в ​​GNU Make 3.80. Когда $(eval) оценивает строку, длина которой превышает 193 символа, Make аварийно завершает работу с ошибкой «Исчерпана виртуальная память».

Код, который у меня есть, который вызывает проблему, выглядит так.

SRC_DIR = ./src/

PROG_NAME = test

define PROGRAM_template
  $(1)_SRC_DIR = $$(SRC_DIR)$(1)/
  $(1)_SRC_FILES = $$(wildcard $$($(1)_SRC_DIR)*.c)
  $(1)_OBJ_FILES = $$($(1)_SRC_FILES):.c=.o)

  $$($(1)_OBJ_FILES) : $$($(1)_SRC_FILES) # This is the problem line
endef

$(eval $(call PROGRAM_template,$(PROG_NAME)))

Когда я запускаю этот Makefile, я получаю

gmake: *** virtual memory exhausted.  Stop.

Ожидаемый результат заключается в том, что все файлы .c в ./src/test/ будут скомпилированы в файлы .o (посредством неявного правила).

Проблема в том, что $$($(1)_SRC_FILES) и $$($(1)_OBJ_FILES) вместе имеют длину более 193 символов (если исходных файлов достаточно).

Я попытался запустить файл make в каталоге, где есть только 2 файла .c, и он отлично работает. Только когда в каталоге SRC много файлов .c, я получаю сообщение об ошибке.

Я знаю, что GNU Make 3.81 исправляет эту ошибку. К сожалению, у меня нет полномочий или возможности установить более новую версию в системе, над которой я работаю. Я остановился на 3.80.

Итак, есть ли обходной путь? Может быть, разделить $$($(1)_SRC_FILES) и объявить каждую зависимость отдельно в eval?


person bengineerd    schedule 11.03.2010    source источник
comment
я только что столкнулся с этой проблемой и с версией 3.81 (ubuntu 10.10)   -  person lurscher    schedule 03.12.2012
comment
Если у вас есть обходной путь для этого, мне интересно, как вы это сделали.   -  person searchengine27    schedule 23.03.2017
comment
Кроме того, у вас есть отчет об ошибке или идентификатор, чтобы я мог сослаться на него?   -  person searchengine27    schedule 23.03.2017


Ответы (2)


лол хаки

ifneq (3.81,$(shell (echo $(MAKE_VERSION); echo 3.81) | sort | head -n1))

make-3.81/make:
        wget -nc http://ftp.gnu.org/pub/gnu/make/make-3.81.tar.gz
        gzip -cd make-3.81.tar.gz | tar xvf -
        cd make-3.81 && ./configure --prefix=$$(pwd)
        $(MAKE) -C make-3.81 make

%: make-3.81/make
        make-3.81/make $@

else

# rest of your makefile

endif

А если серьезно, ничто не может помешать вам установить 3.81, даже если это только локально.

person ephemient    schedule 11.03.2010
comment
На самом деле компьютер не подключен к Интернету, поэтому ваш хак не сработает. Кроме того, установка любого программного обеспечения на машину противоречит политике моей компании. Даже локально. Я не говорю, что это имеет смысл, я просто говорю, что это правила. Я действительно не могу просто установить 3.81. - person bengineerd; 12.03.2010
comment
Включите новую версию в исходное дерево. - person Matt Joiner; 07.09.2010
comment
В дополнение к ответу bengineerd ... Более того, эта проблема не исправлена ​​​​в 3.82, поэтому хак абсолютно бесполезен для этой проблемы. - person Brian Vandenberg; 11.03.2013
comment
@PavelShved о чем ты говоришь? Это не столько ответ, сколько саркастическая насмешка. Это никоим образом не отвечает на вопрос. ОП уже знает, что его версия не решает проблему, и у него нет возможности обновиться, Брайант Вандерберг даже упомянул, что в 3.82 все еще есть проблема, и этот ответ не отвечает на вопрос ОП. Это означает минус. Вы должны проверить stackoverflow.com/help/how-to-answer, если вы действительно не знаете, что представляет собой хороший ответ или нет. - person searchengine27; 23.03.2017

Возможно, это больше никому не нужно, но я думаю, что разумное использование include может преодолеть такое ограничение.

Замените define PROGRAM_template чем-то вроде:

define PROGRAM_template
__template_arg := $(1)
include PROGRAM_template.mk
endef

Создайте PROGRAM_template.mk для реализации ядра макроса шаблона:

$(__template_arg)_SRC_DIR = $(SRC_DIR)$(__template_arg)/
$(__template_arg)_SRC_FILES = $(wildcard $($(__template_arg)_SRC_DIR)*.c)
$(__template_arg)_OBJ_FILES = $($(__template_arg)_SRC_FILES:.c=.o)

$($(__template_arg)_OBJ_FILES) : $($(__template_arg)_SRC_FILES)
__template_arg :=

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

person FooF    schedule 08.08.2012