与 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
。这似乎是“为什么会这样”的答案,因此我真的不需要知道第二个问题的答案,无论如何都在第一条评论中回答)。
- 为什么会这样? make 是如何 运行 使用我显然可以在 shell 脚本中 运行 的命令进入此错误的?
- 如果无法将我的命令 运行 作为一系列较短命令的迭代,我该如何解决这个问题?
关于我的系统的各种可能相关的详细信息:
- 我正在 运行安装一个相当新的 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
ulimit -s
输出:8192(我尝试将其设置为更大的值,例如 ulimit -s 65536
但没有成功,这可能并不令人惊讶,因为 ARG_MAX 看起来很多大于 linker 命令)。
- GNU Make 版本为 4.3
- clang/clang++版本为10.0.1
- Qt 版本是 5.15.1(我很确定这不相关,我们刚刚将我们的项目从 5.9.6 切换过来,那时我也遇到了同样的问题)。
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 所建议的,可以使用 gcc
或 ld
的 @arglist
参数(指示它从文件中获取参数),并使用 file
GNU make 创建 arglist
文件的功能,该文件是 make 的内部文件,不会 运行 进入任何 OS 限制。
仅供参考,删除 echo
解决问题的原因(这也是我要建议的)是当您删除特殊的 shell 运算符时 &&
并且只有一个简单的命令调用,没有 shell 功能,如多命令、特殊引用、通配等。然后 make 使用“快速路径”来调用你的命令。
也就是说,如果 make 可以确定 shell 除了 运行 之外不会对您的命令执行任何特殊操作,make 将跳过调用 shell 而是 运行 直接你的命令。
在那种情况下,您将不会 运行 违反 single-argument 限制,因为它不使用 /bin/sh -c '...'
形式。
当然,这可能有点神奇且不灵活,因为您必须小心确保 link 行中不包含任何特殊的 shell 操作。但是,如果你能确保这一点,那么它应该可以解决你的问题。
我有一个相当大的项目(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
。这似乎是“为什么会这样”的答案,因此我真的不需要知道第二个问题的答案,无论如何都在第一条评论中回答)。
- 为什么会这样? make 是如何 运行 使用我显然可以在 shell 脚本中 运行 的命令进入此错误的?
- 如果无法将我的命令 运行 作为一系列较短命令的迭代,我该如何解决这个问题?
关于我的系统的各种可能相关的详细信息:
- 我正在 运行安装一个相当新的 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
ulimit -s
输出:8192(我尝试将其设置为更大的值,例如ulimit -s 65536
但没有成功,这可能并不令人惊讶,因为 ARG_MAX 看起来很多大于 linker 命令)。- GNU Make 版本为 4.3
- clang/clang++版本为10.0.1
- Qt 版本是 5.15.1(我很确定这不相关,我们刚刚将我们的项目从 5.9.6 切换过来,那时我也遇到了同样的问题)。
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 所建议的,可以使用 gcc
或 ld
的 @arglist
参数(指示它从文件中获取参数),并使用 file
GNU make 创建 arglist
文件的功能,该文件是 make 的内部文件,不会 运行 进入任何 OS 限制。
仅供参考,删除 echo
解决问题的原因(这也是我要建议的)是当您删除特殊的 shell 运算符时 &&
并且只有一个简单的命令调用,没有 shell 功能,如多命令、特殊引用、通配等。然后 make 使用“快速路径”来调用你的命令。
也就是说,如果 make 可以确定 shell 除了 运行 之外不会对您的命令执行任何特殊操作,make 将跳过调用 shell 而是 运行 直接你的命令。
在那种情况下,您将不会 运行 违反 single-argument 限制,因为它不使用 /bin/sh -c '...'
形式。
当然,这可能有点神奇且不灵活,因为您必须小心确保 link 行中不包含任何特殊的 shell 操作。但是,如果你能确保这一点,那么它应该可以解决你的问题。