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

45 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第22天,点击查看活动详情

【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;    //平年
 }