GNU Make 3.80 eval 错误的解决方法

发布于 2024-08-24 10:03:41 字数 1081 浏览 7 评论 0原文

我正在尝试为我的 Makefile 创建一个通用构建模板,有点像他们在 评估文档

我在 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.

预期的输出是 ./src/test/ 中的所有 .c 文件都被编译成 .o 文件(通过隐式规则)。

问题是 $$($(1)_SRC_FILES) 和 $$($(1)_OBJ_FILES) 总共超过 193 个字符长(如果有足够的源文件)。

我尝试在只有 2 个 .c 文件的目录上运行 make 文件,并且工作正常。只有当 SRC 目录中有很多 .c 文件时,我才会收到错误。

我知道 GNU Make 3.81 修复了这个错误。不幸的是,我没有权限或能力在我正在使用的系统上安装较新的版本。我坚持3.80。

那么,有什么解决方法吗?也许将 $$($(1)_SRC_FILES) 分开并在 eval 中单独声明每个依赖项?

I'm trying to create a generic build template for my Makefiles, kind of like they discuss in the eval documentation.

I've run into a known bug with GNU Make 3.80. When $(eval) evaluates a line that is over 193 characters, Make crashes with a "Virtual Memory Exhausted" error.

The code I have that causes the issue looks like this.

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)))

When I run this Makefile, I get

gmake: *** virtual memory exhausted.  Stop.

The expected output is that all .c files in ./src/test/ get compiled into .o files (via an implicit rule).

The problem is that $$($(1)_SRC_FILES) and $$($(1)_OBJ_FILES) are together over 193 characters long (if there are enough source files).

I have tried running the make file on a directory where there is only 2 .c files, and it works fine. It's only when there are many .c files in the SRC directory that I get the error.

I know that GNU Make 3.81 fixes this bug. Unfortunately I do not have the authority or ability to install the newer version on the system I'm working on. I'm stuck with 3.80.

So, is there some workaround? Maybe split $$($(1)_SRC_FILES) up and declare each dependency individually within the eval?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

对岸观火 2024-08-31 10:03:41

哈哈 hacks

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,即使它只是在本地。

lol hacks

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

Seriously though, there can't possibly be anything preventing you from installing 3.81, even if it is only locally.

愿与i 2024-08-31 10:03:41

也许没有人再需要这个了,但我想巧妙地使用 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 :=

当然,这有点难看(使用全局变量来传递参数)从技术上讲是宏)。我更喜欢第一个答案......:-)

Perhaps nobody needs this any more, but I guess clever use of include could overcome this kind of limitation.

Replace define PROGRAM_template with something like:

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

Create PROGRAM_template.mk to implement the core of the template macro:

$(__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 :=

Of course, this is a bit ugly (use of global variable to pass argument to what technically is a macro). I like the first answer better... :-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文