autools工具制作Makefile

一、configure.ac 或 configure.in

在顶级目录执行autoscan, 会生成configure.scan ,将configure.scan 改成configure.ac 或configure.in    

[root@nn nn]# ls
include  src

[root@nn nn]# autoscan
[root@nn nn]# ls
autoscan.log  configure.scan  include  src
[root@nn nn]# mv configure.scan configure.in
AC_PREREQ([2.63])                                                #自动检测到你系统中装的autotools的版本号
AC_INIT([zhangna], [1.0], [BUG-REPORT-ADDRESS])                 #需要你改,可执行文件的名字、版本号
AM_INIT_AUTOMAKE(zhangna,1.0)                                   #这个一定要写上,省得下一步生成不了aclocal.m4
AC_CONFIG_SRCDIR([include/libscanname.h])                       #用来定位自己目录所在的宏,里面的内容是所在目录下的任意一个文件
AC_CONFIG_HEADERS([config.h])                                   #这个是用来生成config.h的宏

# Checks for programs.
AC_PROG_CC

# Checks for libraries.


# Checks for header files.
AC_CHECK_HEADERS([arpa/inet.h fcntl.h locale.h netdb.h stdlib.h string.h sys/socket.h unistd.h])

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.
AC_FUNC_MALLOC
AC_CHECK_FUNCS([dup2 getcwd memset mkdir setlocale socket strstr uname])
AC_CONFIG_FILES(Makefile)                                      <span style="color:#009900;"> #生成Makefile的位置</span>
AC_OUTPUT
            
[root@nn nn]# aclocal
[root@nn nn]# ls
aclocal.m4  autom4te.cache  autoscan.log  configure.in  include  src
[root@nn nn]# ls
aclocal.m4  autom4te.cache  autoscan.log  config.h.in  configure  configure.in  include  Makefile.am  src
[root@nn nn]# vim Makefile.am                                             #Makefile.am 需要手动写

AUTOMAKE_OPTIONS=foreign
INCLUDES= -I ./include/ -I /usr/include/rpm -I /usr/include/libxml2/       #所要包含的头文件
bin_PROGRAMS=zhangna                                                       #所要生成的可执行程序
zhangna_SOURCES=./src/main.c ./src/libconnect.c ./src/libscanname.c ./src/systeminfo.c ./src/translate.c              #所需的源文件
zhangna_LDADD= -lxml2  -lrpm                                              #所需要的链接库



