【发布时间】:2021-08-09 23:02:23
【问题描述】:
GNU make 正在生成错误,其根本原因是我无法理解的。
一些简要背景:该项目是一个嵌入式固件。我们在 Windows 主机上进行交叉编译。该构建实际上在 cygwin 环境中运行。我一直在构建该项目一段时间,没有任何问题。这是一个关键点。该项目正在构建中,我没有对项目源或 Makefile 进行任何更改。
几天前我在我的cygwin环境中安装了python3。自从我运行 Cygwin 安装程序以来已经有一段时间了,安装程序建议我更新十几个其他软件包。我不假思索地接受了更新建议。我没有捕获软件包列表或旧版本。我的意思是,会出什么问题?
出了问题:下次我构建这个项目时,make 失败了。这个错误是神秘的,根本原因是我无法理解的。我将 GNU make 从 4.3-1(新版本)降级回 4.2.1-2,但项目仍然无法正常构建。
这是错误:
$ make -j8
compile message for file1.c
compile message for file2.c
...
compile message for fileN.c
make: *** [../../build/rules.mak:407: ../obj/fileN.o] Error 127
错误 127 未在文档中列出:https://www.gnu.org/software/make/manual/html_node/Error-Messages.html
搜索错误 127,我在 SO:Make Error 127 when running trying to compile code 上发现了这个问题。从表面上看,问题看起来很相似,答案帮助我深入研究了问题。该答案中确定的根本原因是执行了与主机架构不匹配的命令。但是 (1) 我不认为根本原因是相同的 - 请参阅下面的详细信息,并且 (2) 如果根本原因相同,则建议的解决方案都不是该项目的可行选项。
这就是为什么我说根本原因难以捉摸:
-
如果我再次运行
make -j8,make 将毫无问题地构建 fileN.c,但稍后在文件 X 上失败。我可以重复此过程几次,直到一切都构建好,但这不是一个有效的答案,对人类来说也不是或用于自动构建。 -
如果我运行
make clean然后重新开始,make 会因不同的文件而失败,例如文件 N 将构建成功,但在文件 M 或 P 上生成将失败。 -
如果我只使用一项作业运行
make -j1,则构建通常会成功且没有错误,但并非总是如此。 -
make 调用的行号——最初——是一个包含多个命令的 make 宏,因此不清楚哪个命令可能是问题所在。所以我在配方中添加了一些诊断:
which dos2unix、file -L dos2unix、dos2unix --version,诸如此类。现在,随着这些诊断的添加,当 make 失败时,它有时会在一行上使用像echo "dos2unix version:"这样的简单命令生成 127 错误。echo怎么会导致错误 127?为什么不执行前两次完全相同的 echo 命令?
我想提请注意最后一点,因为 make 根本没有提供任何有用的诊断信息。
很明显,错误不是执行与主机架构不匹配的命令。 Make 一遍又一遍地执行相同的命令而不会出错。
很明显,问题不在于任何特定的源文件,因为重新运行 make 会产生不同的成功/失败配置文件。
这是一个失败的配方示例。请记住,相同的配方在失败之前会成功数十次。而如果我make clean/make,在处理差异源文件的时候就会失败。
357 define GENERATE_DEPENDENCY
358 @dos2unix -q $(@:.o=.d)
359 @sed -e '/[a-zA-Z]:/ {' \
360 -e 's/\([a-zA-Z]\):[\\\/]/\/cygdrive\/\L\1\//g' \
361 -e 's/\(.\)\\\(.\)/\1\/\2/g' \
362 -e '}' < $(@:.o=.d) > $(@:.o=.dep)
363 @cp $(@:.o=.dep) $(@:.o=.dp2)
364 @sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
365 -e '/^$$/ d' -e 's/$$/ :/' < $(@:.o=.dp2) >> $(@:.o=.d)
366 @rm $(@:.o=.dp2)
367
368 endef
...
404 $(COBJS) : $(OBJOUTPUTDIR)/%.o : %.c $(EVERYTHING_DEPENDS_ON) | $(OBJOUTPUTDIR)
405 $(COMPILEHOOK)
406 $(CC) $(LISTINGFLAG)=$(@:.o=.lst) -c $(CPPINC) $(CPPFLAGS) -MD $(call fixpath,$<) -o $@
407 $(GENERATE_DEPENDENCY)
问题似乎根本不在项目中。我什至删除了该项目并提取了在我的 cygwin 升级之前正确构建的项目的新副本。但这并没有解决问题。
我希望我可以回到之前安装的 cygwin,但我没有备份。我什至不知道升级了哪些软件包。
是否有任何命令行选项可以告诉 make 打印更好的故障诊断信息,我将不胜感激。我尝试了“所有调试信息”选项:
$ make -j8 -d > make-output 2>&1
Make 生成了 4.8MB(86K 行)的输出并且构建成功。但这与建立一份工作一样慢,这是非常不可取的。使用make -d 也会使在实际构建问题发生时定位变得复杂。
或者,如果根本原因确实是架构不匹配,是否有某种方法可以让 make 识别错误发生时它试图执行的命令?就目前而言,我不知道哪个命令可能导致问题,或者问题是否确实是架构不匹配。
【问题讨论】:
-
如果你正在运行
make -j8,你可以看到几个istance重叠的消息。错误可能不是来自echo。您在构建中使用什么工具?所有python3.x都将python分配给默认安装的最高python3.x。 sourceware.org/pipermail/cygwin-announce/2021-May/010038.html -
我为另一个项目安装了 python。 Python 不用于构建这个项目——python 安装只是 cygwin 升级的催化剂。我指向
echo的原因是因为make 指向echo。我添加了自己的诊断命令来隔离故障的根本原因。我还添加了 echo 命令来阐明诊断输出。就在那时,make 开始使用 echo 命令在行上报告“错误 127”。