我到处都有一堆 Raspberry Pi 系统,它们真是愚蠢的东西。他们在陌生的地方做愚蠢而烦人的工作。我什至还有一款较旧的型号,称为 B+。您可以将其视为“1B+”,但显然它从未被正式命名为 1。
如果您有其中之一,或者可能有一个原始的 Pi Zero,您可能会发现使用 clang 构建的 C++ 程序不再工作。当我开始尝试从我的“构建主机”(更快的 Pi 4B)获取二进制文件并在这个原始野兽上运行它们时,我就遇到了这个问题。它抛出非法指令。
这曾经在旧版本(牛眼)中工作。现在它打破了当前的状态(书虫)。我想,好吧,也许它正在做一些优化,因为它是基于 4B 构建的。因此,我在 B+ 上进行了原生构建。它也坏了。
因此,我将另一个级别退回到一个更简单的复制案例:只需声明 main() 并返回。那还是坏了。
查一下,有一堆奇怪的死胡同论坛帖子,人们来来回回地断言这个软件包已安装,这使得编译器变得愚蠢,或者是因为他们进行了“精简”安装与“推荐”安装安装,或者谁知道什么。
我想做的比这更好,所以今天下午我拿起一张全新的 SD 卡,将整个“桌面 + 推荐”操作系统映像放到上面,启动*那个*,然后安装 clang,然后……
raspberrypi:~/prog$ 猫 t.cc #include <stdio.h> int main() { 返回0; } raspberrypi:~/prog$ clang++ -Wall -ot t.cc 树莓派:~/prog$ ./t 非法指令
惊人的。它可以编译一些它甚至无法运行的东西。什么是不好的指令? gdb 会立即回答这个问题。
(gdb) 反汇编 函数 main 的汇编代码转储: 0x004005a4 <+0>:子 sp,sp,#4 => 0x004005a8 <+4>: movw r0, #0
movw。显然,这不在armv6l中。所以是的,默认情况下,这个编译器实际上是针对armv7(或其他东西)进行有效的交叉编译。那不是很有用。
您可以通过抓住编译器的翻领并说“为armv6构建,朋克”来解决这个问题,它会给您一个工作二进制文件:
raspberrypi:~/prog$ clang++ --target=armv6-unknown-linux-gnueabihf -Wall -ot t.cc 树莓派:~/prog$ ./t 树莓派:~/prog$
它是如何以及为何发展到这个地步的?我只能想象这是从版本 11 升级到版本 12 的一些默认设置,不知何故没有人注意到?我想没人还会在任何地方运行这些旧东西吗?
太奇怪了。