我有一个相当大的项目(4272个.o文件),我无法让它链接到GNU。我遇到了make: /bin/sh: Argument list too long。这是一个Qt 5项目,它使用qmake生成makefile。
我知道这方面有很多问题,但我不知道如何解决我的问题。我也不完全确定为什么我会在链接步骤中遇到这个问题。我得到的错误是:
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)它扩展到类似于:
@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脚本中时,它就运行了。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)不过,我不认为我能让qmake来做这件事,所以我只能手工编辑makefile,除非我能找到另一个解决方案。
类似问题的答案似乎集中在中断线以及如何在makefile中处理它们。我的shell脚本只有两行(一行在#!/bin/sh后面,一条在实际命令之后)。另外,人们想出的一个解决方案(例如,this one)使用for循环来迭代地运行每个参数的命令。我不知道如何在这里应用这一点,因为(我想)我需要链接器命令中的所有对象文件。
@echo如何导致最大参数长度被超过?
我最初问的问题并不是真正相关的:(注意:正如最初发布的一样,这个问题在链接命令的开头没有看到@echo )。这似乎是“为什么会发生这种情况”的答案,因此,我不需要知道第二个问题的答案,在任何情况下,第一个问题的答案都是这样的)。
有关我的系统的各种可能相关的详细信息:
我正在运行一个最新的Arch系统,内核5.8.10
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): 2147483647ulimit -s输出: 8192 (我尝试将其设置为更大的值,例如ulimit -s 65536,这一点也不奇怪,因为ARG_MAX似乎比链接器command).发布于 2020-10-05 04:59:33
只是FYI,删除echo的原因是修复了这个问题(这也是我的建议),因为当您删除特殊的shell操作符&&,并且只有一个简单的命令调用,没有shell特性,比如多个命令、特殊的引用、全球化等等,然后使用“快速路径”调用命令。
也就是说,如果make可以确定shell除了运行命令没有什么特别之处,make将跳过调用shell,而直接运行命令。
在这种情况下,您不会遇到单参数限制,因为它不使用/bin/sh -c '...'表单。
当然,这可能有点神奇和不灵活,因为您必须小心,以确保没有特殊的shell操作包括在您的链接线。但如果你能确保这一点,那么它就能解决你的问题。
发布于 2020-10-05 04:03:30
为什么会发生这种事?make是如何使用我显然可以在shell脚本中运行的命令来运行这个错误的?
因为make是通过将shell命令作为单个参数传递给/bin/sh -c来运行的,这不仅会遇到操作系统对命令行参数+环境变量的限制,而且还会影响到Linux在命令行或环境中对单个字符串施加的低得多的限制(通常为128 k字节)。
如果没有办法将我的命令作为一系列较短的迭代命令运行,那么
如何解决这个问题呢?
正如@ephemient所建议的那样,可以使用gcc或ld的gcc参数或ld参数(指示它从文件中获取参数),并使用GNU的file函数创建要创建的arglist文件,该文件是要创建的,不会遇到任何操作系统限制。
https://stackoverflow.com/questions/64201512
复制相似问题