找回密码
 立即注册
  • QQ空间
  • 回复
  • 收藏

嵌入式linux第三篇

admin 2019-4-24 06:12 163人围观 嵌入式相关

一、静态库和动态库

1、两种库的介绍与对比

1.1、首先什么是库呢?

库就是已经写好的、具有实现特定功能的、可以重用的代码。

1.2、静态库和动态库的有啥区别呢?

静态库是后缀名为.a的归档文件(格式为:libname.a),在程序编译时会被连接到目标代码中,所以程序运行时将不再需要该静态库。动态库是后缀名为.so的归档文件(格式为:libname.so[主版本号.次版本号.发行号]),在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入。所以,后续运行时需要函数库的支持。

1.3、静态库有什么弊端呢?

第一,因为静态库是在编译时嵌入到使用它的程序中的,所以容易造成资源空间的浪费。第二,当静态库更新时,所有使用它的程序也要重新编译,这就会造成一个小小的改动也变得极其麻烦。所以在一些项目开发中基本上用的都是动态库。

2、 gcc命令的相关库选项



3、 库的生成

3.1  生成静态库

vim Sort_Array.c   内容如下
    /******************    排序代码  *************************/void Sort_Array(int *Array, int lenth){ int i,j,temp;for(i=0;i<lenth;i++) {for(j=0;j<lenth-1-i;j++) {if(Array[j] > Array[j+1]) { temp = Array[j];Array[j] = Array[j+1];Array[j+1] = temp; } } }}

    vim  main.c    内容如下

      #include<stdio.h>int main(int argc,char **argv){int i;int Array[10]={1,5,3,2,7,8,45,62,24,66};for(i=0;i<10;i++)printf("%d\t",Array[i]);
      Sort_Array(Array,10); //排序printf("\n");
      for(i=0;i<10;i++)printf("%d\t",Array[i]);return0;}

      第一步:编译源程序Sort_Array.c生成目标文件Sort_Array.o

        gcc -c Sort_Array.c -o Sort_Array.o
        第二步:对目标文件*.o进行归档,生成 lib*.a库文件
          ar crsv libSort_Array.a Sort_Array.o

          第3步:编译程序的时候链接静态库
            gcc -o main main.c -static -L./ -lSort_Array


            3.2  生成动态库

            第一步:编译源程序Sort_Array.c生成目标文件Sort_Array.o
              gcc -fPiC -c Sort_Array.c -o Sort_Array.o
              第二步:对目标文件*.o进行归档,生成 lib*.so库文件
                gcc -shared -o libSort_Array.so Sort_Array.o
                第3步:编译并链接动态库

                  gcc -o main main.c -L./ -lSort_Array
                  此时已经生成可执行文件main,但是你会发现你直接运行时会出错,因为系统找不到这个库,所以我们要把库文件拷贝到/lib或者/usr/lib(系统默认搜索库路径)下。



                  二、makefile介绍

                  1、简介

                  Make(工程管理器)是一款能够帮助我们自动检查文件的更新情况,并通过makefile(工程管理配置文件)指定相关配置选项来指引其进行编译工作的软件。

                  2、书写格式
                    object:source1.o source2.o          //这里指明了终极目标项和依赖项  gcc -o object source1.o source2.o  //要执行的命令语句source1.o:source1.c                 //指明目标和依赖项  gcc -c source1.c -o source1.o    //要执行的命令语句
                    source2.o:source2.c //指明目标和依赖项  gcc -c source2.c -o source2.o     //要执行的命令语句
                    首先我们要知道第一个目标被称为终极目标,也就是当我们执行make的时候要生成的那个文件,其次要知道命令要以TAB制表符开头的。

                    makefile的执行过程:

                    因为刚开始的时候终极目标以及其依赖文件都不存在,所以会执行下面两段语句生成source1.o和source2.o,最后再根据这两个生成终极目标。之后若是有哪个源文件(如:source1.c)改变了,执行make时将会发现目标文件(source1.o)比依赖文件(source1.c)旧,这时就会重新生成目标文件,最后通过重新生成的目标文件生成终极目标。

                    3、变量

                    3.1  自定义变量
                      a = hi                  //定义变量a的值a += everybody          //在变量后面追加一个值s = $(a) xiao ming      //引用变量的值($代表取该变量的值)object:        @echo $(s)      //打印变量s的值(@代表不打印命令行本身) @echo $(a)~
                      3.2  系统预定义变量(系统提前帮我们定义好的变量)



                      通过变量的使用上面那段代码可以重写成一下这个样子

                        OBJ = source1.o  source2.o  //定义变量EXE = object$(EXE):$(OBJ)               //这里指明了终极目标项和依赖项   $(CC) -o object $(OBJ)  //使用系统预定义变量
                        source1.o:source1.c//生成目标source1.o   $(CC) -c source1.c -o source1.o    
                        source2.o:source2.c//生成目标source2.o   $(CC) -c source2.c -o source2.o     
                        3.3  自动变量(上面的系统预定义变量,如果你不重新赋值,那它的值就是固定不变,相对而言自动变量是可以自动的变化的)



                        通过自动变量对上面的代码进一步改写

                          OBJ = source1.o source2.o //定义变量EXE = object$(EXE):$(OBJ) //这里指明了终极目标项和依赖项   $(CC) -o $(@) $(^)       //使用自动变量代表目标文件和依赖文件
                          source1.o:source1.c//生成目标source1.o   $(CC) -c $(^) -o $(@)    
                          source2.o:source2.c//生成目标source2.o $(CC) -c $(^) -o $(@)

                          4、规则

                          4.1、隐式规则(make会根据目标文件去寻找同名的依赖文件,并生成对与的编译语句)
                            OBJ = source1.o source2.o //定义变量EXE = object$(EXE):$(OBJ) //这里指明了终极目标项和依赖项   $(CC) -o $(@) $(^)    //使用系统预定义变量CC
                            上面的代码改写成这样就可以了,因为make会通过.o目标文件自动去找到同名的.c并生成对应的编译语句。

                            但是隐式规则业也有不足的地方,就是当我们的目标只是一个动作而不是文件的时候,如下面所示:

                              OBJ = source1.o source2.o //定义变量EXE = object$(EXE):$(OBJ) //这里指明了终极目标项和依赖项   $(CC) -o $(@) $(^)      clean:                     //清理文件   $(RM) $(OBJ) $(EXE)     //执行清理命令.PHONY:clean       //.PHONY明确告诉makefile不要对clean运用隐式规则
                              clean这个目标只是想执行一个动作而已,但假如刚好有一个clean.c文件的话,那因为隐式操作,则会生成对应的编译语句,从而造成混淆。所以,我们必须通过指示符.PHONY告诉makefile不要对clean运用隐式操作。我们把这种不能进行隐式操作的目标叫做伪目标。

                              4.2、模式规则(%通配符)

                                OBJ = source1.o source2.o //定义变量EXE = object$(EXE):$(OBJ) //这里指明了终极目标项和依赖项 $(CC) -o $(@) $(^) //使用系统预定义变量CC
                                %.o:%.c            //模式通配,将所有.c编译成同名的.o文件 $(CC) -c $(^) -o $(@)

                                模式规则利用通配符一句话可以生成多个目标文件。

                                4.3、多目标规则   (多个目标具有相同的依赖项)

                                  a.o b.o c.o:head.h    //多个目标依赖head.h
                                  当head.h头文件一改变,多个目标将都重新进行编译。

                                  4.4、双冒号规则(一个目标可以有多种编译方法,分别通过冒号说明)

                                  当同一个文件作为多个双冒号规则的目标时,这些规则会被独立地处理。可以把他们当成多条不同普通的规则一样。当双冒号规则的每一个依赖文件发生改变时,只执行该规则对应的命令。如下所示:

                                    object:a.c    cc a.c -o object    object:b.c    cc b.c -o object     object:d.c    cc d.c -o object
                                    假如a.c发生改变,则只会编译a.c,而其它的则不编译。

                                    5、条件判断
                                      ifdef  VARIABLE          //判断定义了VARIABLE这个变量obj = $(VARIABLE)elseobj = EXAMPLEendif
                                      $(obj):object.oifeq ($(CC),gcc)       // 判断变量CC是否跟gcc相等    $(CC) object.o -o $(obj)else gcc object.o -o $(obj)endif 


                                      6、make的命令行选项



                                      注:makefile这一块内容比较晦涩我们无需深究,只要能写下简单的makefile以及能够看得懂就好了,因为复杂的makefile都是用工具生成的(如autotools)。

                                      总结:这一篇就介绍到这里,精彩后续!




                                      ----------------------------------------------------------------------------------------------------------------------
                                      我们尊重原创,也注重分享,文章来源于微信公众号:交流基地,建议关注公众号查看原文。如若侵权请联系qter@qter.org。
                                      ----------------------------------------------------------------------------------------------------------------------

                                      鲜花

                                      握手

                                      雷人

                                      路过

                                      鸡蛋

                                      yafeilinux和他的朋友们微信公众号二维码

                                      微信公众号

                                      专注于Qt嵌入式Linux开发等。扫一扫立即关注。

                                      Qt开源社区官方QQ群二维码

                                      QQ交流群

                                      欢迎加入QQ群大家庭,一起讨论学习!

                                      我有话说......