使用Clang作为编译器 —— 使用 Clang 交叉编译

2023-10-27


本文为译文,点击 此处查看原文。

1. 介绍

本文档将指导您选择正确的 Clang 选项,以便将代码交叉编译到不同的体系结构。它假定您已经知道如何为主机体系结构编译相关代码,并且知道如何选择附加的include和库路径。
然而,这个文档不是一个“如何做”的文档,也不会帮助您设置build系统或Makefiles,也不会帮助您选择正确的 CMake 选项,等等。此外,它没有涵盖所有可能的选项,也没有包含特定架构的特定示例。对于一个具体的例子,交叉编译LLVM本身的说明可能会很有趣。
阅读本文之后,您应该熟悉与交叉编译相关的主要问题,以及 Clang 为执行交叉编译提供了哪些主要编译器选项。

2. 交叉编译问题(Cross compilation issues)

在 GCC 世界中,每个主机/目标(host/target)组合都有自己的一组二进制文件、头文件、库等。因此,通常很容易下载一个包含所有文件的包,解压缩到一个目录,然后将build系统指向该编译器,该编译器将知道其位置,并在编译代码时找到所需的所有内容。

另一方面,Clang/LLVM 本质上是一个交叉编译器,这意味着一组程序可以通过设置-target选项编译到所有目标。对于希望编译到不同平台和体系结构的程序员,对于只需要维护一个build系统的编译器开发人员,对于OS发布,只需要一组main包,这使得编译变得容易得多。

但是,与任何交叉编译器一样,考虑到不同体系结构、操作系统和选项的复杂性,要找到头文件、库或binutils来生成目标特定的代码并不总是那么容易。因此,您需要指定选项(options)来帮助 Clang 了解您要编译的目标、工具的位置等等。

另一个问题是编译器只附带标准库(如compiler-rtlibcxxlibgcclibm等),因此您必须找到并提供给构建系统,以及构建软件所需的每个特定于您的目标(target)的其他库。仅仅安装主机(host)的库是不够的。

最后,并不是所有的工具链(toolchains)都是相同的,因此,并不是每个 Clang 选项都能神奇地工作。有些选项,比如--sysroot(它可以有效地更改头文件和库的逻辑根),假设所有二进制文件和库都在同一个目录中,当发行版的包管理安装了交叉编译器时,这可能不是真的。因此,对于每个特定的情况,您可以使用多个选项,并且在大多数情况下,您最终将手动设置include paths (-I)library paths (-L)

综上所述,不同的工具链可能:

  • 特定于 host/target 或更灵活
  • 放在一个目录中,或者分散在整个系统中
  • 默认情况下有不同的库集和头文件集
  • 需要特殊的选项,这是您的构建系统无法自己解决的

3. Clang中的一般交叉编译选项(General Cross-Compilation Options in Clang)

3.1 Target Triple

基本选项是定义目标体系结构。为此,使用-target <triple>。如果不指定目标,CPU 名称将不匹配(因为 Clang 假设host triple),编译将继续进行,为主机平台创建代码,稍后在汇编或链接时代码将中断。

triple 的一般格式为<arch><sub>-<vendor>-<sys>-<abi>,其中:

  • arch = x86_64i386armthumbmips等。
  • sub = v5, v6m, v7a, v7m等。
  • vendor = pc, apple, nvidia, ibm,等。
  • sys = none, linux, win32, darwin, cuda等。
  • abi = eabi, gnu, android, macho, elf等。

当然,sub体系结构选项对于它们自己的体系结构是可用的,所以“x86v7a”没有意义。只有在发生相关更改时才需要指定vendor,例如在PC和Apple之间。大多数情况下,可以忽略它(并且未知),这将为指定的体系结构设置默认值。system名称通常是OS (linux, darwin),但也可以像裸金属“none”一样特殊。
当一个参数不重要时,可以省略它,或者您可以选择unknown并使用缺省值。如果您选择一个 Clang 不知道的参数,比如blerg,它将忽略并假设未知,这并不总是需要的,所以要小心。
最后,ABI选项将选择默认的CPU/FPU,定义代码的特定行为(pc、扩展),并选择正确的库调用,等等。

3.2 CPU、FPU、ABI

一旦指定了目标,就到了选择要编译到的硬件的时候了。对于每种体系结构,都会选择一组默认的CPU/FPU/ABI,因此您几乎总是必须通过flag更改它。
典型的flag包括:

  • -mcpu=<cpu-name>,如x86-64, swift, cortex-a15
    -mfpu=<fpu-name>,如SSE3, NEON,控制FP单元可用
  • -mfloat-abi=<fabi>,如控制浮点寄存器的软、硬件
    默认值通常是公分母,因此Clang不会生成中断的代码。但这也意味着您无法为特定的硬件获得最佳代码,这可能意味着速度比您预期的要慢几个数量级。

