写点什么

Linux 开发 _ 动态静态库创建与 Makefile 规则

作者:DS小龙哥
  • 2022 年 6 月 15 日
  • 本文字数:3897 字

    阅读完需:约 13 分钟

介绍 Linux 下静态库、动态库创建方式、完成静态库、动态库调用,贴出字符串处理、时间管理两个例子代码。


【1】查找文件:


[root@wbyq /]# find / -name stdio.h


【2】文本搜索工具:


# grep -q "12345" /123.c || echo "12345" >> /123.c


【3】文本修改工具:sed


【4】练习:


(1)制作动态库与静态库


(2)(扩展) 编写一个 find 功能的程序:可以查找指定目录下指定的文件。(关心多层目录)


(3)编写一个文本修改程序:可以修改指定文件中的内容。


​ (a) 将指定一行的内容全部替换为空格


​ (b) 将指定一个字符串替换为传入指定的字符串。./a.out /123.c 888 666


安装软件的命令:


[root@wbyq Packages]# rpm -ivh tree-1.5.3-2.el6.i686.rpm

任务 1:静态库与动态库

[root@wbyq test]# arm-linux-gcc 123.c -o app_1 
[root@wbyq test]# arm-linux-gcc -static 123.c -o app_2
复制代码


Linux 下库文件存放的位置: /lib (存放的是动态库)


.so 属于动态库, .a 属于静态库


动态库称为共享库:gcc 123.c -o app


共享库:程序在运行的时候去调用函数(载入函数)。


静态库:相关的函数在编译的时候就已经拷贝到目标中。


[root@wbyq test]# file app_1  app_1: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.27, not stripped 
[root@wbyq test]# file app_2 app_2: ELF 32-bit LSB executable, ARM, version 1 (SYSV), statically linked, for GNU/Linux 2.6.27, not stripped
[root@wbyq test]# gcc 123.c -o app_3
[root@wbyq test]# file app_3 app_3: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
复制代码


GCC 编译器的选项参数


-o :指定生成的目标文件名称
-c :指定生成.o文件(编译好的二进制文件)。
-g :在生成的目标文件中加入调试参数。适用于GDB调试。
-I :指定头文件的路径 。 gcc 123.c -I/work
-L :指定库文件的路径。gcc 123.c -L/work
-l :指定库文件的名称。gcc 123.c -L/work -labc
(实际上: libabc.so)
复制代码


生成动态库的指令


gcc -fPIC -shared -o <库文件名称>.so 源文件名称.c


库文件名称的命名规则: libxxx.so


调用动态库出现的错误:


[root@wbyq test]# ./a.out  ./a.out: error while loading shared libraries: libsum.so: cannot open shared object file: No such file or directory
复制代码


【1】将 xxx.so 直接放到/lib 目录下。


【2】设置环境变量:LD_LIBRARY_PATH (存放系统库文件的搜索路径)


生成静态库。 xxx.a


如果在相同的目录下有静态库和动态库,优先使用动态库


# ar crv libsum.a sum.o

任务 2:Makefile

Makefile :用于编写程序的编译规则。 make命令用于执行Makefile文件。
make常用的选项参数:
-n : 输出命令的执行过程,不执行名称
-s : 隐藏命令本身。 在命令前面加上@符号,可以隐藏命令本身。
$(shell pwd)
CC :特殊变量,用于存放编译器。
复制代码


练习


【1】Makefile 自动化编译


只是创建 3 个目录,每个目录下各有一个.c 一个.h,一个 Makefile 文件


在顶层目录下创建一个 Makefile 文件,,实现自动化编译。


【2】Makefile 自动化编译


只是创建 3 个目录,每个目录下各有一个.c 一个.h


在顶层目录下创建一个 Makefile 文件,实现自动化编译。

任务 3: 字符串案例代码

查找字符串并替换为其他字符串:


查找字符串并替换为其他字符串。  比如: “123dfjdfv123”  将123替换为888  结果: “888dfjdfv888”“123dfjdfv123”  将123替换为8888  结果: “8888dfjdfv8888”“123dfjdfv123”  将123替换为88  结果: “88dfjdfv88”

