zoukankan      html  css  js  c++  java
  • makefile 转载

    http://blog.csdn.net/hongfuhaocomon/article/details/51523394

    http://blog.csdn.net/lanmanck/article/details/8462088

    一.库

    什么是库,简单的可以说是可执行代码的二进制形式,能够被操作系统载入内存执行。操作系统的不同,二者的库也是不兼容的,如windows与linux.

    库又分为静态库和动态库,动态库又称为共享库。linux下静态库(.a)文件,动态库(.so)文件。主要存放函数库的路径有:/lib , /usr/lib.

    二.静态库与动态库

    1.静态库

    这类库的名字一般是libname.a.利用静态库编写的文件比较大,原因是整个函数库中的数据都被整合进目标代码文件中去。它的优点是,编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进可执行文件了。同样它的不足,如果静态函数库改变了,那么你的程序必须重新编译,而且体积也较大。

    2.动态库

    名字一般是libname.so.相对于静态函数库,动态函数库在编译的时候并没有被编译进目标代码中,你的程序执行到相关函数是菜调用函数库里的函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。而且如果多个应用程序都要使用同一函数库,动态库就非常适合,可以减少应用程序的体积。

    三.库的创建

    静态库的创建

    gcc -c filen.c

    ar -cr libname.a file1.o file2.o 。。

    ar:静态函数库创建的命令
    -c :create的意思
    -r :replace的意思,表示当前插入的模块名已经在库中存在,则替换同名的模块。如果若干模块中有一个模块在库中不存在,ar显示一个错误信息,并不替换其他同名的模块。默认的情况下,新的成员增加在库德结尾处。

    动态库的创建

    gcc -shard -fpic -o libname.so test1.c test2.c ....

    -fpic:产生代码位置无关代码

    -shared 生成一个共享库

    四.实际操作

    1.编写三个简单函数ADD.c SUB.c MUL.c如下

    ADD.c

     #include <stdio.h>
     int ADD(int a, int b)
      {
          return a+b;
      }


     SUB.c

    #include <stdio.h>
      int SUB(int a ,int b)
      {
          return a-b;
      }


    MUL.c

     #include <stdio.h>
      int MUL(int a , int b)
      
      {
          return a*b;
      }
     和一个头文件 fun.h

    #ifdef __FUN_H_
    #define __FUN_H_
      extern ADD(int a , int b);
      extern SUB(int a , int b);
      extern MUL(int a , int b);
    #endif
    以及一个main函数main.c

    main.c

    #include <stdio.h>

     #include <fun.h>
     int main (void)
    {
         int a=5;
         int b=10;
         printf("a=5,b=10 ");
         printf("a+b=%d ",ADD(a,b));
         printf("a-b=%d ",SUB(a,b));
         printf("a*b=%d ",MUL(a,b));
         return 0;
     }
     其中main.c 放在~/app下 fun.h ADD.c SUB.c MUL.c放在~/src下

    2.生成静态库

    [hongfuhao@localhost src]$ ls
    ADD.c  fun.h  makefile  MUL.c  SUB.c
    [hongfuhao@localhost src]$ gcc -c *.c
    [hongfuhao@localhost src]$ ls
    ADD.c  ADD.o  fun.h  makefile  MUL.c  MUL.o  SUB.c  SUB.o
    [hongfuhao@localhost src]$ ar -cr libfun.a *.o
    [hongfuhao@localhost src]$ ls
    ADD.c  ADD.o  fun.h  libfun.a  makefile  MUL.c  MUL.o  SUB.c  SUB.o

    上中libfun.a即是一个静态库

    生成动态库

    [hongfuhao@localhost src]$ ls
    ADD.c  ADD.o  fun.h  libfun.a  makefile  MUL.c  MUL.o  SUB.c  SUB.o
    [hongfuhao@localhost src]$ gcc -shared -fpic -o libfun.so  *.c  
    [hongfuhao@localhost src]$ ls
    ADD.c  ADD.o  fun.h  libfun.a  libfun.so  makefile  MUL.c  MUL.o  SUB.c  SUB.o

    上中libfun.so 就是一个动态库

    3.静态库与动态库的使用

    对main.c进行编译

    [hongfuhao@localhost app]$ ls
    main.c  makefile
    [hongfuhao@localhost app]$ gcc main.c
    main.c:14:17: 错误:fun.h:没有那个文件或目录


    编译器报错 找不到头文件  需要指定头文件的位置 

    -I选项 指定头文件的路径

    [hongfuhao@localhost app]$ gcc -I../src main.c
    /tmp/ccZw9v3Q.o: In function `main':
    main.c:(.text+0x30): undefined reference to `ADD'
    main.c:(.text+0x5a): undefined reference to `SUB'
    main.c:(.text+0x84): undefined reference to `MUL'
    collect2: ld 返回 1    

      链接器再一次报错  未能找库

    -L选项来指定库的路径

    -l选项来指定库的名字 (去掉lib和.a .so)剩下的部分  即-lfun

    [hongfuhao@localhost app]$ gcc -I../src main.c -L../src -lfun -o app
    [hongfuhao@localhost app]$ ls
    app  main.c  makefile

    生成一个可执行文件 app

    [hongfuhao@localhost app]$ ./app
    ./app: error while loading shared libraries: libfun.so: cannot open shared object file: No such file or directory

    执行时出错  找不到动态库

    [hongfuhao@localhost app]$ file app
    app: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped

    这时我们可以发现 系统编译时默认使用的是动态链接  执行时我们需要指定动态库的位置

    两种方法:

    1:将函数库移动到/lib 或者/usr/lib下 (需要root权限)

    2:修改一个环境变量 LD_LIBRARY_PATH

    在这里我采用第二种方法

    [hongfuhao@localhost app]$ ./app
    ./app: error while loading shared libraries: libfun.so: cannot open shared object file: No such file or directory
    [hongfuhao@localhost app]$ file app
    app: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
    [hongfuhao@localhost app]$ cd ../src
    [hongfuhao@localhost src]$ ls
    ADD.c  ADD.o  fun.h  libfun.a  libfun.so  makefile  MUL.c  MUL.o  SUB.c  SUB.o
    [hongfuhao@localhost src]$ pwd
    /home/hongfuhao/src
    [hongfuhao@localhost src]$ cd ../app
    [hongfuhao@localhost app]$ ls
    app  main.c  makefile
    [hongfuhao@localhost app]$ export LD_LIBRARY_PATH='/home/hongfuhao/src'
    [hongfuhao@localhost app]$ ./app
    a=5,b=10
    a+b=15
    a-b=-5
    a*b=50

    可以看到程序成功执行

    如果想采用静态链接方式  需要-static关键字

    [hongfuhao@localhost app]$ ls
    main.c  makefile
    [hongfuhao@localhost app]$ gcc -static -I../src main.c -o bpp -L../src -lfun
    [hongfuhao@localhost app]$ ls
    bpp  main.c  makefile
    [hongfuhao@localhost app]$ ./bpp
    a=5,b=10
    a+b=15
    a-b=-5
    a*b=50

    这时再看bpp文件

    [hongfuhao@localhost app]$ file bpp
    bpp: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.18, not stripped

    采用的静态链接执行时不需要指定库的路径

    两个文件app与bpp的大小 使用du命令

    [hongfuhao@localhost app]$ du app
    8       app
    [hongfuhao@localhost app]$ du bpp
    744     bpp

    看一个文件执行依赖的动态库

    [hongfuhao@localhost app]$ ldd app
            linux-vdso.so.1 =>  (0x00007ffe7a3bf000)
            libfun.so => /home/hongfuhao/src/libfun.so (0x00007f775018f000)
            libc.so.6 => /lib64/libc.so.6 (0x00000030cee00000)
            /lib64/ld-linux-x86-64.so.2 (0x00000030ce600000)

    以上为app依赖的动态库文件
    [hongfuhao@localhost app]$ ldd bpp
            不是动态可执行文件

    bpp不是动态链接所以不显示

    上述就完成一个静态库和动态库的创建和使用

    五.makefile

    1.概述

    Linux 环境下的程序员如果不会使用GNU make来构建和管理自己的工程,应该不能算是一个合格的专业程序员,至少不能称得上是 Unix程序员。在 Linux(unix )环境下使用GNU 的make工具能够比较容易的构建一个属于你自己的工程,整个工程的编译只需要一个命令就可以完成编译、连接以至于最后的执行。不过这需要投入一些时间去完成一个或者多个称之为Makefile 文件的编写。

    所要完成的Makefile 文件描述了整个工程的编译、连接等规则。其中包括:工程中的哪些源文件需要编译以及如何编译、需要创建那些库文件以及如何创建这些库文件、如何最后产生想要得可执行文件。尽管看起来可能是很复杂的事情,但是为工程编写Makefile 的好处是能够使用一行命令来完成“自动化编译”,一旦提供一个(通常对于一个工程来说会是多个)正确的 Makefile。编译整个工程你所要做的唯一的一件事就是在shell 提示符下输入make命令。整个工程完全自动编译,极大提高了效率。

    make是一个命令工具,它解释Makefile 中的指令(应该说是规则)。在Makefile文件中描述了整个工程所有文件的编译顺序、编译规则。Makefile 有自己的书写格式、关键字、函数。像C 语言有自己的格式、关键字和函数一样。而且在Makefile 中可以使用系统shell所提供的任何命令来完成想要的工作。Makefile(在其它的系统上可能是另外的文件名)在绝大多数的IDE 开发环境中都在使用,已经成为一种工程的编译方法

    2.makefile 小结即规范

    Make  执行总目标

    Make clean 执行makefile 中的clean目标

    Make -C directory 到directory中执行make

    Make clean -C directory  同上两命令

    Make -f common_makefile 通过-f 指定一个makefile文件

    Make var=value   给makefie传一个参数其值为value

    # 注释

    VAR=XXX    定义变量VAR,强制赋值

    VAR+=XXX 追加

    VAR?=XXX   之前定义这用之前  没有定义 则定义

    Target: depend1 depend2 . .          #依赖可以是文件(目录)或其他目标

    (tab)  action1 action2            #动作那一行必须以TAB键打头

    Depend1:

    @(tab)Action1 action2    #@j键表示不打印该行动作信息

    2.实际操作

    编写自己的makefile

    使用之前静态库与动态库的案例

    创建一个makefile

      1 LIB_NAME?=fun
      2 
      3 all:static_library shared_library
      4 
      5 static_library:
      6     gcc -c *.c;
      7     ar  -cr lib${LIB_NAME}.a *.o;
      8 
      9 shared_library:
     10     gcc -shared -fpic -o lib${LIB_NAME}.so *.c;
     11 
     12 clean:
     13     rm -rf *.o
     14     rm -rf *.a *.so
     

    [hongfuhao@localhost src]$ ls
    ADD.c  fun.h  makefile  MUL.c  SUB.c

    makefile已经创建完成  

    make命令可以完成之前的操作

    [hongfuhao@localhost src]$ ls
    ADD.c  fun.h  makefile  MUL.c  SUB.c
    [hongfuhao@localhost src]$ make
    gcc -c *.c;
    ar  -cr libfun.a *.o;
    gcc -shared -fpic -o libfun.so *.c;
    [hongfuhao@localhost src]$ ls
    ADD.c  ADD.o  fun.h  libfun.a  libfun.so  makefile  MUL.c  MUL.o  SUB.c  SUB.o

    完成了静态库和动态库的创建  只需要make一下

    对main.c进行makefile的编写

    makefile                                                                                                                           
      1 APP_NAME?=APP
      2 
      3 all:lib_make
      4     gcc -static -I../src main.c -L../src -lfun -o ${APP_NAME};
      5 
      6 lib_make:
      7     make -C ../src;
      8 
      9 clean:
     10     rm -rf ${APP_NAME}

    [hongfuhao@localhost app]$ ls
    main.c  makefile
    [hongfuhao@localhost app]$ ls
    main.c  makefile

    只需要make一下 就可以完成main.c编译

    [hongfuhao@localhost app]$ make
    make -C ../src;
    make[1]: Entering directory `/home/hongfuhao/src'
    gcc -c *.c;
    ar  -cr libfun.a *.o;
    gcc -shared -fpic -o libfun.so *.c;
    make[1]: Leaving directory `/home/hongfuhao/src'
    gcc -static -I../src main.c -L../src -lfun -o APP;
    [hongfuhao@localhost app]$ ls
    APP  main.c  makefile

    生成一个APP的可执行文件makefile中执行的是静态链接

    可以直接执行APP

    [hongfuhao@localhost app]$ ./APP
    a=5,b=10
    a+b=15
    a-b=-5
    a*b=50

    程序成功执行

    即完成了一个简单的makefile的编写

  • 相关阅读:
    【转】Java并发编程:synchronized
    【转】Java并发编程:Thread类的使用
    【转】Java并发编程:如何创建线程?
    【计算机二级C语言】卷005
    【计算机二级C语言】卷004
    【计算机二级C语言】卷003
    【计算机二级C语言】卷002
    【计算机二级C语言】卷001
    汇编窥探Swift String的底层
    【KakaJSON手册】08_其他用法
  • 原文地址:https://www.cnblogs.com/bitter-first-sweet-last/p/7514804.html
Copyright © 2011-2022 走看看