DNK基础之静态库、动态库、编译流程

区分DNK和JNI的概念

DNK:Android Native Development Kit 一套允许使用原生代码语言C/C++,实现部分应用的工具集。包含Android平台的交叉编译器,包含Android平台可用的静、动态库。 C/C++与Java通过JNI交互。

JNI:是一套本地编程接口。它允许运行在JAVA虚拟机中的JAVA代码和用其他编程语言,诸如C语言、C++、汇编,写的应用和库之间的交互操作。

编译器 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++会

动态库、静态库原理,编译流程

  • 库的概念

在 windows平台和 alinux平台下都大量存在着库。 Android中也存在库。库,顾名思义,指的是一个容器文件,里面装的是函数,由于 Windows和 linux的平台不同(主要是编译器、汇编器和连接器的不同),因此二者库的二进制是不兼容的。

  • 库的存在意义

库是别人写好的现有的,成熟的,可以复用的代码。现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。

编译流程

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

test.c文件内容

#include <stdio. h>
int main( ){printf("hello world!\n");return 0;
}

1.预处理——生成test.i文件(预处理后的文件)

#-E:让gcc在预处理结束后停止编译
#“test.i”文件为预处理后输出的文件
#-o:指定输出文件
$ gcc -E test.c -o test.i

2.编译——得到test.s文件(编译后生成的汇编代码)

# -S:让gcc在编译结束后停止编译过程
#“test.s”文件为编译后生成的汇编代码
$ gcc -S test.i -o test.s

3.汇编——汇编就是把编译阶段生成的“.s”文件转成二进制目标代码,也就是机器代码(01序列)。

也可以直接执行命令: gcc -c test.c 能直接生成test.c同名的test.o文件

#-c:让gcc在汇编结束后停止编译过程
#“test.o” 文件为汇编后生成的机器码目标文件
$ gcc -c test.s -o test.o

4.链接——生成text文件(这里它是可执行文件)

也可以直接执行命令: gcc -o test test.c 能直接生成test可执行文件

$ gcc test.o -o test          #-o本质上是一个重命名选项。不使用-o选项时,默认生成的是a.out文件。这里生成的是可执行文件test。
$ ./test                      #执行结果:hello world!

静态库

静态库:静态库实际就是一些目标文件(一般以.a结尾)的集合,静态库一般以.a结尾,只用于生成可执行文件阶段。

在链接步骤中,链接器将从库文件取得所需代码,复制到生成的可执行文件中。这种库称为静态库。其特点是可执行文件中包含了库代码的一份完整拷贝,在编译过程中被载入程序中。缺点就是多次使用就会有多份冗余拷贝,并且对程序的更新、部署和发布会带来麻烦,如果静态库有更新,那么所有使用它的程序都需要重新编译、发布。

静态库例如:.a / .lib (可以理解为类似Java中的 .aar)

生成静态库:

#首先生成目标文件tool.o
$ gcc -c tool.c -o tool.o
#使用ar命令将目标文件打包成静态库   【rcs含义:r : 更新或增加新文件到静态库中 c: 创建一个库,不管是否存在都创建 s:表示创建文档索引】
$ ar rcs libtool.a tool.o           #使用ar t libtest.a查看静态库内容
$ ar t libtool.a             #-------方式二 交叉编译
#交叉编译静态库,同样原理,利用NDK目录下的ar工具
export AR="/root/ndk/android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ar"
export CC="/root/ndk/android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc"
export CFLAGS="--sysroot=/root/ndk/android-ndk-r17b/platforms/android-21/arch-arm -isysroot /root/ndk/android-ndk-r17b/sysroot -isystem /root/ndk/android-ndk-r17b/sysroot/usr/include/arm-linux-androideabi -pie"
$ $CC $CFLAGS -fPIC test.c -o test.o
$ $AR rcs libTest.a test.o

使用静态库

#main.c链接为执行文件main,
#参数一:-L. 编译程序按照指定的路径去寻找库文件,这里点是代表当前目录下
#参数二:-ltool , -l 后面带的是指定要链接的库(这里是因为main中引入了 tool.h)
$ gcc -o main main.c -L. ltool

动态库

