网站建设招标要求,企业官网有哪些网站,登封郑州网站建设,设计网站建站OpenHarmony下musl编译工具链普法 引言
欠的债总是要还的#xff0c;这不前面欠的关于OpenHarmony下musl相关的还是要还的。这里我对其中的相关知识点#xff0c;梳理#xff0c;归纳重新消化下#xff01; 一.GCC/Clang/LLVM的区别与联系
说实话#xff0c;这块我现在都… OpenHarmony下musl编译工具链普法 引言
欠的债总是要还的这不前面欠的关于OpenHarmony下musl相关的还是要还的。这里我对其中的相关知识点梳理归纳重新消化下 一.GCC/Clang/LLVM的区别与联系
说实话这块我现在都木有搞清楚GCC/Clang/LLVM之间的区别与联系这里只能硬着头皮,捡一捡网上各路大神的总结先理解一波有个基本概念 先了解后面再深入吗先搞个普法对概念先有个基本的认识 1.1 GCC的简介
传统的编译器譬如gcc设计是分为三个部分如下图所示 前端 front end解析源码检查错误词法分析lexical analysis, 语法分析syntax analysis, 语义分析semantic analysis所以前端又称为分析阶段。并且构建一个特定于语言的抽象语法树Abstract Syntax TreeAST来代表输入的代码。 优化器optimizer 负责进行各种转换尝试改善代码的执行时间比如消除冗余计算。通常或多或少与语言及目标无关。 后端back end代码产生器将代码映射到目标指令集除了编写正确的代码外它还负责生成利用所支持体系结构的不寻常特性的良好代码。一个编译器后端的通用部分包含指令选择寄存器分配及指令调度instruction selection, register allocation, and instruction scheduling 1.2 GCC架构的优点
GCC架构的优点总结为如下几点:
使用通用的中间代码新增支持语言只需要新增一个前端新增支持目标机器只需要新增一个后端针对前后端开发人员技术栈不同开发人员只需要关注自身的技术栈有利于让更多人员参与进来
总结来说前端优化器后端的结构有三大好处灵活程度高组件复用率高维护成本低 1.3 GCC架构的缺点
GCC的三段式模块必须配套使用很难做到部分重用不能将 GCC 部分功能作为库重用的原因有很多包括滥用全局变量、不可变变量不能更改限制不严、设计不良的数据结构、庞大的代码库、以及使用宏来防止代码库一次编译可以支持多个编译前端-目标机对。不过最难解决的问题是其早期设计和那个时代所固有的架构设计。具体来说GCC 饱受分层问题和抽象漏洞的困扰编译后端遍历编译前端抽象语法树AST来生成调试信息debug info编译前端生成编译后端数据的结构整个编译器依赖命令行设置的全局数据结构。 上面的这些优缺点不是专业人士基本是体会不到相关差异的。我是木有体会到 1.4 LLVM介绍
LLVM是开源的编译器(compiler)架构以cpp编写而成用于优化以随意程序语言编写的程序的编译时间(compile-time)、链接时间(link-time)、执行时间(run-time)以及空暇时间(idle-time)对开发人员保持开放并兼容已有脚本。LLVM的设计就采用了上述前端优化器后端的设计。如下图所示 基于这个认知我们可以认为 LLVM 包括了两个概念一个广义的 LLVM 和一个狭义的 LLVM 。广义的 LLVM 指的是一个完整的 LLVM 编译器框架系统包括了前端、优化器、后端、众多的库函数以及很多的模块而狭义的 LLVM 则是聚焦于编译器后端功能的一系列模块和库包括代码优化、代码生成、JIT 等。
整体的编译器架构就是 LLVM 架构
Clang 大致可以对应到编译器的前端主要处理一些和具体机器无关的针对语言的分析操作编译器的优化器和后端部分就是之前提到的 LLVM 后端即狭义的 LLVM。
此外由于 LLVM 的命名最早源自于底层虚拟机Low Level Virtual Machine 的首字母缩写但这个项目的范围并不局限于创建一个虚拟机这个缩写导致了大量的疑惑。LLVM 成长之后已成为众多编译工具及低级工具技术的统称使得这个名字变得更不贴切所以开发者决定放弃这个缩写的涵义现在 LLVM 已独立成为一个品牌适用于 LLVM 下的所有项目包括 LLVM 中介码、LLVM 除错工具、LLVM cpp 标准库等。 1.5 clang介绍
Clang 是一个 C、cpp、Objective-C 和Objective-cpp编程语言的编译器前端采用底层虚拟机LLVM作为后端。
Clang 采用的是 BSD 协议的许可证而 GCC 采用的是 GPL 协议显然前者更为宽松Clang 是一个高度模块化开发的轻量级编译器编译速度快、占用内存小、有着友好的出错提示Clang项目包括Clang前端和Clang静态分析器等目的是输出代码对应的抽象语法树并将代码编译成LLVM bitcode接着后端使用LLVM编译成平台相关的机器语言 1.6 gcc和clang的交叉编译
gcc和clang都支持交叉编译链gcc这个就比较常见了像后面章节2.2所描述的就是gcc的一个交叉编译工具链clang通过–target基本选项是定义目标体系结构triple 的一般格式为sub---其中
arch x86_64、i386、arm、thumb、mips等。sub v5, v6m, v7a, v7m等。vendor pc, apple, nvidia, ibm,等。sys none, linux, win32, darwin, cuda等。abi eabi, gnu, android, macho, elf等。
譬如:
--targetarm-linux-gnueabihf并且通常一个大型的编译工程不会是上面这么直接裸写的一般会通过环境变量进行控制的。
export LINUX_ROOT$HOME/OH_V3.2_BETA2/code-v3.2-Beta2
export SYSROOT${LINUX_ROOT}/OpenHarmony/out/rk3568/obj/third_party/musl
export LLVM_BUILD_DIR${LINUX_ROOT}/llvm
export PATH${LINUX_ROOT}/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/bin:$PATH
export ARCHarm64
export CROSS_COMPILEaarch64-linux-ohos-
export HOSTCCclang
export BUILDdebug1.使用Clang作为编译器 —— 使用 Clang 交叉编译 2. 使用 Clang 交叉编译 3. How To Cross-Compile Clang/LLVM using Clang/LLVM 4. LLVM cross-compiled Linux From Scratch: C cpp libraries 1.7 小结
前面说了这么多其实我也还还不是很清楚先不管吗先把参考的链接放上
这里我对gccclang和llvm的理解可以用一句话来概括就是: gcc clang(前端) 狭义的llvm后端
1.经典编译器组成前端优化器后端以及LLVM和Clang简介 2.【编译原理】GCC/Clang/LLVM的区别与联系 3.请问LLVM与GCC之间的关系 4.GCC和clang/LLVM 5.详解三大编译器gcc、llvm 和 clang 二.musl你究竟是个啥
musl你是个啥还得从它的的出生发展历程出发一一道来。这里我们就从各个方面来捋一捋它musl 是基于 Linux 系统调用 API 之上实现的 C 语言标准库(libc)历史可以追溯到 2005 年但在 2011 年才正式确定了 MUSL 这个名称开始对标 glibc、uClibc从 2012 年开始musl 开始使用 MIT License。
musl 致力于简单、高效凭借 libc 优秀的松耦合性做到了静态版本最小10kB即使添加了线程等高级特性也可以控制到 50kB所以特别适合嵌入式设备。为了控制资源的使用 musl自己竟然不做动态内存分配。 2.1 glibc和musl-libc 这个我们分别来介绍下: glibc: glibc是GNU C Library 是GNU项目GNU Project所实现的 C语言标准库C standard library。 目前常见的桌面和服务器中的GNU/Linux类的系统中都是用的这套C语言标准库。 其实现了常见的C库的函数支持很多种系统平台功能很全但是也相对比较臃肿和庞大 musl-libc:C语言标准库Musl-libc项目发布了1.0版。Musl是一个轻量级的C标准库设计作为GNU C library (glibc)、 uClibc或Android Bionic的替代用于嵌入式操作系统和移动设备。它遵循POSIX 2008规格和 C99 标准采用MIT许可证授权使用Musl的Linux发行版和项目包括sabotagebootstrap-linuxLightCube OS等等
musl libc 和 glibc 是两个常见的 C 标准库实现它们有一些差异。下面列出了其中一些主要的差异 大小和速度musl libc 要小得多因为它没有像 glibc 那样提供大量的额外功能。相反musl libc 专注于尽可能减少代码大小和函数调用开销以提高性能。 兼容性glibc 是 Linux 系统上最常见的 C 标准库并且具有广泛的兼容性支持许多架构和操作系统。相比之下musl libc 对其他平台和操作系统的移植性较差。 实现方法musl libc 是使用静态链接编译的这使得它更易于构建和管理并且不需要动态链接器。相反glibc 使用动态链接器这也使得它更灵活因为它可以动态加载所需的库。 POSIX 标准musl libc 更加严格地遵循 POSIX 标准而glibc 则添加了一些扩展以提供更多的功能和兼容性。 错误处理musl libc 实现的错误处理更严格和更规范而 glibc 则有更多的错误处理选项并且支持不同的语言环境。 版权问题由于采用了 BSD 许可证musl libc 比 glibc 更容易以开源、商业和专有软件的形式使用。
综上所述选择使用 musl libc 还是 glibc 取决于您的具体需求。如果您需要一个小巧且速度较快的 C 标准库在 Linux 系统上使用则可以考虑使用 musl libc。如果您需要更广泛的兼容性和功能则可以使用 glibc。 额外补充:两个都是C标准库。libc是针对clang编译器特别重写的cpp标准库那libstdc自然就是gcc的事儿了。无关的科普 libc.so.6是c运行时库glibc的软链接而系统几乎所有程序都依赖C运行时库。程序启动和运行时是根据libc.so.6软链接找到glibc库。删除libc.so.6将导致系统的几乎所有程序不能工作。如果程序编译的时候链接的libc库版本不在程序运行环境下的glibc库支持的libc版本之内也会报错。于是系统的所有命令 IS,cp,cd等等都无法使用了。 1.Musl libc为什么我们会需要另一个 libc 2.musl和glibc性能区别到底有多大 3.理清gcc、glibc、libstdc的关系 4.uclibc、eglibc、glibc、Musl-libc之间的区别和联系 5.如何紧急修复当你在linux中干穿了libc丢了libc.so.6,ld-linux-x86-64.so.2其中一个 干穿了我就提桶跑路,还修复个啥 6.musl简介 7.glibc和musl libc的区别 8.在同一个进程中加载 musl libc.so 和 gcc libc.so 9.musl 的 GCC 包装器与 musl 的交叉编译器有何不同 10.gcc编译静态库到自己的程序 解决在不同linux下因libc版本问题而不能运行 版本兼容问题 11.glib和glibc的联系区别 12.libc、glibc 和 glib 的关系 13.glibc所包含的各个库 2.2 aarch64-linux-musl-xxx
前面搞完了一个musl-libc库这里又来了一个aarch64-linux-musl-xxx。你们是逗比吗来这么多。真的逗比今天又联系补上
这里我们对aarch64-linux-musl其简单介绍下: aarch64 是随 ARMv8 ISA 一起引入的 64 位架构用于执行 A64 指令的计算机。而且在 aarch64 状态下执行的代码只能使用 A64 指令集。而不能执行 A32 或 T32 指令。但是与 AArch32 中不同在64位状态下指令可以访问 64 位和 32 位寄存器。 aarch64-linux-musl 是一个交叉编译工具链可以在其他架构的系统中编译安装 64 位 arm 架构的程序。常用在嵌入式代码的移植中。aarch64-linux-musl 是由musl官网基于 GCC 推出的的 ARM 交叉编译工具。可用于交叉编译 ARMv8 64 位目标中的裸机程序、u-boot、Linux kernel、filesystem 和 App 应用程序。aarch64-linux-musl 交叉编译器必须安装在 64 位主机上才能编译目标代码。
aarch64-linux-musl-xxx如下所示:
$/opt/musl/bin$ ls
aarch64-linux-musl-addr2line aarch64-linux-musl-gcc-9.4.0 aarch64-linux-musl-nm
aarch64-linux-musl-ar aarch64-linux-musl-gcc-ar aarch64-linux-musl-objcopy
aarch64-linux-musl-as aarch64-linux-musl-gcc-nm aarch64-linux-musl-objdump
aarch64-linux-musl-c aarch64-linux-musl-gcc-ranlib aarch64-linux-musl-ranlib
aarch64-linux-musl-cc aarch64-linux-musl-gcov aarch64-linux-musl-readelf
aarch64-linux-musl-cfilt aarch64-linux-musl-gcov-dump aarch64-linux-musl-size
aarch64-linux-musl-cpp aarch64-linux-musl-gcov-tool aarch64-linux-musl-strings
aarch64-linux-musl-elfedit aarch64-linux-musl-gprof aarch64-linux-musl-strip
aarch64-linux-musl-g aarch64-linux-musl-ld
aarch64-linux-musl-gcc aarch64-linux-musl-ld.bfd 这里我们可以把 aarch64-linux-musl-xxx和aarch64-linux-gnu-gcc做对比。它是一个gcc交叉编译工具链。 XXX:/opt/musl$ tree -L 1
.
├── aarch64-linux-musl
├── bin
├── include
├── lib
├── libexec
└── share#其中git仓库地址如下对应的https://github.com/richfelker/musl-cross-make.git
https://gitee.com/stesen/musl-cross-make_for_openharmony.git 三.其它关于工具链知识的一些普法
工具链的知识真多搞了一个又是一个搞不完记不住。但是还是木的办法只能硬着头皮上我不入地狱谁入地狱。我是超人 3.1 什么是sysroot sysroot 被称为逻辑根目录只在链接过程中起作用作为交叉编译工具链搜索库文件的根路径如配置–sysrootdir则dir作为逻辑根目录链接器将在dir/usr/lib中搜索库文件。
export LINUX_ROOT$HOME/xxx/linux
export SYSROOT${LINUX_ROOT}/sysroot-ubuntu-20.04-arm64export LINUX_ROOT$HOME/OH_V3.2_BETA2/code-v3.2-Beta2
export SYSROOT${LINUX_ROOT}/OpenHarmony/out/rk3568/obj/third_party/musl只有链接器开启了–with-sysroot选项–sysrootdirector才生效 1.编译链接实战4–sysroot和-isysroot选项对编译的影响 2.GCC编译选项和环境变量 3.sysroot位何物 3.2 pkg-config是个什么东东?
pkg-config的功能主要是在编译应用程序和库的时候作为一个工具来使用。pkg-config可以使用第三方库编译程序指定库文件和头文件的位置。pkg-config就是通过.pc文件获取库的各种必要信息包括版本信息、编译和链接需要的参数等。不同的系统的库文件的路径不同用户也可以把库安装到不同的目录下
对于一个比较大第三方库其头文件和库文件的数量是比较多的。如果我们一个个手动地写那将是相当麻烦的。所以pkg-config就应运而生了。大家应该都知道一般用第三方库的时候就少不了要使用到第三方的头文件和库文件。我们在编译、链接的时候必须要指定这些头文件和库文件的位置。对于一个比较大的第三方库其头文件和库文件的数量是比较多的如果我们一个个手动地写那将是相当的麻烦的。因此pkg-config就应运而生了。pkg-config能够把这些头文件和库文件的位置指出来给编译器使用。pkg-config主要提供了下面几个功能
检查库的版本号。 如果所需要的库的版本不满足要求它会打印出错误信息避免链接错误版本的库文件获得编译预处理参数如宏定义、头文件的位置获得链接参数如库及依赖的其他库的位置文件名及其他一些链接参数自动加入所依赖的其他库的设置
pkg-config能够把这些头文件和库文件的位置指出来给编译器使用。如果你的系统装有libdrm可以尝试一下下面的命令$pkg-config --cflags libdrm。可以看到其输出是gtk的头文件的路径。
我们平常都是这样用pkg-config的。
$gcc main.c pkg-config --cflags --libs libdrm -o main$pkg-config --cflags --libs libdrm
-I/usr/local/include -I/usr/local/include/libdrm -L/usr/local/lib -ldrm上面的编译命令中pkg-config --cflags --libs libdrm的作用就如前面所说的把gtk的头文件路径和库文件列出来让编译去获取。–cflags和–libs分别指定头文件和库文件。 命令中的不是引号而是数字1左边那个键位的那个符号。 其实pkg-config同其他命令一样有很多选项不过我们一般只会用到–libs和–cflags选项。
$pkg-config --help
Usage:pkg-config [OPTION?]Help Options:-h, --help Show help optionsApplication Options:--version output version of pkg-config--modversion output version for package--atleast-pkgconfig-versionVERSION require given version of pkg-config--libs output all linker flags--static output linker flags for static linking--short-errors print short errors--libs-only-l output -l flags--libs-only-other output other libs (e.g. -pthread)--libs-only-L output -L flags--cflags output all pre-processor and compiler flags--cflags-only-I output -I flags--cflags-only-other output cflags not covered by the cflags-only-I option--variableNAME get the value of variable named NAME--define-variableNAMEVALUE set variable NAME to VALUE--exists return 0 if the module(s) exist--print-variables output list of variables defined by the module--uninstalled return 0 if the uninstalled version of one or more module(s) or their dependencies will be used--atleast-versionVERSION return 0 if the module is at least version VERSION--exact-versionVERSION return 0 if the module is at exactly version VERSION--max-versionVERSION return 0 if the module is at no newer than version VERSION--list-all list all known packages--debug show verbose debug information--print-errors show verbose information about missing or conflicting packages (default unless --exists or --atleast/exact/max-version given on the command line)--silence-errors be silent about errors (default when --exists or --atleast/exact/max-version given on the command line)--errors-to-stdout print errors from --print-errors to stdout not stderr--print-provides print which packages the package provides--print-requires print which packages the package requires--print-requires-private print which packages the package requires for static linking--validate validate a packages .pc file--define-prefix try to override the value of prefix for each .pc file found with a guesstimated value based on the location of the .pc file--dont-define-prefix dont try to override the value of prefix for each .pc file found with a guesstimated value based on the location of the .pc file--prefix-variablePREFIX set the name of the variable that pkg-config automatically sets
3.2.1 pkg-config配置环境变量
事实上pkg-config只是一个工具所以不是你安装了一个第三方库pkg-config就能知道第三方库的头文件和库文件的位置的。为了让pkg-config可以得到一个库的信息就要求库的提供者提供一个.pc文件。默认情况下比如执行如下命令
# pkg-config --libs --cflags glib-2.0
-I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -lglib-2.0pkg-config会到/usr/lib/pkconfig/目录下去寻找glib-2.0.pc文件。也就是说在此目录下的.pc文件pkg-config是可以自动找到的。然而假如我们安装了一个库其生成的.pc文件并不在这个默认目录中的话pkg-config就找不到了。此时我们需要通过PKG_CONFIG_PATH环境变量来指定pkg-config还应该在哪些地方去寻找.pc文件。
我们可以通过如下命令来设置PKG_CONFIG_PATH环境变量
# export PKG_CONFIG_PATH$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig/这样pkg-config就会在/usr/local/lib/pkgconfig/目录下寻找.pc文件了。另外还需要注意的是,上述环境变量的设置只对当前的终端窗口有效。为了让其永久生效我们可以将上述命令写入到/etc/bash.bashrc等文件中配置环境变量有很多方法不止这一种以方便后续使用。 3.3 pc文件是个什么东东?
pc文件是个什么东东这里我用一句话来概括就是pkg-config用来在PKG_CONFIG_PATH查找库相关依赖的一种特殊格式文件既然是OpenHarmony系统这里我们就以OpenHarmony下开源mesa3d里面的pc文件为例来举例说明:
$pwd
/home/xxx/xxx/third_party/mesa3d
$cat ohos/pkgconfig_template/zlib.pc
prefixohos_project_directory_stub
exec_prefix${prefix}
libdir${prefix}/out/ohos-arm-release/obj/third_party/zlib
sharedlibdir${libdir}
includedir${prefix}/third_party/zlibName: zlib
Description: zlib compression library
Version: 1.2.12Requires:
Libs: -L${libdir} -L${sharedlibdir} -lz
下面我们简单描述一下pc文件中的用到的一些关键词 Name: 一个针对library或package的便于人阅读的名称。这个名称可以是任意的它并不会影响到pkg-config的使用pkg-config是采用pc文件名的方式来工作的。 Description: 对package的简短描述 URL: 人们可以通过该URL地址来获取package的更多信息或者package的下载地址 Version: 指定package版本号的字符串 Requires: 本库所依赖的其他库文件。所依赖的库文件的版本号可以通过使用如下比较操作符指定,,,, Requires.private: 本库所依赖的一些私有库文件但是这些私有库文件并不需要暴露给应用程序。这些私有库文件的版本指定方式与Requires中描述的类似。 Conflicts: 是一个可选字段其主要用于描述与本package所冲突的其他package。版本号的描述也与Requires中的描述类似。本字段也可以取值为同一个package的多个不同版本实例。例如: Conflicts: bar 1.2.3, bar 1.3.0 Cflags: 编译器编译本package时所指定的编译选项和其他并不支持pkg-config的library的一些编译选项值。假如所需要的library支持pkg-config,则它们应该被添加到Requires或者Requires.private中 Libs: 链接本库时所需要的一些链接选项和其他一些并不支持pkg-config的library的链接选项值。与Cflags类似 Libs.private: 本库所需要的一些私有库的链接选项 1.pkg-config 与.pc文件 2.pkgconfig和环境变量PKG_CONFIG_PATH和PKG_CONFIG_LIBDIR 3.Linux中pkg-config的使用 4.Linux修改环境变量的4种方法 3.4 怎么通过OpenHarmony源码编译ohos-sdk
很简单如下:
./build/prebuilts_download.sh
./build.sh --product-name ohos-sdk –ccache --target-cpu arm641.Musl-libc库编译 该博客简单介绍了怎么编译生成musl libc库 2.OpenHarmony富设备移植指南—开源GPU驱动编译 这篇博客我们并不是学习怎么编译GPU而是学习musl clang配置编译 3.aarch64-linux-ohos交叉编译rust 4.ohos_cross_tools交叉编译工具链 5.一文带你读懂如何移植三方库到OpenHarmony 参考价值不大已经完全过时了主要描述了如何移植第三方库到OH平台这个可以为后续vivante GPU移植到OH参考使用 6.基于OpenHarmony的第三方库编译移植环境(arm-linux-ohos平台) 7.交叉编译 Arm64 OHOS鸿蒙系统版本 8.OpenHarmony musl交叉编译 这篇博客可以参考可以怎么使用musl gcc编译 9.clang交叉编译Android clang交叉编译使用musl库 10.Building Linux with Clang/LLVM