Linux库概念及如何制作静态库和动态库
1: gcc编译的过程
1 预处理: 处理所有以#开头的代码,包括头文件、宏定义、条件编译
gcc -E hello.c -o hello.i
2 编译: 语法检查以及将C语言转成汇编语言
gcc -S hello.i -o hello.s
3 汇编: 将汇编语言转成二进制文件
gcc -c hello.s -o hello.o
4 链接: 链接代码需要用到其他文件(库文件等)
gcc hello.o -o hello
参数的介绍
参数介绍
-E: 只进行预编译,不做其他处理
-c: 只是编译不链接 生成目标文件 .o
-S: 只是编译不汇编 生成汇编代码
-g: 在可执行程序中包含标准调试信息
-o file 输出文件 到 file 这个文件中
-v: 打印出编译器内部编译各过程的命令行信息和编译器的版本
-I dir: 在头文件的搜索路径列表中添加dir目录
-L dir: 在库文件的搜索路径列表中添加dir目录
-static 链接静态库
-l library 链接名为library的库文件
2: 分文件编程
如果玩过单片机啥的都会知道,当你的代码写的很多,一般分文件写就会更好的阅读,或者说各个模块都分别有一个.c 和.h的代码。或者就是大家合作做东西,都会分开 各做各的,然后给你接口你去使用。
比如你做一个项目 避障智能小车
网络: A同学
超声波: B同学
电机: C同学
好处:分模块的编程思想
a.分工明确(功能责任划分)、b.方便调试、c.主程序简洁
分文件编程步骤:
1.写一个调用的函数 add.c
#include "add.h"
int add(int num1,int num2)
{
return (num1+num2);
}
2.声明函数 add.h
#ifndef __ADD_H
#define __ADD_H
int add(int num1,int num2);
#endif
3.main函数(主程序入口)
#include <stdio.h>
#include "add.h"
int main()
{
int ret = add(1,2);
printf("ret = %d\n",ret);
return 0;
}
4.编译main函数的和 函数的一起编译。
gcc main.c add.c -o main
5.运行程序
./main
3: 库(静态库和动态库)
3.1: 库的基本介绍
共享库,静态库,动态库相关资料参考来源网址
3.2: 静态和动态库的区别
1.静态库
静态函数库: 是在程序执行前(编译)就加入到目标程序中去了;
优点:
1. 运行快,
2. 静态库被打包到应用程序中加载速度快。
3. 发布程序无需提供静态库,因为已经在APP中,移植方便。
缺点:
1. 程序大
2. 更新,部署,发布麻烦(一更新就要往厂家发)
3. 链接时完整地拷贝至可执行文件中,别多次使用就有多份冗余拷贝。
2.动态库
动态函数库: 是在程序执行时动态(临时)由目标程序去调用;
优点:
1. 程序小
2. 链接时不复制,程序运行时由系统动态加载到内存,供内存调用,系统只加载一次,多个程序可以共用,节省内存。
3.程序升级简单,因为APP里面没有库的源代码,升级之后只要库名字不变,函数名以及参数不变,只是实现做了优化,就能加载成功。
缺点:
1. 运行慢
2. 加载速度比静态库慢
3. 发布程序需要提供依赖的动态库。
3.3: 库的制作及使用
3.3.1: 静态库制作
静态库文件名格式: libxxx.a
库名前加lib
库的名称xxx
库名后缀.a
0-首先我们写几个代码
main.c
void func1();
void func2();
int main()
{
func1();
func2();
return 0;
}
func1.c
#include <stdio.h>
void func1()
{
printf("This is func1\n");
}
func2.c
#include <stdio.h>
void func2()
{
printf("This is func2\n");
}
步骤1:将func1.c func2.c 编译成二进制 (.o文件)
我们在编译程序的时候在加一个 -c
gcc -c func1.c func2.c
这样会得到两个.o文件 分别是 func1.o func2.o
步骤2:然后将这两个.o文件生成静态库
名字随意,我这里就叫 my_static 吧
ar -crv libmy_static.a func1.o func2.o
或者
ar rcs libmy_static.a func1.o func2.o
注意:
静态库是.a结尾
这样你会得到了一个名字叫 libmy_static.a 的文件
步骤3:编译main
gcc main.c -o main -L . -l my_static
-L: 是指告诉gcc编译器先从-L指定的路径去找静态库,
. : 是当前路径的意思
my_static: 是我最后想生成的文件名(这里可随意起名字)
完整步骤
3.3.2: 动态库制作
步骤1:直接对.c文件生成.so文件
比如我这里就叫 my_synamic 吧
gcc -fPIC -shared -o libmy_dynamic.so func1.c func2.c
或者
gcc -fpic -shared libmy_dynamic.so func1.c func2.c
-fPIC: 选项作用于编译阶段,在生成目标文件时就得使用该选项,
以生成位置无关的代码。
-shared: 指定生成动态库
步骤2:编译成可执行文件
gcc main.c -o main -L . -l my_synamic
步骤3:运行main程序
这里就和静态库不一样了,不能直接运行。
方法一(很少用):
把.so 结尾的文件拷贝到 /usr/lib/中去或者 ldd命令查看一下得到的位置(得切换会超级用户 在前面加sudo)
ldd main
我这里默认是去 /lib/x86_64-linux-gnu
找的,所以我们可以直接把我们的动态库放到那里去。
sudo cp libmy_dynamic.so /usr/lib/
或
sudo cp libmy_dynamic.so /lib/x86_64-linux-gnu/
这样就可以直接运行了
方法二:(推荐)
1.添加指令:export LD_LIBRARY_PATH=”路径”
例如 :
export LD_LIBRARY_PATH=/home/pikaqiu/linux_c/library/dynamicLibMake
路径可以通过输入命令pwd查看
但是这种也是有点缺陷,就是你换了一个窗口就没办法运行了
所以直接写一个脚本。
start.sh
export LD_LIBRARY_PATH=/home/pikaqiu/linux_c/library/dynamicLibMake/
./main
给 脚本 可执行权限
chmod +x start.sh
运行
./start.sh
这样不管换了新的窗口我们直接运行脚本就可以了.