⑴ android 静态库 怎么push
要有adb
小机要root
用USB线连接小机和PC,在命令行下按以下顺序执行
1.adb root
2.adb remount
3.adb push 要push的.so push到小机的路径
Linux库有动态与静态两种,动态通常用.so为后缀,静态用.a为后缀。例如:libhello.so libhello.a
为了在同一系统中使用不同版本的库,可以在库文件名后加上版本号为后缀,例如: libhello.so.1.0,由于程序连接默认以.so为文件后缀名。所以为了使用这些库,通常使用建立符号连接的方式。
ln -s libhello.so.1.0 libhello.so.1
ln -s libhello.so.1 libhello.so
动态库和静态库的区别:
当要使用静态的程序库时,连接器会找出程序所需的函数,然后将它们拷贝到执行文件,由于这种拷贝是完整的,所以一旦连接成功,静态程序库也就不再需要了。然而,对动态库而言,就不是这样。动态库会在执行程序内留下一个标记‘指明当程序执行时,首先必须载入这个库。由于动态库节省空间,linux下进行连接的缺省操作是首先连接动态库,也就是说,如果同时存在静态和动态库,不特别指定的话,将与动态库相连接。
两种库的编译产生方法:
第一步要把源代码编绎成目标代码。以下面的代码hello.c为例,生成hello库:
/* hello.c */
#include
void sayhello()
{
printf("hello,world\n");
}
用gcc编绎该文件,在编绎时可以使用任何全法的编绎参数,例如-g加入调试代码等:
gcc -c hello.c -o hello.o
1.连接成静态库
连接成静态库使用ar命令,其实ar是archive的意思
$ar cqs libhello.a hello.o
2.连接成动态库
生成动态库用gcc来完成,由于可能存在多个版本,因此通常指定版本号:
$gcc -shared -Wl,-soname,libhello.so.1 -o libhello.so.1.0 hello.o
另外再建立两个符号连接:
$ln -s libhello.so.1.0 libhello.so.1
$ln -s libhello.so.1 libhello.so
这样一个libhello的动态连接库就生成了。最重要的是传gcc -shared 参数使其生成是动态库而不是普通执行程序。
-Wl 表示后面的参数也就是-soname,libhello.so.1直接传给连接器ld进行处理。实际上,每一个库都有一个soname,当连接器发现它正在查找的程序库中有这样一个名称,连接器便会将soname嵌入连结中的二进制文件内,而不是它正在运行的实际文件名,在程序执行期间,程序会查找拥有 soname名字的文件,%B
⑶ 如何生成静态库和动态库
静态库
静态库的后缀是.a,它的产生分两步
Step 1.由源文件编译生成一堆.o,每个.o里都包含这个编译单元的符号表
Step 2.ar命令将很多.o转换成.a,成为静态库
动态库的后缀是.so,它由gcc加特定参数编译产生。具体方法参见后文实例。123123
在 GNU/Linux 系统中静态链接文件实际上就是多个 .o 文件的压缩包。假设我们有 cool.h cool.c 和 some.c 文件,要得到静态链接库 libcool.a。首先使用如下指令得到相应的 object 文件 cool.o 和 some.o:
gcc -c cool.c
gcc -c some.c1212
用这种方法生成的 object 文件称为 PDC 即位置相关代码(position-dependence code)。再使用如下指令可以得到静态链接文件 libcool.a:
ar -r libcool.a cool.o some.o
ranlib libcool.a1212
静态链接库 libcool.a 遵从 GNU/Linux 规定的静态链接库命名规范,必须是”libyour_library_name.a”
动态库
在 GNU/Linux 中动态链接文件,必需通过链接器 ld 生成。假设我们有 hot.c other.c 等文件要生成动态链接库 libhot.so 。首先使用如下指令得到相应的 object 文件 hot.o 和 some.o
gcc -fPIC -c hot.c
gcc -fPIC -c other.c1212
参数 -fPIC 指定生成的 object 文件为位置无关代码(position-independence code),只有 PIC 可以被用作生成动态链接库。然后使用如下指令得到动态库:
ld -Bshared -o libhot.so hot.o other.o11
或者可以使用编译器的ld wrapper:
gcc -shared -o libhot.so hot.o other.o11
也可以使用编译器直接生成动态库:
gcc -fPIC -shared -o libhot.so hot.c other.c11
这里选项 -shared 指示目标文件的类型是动态链接库,动态库的命名规范是”libyour_library_name.so”
⑷ makefile 生成动态库和静态库的区别
生成动态库的时候要注意,编译生成目标文件的时候加上-fPIC参数,生成位置无关的可重定位代码,然后链接的时候加上-shared生成动态共享库。比如一个hello.c,生成静态库:
gcc-ohello.o-chello.c
arrcslibhello.ahello.o
生成动态库的命令:
gcc-fPIChello.o-chello.c
gcc-shared-olibhelllo.sohello.o
还有一个区别是:静态库参与链接过程,而动态库不链接到可执行文件中,可执行程序在运行的时候,对应的动态库也要加载到内存中,否则可执行程序运行不了。
更多详细细节,可以网络搜索视频教程:Makefile工程实践
⑸ 静态库和动态库的区别以及使用
我们通常把一些公用函数制作成函数库,供其它程序使用。
函数库分为静态库和动态库两种。
静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。
动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。
本文主要通过举例来说明在Linux中如何创建静态库和动态库,以及使用它们。
在创建函数库前,我们先来准备举例用的源程序,并将函数库的源程序编译成.o文件。
第1步:编辑得到举例的程序--hello.h、hello.c和main.c;
hello.h(见程序1)为该函数库的头文件。
hello.c(见程序2)是函数库的源程序,其中包含公用函数hello,该函数将在屏幕上输出"Hello XXX!"。
main.c(见程序3)为测试库文件的主程序,在主程序中调用了公用函数hello。
程序1: hello.h
#ifndef HELLO_H
#define HELLO_H
void hello(const char *name);
#endif //HELLO_H
程序2: hello.c
#include
void hello(const char *name)
{
printf("Hello %s!/n", name);
}
程序3: main.c
#include "hello.h"
int main()
{
hello("everyone");
return 0;
}
第2步:将hello.c编译成.o文件;
无论静态库,还是动态库,都是由.o文件创建的。因此,我们必须将源程序hello.c通过gcc先编译成.o文件。
在系统提示符下键入以下命令得到hello.o文件。
# gcc -c hello.c
#
(注1:本文不介绍各命令使用和其参数功能,若希望详细了解它们,请参考其他文档。)
(注2:首字符"#"是系统提示符,不需要键入,下文相同。)
我们运行ls命令看看是否生存了hello.o文件。
# ls
hello.c hello.h hello.o main.c
#
(注3:首字符不是"#"为系统运行结果,下文相同。)
在ls命令结果中,我们看到了hello.o文件,本步操作完成。
下面我们先来看看如何创建静态库,以及使用它。
第3步:由.o文件创建静态库;
静态库文件名的命名规范是以lib为前缀,紧接着跟静态库名,扩展名为.a。例如:我们将创建的静态库名为myhello,则静态库文件名就是libmyhello.a。在创建和使用静态库时,需要注意这点。创建静态库用ar命令。
在系统提示符下键入以下命令将创建静态库文件libmyhello.a。
# ar cr libmyhello.a hello.o
#
我们同样运行ls命令查看结果:
# ls
hello.c hello.h hello.o libmyhello.a main.c
#
ls命令结果中有libmyhello.a。
第4步:在程序中使用静态库;
静态库制作完了,如何使用它内部的函数呢?只需要在使用到这些公用函数的源程序中包含这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明静态库名,gcc将猛键会从静态库中将公用函数连接到目标文件中。注运知厅意,gcc会在静态库名前加上前缀lib,然后追加扩旁隐展名.a得到的静态库文件名来查找静态库文件。
在程序3:main.c中,我们包含了静态库的头文件hello.h,然后在主程序main中直接调用公用函数hello。下面先生成目标程序hello,然后运行hello程序看看结果如何。
# gcc -o hello main.c -L. -lmyhello
# ./hello
Hello everyone!
#
我们删除静态库文件试试公用函数hello是否真的连接到目标文件 hello中了。
# rm libmyhello.a
rm: remove regular file `libmyhello.a'? y
# ./hello
Hello everyone!
#
程序照常运行,静态库中的公用函数已经连接到目标文件中了。
我们继续看看如何在Linux中创建动态库。我们还是从.o文件开始。
第5步:由.o文件创建动态库文件;
动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀lib,但其文件扩展名为.so。例如:我们将创建的动态库名为myhello,则动态库文件名就是libmyhello.so。用gcc来创建动态库。
在系统提示符下键入以下命令得到动态库文件libmyhello.so。
# gcc -shared -fPCI -o libmyhello.so hello.o
#
我们照样使用ls命令看看动态库文件是否生成。
# ls
hello.c hello.h hello.o libmyhello.so main.c
#
第6步:在程序中使用动态库;
在程序中使用动态库和使用静态库完全一样,也是在使用到这些公用函数的源程序中包含这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明动态库名进行编译。我们先运行gcc命令生成目标文件,再运行它看看结果。
# gcc -o hello main.c -L. -lmyhello
# ./hello
./hello: error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory
#
哦!出错了。快看看错误提示,原来是找不到动态库文件libmyhello.so。程序在运行时,会在/usr/lib和/lib等目录中查找需要的动态库文件。若找到,则载入动态库,否则将提示类似上述错误而终止程序运行。我们将文件 libmyhello.so复制到目录/usr/lib中,再试试。
# mv libmyhello.so /usr/lib
# ./hello
Hello everyone!
#
成功了。这也进一步说明了动态库在程序运行时是需要的。
我们回过头看看,发现使用静态库和使用动态库编译成目标程序使用的gcc命令完全一样,那当静态库和动态库同名时,gcc命令会使用哪个库文件呢?抱着对问题必究到底的心情,来试试看。
先删除 除.c和.h外的 所有文件,恢复成我们刚刚编辑完举例程序状态。
# rm -f hello hello.o /usr/lib/libmyhello.so
# ls
hello.c hello.h main.c
#
在来创建静态库文件libmyhello.a和动态库文件libmyhello.so。
# gcc -c hello.c
# ar cr libmyhello.a hello.o
# gcc -shared -fPCI -o libmyhello.so hello.o
# ls
hello.c hello.h hello.o libmyhello.a libmyhello.so main.c
#
通过上述最后一条ls命令,可以发现静态库文件libmyhello.a和动态库文件libmyhello.so都已经生成,并都在当前目录中。然后,我们运行gcc命令来使用函数库myhello生成目标文件hello,并运行程序 hello。
# gcc -o hello main.c -L. -lmyhello
# ./hello
./hello: error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory
#
从程序hello运行的结果中很容易知道,当静态库和动态库同名时, gcc命令将优先使用动态库。
⑹ linux下使用nm指令查看静态库/动态库编译内容
在Linux环境下,当你遇到链接库问题时,深入理解库的编译内容变得尤为重要。这时,nm指令就成为一个有效的工具,帮助我们揭示静态库和动态库内的编译细节。
首先,对于静态库,我们可以使用命令
nm -g libname.a
执行后,如图所示,它会列出静态库中的全局变量和函数接口,让你清晰地看到库的内部结构。
而对于动态库,其查看方式为
nm -g libname.so
同样会显示出动态库的编译内容,包括函数和符号,这对于定位和修复与库相关的bug时非常有用。
因此,在链接第三方库或处理bug时,记得利用nm指令来记录和分析库的编译内容,它能提供宝贵的线索和信息。
⑺ Cmake命令之find_library介绍
该命令用于查找库(动态库或者静态库),当构建依赖于第三方库/系统库,可以使用该命令来查找并使用库(Cmake中有另外一个命令 find_package ,能获取库的更多信息,具体可以参考 Cmake命令之find_package介绍 )
通过一个例子来看下基本的使用,假设我们目录和文件树如下,:
我们在 mylib 中生成最终的库 libmymath.a ,然后在顶层的 CMakeLists.txt 中查找这个库文件,几个文件的具体内容如下:
在 ./mylib/ 下执行 cmake . 和 make 以便生成库 libmymath.a ,然后在 ./ 目录下执行 cmake . 和 make ,得到可执行文件 test ,运行 test 的结果为:
库的搜索路径分为两大类: 默认搜索路径 和 附加搜索路径 。
默认搜索 路径包含 cmake 定义的以 CMAKE 开头的一些变量(例如 CMAKE_LIBRARY_ARCHITECTURE 、 CMAKE_PREFIX_PATH 、 CMAKE_LIBRARY_PATH 、 CMAKE_FRAMEWORK_PATH )、标准的系统环境变量(例如系统环境变量 LIB 和 PATH 定义的路径)、系统的默认的库安装路径(例如 /usr 、 /usr/lib 等);
附加搜索路径 即 find_library 命令中通过 HINTS 或 PATHS 指定的路径;
1) 通过命令行使用 -D 指定的 CMAKE_XXX_PATH 变量,也就是形如 cmake . -DCMAKE_XXX_PATH=paths 的格式。其中 CMAKE_XXX_PATH 包含如下几个:
CMAKE_PREFIX_PATH :指定搜索目录的前缀,如果前缀有多个,需要以 分号分割的列表 方式提供,该变量默认为空,一旦该变量非空,那么会搜索该变量提供的目录,以及 ${CMAKE_PREFIX_PATH}/lib ;例如 CMAKE_PREFIX_PATH=A;B ,那么 find_library 会从 A 、 B 以及 A/lib 、 B/lib 中搜索库是否存在;
CMAKE_LIBRARY_ARCHITECTURE :如果该变量被设置,那么会搜索目录 ${CMAKE_PREFIX_PATH}/lib/${CMAKE_LIBRARY_ARCHITECTURE} ;
CMAKE_LIBRARY_PATH :指定 find_library 的库查找目录,默认值为空,多个值时需要以分号分割列表指定;
CMAKE_FRAMEWORK_PATH *:指定 macOS 的框架作为搜索路径。
2) 通过在 环境变量 中指定 CMAKE_XXX_PATH 变量,例如在 window 的环境变量中增加 CMAKE_XXX_PATH (以 ; 分割多个路径)、 Linux 中 shell 配置文件中添加(以 : 分割多个路径)。用法和 cmake -D 指定类似,例如在我的机器中( macOS ),在 .zshrc (我的命令行配置文件)中增加 export CMAKE_LIBRARY_PATH="/XXX/……/mylib" ,即可在将该目录加入到搜索路径中。
3) HINTS 选项指定的路径。
4) 系统环境变量指定的目录,默认是 LIB 和 PATH 指定的路径。例如在 PATH 中指定库搜索目录;
也可以通过 find_library 中的 PATHS ENV 环境变量名称 ( cmake 中使用环境变量名称的格式为 $ENV{环境变量名称} )来指定从哪个环境变量名称中获取路径,例如定义一个 TESTPATH 环境变量并赋值为 ./mylib ,并在 find_library 命令中指定使用该环境变量:
5)跟当前系统相关的平台文件路径,一般来说指的是当前系统安装软件的标准目录,不同的操作系统对应的路径有所不同。 camke 中 find_library 与此相关的也有如下几个, CMAKE_SYSTEM_XXX_PATH 变量,这些:
CMAKE_SYSTEM_PREFIX_PATH :指定安装目录的前缀,例如在 Windows 下的 /XXXX/Program Files , Linux 下的 /usr 或 /usr/local 等。 find_library 命令会搜索这些前缀目录,也会以这些目录加上 lib 进行搜索,例如搜索 /usr/local/lib ;
CMAKE_SYSTEM_LIBRARY_PATH :默认是当前系统的标准目录,不建议修改它;例如在我的系统,这个变量的值是 /usr/lib/X11 ;
CMAKE_SYSTEM_FRAMEWORK_PATH : macOS 框架路径,默认是当前系统的标准目录,不建议修改它;例如在我的系统,这个变量的值包含了路径 /Library/Frameworks ;
6) PATHS 选项指定的路径。