Makefile 管理工具 — Automake and Autoconf

来源:互联网 发布:淘宝开店详细流程 编辑:程序博客网 时间:2024/05/01 11:41

该工程下载路径:http://files.cnblogs.com/iTsihang/hello-2.0.zip

automake 参考资料:http://www.linuxforum.net/books/automake.html

autoconf 参考资料:http://www.linuxforum.net/books/autoconf.html

automake源码下载:ftp://ftp.gnu.org/gnu/automake/

autoconf源码下载:ftp://ftp.gnu.org/gnu/autoconf/

 

Automake支持的目录结构

目前automake支持三种目录层次:flat、shallow和deep。

  • flat(平),指的是所有文件都位于同一个目录中

      就是所有源文件、头文件以及其他库文件都位于当前目录中,且没有子目录。Termutils就是这一类。

  • shallow(浅),指的是主要的源代码都储存在顶层目录,其他各个部分则储存在子目录中

      就是主要源文件在当前目录中,而其它一些实现各部分功能的源文件位于各自不同的目录。automake本身就是这一类。

  • deep(深),指的是所有源代码都被储存在子目录中;顶层目录主要包含配置信息

本例子目录结构如图所示,属于deep类:

复制代码
 1 hello-2.0 2 ├── aclocal.m4 3 ├── AUTHORS 4 ├── autom4te.cache 5 │   ├── output.0 6 │   ├── output.1 7 │   ├── requests 8 │   ├── traces.0 9 │   └── traces.110 ├── autoscan.log11 ├── ChangeLog12 ├── configure13 ├── configure.in14 ├── COPYING -> /usr/share/automake-1.11/COPYING15 ├── depcomp -> /usr/share/automake-1.11/depcomp16 ├── home17 │   ├── li18 │   │   ├── inc19 │   │   │   └── li.h20 │   │   └── src21 │   │       ├── li.c22 │   │       ├── Makefile.am23 │   │       └── Makefile.in24 │   ├── wang25 │   │   ├── inc26 │   │   │   └── wang.h27 │   │   └── src28 │   │       ├── Makefile.am29 │   │       ├── Makefile.in30 │   │       └── wang.c31 │   └── zhang32 │       ├── inc33 │       │   └── zhang.h34 │       └── src35 │           ├── Makefile.am36 │           ├── Makefile.in37 │           └── zhang.c38 ├── INSTALL -> /usr/share/automake-1.11/INSTALL39 ├── install-sh -> /usr/share/automake-1.11/install-sh40 ├── main41 │   ├── main.c42 │   ├── Makefile.am43 │   └── Makefile.in44 ├── Makefile.am45 ├── Makefile.in46 ├── missing -> /usr/share/automake-1.11/missing47 ├── NEWS48 ├── park49 │   ├── Makefile.am50 │   ├── Makefile.in51 │   ├── public.c52 │   └── public.h53 └── README54 55 13 directories, 39 files
复制代码

这是一个基本的架构结构,可以形成一个比较成熟的软件框架。

 

例子介绍

如上图所示为该例子的结构层次,有主目录main,家目录home和公园目录part。home下根据姓氏分了三家:li家,wang家和zhang家,每家都有相同的结构:src和inc;part是三家共同拥有的公共目录,里面包含了三家共用的接口;main目录是我们的主目录,存放执行入口。每家的人(程序)做一件事情,那就是依次在入口(main)中说一句:hello。

复制代码
 1 int main(void) 2 { 3  4       /* access home li */ 5       lisayhello(); 6  7       /* access home wang */ 8       wangsayhello(); 9 10       /* access home zhang */11       zhangsayhello();12 13       return 0;14 }
复制代码

 

步骤    

分别在每个目录下创建Makefile.am文件,并编辑

在使用autoconf和automake自动工具生成Makefile的时候,该工具会在工程目录下查找Makefile.am文件,有该文件的目录下会自动生成相应的Makefile文件。当然也可以后期手动添加。一般的生成顺序是:

1> 根据工程结构,在需要生成Makefile的目录下创建Makefile.am文件。

我们需要生成Makefile的目录有home/li/src/,home/wang/src/,home/zhang/src/和main/,所以我们共需创建4个Makefile.am文件。

