使用Automake 建立和使用静态库

使用Automake 建立和使用静态库linux


1. 目录结构以下:shell

example
|——src 目录(存放源代码文件)
        |——hello.c
|——lib 目录(存放用来生成库的文件)
        |——test.c 用来生成静态库libhello.a
|——include 目录(存放程序中使用的头文件)
        |——hello.h


2. 编写的各个目录下的源文件缓存

hello.h 文件  
extern void print(char *);  

test.c 文件  
#include<stdio.h>  
void print(char *msg)  
{  
    print(“%s/n”, msg);  
}  

hello.c 文件  
#include “hello.h”  
int main()  
{  
    print(“Hello static library!”);//这里用到的是静态库中的函数  
    return 0;  
}

 
3. 编写lib/Makefile.am 文件
函数

noinst_LIBRARIES=libhello.a  
libhello_a_SOURCES=test.c  
AUTOMAKE_OPTIONS=foreign

 
第一行noinst 表示生成的是静态库,不须要make install ,直接制定它的位置和名字就
可使用。
第二行表示用来生成静态库的源文件。若是要把静态库生成到其余地方,能够在=后面
加上路径(建议用绝对路径,并将所要用到的静态库生成在同一个文件夹下,如lib)。
第三行AUTOMAKE_OPTIONS 是Automake 的选项。Automake 主要是帮助开发 GNU 软
件的人员来维护软件,因此在执行Automake 时,会检查目录下是否存在标准 GNU 软件中
应具有的文件,例如 'NEWS'、'AUTHOR'、 'ChangeLog' 等文件。设置为foreign 时,Automake
会改用通常软件的标准来检查。若是不加这句的话,须要在autoconf以前,先执行touch NEWS
README AUTHORS ChangeLog 来生成'NEWS'、'AUTHOR'、 'ChangeLog' 等文件
4. 编写src/Makefile.am 文件
测试

AUTOMAKE_OPTIONS=foreign  
INCLUDES= -I../include  
bin_PROGRAMS=hello  
hello_SOURCES=hello.c  
hello_LDADD=../lib/libhello.a

 
第二行指定头文件的位置,-I 是idirafter 的缩写。../include 指定头文件的位置,..是上
一级目录,也就是这里的example 目录。
第三行指定生成可执行文件名hello,在这里可执行文件生成在src 下,建议将可执行文
件生成到一个特定的文件夹下,让它和源代码分开,如/root/test 目录下。写法为:
this

bin_PROGRAMS=/root/test/hello,后面的第4、五行也相对应地变为:  
_root_test_hello_SOURCES=hello.c  
_root_test_hello_LDADD=../lib/libhello.a

 
第四行指定生成可执行文件hello 的源代码文件,若是hello.c 在其余目录下,须要加上
完整的路径。
第五行指定须要使用静态库的位置。
5. 生成静态库文件lib/libhello.a。
执行autoscan 生成configure.scan 文件,将它重命名为configure.in 并修改其内容。
code

#configure.in  
# Process this file with autoconf to produce a configure script.  
AC_PREREQ(2.59)  
AC_INIT(libhello.a,1.1,[])  
AM_INIT_AUTOMAKE  
# Checks for programs.  
AC_PROG_CC  
# Checks for libraries.  
AC_PROG_RANLIB//须要加入的内容,由于使用了静态库  
# Checks for header files.  
# Checks for typedefs, structures, and compiler characteristics.  
# Checks for library functions.  
AC_OUTPUT([Makefile])  
AC_INIT(FILE)

 
该宏用来检查源代码所在路径,autoscan 会自动产生,通常无须修改它。
AM_INIT_AUTOMAKE(PACKAGE,VERSION)
这个是使用 Automake 所必备的宏,PACKAGE 是所要产生软件的名称,VERSION 是版
本编号。也能够把包和版本号等信息放在AC_INIT(FILE) 宏里。
AC_PROG_CC
检查系统可用的C 编译器,若源代码是用C 写的就须要这个宏。
AC_OUTPUT(FILE)
设置 configure 所要产生的文件,如果Makefile ,configure 便会把它检查出来的结果
填充到Makefile.in 文件后产生合适的 Makefile。 后面的FILE 是一个Makefile 的输出列表,
你能够选着将要输出的Makefile 的位置和个数。建议只在src 中输出Makefile。
在lib 目录下依次执行 aclocal 、autoconf、automake --add-missing、./configure、make,
此时在该目录下就能够看到生成的静态库文件libhello.a
6. 在src 目录下,执行autoscan 生成configure.scan 文件,将它重命名为configure.in 并修
改其内容。
接口

