与 GNU Make 链接时参数列表太长

rai*_*lin 5 linux makefile gnu-make clang++

我有一个相当大的项目(4272 .o 文件),但无法将其与 GNU Make 链接。我遇到了make: /bin/sh: Argument list too long。这是一个使用 qmake 生成 makefile 的 Qt 5 项目。

我知道有很多关于此的问题,但我不知道如何将任何解决方案应用于我的问题。我也不完全确定为什么我在链接步骤中遇到这个问题。我得到的错误是:

make: /bin/sh: Argument list too long

用于链接我的项目的 makefile 条目如下所示:

build/debug/my_target/my_target:  $(OBJECTS)  
    @test -d build/debug/my_target/ || mkdir -p build/debug/my_target/
    $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS)
Run Code Online (Sandbox Code Playgroud)

它扩展到类似:

@echo linking /build/debug/my_target/my_target && clang++ -ccc-gcc-name g++ -lc++ -L/path/to/licensing/lib -Wl,-rpath,/path/to/qt/lib -Wl,-rpath-link,/path/to/qt/lib -o build/debug/my_target/my_target build/debug/my_target/obj/object1.o build/debug/my_target/obj/object2.o ... build/debug/my_target/obj/object4272.o  ... [ a bunch of moc_X.o ] ... [ a bunch of libs ] -lGL -lpthread -no-pie
Run Code Online (Sandbox Code Playgroud)

这很长。但奇怪的是:当我将 后的扩展命令@echo linking build/debug/my_target/my_target &&放入 shell 脚本中时,它就会运行。shell 脚本有 202,420 个字符(包括行#!/bin/sh)。另外,如果我去掉@echo ... &&命令的一部分,我可以运行make并链接工作。

另一个解决方法:如果我手动编辑我的 makefile,以便链接命令包含build/debug/my_target/*.o而不是$(OBJECTS)它起作用:

build/debug/my_target/my_target:  $(OBJECTS)  
    @test -d build/debug/my_target/ || mkdir -p build/debug/my_target/
    $(LINK) $(LFLAGS) -o $(TARGET) build/debug/my_target/*.o $(OBJCOMP) $(LIBS)
Run Code Online (Sandbox Code Playgroud)

不过,我不认为我可以让 qmake 来做到这一点,所以我只能手动编辑我的 makefile,除非我能找到另一个解决方案。

类似问题的答案似乎集中在换行符以及它们在 makefile 中的处理方式。我的 shell 脚本只有两行(一行在#!/bin/sh实际命令之后,另一行在实际命令之后)。此外,人们提出的一种解决方案(例如这个)使用 for 循环对每个参数迭代运行命令。我不确定如何在这里应用它,因为(我认为)我需要链接器命令中的所有这些对象文件。

如何@echo导致超出最大参数长度?

我最初问的问题并不真正相关:( 注意:正如最初发布的那样,这个问题错过了@echo链接命令开头的问题。这似乎是“为什么会发生这种情况”的答案,因此我真的不知道需要知道第二个问题的答案,无论如何,该答案在第一条评论中得到了回答)。

  1. 为什么会发生这种情况?我显然可以在 shell 脚本中运行的命令为什么 make 会遇到此错误?
  2. 如果无法将我的命令作为一系列较短命令的迭代运行,我该如何解决这个问题?

有关我的系统的各种可能相关的详细信息:

  • 我正在运行一个相当最新的 Arch Linux 系统,内核 5.8.10
  • ARG_MAX 值为 2097152,输出xargs --show-limits为:
Your environment variables take up 2343 bytes
POSIX upper limit on argument length (this system): 2092761
POSIX smallest allowable upper limit on argument length (all systems): 4096
Maximum length of command we could actually use: 2090418
Size of command buffer we are actually using: 131072
Maximum parallelism (--max-procs must be no greater): 2147483647
Run Code Online (Sandbox Code Playgroud)
  • ulimit -s输出:8192(我尝试将其设置为更大的值,例如ulimit -s 65536没有成功,这可能并不奇怪,因为 ARG_MAX 似乎比链接器命令大得多)。
  • GNU Make 版本是 4.3
  • clang/clang++ 版本是 10.0.1
  • Qt 版本是 5.15.1(我相当确定这不相关,我们刚刚将项目从 5.9.6 切换过来,当时我也遇到了同样的问题)。

Mad*_*ist 5

仅供参考,删除修复问题的原因echo(这也是我要建议的)是,当您删除特殊的 shell 操作符&&并且只有一个简单的命令调用,没有 shell 功能(如多个命令、特殊引用、通配符)时等,然后 make 使用“快速路径”来调用您的命令。

也就是说,如果 make 可以确定 shell 除了运行它之外不会对您的命令执行任何特殊操作,那么 make 将跳过调用 shell 并直接运行您的命令。

在这种情况下,您不会遇到单参数限制,因为它不使用该/bin/sh -c '...'形式。

当然,这可能有点神奇且不灵活,因为您必须小心确保链接行中不包含任何特殊的 shell 操作。但如果你能确保这一点,那么它应该可以解决你的问题。