【NDK系列12】编译器 clang gcc g++

博客介绍了C/C++编译器gcc、g++、clang的基本使用和特点,如clang编译速度快、产出小,但部分软件编译会出错,gcc和g++编译行为有差异。还阐述了C/C++文件变成可执行文件需经过预处理、编译、汇编和链接四个阶段,以及静态库和动态库的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. gcc/g++/clang

了解c/c++编译器的基本使用,能够在后续移植第三方框架进行交叉编译时,清楚的了解应该传递什么参数。

clang

clang 是一个C、C++、Object-C的轻量级编译器。基于LLVM (LLVM是以C++编写而成的构架编译器的框架系统,可以说是一个用于开发编译器相关的库)

gcc

GNU C编译器。原本只能处理C语言,很快扩展,变得可处理C++。(GNU计划,又称革奴计划。目标是创建一套完全自由的操作系统)

g++

GNU c++编译器

gcc、g++、clang都是编译器。

  • gcc和g++都能够编译c/c++,但是编译时候行为不同。
  • clang也是一个编译器,对比gcc,它具有编译速度更快、编译产出更小等优点,但是某些软件在使用clang编译时候因为源码中内容的问题会出现错误。
  • clang++与clang就相当于gcc与g++。

对于gcc与g++:

  1. 后缀为.c的源文件,gcc把它当作是C程序,而g++当作是C++程序;后缀为.cpp的,两者都会认为是c++程序
  2. g++会自动链接c++标准库stl,gcc不会
  3. gcc不会定义__cplusplus宏,而g++会

linux安装gcc

apt install build-essential #安装gcc、g++与make

2. 编译器过程

一个C/C++文件要经过预处理(preprocessing)、编译(compilation)、汇编(assembly)、和连接(linking)才能变成可执行文件。

1、预处理

​  gcc -E main.c  -o main.i

-E的作用是让gcc在预处理结束后停止编译。

​ 预处理阶段主要处理include和define等。它把#include包含进来的.h 文件插入到#include所在的位置,把源程序中使用到的用#define定义的宏用实际的字符串代替

2、编译阶段

​ gcc -S main.i -o main.s

-S的作用是编译后结束,编译生成了汇编文件。

​ 在这个阶段中,gcc首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc把代码翻译成汇编语言。

3、汇编阶段

​ gcc -c main.s -o main.o

​ 汇编阶段把 .s文件翻译成二进制机器指令文件.o,这个阶段接收.c, .i, .s的文件都没有问题。

4、链接阶段

​ gcc -o main main.s

​ 链接阶段,链接的是函数库。在main.c中并没有定义”printf”的函数实现,且在预编译中包含进的”stdio.h”中也只有该函数的声明。系统把这些函数实现都被做到名为libc.so的动态库。

函数库一般分为静态库和动态库两种

  • 静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。Linux中后缀名为”.a”。
  • 动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库。Linux中后缀名为”.so”,如前面所述的libc.so就是动态库。gcc在编译时默认使用动态库。

静态库节省时间:不需要再进行动态链接,需要调用的代码直接就在代码内部

动态库节省空间:如果一个动态库被两个程序调用,那么这个动态库只需要在内存中

Java中在不经过封装的情况下只能直接使用动态库。

<think>嗯,用户这次问的是Android NDK是否包含GCC编译器,还附带了之前的对话历史。从引用内容看,用户似乎遇到了NDK编译器的内部错误,特别是使用NEON intrinsics时出现的崩溃问题。 用户可能是个移动端开发者,正在处理ARM架构的底层优化。ta的引用显示在2012年就有人遇到类似问题,说明这可能是历史遗留问题。有趣的是用户特意标注"不是真正需求",说明ta很专业,能区分引用内容实际需求。 关于核心问题:当前主流NDK版本确实不再内置GCC了。从r13开始NDK就转向clang,r18彻底移除GCC。但用户引用的r8版本确实包含GCC 4.4.3,这解释了ta遇到的崩溃问题——GCC 4.4.3对NEON支持确实有问题。 需要强调迁移到clang的必要性:clang不仅修复了这些历史bug,还支持更新的C++标准。考虑到用户还在用老版本NDK,应该提醒ta注意兼容性风险。那些NEON代码在clang下应该能正常编译。 用户没问但可能关心的是:如何区分NDK版本对应的编译器?老项目迁移到clang要注意什么?这些都可以作为衍生问题。另外ta提到Linaro工具链,说明可能有交叉编译需求,这点在回答里可以埋个伏笔。</think>是的,**Android NDK 包含 GCC 编译器**,但需注意其版本历史演变: 1. **历史版本包含 GCC** 在较旧的 NDK 版本(如您引用的 **R8**)中,默认工具链是基于 **GCC 4.4.3** 的[^1][^3]。用户可通过 NDK 路径访问 GCC,例如: ```bash ${ANDROID_NDK_HOME}/toolchains/arm-linux-androideabi-4.9/prebuilt/.../bin/arm-linux-androideabi-gcc ``` 此路径中的 `4.9` 或 `4.4.3` 即对应 GCC 版本。 2. **现代 NDK 的转变** - **NDK r13+**:开始默认使用 **Clang** 替代 GCC 作为推荐编译器。 - **NDK r18+**:**完全移除了 GCC 工具链**,仅保留 Clang[^2][^3]。 若需使用 GCC,必须手动下载旧版本 NDK(如 r17c 或更早)。 3. **GCCNDK 中的问题** 您引用的崩溃问题(`internal compiler error`)是 NDK 旧版 GCC 的已知缺陷,尤其在处理 ARM NEON 浮点类型(如 `float32_t`)时易触发[^1]。原因包括: - Android 的 `float32_t` 是编译器内置类型(`__builtin_neon_sf`),而 Linaro 等工具链将其定义为标准 `float`。 - 直接修改 `float32_t` 的 typedef 会导致 NEON 内部函数失效[^1]。 **解决方案**:升级到 Clang 或使用修复后的新版 GCC(需外部工具链)。 4. **如何确认当前 NDK编译器** - 检查 `ndk-build --version` 输出。 - 查看 `${NDK_HOME}/toolchains` 目录:若存在 `llvm` 子目录为主流,`arm-linux-androideabi-4.9` 等目录包含旧版 GCC。 > **总结**:NDK **曾长期内置 GCC**,但新版已转向 Clang。若需 GCC,需使用 NDK r17c 或更早版本,或集成外部 GCC 工具链[^1][^2][^3]。 --- ### 相关问题 1. 如何为 Android NDK 配置外部 GCC 工具链? 2. ClangGCC 在 Android 原生开发中的性能差异有哪些? 3. 如何解决 NDK 旧版 GCC 的 `internal compiler error` 崩溃问题? 4. Android NDKGCC 迁移到 Clang 的主要动机是什么? 5. 是否能在现代 NDK 中强制使用 GCC 编译项目? [^1]: NDK 旧版 GCC 存在 NEON 类型处理缺陷[引用1]。 [^2]: NDK 工具链路径包含 GCC 可执行文件[引用2]。 [^3]: NDK 编译器版本及路径说明[引用3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ddssingsong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值