Обходной путь для GNU Make 3.80 eval bug - PullRequest
4 голосов
/ 11 марта 2010

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

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

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

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?

Ответы [ 2 ]

5 голосов
/ 12 марта 2010

LOL хаки

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, даже если это только локально.

3 голосов
/ 08 августа 2012

Возможно, это больше никому не нужно, но, думаю, разумное использование 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 :=

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

...