Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1732178
  • 博文数量: 782
  • 博客积分: 2455
  • 博客等级: 大尉
  • 技术积分: 4140
  • 用 户 组: 普通用户
  • 注册时间: 2011-04-06 21:37
个人简介

Linux ,c/c++, web,前端,php,js

文章分类

全部博文(782)

文章存档

2015年(8)

2014年(28)

2013年(110)

2012年(307)

2011年(329)

分类:

2011-12-23 09:07:20

原文地址:automake的简要使用 作者:draytek58

写在前面:
    本人才疏学浅,本博客仅供自己学习用。若能帮助读者解决问题,则甚感欣慰,如若误导,还请谅解。


这是一个 autoconf / automake 的 "Hello World"
gztt.ll@gmail.com

主要步骤是
- 准备工程目录结构和程序
- autoscan 生成 configure.scan
- 编辑修改 configure.scan,重命名为 configure.ac 或 configure.in
- aclocal; libtoolize; autoheader; autoconf 生成 'configure' 可执行文件
- 写 Makefile.am
- automake 生成 Makefile
- 完成。后面就可以 ./configure; make; make install; make dist; ...

试验工程结构如下

hello
|
|---- src
|     |---- main
|     |     |---- main.c
|     |
|     |---- foo
|     |     |---- foo.c
|     |
|     |---- bar
|           |---- bar.c
|
|---- include
       |---- foo.h
       |---- bar.h


说明一下
"hello"     工程的 $(top_srcdir)
"src/main"   生成可执行文件 hello 主目录
"src/foo"   生成静态库的目录 libfoo.a;hello 主程序 link 时用
"src/bar"   生成动态库的目录 libbar.so;hello 主程序运行时加载
"include"   头文件目录

$mkdir hello && cd hello

准备示例程序,如下

### 文件内容 ###

/* ### src/main/main.c ### */
#include
#include "foo.h"
#include "bar.h"
int main(int argc, char *argv[])
{
     printf("main +\n");
     func_foo();
     func_bar();
     printf("main -\n");
    return 0;
}

/* ### include/foo.h ### */
#include
void func_foo(void);

/* ### src/foo/foo.c ### */
#include "foo.h"
void func_foo(void)
{
     printf("foo +-\n");
}

/* ### include/bar.h ### */
#include
void func_bar(void);

/* ### src/bar/bar.c ### */
#include "bar.h"
void func_bar(void)
{
     printf("bar +-\n");
}

下面进入顶层目录 $(top_srcdir)

$cd hello
$autoscan

自动生成 configure.scan 文件,我们要作稍许修改,重命名为 configure.ac 或 configure.in
(configure.in 是老版本 autoconf 支持的)

$mv configure.scan configure.ac

修改 configure.ac 如下

/* ### configure.ac ### */
#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ(2.61)
AC_INIT(hello, 1.0.0, gztt.ll@gmail.com)                ### Modified
AM_INIT_AUTOMAKE(hello, 1.0.0, gztt.ll@gmail.com)       ### Added
AC_CONFIG_SRCDIR([src/main/main.c])
AC_CONFIG_HEADER([config.h])

# Checks for programs.
AC_PROG_CC
# AC_PROG_RANLIB                                         ### Added if static libary used
AC_PROG_LIBTOOL                                         ### Added if dynamic libary used

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST

# Checks for library functions.
AC_OUTPUT(Makefile                                       ### Added
           include/Makefile
           src/main/Makefile
           src/foo/Makefile
           src/bar/Makefile
          )

说明一下:
如果不使用静态库或动态库 'AC_PROG_RANLIB' 和 'AC_PROG_LIBTOOL' 则都不需要
如果仅使用静态库,增加 'AC_PROG_RANLIB' 即可
如果需要使用动态库,需加上 'AC_PROG_LIBTOOL'
'AC_CONFIG_HEADER(...)',我在 RedHat 9 上试的时候,这行要改面 'AM_CONFIG_HEADER(...)',原因未知。
用 RedHat 9 时,最后 'AC_OUTPUT(...)' 里文件也不太一样, RedHat 9 需要多一行 'src/Makefile',详见下面说明。
(我默认是用 debian 5)

