首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用GNU链接时,参数列表过长

问使用GNU链接时,参数列表过长
EN

Stack Overflow用户
提问于 2020-10-05 01:46:15
回答 2查看 3K关注 0票数 4

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

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

make: /bin/sh: Argument list too long

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

代码语言:javascript
复制
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)

它扩展到类似于:

代码语言:javascript
复制
@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),那么它可以工作:

代码语言:javascript
复制
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 )。这似乎是“为什么会发生这种情况”的答案,因此,我不需要知道第二个问题的答案,在任何情况下,第一个问题的答案都是这样的)。

  1. 为什么会发生这种事?如果一个命令显然可以在shell脚本中运行,那么它是如何运行到这个错误的呢?
  2. ,如果无法将我的命令作为一系列较短的命令来运行,那么如何绕过它呢?

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

我正在运行一个最新的Arch系统,内核5.8.10

  • ARG_MAX值为2097152,xargs --show-limits的输出为:

。

代码语言:javascript
复制
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似乎比链接器command).
  • GNU Make版本是10.0.1大得多,
  • Qt版本为5.15.1 (我相当肯定这与此无关,我们刚刚将项目从5.9.6转移到了同样的问题)。
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-10-05 04:59:33

只是FYI,删除echo的原因是修复了这个问题(这也是我的建议),因为当您删除特殊的shell操作符&&,并且只有一个简单的命令调用,没有shell特性,比如多个命令、特殊的引用、全球化等等,然后使用“快速路径”调用命令。

也就是说,如果make可以确定shell除了运行命令没有什么特别之处,make将跳过调用shell,而直接运行命令。

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

当然,这可能有点神奇和不灵活,因为您必须小心,以确保没有特殊的shell操作包括在您的链接线。但如果你能确保这一点,那么它就能解决你的问题。

票数 4
EN

Stack Overflow用户

发布于 2020-10-05 04:03:30

为什么会发生这种事?make是如何使用我显然可以在shell脚本中运行的命令来运行这个错误的?

因为make是通过将shell命令作为单个参数传递给/bin/sh -c来运行的,这不仅会遇到操作系统对命令行参数+环境变量的限制,而且还会影响到Linux在命令行或环境中对单个字符串施加的低得多的限制(通常为128 k字节)。

如果没有办法将我的命令作为一系列较短的迭代命令运行,那么

如何解决这个问题呢?

正如@ephemient所建议的那样,可以使用gcc或ld的gcc参数或ld参数(指示它从文件中获取参数),并使用GNU的file函数创建要创建的arglist文件,该文件是要创建的,不会遇到任何操作系统限制。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64201512

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档