#configure.in  
# Process this file with autoconf to produce a configure script.  
AC_PREREQ(2.59)  
AC_INIT(hello,1.1,[])  
AM_INIT_AUTOMAKE  
AC_CONFIG_SRCDIR([hello.c])  
# Checks for programs.  
AC_PROG_CC  
# Checks for libraries.  
# Checks for header files.  
# Checks for typedefs, structures, and compiler characteristics.  
# Checks for library functions.  
AC_OUTPUT([Makefile])

 
7. 在src 目录下依次执行 aclocal 、autoconf、automake --add-missing、./configure、make,
生成可执行文件hello
8. 执行make install 进行安装,最后输入hello 来运行程序,查看效果:
Hello static library!
执行成功!
使用gcc 建立和使用静态库
1. 编写mylib.h 文件
ip

#ifndef _mylib_h_  
#define _mylib_h_  
void welcome();  
void outstring(const char * str);  
#endif

 
2. 编写mylib.c 文件,用来生成静态库。
内存

#include <stdio.h>  
void welcome()  
{  
printf(“welcome to libmylib/n”);  
}  
void outstring(const char * str)  
{  
if(str!=NULL)  
printf(“%s”,str);  
}

 
3. 编译源文件,产生目标代码

gcc –o mylib.o –c mylib.c


4. 将上面产生的目标文件加入到静态库中,并把静态库拷贝到系统默认的路径

ar rcs libmylib.a mylib.o  
cp libmylib.a /usr/lib/

 
5. 编写测试程序来使用刚才建立的静态库 libmylib.a

#include “mylib.h”  
#include <stdio.h>  
Int main()  
{  
printf(“create and use library:/n”);  
welcome();  
outstring(“It’s a successful/n”);  
}

 
6. 编译使用库函数的程序

gcc –o test test.c -lmylib


运行./test 查看结果。


使用Automake 建立和使用动态库


动态库与静态库的差异在于:动态库是在程序执行的时候加载到内存,供调用函数使用。
1. 目录结构以下:

 

example  
|——src 目录(存放源代码文件)  
|——hello.c  
|——lib 目录(存放用来生成库的文件)  
|——test.c 用来生成动态库libhello.la  
|——include 目录(存放程序中使用的头文件)  
|——hello.h

 
2. 编写各个目录下的源文件以下:

hello.h 文件  
extern void print(char *);  
test.c 文件  
#include<stdio.h>  
void print(char *msg)  
{  
print(“%s/n”, msg);  
}  
hello.c 文件  
#include “hello.h”  
int main()  
{  
print(“Hello static library!”);//这里用到的是动态库中的函数  
return 0;  
}

 
3. 在lib 目录下编译须要生成动态库的文件,生成动态库,并安装到系统的标准库中,供
程序调用。具体步骤以下:
(1) 编写Makefile.am 文件

AUTOMAKE_OPTIONS=foreign  
lib_LTLIBRARIES=libhello.la  
libhello_la_SOURCES=test.c

 
这里lib_LTLIBRARIES 的意思是生成的动态库,而后指定动态库依赖的源文件
test.c ,如有多个源文件用空格隔开。
(2) 在lib 目录下,用命令autoscan 产生configure.scan 文件,并更名为configure.in。 这
里需加上宏AC_PROG_LIBTOOL,表示利用libtool 来自动生成动态库

#configure.in  
# Process this file with autoconf to produce a configure script.  
AC_PREREQ(2.59)  
AC_INIT(hello,1.0, [miaoquan@nou.com.cn])  
AM_INIT_AUTOMAKE  
AC_CONFIG_SRCDIR([test.c])  
#AC_CONFIG_HEADER([config.h])  
# Checks for programs.  
AC_PROG_CC  
# Checks for header files.  
# Checks for typedefs, structures, and compiler characteristics.  
# Checks for library functions.  
AC_PROG_LIBTOOL  
AC_CONFIG_FILES([Makefile])  
AC_OUTPUT

 
(3) 执行命令aclocal、libtoolize -f -c 、autoconf、automake --add-missing、./configure、
make、make install 将动态库安装到系统的标准库中,以供调用(通常为/usr/local/lib)。
注:libtoolize 提供了一种标准的方式来将libtool 支持加入一个软件包,而GNU libtool 是
一个通用库支持脚本,将使用动态库的复杂性隐藏在统1、可移植的接口中。
4. 生成src 目录下的hello 可执行文件
(1) 编写src/Makefile.am 文件