[root@nn nn]# automake
configure.in:6: required file `./install-sh' not found
configure.in:6:   `automake --add-missing' can install `install-sh'
configure.in:6: required file `./missing' not found
configure.in:6:   `automake --add-missing' can install `missing'
Makefile.am: required file `./depcomp' not found
Makefile.am:   `automake --add-missing' can install `depcomp'
[root@nn nn]# automake --add-missing
configure.in:6: installing `./install-sh'
configure.in:6: installing `./missing'
Makefile.am: installing `./depcomp'
[root@nn nn]# ls
aclocal.m4  autom4te.cache  autoscan.log  config.h.in  configure  configure.in  depcomp  include  install-sh  Makefile.am  Makefile.in  missing  src
[root@nn nn]# automake
[root@nn nn]# ls
aclocal.m4  autom4te.cache  autoscan.log  config.h.in  configure  configure.in  depcomp  include  install-sh  Makefile.am  Makefile.in  missing  src
[root@nn nn]# automake
[root@nn nn]# ./configure 
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for gcc... gcc
checking for C compiler default output file name... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables... 
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking for style of include used by make... GNU
checking dependency style of gcc... gcc3
checking how to run the C preprocessor... gcc -E
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking for ANSI C header files... yes
checking for sys/types.h... yes
checking for sys/stat.h... yes
checking for stdlib.h... yes
checking for string.h... yes
checking for memory.h... yes
checking for strings.h... yes
checking for inttypes.h... yes
checking for stdint.h... yes
checking for unistd.h... yes
checking arpa/inet.h usability... yes
checking arpa/inet.h presence... yes
checking for arpa/inet.h... yes
checking fcntl.h usability... yes
checking fcntl.h presence... yes
checking for fcntl.h... yes
checking locale.h usability... yes
checking locale.h presence... yes
checking for locale.h... yes
checking netdb.h usability... yes
checking netdb.h presence... yes
checking for netdb.h... yes
checking for stdlib.h... (cached) yes
checking for string.h... (cached) yes
checking sys/socket.h usability... yes
checking sys/socket.h presence... yes
checking for sys/socket.h... yes
checking for unistd.h... (cached) yes
checking for stdlib.h... (cached) yes
checking for GNU libc compatible malloc... yes
checking for dup2... yes
checking for getcwd... yes
checking for memset... yes
checking for mkdir... yes
checking for setlocale... yes
checking for socket... yes
checking for strstr... yes
checking for uname... yes
configure: creating ./config.status
config.status: creating Makefile
config.status: creating config.h
config.status: executing depfiles commands
[root@nn nn]# ls
aclocal.m4      autoscan.log  config.h.in  config.status  configure.in  include     Makefile     Makefile.in  src
autom4te.cache  config.h      config.log   configure      depcomp       install-sh  Makefile.am  missing      stamp-h1
[root@nn nn]# make






二、automake制作Makefile 带静态库、动态库

静态库

1. 目录结构如下:
example
|——src 目录(存放源代码文件)
        |——hello.c
|——lib 目录(存放用来生成库的文件)
        |——test.c 用来生成静态库libhello.a
|——include 目录(存放程序中使用的头文件)
        |——hello.h
2. 编写的各个目录下的源文件
include/hello.h 文件

extern void print(char *);
lib/test.c 文件
#include<stdio.h>
void print(char *msg)
{
printf(“%s\n”, msg);
}
src/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 目录下。写法为:
bin_PROGRAMS=/root/test/hello,后面的第四、五行也相对应地变为:
_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 并修改其内容。
#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      <span style="color:#FF6666;">//这一行也需要加上,否则可能会造成生成aclocal.m4失败</span>
# Checks for programs.
AC_PROG_CC
# Checks for libraries.
AC_PROG_RANLIB       <span style="color:#FF6666;">//需要加入的内容,因为使用了静态库</span>
# Checks for header files.
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
AC_CONFIG_FILES(Makefile)
AC_OUTPUT


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、autoheader、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、autoheader、automake --add-missing、./configure、make,
生成可执行文件hello
8. 执行make install 进行安装 (/usr/local/bin/hello),最后输入hello 来运行程序,查看效果:
Hello static library!
执行成功!


使用gcc 创建和使用静态库
1. 编写mylib.h 文件
#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. 编写各个目录下的源文件如下:
include/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) 编写lib/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          //此处一定要加上,表示利用libtool来自动生成动态库

AC_CONFIG_FILES([Makefile])
AC_OUTPUT


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

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、autoheader、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 动态库搜索路径,运行生成的可执行文件。
---------------------------------------------------------------------------

AUTOMAKE_OPTIONS=foreign

INCLUDES=-I$(top_srcdir)/libpr/include -I$(top_srcdir)/vt/include

noinst_PROGRAMS =libvt.so    
libvt_so_SOURCES=vty/vtcmd.c vty/vtdrv.c vty/vty.c vty/evtd.c telnet/telcmd.c telnet/teldrv.c telnet/telnegot.c telnet/telsvr.c telnet/telsess.c vty/defcmd.c vty/vtobj.c
libvt_so_LDFLAGS = -fPIC -shared
libvt_so_LDADD=$(top_srcdir)/libpr/libpr.a

bin_PROGRAMS = test_telnetd
test_telnetd_SOURCES = test/test_telnetd.c 
test_telnetd_LDADD=$(top_srcdir)/libpr/libpr.a libvt.so

上面这段代码是从我的一个工程的Makefile.am中摘抄过来的,使用不少技巧。

1、动态库实际上也是ELF格式,所以我们使用PROGRAMS宏,automake将他按执行文件规格设置环境,如果使用noinstall_LIBRARIES那么就变成*.a静态库了。

2、因为是动态库,所以我们有必要加入-fPIC -shared

3、 test_telnetd需要调用libvt.so,所以他们之间存在依赖关系。我们将libvt.so直接添加在LDADD 中,automake会自动他们建立依赖关系,在Makefile中可以到test_telnetd_DEPENDENCIES,里面包含 libvt.so。

这里有几个要紧需要注意:

1、$(bin_PROGRAMS)编译顺序在$(noinstall_PROGRAMS)之前,因为test_telnetd需要libvt.so,所以会找不到libvt.so。

2、在LDADD中如果使用-lvt不会建立依赖关系,如果使用$(top_srcdir)/vt/libvt.so也不行。

3、实际上如果不行的话,我们可以直接使用test_telnetd_DEPENDENCIES来指定libvt.so

4、如果需要make install 安装libvt.so到lib,那么使用XXX_PROGRAMS=...的方法,然后指定XXXbin=...就行了。类似于bin_PROGRAMS。

这里使用到的技巧都很有用,值得记录下来。

出处:使用Automake 创建和使用静态库/动态库


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值