如何自动生成Makefile

来源:互联网 发布:苹果迅雷没网络异常 编辑:程序博客网 时间:2024/05/18 01:26

四:自动生成makefile

4.1 以helloworld.c为源文件

root@parson-desktop:/home/parson/tmp/automk# ls

hellolinux.c

4.2.使用Autoscan工具生成configure.ac文件

root@parson-desktop:/home/parson/tmp/automk# autoscan

程序“autoscan”尚未安装。  您可以使用以下命令安装:

apt-get install autoconf

安装autoconf,输入如下命令

root@parson-desktop:/home/parson/tmp/automk# apt-get install autoconf

正在读取软件包列表... 完成

正在分析软件包的依赖关系树      

正在读取状态信息... 完成      

将会安装下列额外的软件包:

  automake autotools-dev

建议安装的软件包:

  autoconf2.13 autoconf-archive gnu-standards autoconf-doc libtool gettext

下列【新】软件包将被安装:

  autoconf automake autotools-dev

升级了 0 个软件包,新安装了 3 个软件包,要卸载 0 个软件包,有 273 个软件包未被升级。

需要下载 1,444kB 的软件包。

解压缩后会消耗掉 4,325kB 的额外空间。

您希望继续执行吗?[Y/n]y

获取:1 http://ftp.sjtu.edu.cn/ubuntu/ lucid/main autoconf 2.65-3ubuntu1 [772kB]

获取:2 http://ftp.sjtu.edu.cn/ubuntu/ lucid/main autotools-dev 20090611.1 [64.1kB]                               

获取:3 http://ftp.sjtu.edu.cn/ubuntu/ lucid/main automake 1:1.11.1-1 [608kB]                                     

下载 1,444kB,耗时 2分 59秒 (8,044B/s)                                                                             

选中了曾被取消选择的软件包 autoconf。

(正在读取数据库 ... 系统当前总共安装有 149752 个文件和目录。)

正在解压缩 autoconf (从 .../autoconf_2.65-3ubuntu1_all.deb) ...

选中了曾被取消选择的软件包 autotools-dev。

正在解压缩 autotools-dev (从 .../autotools-dev_20090611.1_all.deb) ...

选中了曾被取消选择的软件包 automake。

正在解压缩 automake (从 .../automake_1%3a1.11.1-1_all.deb) ...

正在处理用于 man-db 的触发器...

正在处理用于 doc-base 的触发器...

Processing 39 changed 1 added doc-base file(s)...

Registering documents with scrollkeeper...

正在处理用于 install-info 的触发器...

正在设置 autoconf (2.65-3ubuntu1) ...

正在设置 autotools-dev (20090611.1) ...

正在设置 automake (1:1.11.1-1) ...

update-alternatives: 使用 /usr/bin/automake-1.11 来提供 /usr/bin/automake (automake),于 自动模式 中。

root@parson-desktop:/home/parson/tmp/automk# ls

hellolinux.c

再一次执行autoscan

root@parson-desktop:/home/parson/tmp/automk# autoscan

root@parson-desktop:/home/parson/tmp/automk# ls

autoscan.log  configure.scan  hellolinux.c

生成了autoscan.log和configure.scan

我们看看生成了两个文件是什么东西

root@parson-desktop:/home/parson/tmp/automk# cat autoscan.log

autoscan.log没有内容

root@parson-desktop:/home/parson/tmp/automk# cat configure.scan

#                                               -*- Autoconf -*-

# Process this file with autoconf to produce a configure script. 

AC_PREREQ([2.65])

AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])

AC_CONFIG_SRCDIR([helloworld.c])

AC_CONFIG_HEADERS([config.h]) 

# 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

(1)AC_PREREQ宏声明本文件要求的autoconf版本,本例使用的版本为2.65。

(2)AC_INIT宏用来定义软件的名称和版本等信息,”FULL-PACKAGE-NAME”为软件包名称,”VERSION”为软件版本号,”BUG-REPORT-ADDRESS”为BUG报告地址(一般为软件作者邮件地址)。

(3)AC_CONFIG_SRCDIR宏用来侦测所指定的源码文件是否存在,来确定源码目录的有效性。此处为当前目录下的helloworld.c。

(4)AC_CONFIG_HEADER宏用于生成config.h文件,以便autoheader使用。

(5)AC_PROG_CC用来指定编译器,如果不指定,选用默认gcc。

(6)AC_OUTPUT用来设定 configure 所要产生的文件,如果是makefile,configure会把它检查出来的结果带入makefile.in文件产生合适的makefile。使用 Automake时,还需要一些其他的参数,这些额外的宏用aclocal工具产生。

root@parson-desktop:/home/parson/tmp/automk# mv configure.scan configure.ac

root@parson-desktop:/home/parson/tmp/automk# vim configure.ac

#                                               -*- Autoconf -*-

# Process this file with autoconf to produce a configure script. 

AC_PREREQ([2.65])

AC_INIT(hellolinux,1.0,somy@xiajiashan.com)