动态库:动态库在链接阶段没有被复制到程序中,而是在程序运行时由系统动态加载到内存中供程序调用。系统只需载入一次动态库,不同的程序可以得到内存中相同动态库的副本,因此节省了很多内存。相比于静态库而言内存开销较小。

动态库例如:.so / .dll (可以理解为类似Java中的 .jar)

生成动态库:

#------方式一
#首先生成目标文件test.o
$ gcc -c test.c
#使用-fPIC和-shared参数生成动态库
$ gcc -shared -fPIC -o libtool.so tool.o           #------方式二
#直接将.c文件生成.so
$ gcc -shared -fPIC test.c -o xxx.so#------方式三:配合NDK进行交叉编译,生成能在AS上Android使用的动态库 xxx.so
#这种方式需先配置到环境变量
export CC="/root/ndk/android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc"
export CFLAGS="--sysroot=/root/ndk/android-ndk-r17b/platforms/android-21/arch-arm -isysroot /root/ndk/android-ndk-r17b/sysroot -isystem /root/ndk/android-ndk-r17b/sysroot/usr/include/arm-linux-androideabi"
$ $CC $CFLAGS -shared -fPIC test.c -o libTest.so

使用动态库

$ gcc -o main main.c -L. ltool            #存在同名的静态库和动态库时候,系统会优先加载动态库

LD_LIBRSRY_PATH=. 是配置环境变量,指定查找共享库

动态库与静态库的区别

  • 静态库文件比较大动态库比较小

  • 静态库需要在编译时被链接在目标代码中,动态库在运行时才会被加载到目标代码

  • 静态库类似于 Android中的 Module,一旦打包APK需要重新进行编译

  • 动态库类似于jar包打包是不需要重新进行编译

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

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

编译脚本头文件与库文件指定

--sysroot=XX使用xx作为这一次编译的头文件与库文件的查找目录,查找下面的 usr/include usr/lib目录
-isysroot XX头文件查找目录,覆盖--sysroot ,查找 XX/usr/include
-isystem XX指定头文件查找路径(直接查找根目录)
-IXX头文件查找目录
优先级:-I -> -isystem -> sysroot-LXX指定库文件查找目录
-lxx.so指定需要链接的库名#查找 目录1/usr/lib的库文件     目录2 /usr/include 的头文件   还去查找 目录3 下的头文件  还去查找 目录4 下的头文件
gcc --sysroot=目录1 -isysroot 目录2 -isystem 目录3 -I目录4  main.cgcc -L目录1 -l库名javac -classpath xxx例子: 链接ndk的日志库
gcc -LC:\Users\Administrator\AppData\Local\Android\Sdk\ndk-bundle\platforms\android-21\arch-arm\usr\lib
-llog  -lGLESv2gcc --sysroot=C:\Users\Administrator\AppData\Local\Android\Sdk\ndk-bundle\platforms\android-21\arch-arm
-llog -lGLESv2    #pie 位置无关的可执行程序
export CC="/root/android-ndk-r17b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc"
export CFLAGS="--sysroot=/root/android-ndk-r17b/platforms/android-21/arch-arm -isysroot /root/android-ndk-r17b/sysroot -isystem /root/android-ndk-r17b/sysroot/usr/include/arm-linux-androideabi -pie"
$CC $CFLAGS -o main main.c