例如,如果您的目标是arm-none-eabi,那么默认的CPU将是使用软浮点数的arm7tdmi,这在现代内核上是非常慢的,而如果您的三元组是armv7a-none-eabi,那么它将是带NEON的Cortex-A8,但是仍然使用软浮点数,这要好得多,但是仍然不是很好。

3.3 工具链选项

控制对交叉编译器的访问有三个主要选项:-sysroot-I-L。最后两个是众所周知的,但是对于特定于目标的附加库和头文件来说,它们尤其重要。
有两种主要的方式获得一个交叉编译器:

  1. 当您将交叉编译器从zip文件解压缩到目录中时,必须使用--sysroot=<path>path是您解压缩文件的根目录,Clang 将查找其中包含的目录bin、lib。
    在这种情况下,您的设置应该已经基本完成(如果不需要额外的头文件或库),因为Clang将在其中找到它需要的所有二进制文件(汇编器、链接器等)。
  2. 当您通过包管理器安装(现代Linux发行版有交叉编译器包可用)时,请确保您设置的目标triple也是交叉编译器工具链的前缀。
    在本例中,Clang 将找到其他二进制文件(汇编器、链接器),但并不总是在目标头文件和库所在的位置。人们经常在Clang 中添加特定于系统的线索,但是随着事情的变化,它很可能不会发现,而不是相反。
    因此,在这里,如果手动指定include/library目录(通过-I-L),将会安全得多。

4. 特定目标的库(Target-Specific Libraries)

作为构建的一部分编译的所有库都将被交叉编译到目标,构建系统可能会在正确的位置找到它们。但是,通常检查的所有依赖项(如libxmllibz等)都将与主机平台匹配,而不是与目标平台匹配。
因此,如果构建系统没有意识到您想交叉编译代码,那么它将错误地获得每个依赖项,并且编译将在构建期间失败,而不是在配置期间。

此外,查找目标的库并不像查找主机那么容易。大多数OS的包中没有多少跨库可用,所以您必须从源代码交叉编译它们,或者下载目标平台的包,提取库和头文件,将它们放在特定的目录中,并添加-I-L指向它们。

此外,一些库对不同的目标具有不同的依赖关系,因此,在主机中查找依赖关系的配置工具可能会将目标平台的列表弄错。这意味着在设置自己的库路径时,您的构建的配置可能会出错,您必须通过附加标志(configure、Make、CMake等)来扩充它。

5. Multilibs

当您希望交叉编译到多个配置时,例如hard-float-ARMsoft-float-ARM,您必须拥有库的多个副本和(可能的)头文件。

有些Linux发行版支持Multilib,用一种更简单的方式为你处理,但是如果你不小心,例如,忘记指定-ccc-gcc-name armv7l-linux-gnueabihf-gcc(使用hard-float),Clang将选择armv7l-linux-gnueabi-ld(使用soft-float),并且将会发生链接器错误。

如果您正在为不同的ABIs(如gnueabiandroideabi)编译,甚至可能链接并运行,但会产生运行时错误,这将更加难以跟踪和修复,那么情况也是一样的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用Clang作为编译器 —— 使用 Clang 交叉编译 的相关文章