AM_INIT_AUTOMAKE(hellolinux,1.0)

AC_CONFIG_SRCDIR([hellolinux.c])

#AC_CONFIG_HEADERS([config.h]) 

# 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)~

"configure.ac" 21L, 498C 已写入                                                            

root@parson-desktop:/home/parson/tmp/automk# ls

autoscan.log  configure.ac  hellolinux.c

4.3 利用aclocal工具制作aclocal.m4文件

root@parson-desktop:/home/parson/tmp/automk# aclocal

root@parson-desktop:/home/parson/tmp/automk# ls

aclocal.m4  autom4te.cache  autoscan.log  configure.ac  hellolinux.c

4.4 利用autoconf制作configure工具

root@parson-desktop:/home/parson/tmp/automk# autoconf

root@parson-desktop:/home/parson/tmp/automk# ls

aclocal.m4  autom4te.cache  autoscan.log  configure  configure.ac  hellolinux.c

4.5编写Makefile.am文件

root@parson-desktop:/home/parson/tmp/automk# vim Makefile.am 

AUTOMAKE_OPTIONS=foreign

bin_PROGRAMS=hellolinux

hellolinux_SOURCES=hellolinux.c~

"Makefile.am" [新] 3L, 81C 已写入       

4.6 通过automake产生Makefile.in文件                                                  

root@parson-desktop:/home/parson/tmp/automk# ./configure

configure: error: cannot find install-sh, install.sh, or shtool in "." "./.." "./../.."

root@parson-desktop:/home/parson/tmp/automk# automake --add-missing

configure.ac:6: installing `./install-sh'

configure.ac:6: installing `./missing'