DNK基础之静态库、动态库、编译流程相关推荐

  1. C/C++ 跨平台交叉编译、静态库/动态库编译、MinGW、Cygwin、CodeBlocks使用原理及链接参数选项

    0. 引言 UNIX是一个注册商标,是要满足一大堆条件并且支付可观费用才能够被授权使用的一个操作系统.linux是unix的克隆版本,是由其创始人Linus和诸多世界知名的黑客手工打造的一个操作系统. ...

  2. Linux学习---静态库 动态库

    今天我们主要来说说Linux系统下基于动态库(.so)和静态(.a)的程序那些猫腻.在这之前,我们需要了解一下源代码到可执行程序之间到底发生了什么神奇而美妙的事情. 在Linux操作系统中,普遍使用E ...

  3. 软件库Library之静态库\动态库和静态加载\动态加载

    软件库Library之静态库\动态库和静态加载\动态加载 动态库之导入库 https://blog.csdn.net/wallaceli1981/article/details/5740718 * 动 ...

  4. 【Android NDK 开发】Visual Studio 2019 使用 CMake 开发 JNI 动态库 ( 动态库编译配置 | JNI 头文件导入 | JNI 方法命名规范 )

    文章目录 I . JNI 与 NDK 区别 II . Visual Studio 编译动态库 III. 配置 导入 jni.h 头文件 IV . IntelliJ IDEA Community Edi ...

  5. Linux-(C/C++)生成并使用静态库/动态库

    静态库/动态库概要 在Windows下静态库的后缀为:.lib.动态库后缀为:.dll:而在Linux下静态库的后缀为:.a.动态库的后缀为:.so. 那么什么是静态库呢? 首先我们来看看程序编译的大 ...

  6. NDK01-打包静态库 动态库在mk和cmake环境配置使用

    动态库和静态库 动态库: libxxx.so 运行的时候,才会去加载,加载一次就在内存中存在副本,其他地方使用就都是公用的.使用场景就是 高德百度sdk对外开房 静态库: libxxx.a 编译期把静 ...

  7. 【Android NDK 开发】Android.mk 配置动态库 ( Android Studio 配置动态库 | 动态库加载版本限制 | 本章仅做参考推荐使用 CMake 配置动态库 )

    文章目录 I . Android Studio 中使用 Android.mk 配置动态库 总结 II . 第三方动态库来源 III . 配置 Android.mk 构建脚本路径 IV . 预编译 第三 ...

  8. linux centos 编译Lua5.2.0 静态库 动态库

    一 lua下载 lua5.2.0下载地址 :http://download.csdn.net/download/yzf279533105/10109818 二 笔者这里linux环境为centos6. ...

  9. Ubuntu下CodeBlocks的安装、配置及静态库动态库的简单使用举例

    1.  从Ubuntu Software Center中搜索Code::Blocks并安装: 2.  在第一次启动时选择GNU GCC Compiler作为默认的编译器: 3.  生成静态库并调用操作 ...

  10. Linux 静态库 动态库

    转自:http://blog.chinaunix.net/uid-26833883-id-3219335.html 一.什么是库 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. ...

最新文章

  1. 01 小程序开发入门
  2. 大数据时代 安全与应用的博弈
  3. Android java 多线程(三)
  4. java 通用取得 系统硬件信息及 jvm 信息的 jar 包 oshi-core
  5. sql int 转string_SQL智能代码补全引擎【sql-code-intelligence】介绍
  6. book: Effective Java
  7. 只包含因子2 3 5的数(51nod 思维 打表)
  8. CF741C Arpa’s overnight party and Mehrdad’s si
  9. Mr.J-- jQuery学习笔记(三)--静态方法详解
  10. 读书笔记-集体智慧编程
  11. c语言编程思想pdf,C 编程思想(PDF)
  12. 十行代码替换证件照背景颜色
  13. 简单分析Mysql不同方式联表查询的效率问题
  14. 今天气温达到了39度 单位给买了雪糕降温
  15. 金蝶KSQL 增加字段/改变字段长度
  16. 老java手机有什么什么用,80后熟悉的这些手机功能,用过3种以上说明你已经老了...
  17. 任务调度Schedulerx2.0分布式计算之MapReduce模型
  18. 市场购物篮分析 Market Basket Analysis
  19. 【Get深一度】dB、dBm、dBW和W换分别代表的含义及换算关系
  20. 地图与定位(五)高德地图服务一

热门文章

  1. linux如何设置root权限,linux设置root权限的方法
  2. 方维短信接口常见的问题汇总
  3. 《Inter汇编语言程序设计》8.6 创建多模块程序(ENTERN)
  4. npm install 时 WARN No repository field Or No license field
  5. 加州ucla 计算机学校,美国加州大学洛杉矶分校UCLA计算机硕士CS录取
  6. MarkDown 分割线
  7. mysql 左连接查询记录数,MySQL左连接查询记录行数
  8. vite 构建vue3 项目配置文件的详情配置
  9. linux网桥中stp分析,linux网桥中stp分析
  10. 汽车故障诊断方法及注意事项