随机推荐

  • 卷积神经网络的实际应用,卷积神经网络毕业论文

    旷视首席科学家 知名AI学者孙剑博士去世 他在该领域有哪些贡献 旷视首席科学家 知名AI学者孙剑博士去世 他在该领域有哪些贡献 在学术层面 孙老师是计算机视觉领域全世界最知名 最顶级的一批科学家 他的工作ResNet 12w citatio
  • 西安华为OD面试经验(德科)

    背景 本科某双非邮电软件专业 二战冲985失败 随便写的简历挂boss上 hr电话联系帮我约的机考 华为od网络风评很差 这一点还是hr告诉我这个初入社会的学生党的 态度挺诚恳 我也只是本着随便试试的态度去的 机考是5 7号 技术一面是5
  • SSC 扩频时钟技术(1)

    SSC 全称Spread Spectrum Clocking 即扩频时钟 由于信号的辐射主要是由于信号的能量过于集中在其载波频率位置 导致信号的能量在某一频点位置处的产生过大的辐射发射 因此为了进一步有效的降低EMI辐射 芯片厂家在设计芯片
  • 通过 window.opener.document 获取弹窗弹窗或打开页面中的数据并回显

    通过 window opener document 获取弹窗弹窗或打开页面中的数据并回显 1 html 示例 写法 td td
  • tcp客户/服务器回射程序之五-----用shutdown函数解决在批量方式下所引起的问题

    tcp客户 服务器回射程序之五 用shutdown函数解决在批量方式下所引起的问题 当我们把标准输出和标准输入重定向到文件来运行新的客户程序时 却发现输出文件总是小于输入文件 而对于回射服务器而言 它们应该相等 问题的起因在于我们对于EOF
  • python十个实战项目

    python项目练习一 即时标记 python项目练习二 画幅好画 python项目练习三 万能的XML python项目练习四 新闻聚合 python项目练习五 虚拟茶话会 python项目练习六 使用CGI进行远程编辑 python项目
  • 目标检测算法之YOLOv2损失函数详解

    前言 前面的YOLOv2推文详细讲解了YOLOv2的算法原理 但官方论文没有像YOLOv1那样提供YOLOv2的损失函数 难怪Ng说YOLO是目标检测中最难懂的算法 今天我们尝试结合DarkNet的源码来分析YOLOv2的损失函数 关键点回
  • 终于辞职了,全职ue了

    终于辞职了 然后 这几天睡得特别香 拿到了ue的offer 两万五 从年前开始 其实本来不想辞职 毕竟还是疫情 工作不好找 一年半简历也不好看 但是最终还是走了这一步 外因 1 全员降薪到80 士气打击的厉害 我觉得是不是自己飘了 以自己的
  • 搭建harbor私有镜像仓库

    一 环境准备 1 关闭防火墙 systemctl stop firewalld 禁止防火墙开机自起 systemctl disable firewalld 2 关闭selinux 永久关闭 sed i s enforcing disable
  • 简述Java中的基本数据类型

    本文主要向大家介绍一下Java中的8种基本数据类型 以及数据类型之间的转换 希望对大家学习Java语言有所帮助 一 数据类型的分类 一 基本数据类型 8种 注意 在Java中 所有数据类型都有默认值 定义之后没有赋值 就会有默认值 且默认值
  • 计算机心理活动,计算机科学系关于心理活动的总结

    计算机科学系关于心理活动总结 一 活动概况 时间 10月22 23 25 29 30日 11月5 6 12日 地点 新区湖畔绿地或老区西操场 人员 商丘师院10级新生以及各系心理委员组长 二 活动目的 1 通过游戏等活动的形式带给同学们人生
  • matlab中的符号表达式的使用

    定义了一个表达式 如 y sin x 如何让matlab知道x是自变量 y是因变量 并且y x0 这种格式合法 求出x x0时候的值 三种方法 1 用inline函数 格式 FunctionName inline 任何有效的表达式 表达式中
  • ITextRenderer 生成PDF 文件

    pom xml 文件添加相关依赖
  • django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.13 or newer is required 简单的解决办法

    在Django的工程同名子目录的 init py文件中有如下语句 import pymysql pymysql install as MySQLdb 使用django2或者django3时遇到这个报错 django core excepti
  • LeetCode每日刷题:存在重复的元素II

    题目 给定一个整数数组和一个整数 k 判断数组中是否存在两个不同的索引 i 和 j 使得 nums i nums j 并且 i 和 j 的差的 绝对值 至多为 k 解题思路 这道题有三种解法 暴力 滑动窗口 Set 暴力解法 循环遍历数组
  • wifi密码本 字典(免费)

    需要自取 链接 https pan baidu com s 1ffGwfcvoqkrIgDIOeC3 IA 提取码 ao1i 破解fiwi密码教程 破解wifi密码 暴力破解 保姆式教学 Z Xshan的博客 CSDN博客 如果提取码失效试
  • push 和 pop 函数的使用

    include
  • PySOT单目标跟踪训练、测试、验证全流程(全网最详细,持续更新,建议收藏!)

    目录 数据集准备 数据集介绍 数据集下载解压 代码部署 训练 修改配置文件 开始训练 数据集准备 数据集介绍 PySOT支持多种数据集混合训练 其中包括以下四种数据集 VIDhttp image net org challenges LSV
  • linux安装zabbix,添加监测客户机

    一 linux系统配置 1 临时关闭seLinux setenforce 0 2 永久关闭selinux 需编辑配置文件 etc selinux config 设置SELINUX disabled 重启系统后生效 vi etc selinu
  • 使用Clang作为编译器 —— 使用 Clang 交叉编译

    使用 Clang 交叉编译 1 介绍 2 交叉编译问题 Cross compilation issues 3 Clang中的一般交叉编译选项 General Cross Compilation Options in Clang 3 1 Ta