#include <stdio.h>int main(){ char src_str[100]; //源字符串 char new_str[50]; //替换后的字符串 char find_str[50]; //查找的字符串 int src_len=0,new_len=0,find_len=0; //存放字符串的长度 int i,j,n; int seek_len=0; //记录移动的长度 /*1. 录入字符串*/ printf("输入源字符串:"); scanf("%s",src_str); printf("输入查找的字符串:"); scanf("%s",find_str); printf("输入替换后的字符串:"); scanf("%s",new_str); /*2. 计算字符串的长度*/ while(src_str[src_len]!='\0') { src_len++; } while(find_str[find_len]!='\0') { find_len++; } while(new_str[new_len]!='\0') { new_len++; } /*3. 查找字符串*/ for(i=0;i<src_len;i++) { for(j=0;j<find_len;j++) { if(src_str[i+j]!=find_str[j]) { break; } } /*判断字符串是否查找成功*/ if(j==find_len) { /*4. 替换字符串*/ if(find_len==new_len) //第一种情况:长度相等 { for(n=0;n<find_len;n++) { src_str[i+n]=new_str[n]; //替换 } } else if(find_len<new_len) //第二种情况:查找的长度小于替换的长度,向后移动 { //计算向后移动的长度 seek_len=new_len-find_len; //开始移动 for(n=src_len-1;n>=i+find_len;n--) { src_str[n+seek_len]=src_str[n]; } //开始替换 for(n=0;n<new_len;n++) { src_str[i+n]=new_str[n]; } //添加结束符号 src_len=src_len+seek_len; //新的长度 src_str[src_len]='\0'; //结尾符号 } else if(find_len>new_len)//第三种情况:查找的长度大于替换的长度,向前移动 { //计算向前移动的长度 seek_len=find_len-new_len; //开始移动 for(n=i+find_len-seek_len;n<src_len;n++) { src_str[n]=src_str[n+seek_len]; } //替换 for(n=0;n<new_len;n++) { src_str[i+n]=new_str[n]; } src_len=src_len-seek_len; src_str[src_len]='\0'; } i+=find_len; } } printf("结果: %s\n",src_str); return 0;}
复制代码


模拟电子时钟


#include <stdio.h>#include <time.h>
int year=0,month=0,day=0,hour=0,minute=0,sec=0,week=0;void Get_RTC_Timer(int RTC_CNT);void GET_Week(int sec_cnt);int Get_year(int year);int main(){ while(1) { int data=time(NULL); Get_RTC_Timer(data); printf("当前时间为: %d年%d月%d日 %d时%d分%d秒 星期%d\n",year,month,day,hour,minute,sec,week); sleep(1); } return 0;}
const char month_r[12]={31,29,31,30,31,30,31,31,30,31,30,31}; //闰年月份表const char month_p[12]={31,28,31,30,31,30,31,31,30,31,30,31}; //平年月份表/*将秒为单位的时间转换为:年月日时分秒*/void Get_RTC_Timer(int RTC_CNT){ int i=0; int year_n=1970; //基准年份 GET_Week(RTC_CNT); //获取星期 /*根据基准年份,减去过去年份*/ while(RTC_CNT>=31536000) //31536000是平年的秒数, 31622400是闰年的秒数 { if(Get_year(year_n)) //闰年 { if(RTC_CNT>=31622400) { RTC_CNT-=31622400; //减去闰年一年的秒数 } else { break; //退出循环 } } else { RTC_CNT-=31536000; //减去平年一年的秒数 } year_n++; //年份累加 } year=year_n; //年份 /*减去过去的月份*/ if(Get_year(year_n)) //减去闰年的月份 { while(RTC_CNT>=month_r[i]*86400) //29*24*60*60 { RTC_CNT-=month_r[i]*86400; //减去过去的月份 i++; //累加每一个月的秒数 } } else //减去平年的月份 { while(RTC_CNT>=month_p[i]*86400) //86400=24*60*60 { RTC_CNT-=month_p[i]*86400; //减去过去的月份 i++; //累加每一个月的秒数 } } month=i+1; //因为月份是1月份开始,i是从0开始,这里的实际月份是i+1 day=1; //清空结构体成员--天数,用来存放新数据,天数是从1开始算 /*减去过去的天数*/ while(RTC_CNT>=86400) //86400=24*60*60 一天的秒数 { RTC_CNT-=86400; //减去一天的秒 day++; //天自增 } hour=0; //清空结构体成员--小时数,用来存放新数据,小时数是从0开始算 /*减去过去的小时*/ while(RTC_CNT>=3600) //3600=60*60 { RTC_CNT-=3600; //减去一小时的秒 hour++; //小时自增 } hour+=8; //时区相差8 minute=0;//清空结构体成员--分钟数,用来存放新数据,分钟数是从0开始算 /*减去过去的分钟*/ while(RTC_CNT>=60) { RTC_CNT-=60; minute++; } sec=RTC_CNT; //秒赋值,减到最后,剩下就是秒数}
/*获取星期*/void GET_Week(int sec_cnt){ int day_cnt=0;//天数 day_cnt=sec_cnt/86400; //得到总天数 switch(day_cnt%7) { case 0:week=4;break; case 1:week=5;break; case 2:week=6;break; case 3:week=7;break; case 4:week=1;break; case 5:week=2;break; case 6:week=3;break; }}

/*判断闰年闰年返回1平年返回0*/int Get_year(int year){ if((year%400==0)||((year%4==0)&&(year%100!=0)))//判断闰年的条件 { return 1; //闰年 } return 0; //平年}
复制代码


发布于: 刚刚阅读数: 4
用户头像

DS小龙哥

关注

之所以觉得累,是因为说的比做的多。 2022.01.06 加入

熟悉C/C++、51单片机、STM32、Linux应用开发、Linux驱动开发、音视频开发、QT开发. 目前已经完成的项目涉及音视频、物联网、智能家居、工业控制领域

评论

发布
暂无评论
Linux开发_动态静态库创建与Makefile规则_6月月更_DS小龙哥_InfoQ写作社区