makefile 转载

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

http://blog.csdn.net/lanmanck/article/details/8462088程序员

一.库shell

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

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

二.静态库与动态库函数

1.静态库工具

这类库的名字通常是libname.a.利用静态库编写的文件比较大,缘由是整个函数库中的数据都被整合进目标代码文件中去。它的优势是,编译后的执行程序不须要外部的函数库支持,由于全部使用的函数都已经被编译进可执行文件了。一样它的不足,若是静态函数库改变了,那么你的程序必须从新编译,并且体积也较大。操作系统

2.动态库.net

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

三.库的建立

静态库的建立

 

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\n");
     printf("a+b=%d\n",ADD(a,b));
     printf("a-b=%d\n",SUB(a,b));
     printf("a*b=%d\n",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的编写

相关文章
相关标签/搜索