AUTOMAKE_OPTIONS=foreign  
INCLUDES= -I../include  
bin_PROGRAMS=hello  
hello_SOURCES=hello.c  
hello_LDADD=-lhello

 
-ldir 指定编译时搜索库的路径。与静态库不一样的是,建立动态库时不用指定库路
径,编译器自动在标准库中查找libhello.so 文件。
(2) 执行autoscan 生成configure.scan 文件,将它重命名为configure.in 并修改其内容。

# configure.in  
# Process this file with autoconf to produce a configure script.  
AC_PREREQ(2.59)  
AC_INIT(hello,1.0, [miaoquan@nou.com.cn])  
AM_INIT_AUTOMAKE  
AC_CONFIG_SRCDIR([hello.c])  
#AC_CONFIG_HEADER([config.h])  
# Checks for programs.  
AC_PROG_CC  
# Checks for header files.  
# Checks for typedefs, structures, and compiler characteristics.  
# Checks for library functions.  
AC_CONFIG_FILES([Makefile])  
AC_OUTPUT

  (3) 在src 目录下编译并生成目标文件,执行命令aclocal、libtoolize -f -c 、autoconf、 automake --add-missing、./configure、make,此时你必定会以为,成功近在咫尺了。再 执行目标文件./hello,结果却在你的意料以外: ./hello: error while loading shared libraries: libhello.so.0 : cannot open shared object file: No such file or directory 在执行目标文件的时候,Shell 找不到共享库的位置,须要咱们手工载入库路径。 5. shell 搜索动态库路径位置的两种方法 (1) 使用命令导入动态库的路径,命令以下: export LD_LIBRARY_PATH=dir (如/usr/local/lib) (2) 修改/etc/ld.so.conf 文件,加入搜索路径,修改后用ldconfig 命令载入修改。 将本身可能存放库文件的路径都加入到/etc/ld.so.conf 中是明智的选择 ^_^。添加 方法也极其简单,将库文件的绝对路径直接写进去就OK 了,一行一个。例如: /usr/local/lib /usr/lib /lib 须要注意的是:这种搜索路径的设置方式对于程序链接时的库(包括共享库和静态 库)的定位已经足够了,可是对于使用了共享库的程序的执行仍是不够的。这是 由于 为了加快程序执行时对共享库的定位速度,避免使用搜索路径查找共享库的低效率,所 以是直接读取库列表文件 /etc/ld.so.cache 从中进行搜索的。/etc/ld.so.cache 是一个非 文本的数据文件,不能直接编辑,它是根据 /etc/ld.so.conf 中设置的搜索路径由 /sbin/ldconfig 命令将这些搜索路径下的共享库文件集中在一块儿而生成的(ldconfig 命令 要以 root 权限执行)。所以,为了保证程序执行时对库的定位,在 /etc/ld.so.conf 中 进行了库搜索路径的设置以后,还必需要运行 /sbin/ldconfig 命令更新 /etc/ld.so.cache 文件以后才能够。ldconfig ,简单的说,它的做用就是将/etc/ld.so.conf 列出的路径下的库 文件 缓存到/etc/ld.so.cache 以供使用。所以当安装完一些库文件,(例如刚安装好glib), 或者修改ld.so.conf 增长新的库路径后,须要运行一下/sbin/ldconfig 使全部的库文件都 被缓存到ld.so.cache 中,若是没作,即便库文件明明就在/usr/lib 下的,也是不会被使 用的,结果编译过程当中报错,缺乏xxx 库,去查看发现明明就在那放着,搞的想大骂 computer 蠢猪一个^_^。极力推荐使用这种方法! 利用gcc 建立和使用动态库 1. 用下面的命令将mylib.c 程序建立成一个动态库: gcc –fPIC –o mylib.o –c mylib.c gcc –shared –o libtt.so mylib.o -fPIC 做用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code), 则产生的代码中,没有绝对地址,所有使用相对地址,故而代码能够被加载器加载到内存的 任意位置,均可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不 是固定的。 -shared 做用于连接阶段,实际传递给连接器ld,让其添加做为共享库所须要的额外描 述信息,去除共享库所不需的信息。 也能够直接使用下面一条命令: gcc –fPIC –shared –o libtt.so mylib.c 2. 将动态库拷贝到linux 的标准库中,usr/local/lib 或者/usr/lib 或者/lib: cp libttt.so /usr/local/lib 3. 编译src 目录下的源程序时,指定动态库文件的目录,调用动态库中的函数 gcc –o test test.c /usr/lib/libttt.so 4. 设置shell 动态库搜索路径,运行生成的可执行文件

相关文章
相关标签/搜索