接着执行下面的命令

$aclocal
$libtoolize
$autoheader
$autoconf

注:只有用到动态库时,才需要 '$libtoolize'
否则,只需要运行

$aclocal
$autoheader
$autoconf

即可。

此时应该可以生成 'configure' 可执行文件

然后我们写 Makefile.am

/* ### Makefile.am ### */
SUBDIRS = include src/bar src/foo src/main 

/* ### include/Makefile.am ### */
helloincludedir=$(includedir)
helloinclude_HEADERS=foo.h bar.h 

/* ### src/main/Makefile.am ### */
bin_PROGRAMS=hello
hello_SOURCES=main.c
hello_LDADD=$(top_srcdir)/src/foo/libfoo.a
LIBS=-lbar
INCLUDES=-I$(top_srcdir)/include 
hello_LDFLAGS=-L$(top_srcdir)/src/bar

/* ### src/foo/Makefile.am ### */
noinst_LIBRARIES=libfoo.a
libfoo_a_SOURCES=foo.c
INCLUDES=-I$(top_srcdir)/include  

/* ### src/bar/Makefile.am ### */
lib_LTLIBRARIES=libbar.la
libfoo_la_SOURCES=bar.c
INCLUDES=-I$(top_srcdir)/include  

说明一下,
第一个 'Makefile.am' 文件,即 '$(top_srcdir)/Makefile.am' 只说了子目录说明,按编译顺序排的。
RedHat 9 会报错,说不能含 '/' 符号;解决办法是,我们新增加一个  '$(top_srcdir)/src/Makefile.am'
这样:
/* ### Makefile.am ### */
SUBDIRS = include src
/* ### src/Makefile.am ### */
SUBDIRS = bar foo main
此时,如前面所讲 'configure.ac' 最后的 'AC_OUTPUT' 就需多一行 'src/Makefile' 了

'$(top_srcdir)/src/main/Makefile.am' 相对复杂一点,
特别指出的是 'hello_LDFLAGS' 后,应是 '...=-L$(top_srcdir)/...',而不是 '...=-L $(top_srcdir)/...'
多一个空格,后面就有错误。

接着 automake 的话,无法通过的,还需要下面几个文件,我们暂时 touch 一下即可

$touch README NEWS AUTHORS ChangeLog

注意是在 $(top_srcdir) 目录下面

然后
$automake --add-missing
$./configure

至此,所有 Makefile 文件应该全部生成
我们可以执行
$make
$make clean
$make install
$make uninstall
$make dist
$make ...
###

我的点评:
1.附一张ibm的图
可见 Makefile.in 和 configure 是分别生成的,基本不相干系。若改了 Makefile.am, 则只需重新执行 automake。若是环境改变,比如新装了程序(openssl, 等,我也举不到其它的了^_^),那么可能需要重新执行 aclocal, autoconf. 有些源码包中有一个 autogen.sh 脚本,就是从 aclocal 到 automake 的全套命令。
2. 一般教程都讲首先 autoscan,然后编辑成 configure.ac. 我却发现不如先写 Makefile.am, 这样在autoscan 生成的 configure.scan 中, AC_CONFIG_FILES 的参数中会包含所有与 Makefile.am 相同目录的Makefile 的路径,比如在当前路径的下级路径共有2个 Makefile.am—— lib/Makefile.am 和 src/Makefile.am 则AC_CONFIG_FILES的内容为 (include/Makefile lib/Makefile)。最后保留成原来的类似
AC_CONFIG_FILES([Makefile
                 include/Makefile
                 lib/Makefile
                 src/Makefile])
AC_OUTPUT
这样就好,不用改成前面文档中的 AC_OUTPUT(makefile-path1, makefile-path2...)
3.关于 Makefile.am 中参数的含义可以参照官方文档 
阅读(322) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~