• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

音视频学习之NDK交叉编译基础

android 搞代码 3年前 (2022-03-02) 22次浏览 已收录 0个评论
文章目录[隐藏]

我收集了一些学习用的材料,其中蕴含了很多学习,面试,中高进阶fluuter材料,还有很多视频详解,如果有同学想进一步理解,详情请看文末。也欢送各路大神门前来装X。

穿插编译

穿插编译就是程序的编译环境和理论运行环境不统一,即在一个平台上生成另一个平台上的可执行代码。

比方NDK,你在Mac、Win或者Linux上生成的C/C++的代码要在Android平台上运行,就须要应用到穿插编译了。

艰深点说就是你的电脑和手机应用的CPU不同,所以CPU的指令集就不同,比方arm的指令集在X86上就不能运行。

罕用的编译工具链

gcc

GNU C编译器。本来只能解决C语言,很快扩大,变得可解决C++。(GNU打算,又称革奴打算。指标是创立一套齐全自在的操作系统)

Android在之后彻底移除了gcc,默认应用clang编译,所以应用不同版本的ndk对ffmpeg进行穿插编译时会呈现同样的脚本在旧版的ndk能编译通过,然而旧版的就不编译不通过的问题。

笔者会在前面的学习过程中应用最新的ndk对最新版的ffmpeg进行穿插编译,并且会通过文章记录学习过程,感兴趣的同学能够继续关注。

g++

GNU c++编译器

gcc和g++都可能编译c/c++,然而编译时候行为不同。

对于gcc与g++会有以下区别:

后缀为.c的源文件,gcc把它当作是C程序,而g++当作是C++程序;后缀为.cpp的,两者都会认为是c++程序

g++会主动链接c++规范库stl,gcc不会

gcc不会定义__cplusplus宏,而g++会

clang

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

比照gcc,clang具备编译速度更快、编译产出更小等长处,然而某些软件在应用clang编译时候因为源码中内容的问题会呈现谬误。

另外clang++也是一个编译器,clang++与clang就相当于gcc与g++的区别。

动态库和动静库

动态库是指编译链接时,把库文件的代码全副退出到可执行文件中,因而生成的文件比拟大,但在运行时也就不再须要库文件了。Linux中后缀名为”.a”。

动静库则与动态库相同,在编译链接时并没有把库文件的代码退出到可执行文件中,而是在程序执行时由运行时链接文件加载库。Linux中后缀名为”.so”。gcc在编译时默认应用动静库。

总结起来就是动态库节俭运行工夫,动静库节俭运行空间,典型的工夫换空间,在开发过程中可依据状况自行抉择。

Java中在不通过封装的状况下只能间接应用动静库。

编译器过程

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

咱们以最简略的一个c语言程序来做一个例子:

预处理

gcc -E main.c -o main.i

-E的作用是让gcc在预处理完结后进行编译。

预处理阶段次要解决include和define等。它把#include蕴含进来的.h 文件插入到#include所在的地位,把源程序中应用到的用#define定义的宏用理论的字符串代替。

编译阶段

gcc -S main.i -o main.s

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

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

汇编阶段

gcc -c main.s -o main.o

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

链接阶段

gcc -o main main.s

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

一步到位:

gcc main.c -o main

到这里咱们胜利的在 mac 平台生成了可执行文件,运行即可看到输入。试想一下咱们能够将这个可执行文件拷贝到安卓手机上执行吗?

必定是不行的,次要起因是两个平台的 CPU 指令集不一样,基本就无奈辨认指令,这时候穿插编译就排上用场了。

如果你不信能够把 main 可执行文件 push 到手机 /data/local/tmp 外面执行验证一下是否正确输入。

也不肯定必须要是/data/local/tmp这个门路,push到任意一个有可读可写可执行的权限的目录下测试均可。

穿插编译试验

上面咱们应用ndk来对main.c进行穿插编译,看看编译后的可执行文件是不是真的能在Android上运行。

笔者这里以armeabi为例,在mac平台上进行穿插编译。

既然是gcc被移除了,那咱们应用clang来进行穿插编译。

首先找到clang工具链

执行命令

在mac平台能能失常生成可执行文件,咱们将可执行文件用push到这个目录下,而后应用adb执行即可看到输入。阐明咱们的穿插编译胜利了。

如果不应用clang,如何gcc进行穿插编译呢?

首先也是先找到gcc的工具链

而后执行gcc编译命令

咱们发现报错了

找不到stdio.h头文件

这种谬误是说在咱们编的时候编译器找不到咱们引入的 stdio.h 头文件,那怎么通知编译器 stdio.h 头文件在哪里呢? 上面知识点阐明怎么指定这些报错的头文件

咱们通过参数通知gcc工具链到那个目录上来寻找头文件,传递参数进去再次试一下

还是报错

找不到types.h头文件

因为找不到头文件,咱们进去-isystem配置的头文件查找目录中发现aarch64-linux-android和arm-linux-androideabi都存在asm的子目录,所以编译器就不晓得用那个了,咱们再指定一下即可。

终于胜利了,咱们将可执行文件push到手机的这个目录下,而后应用adb执行即可看到输入。

在这里咱们应用了clang和gcc进行了穿插编译发现clang更加的简略,间接找到工具链的门路即可进行编译了,然而gcc就比较复杂了,须要指定多个参数。

这里须要须要咱们明确每个参数的意思是什么:

例如 gcc –sysroot=目录1 -isysroot 目录2 -isystem 目录3 -I目录4 main.c

的意思就是 查找 目录1/usr/lib 的库文件、

查找目录2 /usr/include 的头文件、

查找 目录3 下的头文件、

查找 目录4 下的头文件。

例如:

gcc -L目录1 -l库名

链接ndk的日志库:

gcc -LC:NDK门路\platforms\android-21\arch-arm\usr\lib

-llog -lGLESv2

或者是

gcc –sysroot=NDK门路\platforms\android-21\arch-arm

-llog -lGLESv2

生成动静库

gcc -fPIC -shared main.c -o libTest.so

或者

clang -fPIC -shared main.c -o libTest.so

即便不加-fPIC也能够生成.so文件,然而对于源文件有要求,

因为不加fPIC编译的so必须要在加载到用户程序的地址空间时重定向所有指标地址,所以在它外面不能引用其它中央的代码。

要想验证编译进去的so动静库能不能失常应用,通过JNI调用测试即可。


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:音视频学习之NDK交叉编译基础

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址