Makefile.am: installing `./depcomp'

root@parson-desktop:/home/parson/tmp/automk# ls

aclocal.m4      autoscan.log  configure     depcomp       install-sh   Makefile.in

autom4te.cache  config.log    configure.ac  hellolinux.c  Makefile.am  missing

4.7 通过运行./configure产生Makefile文件

root@parson-desktop:/home/parson/tmp/automk# ./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 whether the C compiler works... yes

checking for C compiler default output file name... a.out

checking for suffix of executables...

checking whether we are cross compiling... no

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

configure: creating ./config.status

config.status: creating Makefile

config.status: executing depfiles commands

root@parson-desktop:/home/parson/tmp/automk# ls

aclocal.m4      autoscan.log  config.status  configure.ac  hellolinux.c  Makefile     Makefile.in

autom4te.cache  config.log    configure      depcomp       install-sh    Makefile.am  missing 



补充:

4.automake这一步是创建Makefile很重要的一步,automake要用的脚本配置文件是Makefile.am,用户需要自己创建相应的文件。之后,automake工具转换成Makefile.in。在该例中,笔者创建的文件为Makefile.am如下所示:AUTOMAKE_OPTIONS=foreignbin_PROGRAMS= hellohello_SOURCES= hello.c下面对该脚本文件的对应项进行解释。· 其中的AUTOMAKE_OPTIONS为设置automake的选项。由于GNU(在第1章中已经有所介绍)对自己发布的软件有严格的规范,比如必须附 带许可证声明文件COPYING等,否则automake执行时会报错。automake提供了三种软件等级:foreign、gnu和gnits,让用 户选择采用,默认等级为gnu。在本例使用foreign等级,它只检测必须的文件。· bin_PROGRAMS定义要产生的执行文件名。如果要产生多个执行文件,每个文件名用空格隔开。· hello_SOURCES定义“hello”这个执行程序所需要的原始文件。如果”hello”这个程序是由多个原始文件所产生的,则必须把它所用到的 所有原始文件都列出来,并用空格隔开。例如:若目标体“hello”需要“hello.c”、“sunq.c”、“hello.h”三个依赖文件,则定义 hello_SOURCES=hello.c sunq.c hello.h。要注意的是,如果要定义多个执行文件,则对每个执行程序都要定义相应的file_SOURCES。接下来可以使用automake对其生成“configure.in”文件,在这里使用选项“—adding-missing”可以让automake自动添加有一些必需的脚本文件。如下所示:最上层的要写明AUTOMAKE_OPTIONS = foreign如果这个目录没有要编译的文件,只包含了子目录,则只写个SUBDIRS = dir1就ok了。 例如我的工程,最上层只是包含了源码目录,于是就写了 AUTOMAKE_OPTIONS=foreignSUBDIRS=src如果有文件要编译,则要指明target 先。比如我的src目录底下既有文件,又有目录,而src的这层目录中的文件最后是要编译成一个可执行文件,则src目录下的Makefile.am这么写。bin_PROGRAMS= myprogramSUBDIRS= sub1myprogram_SOURCES= \ a.cpp\ b.cpp\ # 要编译的源文件。这儿的_SOURCES是关键字EXTRA_DIST= \ a.h \ b.h# 不用编成.o,但生成target myprogram也需要给编译器处理的头文件放这里myprogram_LDADD = libsub1.a 这个_LDADD是关键字,# 最后生成myprogram这个执行文件,还要link src/sub1这个目录中的内容编成的一个lib :libsub1.a,myprogram_LDFLAGS = -lpthread -lglib-2.0 -L/usr/bin $(all_libraries)# myprogram还要link系统中的动态so,以此类推,需要连自编译的so,也写到这个关键字 _LDFLAGS后面就好了。AM_CXXFLAGS = -D_LINUX# 传递给g++编译器的一些编译宏定义,选项,INCLUDES=-IPassport -Isub1/ -I/usr/include/glib-2.0\ -I/usr/lib/glib-2.0/include $(all_includes)# 传递给编译器的头文件路径。下面是sub1种生成lib的Makefile.amnoinst_LIBRARIES = libprotocol.a # 不是生成可执行文件,而是静态库,target用noinst_LIBRARIES libprotocol_a_SOURCES = \ alib.cppEXTRA_DIST = mylib.h\ alib.hINCLUDES= -I../ $(all_includes)AM_CXXFLAGS = -D_LINUX -DONLY_EPOLL -D_SERVERok ,最后补上AC_PROG_RANLIB涵义,如果要自己生成lib,然后link到最终的可执行文件中,则要加上这个宏,否则不用。2 一点讨论 每个目录至少都要有一个target,或者是可执行文件或者是lib,似乎对目录的划分带来点局限。比如我的目录结构如果是这样 ./Src ./Src/sub1 ./Src/sub2 而我想这样,sub1,sub2都没有target,目录划分只是为了区别代码的不同模块,然后把两个目录中编译出的中间文件一起link ,得到最后需要的 myprogram 。 似乎在Src/Makefile.am中要这么写 myprogram_SOURCES = sub1/a.cpp \ sub2/b.cpp[root@localhost automake]# automake --add-missingconfigure.in: installing ''./install-sh''configure.in: installing ''./missing''Makefile.am: installing ''depcomp''[root@localhost automake]# lsaclocal.m4 autoscan.log configure.in hello.c Makefile.am missingautom4te.cache configure depcomp install-sh Makefile.in config.h.in可以看到,在automake之后就可以生成configure.in文件。5.运行configure在这一步中,通过运行自动配置设置文件configure,把Makefile.in变成了最终的Makefile。如下所示:[root@localhost automake]# ./configure可以看到,在运行configure时收集了系统的信息,用户可以在configure命令中对其进行方便地配置。在./configure的自定 义参数有两种,一种是开关式(--enable-XXX或--disable-XXX),另一种是开放式,即后面要填入一串字符(--with- XXX=yyyy)参数。读者可以自行尝试其使用方法。另外,读者可以查看同一目录下的”config.log”文件,以方便调试之用。到此为止,makefile就可以自动生成了。回忆整个步骤,用户不再需要定制不同的规则,而只需要输入简单的文件及目录名即可,这样就大大方便了用户的使用。下面的图3.9总结了上述过程:图3.9 autotools生成Makefile流程图使用autotools所生成的Makefileautotools生成的Makefile除具有普通的编译功能外,还具有以下主要功能(感兴趣的读者可以查看这个简单的hello.c程序的makefile):1.make键入make默认执行”make all”命令,即目标体为all,其执行情况如下所示:[root@localhost automake]# make此时在本目录下就生成了可执行文件“hello”,运行“./hello”能出现正常结果,如下所示:[root@localhost automake]# ./helloHello!Autoconf!2.make install此时,会把该程序安装到系统目录中去,如下所示:[root@localhost automake]# make installif Gcc -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE=\"hello\" -DVERSION=\"1.0\" -I. -I. -g -O2 -MT hello.o -MD -MP -MF ".deps/hello.Tpo" -c -o hello.o hello.c; \then mv -f ".deps/hello.Tpo" ".deps/hello.Po"; else rm -f ".deps/hello.Tpo"; exit 1; fiGcc -g -O2 -o hello hello.omake[1]: Entering directory ''/root/workplace/automake''test -z "/usr/local/bin" || mkdir -p -- "/usr/local/bin"/usr/bin/install -c ''hello'' ''/usr/local/bin/hello''make[1]: Nothing to be done for ''install-data-am''.make[1]: LeaVing directory ''/root/workplace/automake''此时,若直接运行hello,也能出现正确结果,如下所示:[root@localhost automake]# helloHello!Autoconf!3.make clean此时,make会清除之前所编译的可执行文件及目标文件(object file, *.o),如下所示:[root@localhost automake]# make cleantest -z "hello" || rm -f hellorm -f *.o4.make dist此时,make将程序和相关的文档打包为一个压缩文档以供发布,如下所示:[root@localhost automake]# make dist[root@localhost automake]# ls hello-1.0-tar.gzhello-1.0-tar.gz可见该命令生成了一个hello-1.0-tar.gz的压缩文件。由上面的讲述读者不难看出,autotools确实是软件维护与发布的必备工具,也鉴于此,如今GUN的软件一般都是由automake来制作的。 

0 0