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

Argument list too long when linking with GNU Make

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

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

make: /bin/sh: Argument list too long

link我的项目的 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)

扩展为:

@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

这很长。但这就是它变得奇怪的地方:当我将 @echo linking build/debug/my_target/my_target && 之后的扩展命令放入 shell 脚本时,它 运行s。 shell 脚本有 202,420 个字符(包括 #!/bin/sh 行)。此外,如果我摆脱命令的 @echo ... && 部分,我可以 运行 make 和 linking 工作。

另一种解决方法:如果我手动编辑我的 makefile 以便 linking 命令包含 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)

不过,我认为我无法让 qmake 执行此操作,所以我只能手动编辑我的 makefile,除非我能找到其他解决方案。

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

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

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

  1. 为什么会这样? make 是如何 运行 使用我显然可以在 shell 脚本中 运行 的命令进入此错误的?
  2. 如果无法将我的命令 运行 作为一系列较短命令的迭代,我该如何解决这个问题?

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

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

Why is this happening? How is it that make is running into this error with a command that I can apparently run in a shell script?

因为 make 正在 运行 将 shell 命令(配方)作为单个参数传递给 /bin/sh -c,并且不仅 运行 OS 对命令行参数 + 环境变量的限制,而且 比 Linux 强加给 单个 的限制低得多 =25=]来自命令行或环境的字符串,通常为128k字节。

How can I get around this if there's no way to run my command as an iterative series of shorter commands?

正如@ephemient 所建议的,可以使用 gccld@arglist 参数(指示它从文件中获取参数),并使用 file GNU make 创建 arglist 文件的功能,该文件是 make 的内部文件,不会 运行 进入任何 OS 限制。

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

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

在那种情况下,您将不会 运行 违反 single-argument 限制,因为它不使用 /bin/sh -c '...' 形式。

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