2> 编辑Makefile.am文件,指出需要在该目录下完成的工作,如编译一些源文件,链接某些库文件等等;

这里有三类Makefile.am,现在分类介绍其在整个工程目录中实现的功能。  

家目录下的Makefile.am主要用来编译同目录下的源文件。例如,编辑home/li/src/Makefile.am如下:

复制代码
1 noinst_PROGRAMS= li           #生成的目标 2 li_SOURCES= li.c              #生成目标依赖的源      3 4 li_LDADD=                     #可能需要加载的其他的目标5 li_LDFLAGS=                   #加载目标需要的配置参数6 li_a_LIBADD=                  #可能需要加载的其他的库7 8 DEFS += -D_GNU_SOURCE
复制代码

同理编辑其他两个姓氏目录以及公园目录下的Makefile.am文件,替换相应字段即可。

主目录下的Makefile.am主要用来生成最终的可执行目标程序,它需要家目录下的姓氏提供方法。编辑如下:

复制代码
 1 # executable file last created 2  3 noinst_PROGRAMS= hello 4  5 # main entry file 6  7 hello_SOURCES= main.c 8  9 # object file that needed10 11 OBJECTS= $(top_srcdir)/home/li/src/li.o\12 13          $(top_srcdir)/home/zhang/src/zhang.o\14 15          $(top_srcdir)/home/wang/src/wang.o16 17 # load object file when linking18 19 hello_LDADD= $(OBJECTS)20 21 # flags of libs22 23 hello_LDFLAGS= -D_GNU_SOURCE24 25 DEFS += -D_GNU_SOURCE26 27 #LIBS= -lpthread
复制代码

篇幅有限,每行的具体含义,请自行查看相关文档,或者我提供的链接可能对你有帮助。

顶层目录Makefile.am给automake工具提供工程下各个子目录的路径。在make的时候,告诉automake应该进哪些目录执行makefile,执行过程按照SUBDIRS 定义顺序来。编辑如下:

复制代码
 1 SUBDIRS= home/li/src\ 2  3                  home/zhang/src\ 4  5                  home/wang/src\ 6  7                  park\ 8  9                  main10 11 # automake need known where it is12 13 CURRENTPATH= $(shell pwd)14 15 # head files while linking16 17 INCLUDES= -I$(CURRENTPATH)/park/include -I$(CURRENTPATH)/home/li/inc -I$(CURRENTPATH)/home/wang/inc -I$(CURRENTPATH)/home/zhang/inc18 19 export INCLUDES
复制代码

 

运行autoscan命令,生成configure.scan文件

复制代码
 1 #                                               -*- Autoconf -*- 2  3 # Process this file with autoconf to produce a configure script. 4  5 AC_PREREQ([2.68]) 6  7 AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS]) 8  9 AC_CONFIG_SRCDIR([home/zhang/src/zhang.c])10 11 AC_CONFIG_HEADERS([config.h])12 13 # Checks for programs.14 15 AC_PROG_CC16 17 # Checks for libraries.18 19 # Checks for header files.20 21 # Checks for typedefs, structures, and compiler characteristics.22 23 # Checks for library functions.24 25 AC_CONFIG_FILES([Makefile26 27                  home/li/src/Makefile28 29                  home/wang/src/Makefile30 31                  home/zhang/src/Makefile32 33                  park/Makefile34 35                  main/Makefile])36 37 AC_OUTPUT
复制代码

通过上面的步骤,可以发现,autoscan工具会自动查找工程目录,包括子目录,在发现有Makefile.am存在的目录下为即将创建的Makefile指明工程路径。当然,可以根据自己的需要,指定该文件,如下。

 

修改configure.scan文件

$ mv configure.scan configure.in(老版本支持configure.ac,我没用过)

修改如下部分:

复制代码
 1 AC_CONFIG_SRCDIR([main/main.c])      #指明目录源文件,特指主方法所在源文件 2  3 #AC_CONFIG_HEADERS([config.h])                     4  5 AM_INIT_AUTOMAKE("hello", "2.0.0")    #最终生成的目标文件和版本,版本一般在打包的时候用 6  7 # Checks for programs. 8  9 AC_PROG_CC10 11 # Checks for libraries.12 13 # Checks for header files.14 15 # Checks for typedefs, structures, and compiler characteristics.16 17 # Checks for library functions.18 19 AC_OUTPUT([Makefile20 21           home/li/src/Makefile22 23           home/wang/src/Makefile 24 25           home/zhang/src/Makefile26 27           park/Makefile28 29           main/Makefile])
复制代码

 

在工程目录下创建:NEWS、 README、 ChangeLog 、AUTHORS

touch NEWS README ChangeLog AUTHORS

 

将/usr/share/automake-1.X/目录下的 depcomp 和 complie 文件拷贝到本目录下

1 cp /usr/share/automake-1.x/depcomp   .2 cp /usr/share/automake-1.x/compile  .

 

运行aclocal命令

根据 configure.in 的配置,生成 aclocal.m4 文件和 autom4te.cache 目录

 

运行autoconf

根据configure.in的配置生成配置脚本 — configure。

 

运行automake --add-missing

运行automake后,就从各个目录下的Makefile.am中读取make的宏定义和目标或者更多参数,根据这些配置自动生成新的文件 — Makefile.in。例如,在Makefile.am中定义了要生成的目标文件,同时可能会定义生成目标所需的源文件,依赖文件—包括依赖的头文件,目标文件,目标库等,同时也指定软件的加载标志。

当然,为了符合GNU 发布软件的标准,首次运行该命令后会提示缺少:AUTHORS,ChangeLog,NEWS,README。这些文件,你可以手动创建,如果不发布无需编辑。同时,也会生成install-sh,missing,INSTALL,COPYING 链接文件,这些链接文件分别指向auto工具默认安装路径:/usr/share/automake-1.XX/目录下的相应文件。

此外,最重要的文件就是生成了除过上面的Makefile.in文件外,还生成了我们需要的configure文件。

 

配置

配置工程安装和运行环境,通过该步骤可以向工程传递配置和安装信息等,最后生成Makefile。

 

编译

 执行Makefile ,编译工程,链接文件,生成目标执行程序。

 

问题探讨

指定的install-sh,missing,INSTALL,COPYING文件的链接错误

这根据自己系统当前安装的工具而定,你可以将这些链接重新指向automake安装目录下的相应文件,也可以将automake安装目录下的文件拷贝到工程目录。但是考虑GNU 风格的完整性,建议大家执行拷贝步骤,这样也省去重新链接的麻烦,更主要的是不会像链接那样对安装路径和版本的依赖那么高,拷贝会一劳永逸。

 

如果因为任何原因修改了configure.in,修改后如果不执行autoconf命令,那么是不会生成新的configure

在编译的时候,出现类似 “In function `_start'”的错误

我们知道,automake要求在每个具有源程序的目录下都要创建Makefile.am。但是automake编译完成后,该工具会自动执行链接过程,即将编译的目标文件自动链接成同名的可执行程序,可是源程序中没有指定的入口(在Linux中为”main”方法),所以在链接的时候无法找到入口而产生 “链接错误”。

修改方法:此时该目录下已经生成Makefile.in,编辑找到链接执行出,屏蔽掉。例如本例中屏蔽掉home/li/src/Makefile.in的189行:

#   $(li_LINK) $(li_OBJECTS) $(li_LDADD) $(LIBS)

其他类似问题都做相同处理。

 

各个目标之间的依赖处理

编译的时候,可能会遇到依赖问题。所谓依赖问题,如下:

      A → B

      B → C

      …...

A依赖B, B依赖C,那么在生成目标A的时候,就需要将B和C同时告知A。在本例子中,生成目标hello的时候需要li.o,wang.o,zhang.o目标,所以在最终链接的时候需要将这些目标链接进去。

现在有个问题我没解决,如果编译目标文件(而非最终的可执行文件)的时候,如果存在上面的依赖关系,怎么处理?在这个例子工程的park/public.c文件,如果里面的广播方法被某一家调用,那么这块的Makefile.am怎么写(我没搞定)?

最后,如果因需要,或者任何原因修改了Makefile.am,那么需要运行automake更新makefile.in


转载自:http://www.cnblogs.com/iTsihang 

1 0
原创粉丝点击