autoconf和automake生成makefile

autoconfautomake生成makefile

l        autoconf 的输入文件是 configure.in

l        automake的输入文件是 Makefile.am

 

1.        autoscan扫描源码目录,为你生成configure.scan模板。

2.        configure.scan改名为configure.in

3.        修改configure.in

1.            AC_INIT(ShowServer, 1.0,[email protected]这个宏是必须的。

2.            AC_OUTPUT(Makefile ShowServer/Makefile TestClient/Makefile)这个宏是用于指定需要生成的目标文件,一般是Makefile

3.            指定配置头文件:AC_CONFIG_HEADER([config.h])这个由 autoheader产生

1.        产生的头文件必须被 .c .cpp文件用 #include <config.h>包含。这些宏才能应用到C编译时。

2.        AC_DEFINE定义需要的宏。

4.            启用 automakeAM_INIT_AUTOMAKE(ShowServer, 1.0)

5.            检查编译器

1.        AC_PROG_CXX此宏用于检查系统是否有g++编译器。其它的宏请看autoconf手册

6.            变量:

1.        变量: CFLAGS

C编译器提供的调试和优化选项。如果在运行configure时,没有在环境中设置它,就在你调用AC_PROG_CC的时候设置它的缺省值(如果你没有调用AC_PROG_CC,它就为空)。 configure在编译程序以测试C的特征时,使用本变量。

2.        变量: CPPFLAGS

C预处理器和编译器提供头文件搜索目录选项(`-Idir')以及其他各种选项。如果在运行 configure时,在环境中没有设置本变量,缺省值就是空。configure在编译或者预处理程序以测试C的特征时,使用本变量。

3.        变量: CXXFLAGS

C++编译器提供的调试和优化选项。如果在运行configure时,没有在环境中设置本变量,那么就在你调用AC_PROG_CXX时设置它的缺省值(如果你没有调用AC_PROG_CXX,它就为空)。 configure在编译程序以测试C++的特征时,使用本变量。

4.        变量: FFLAGS

Fortran 77编译器提供的调试和优化选项。如果在运行configure时,在环境中没有设置本变量,那么它的缺省值就在你调用AC_PROG_F77时被设置(如果你没有调用AC_PROG_F77,它就为空)。 configure在编译程序以测试Fortran 77的特征时,使用本变量。

5.        变量: DEFS

传递给C编译器的`-D'选项。如果调用了AC_CONFIG_HEADERconfigure就用 `-DHAVE_CONFIG_H'代替`@DEFS@'(参见配置头文)。在configure进行它的测试时,本变量没有被定义,只有在创建输出文件时候才定义。关于如何检查从前的测试结果,请参见设定输出变

6.        变量: LDFLAGS

为连接器提供的Stripping`-s')选项和其他各种选项。如果在运行configure时,在环境中没有设置本变量,它的缺省值就是空。 configure在连接程序以测试C的特征时使用本变量。

7.        变量: LIBS

传递给连接器的`-l'`-L'选项。

这里可以用环境变量。例如:ACE库存放在环境变量ACE_LIB中,则可以这样指定:

LIBS= -L$ACE_LIB

8.        检查依赖库:

1.           configure检查时的路径为,系统默认库路径,再就是 LIBS中用 –L指定的路径。详见变量中的LIBS

2.           AC_CHECK_LIB([pthread], [pthread_create], , exit 1)

3.           AC_HAVE_LIBRARY([ACE], , exit 1)

4.           AC_HAVE_LIBRARY([Cfg], , exit 1)

9.        其它检查:

a)        详见AUTOCONF文档

b)       2.建立一个a.sh文件:

echo autoheader
autoheader
echo aclocal
aclocal
echo autoconf
autoconf

#产生ltmain.sh

#libtoolize --automake --copy --debug --force
echo automake
automake --add-missing
echo ./configure
./configure


 

c)       执行a.sh就能产生Makefile

7.             从命令行获取参数

AC_ARG_ENABLE

 

opt_debug=yes

AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], [enable debug [[default=yes]]]), opt_debug=$enableval)

if test $opt_debug = "yes"; then

        #AC_DEFINE(_DEBUG)

        CXXFLAGS="-D_DEBUG "

fi

           

 root@root:~#./configure –help            

Optional Features:

 --disable-FEATURE      do not include FEATURE (same as --enable-FEATURE=no)

 --enable-FEATURE[=ARG] include FEATURE [ARG=yes]

 --disable-dependency-tracking speeds up one-time build

 --enable-dependency-tracking  do not reject slow dependency extractors

 --enable-debug         enable debug [default=yes]

 

8.automake 支持条件

 AM_CONDITIONAL (conditional, condition)

AM_CONDITIONAL (conditional, condition) [Macro]
The conditional name, conditional, should be a simple string starting with a letter
and containing only letters, digits, and underscores. It must be different from ‘TRUE’
and ‘FALSE’ that are reserved by Automake.
The shell condition (suitable for use in a shell if statement) is evaluated when
configure is run. Note that you must arrange for every AM_CONDITIONAL to be
invoked every time configure is run. If AM_CONDITIONAL is run conditionally (e.g.,
in a shell if statement), then the result will confuse automake.
Conditionals typically depend upon options that the user provides to the configure
script. Here is an example of how to write a conditional that is true if the user uses the
‘--enable-debug’ option.
AC_ARG_ENABLE([debug],
[ --enable-debug Turn on debugging],
[case "${enableval}" in
yes) debug=true ;;
no) debug=false ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;;
esac],[debug=false])
AM_CONDITIONAL([DEBUG], [test x$debug = xtrue])
Here is an example of how to use that conditional in ‘Makefile.am’:
if DEBUG
DBG = debug
else
DBG =
endif
noinst_PROGRAMS = $(DBG)
            

9.示例:

autoconf文件:

#                                              -*- Autoconf -*-

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

 

AC_PREREQ(2.59)

AC_INIT(ShowServer, 1.0, [email protected])

AC_CONFIG_SRCDIR([.])

AC_CONFIG_HEADER([config.h])

AM_INIT_AUTOMAKE(ShowServer, 1.0)

 

# Checks for programs.

AC_PROG_CXX

 

#从命令行中检查参数,根据参数做相应的定义

opt_debug=yes
AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], [enable debug [[default=yes]]]), opt_debug=$enableval)
if test $opt_debug = "yes"; then   #这个不能用 if [ $opt_debug = "yes" ] then,因为 []在autoconf中有其它含意。
 #AC_DEFINE(_DEBUG)
 CXXFLAGS="-D_DEBUG "
fi

 

CFLAGS=" -O2"

CXXFLAGS+=" -D_DEBUG -I$ACE_INCLUDE -I$LIB_PATH/include"  #头文件目录

LIBS="-L. -L$ACE_LIB " #包含ACE的库的环境变量

 

# Checks for libraries.

AC_CHECK_LIB([pthread], [pthread_create], , exit 1)

AC_HAVE_LIBRARY([ACE], , exit 1) #在LIBS中指定的路径中找,找到后,默认的操作是把ACE库加到LIBS中。

 

# Checks for header files.

AC_HEADER_STDBOOL

AC_C_CONST

 

# Checks for typedefs, structures, and compiler characteristics.

 

# Checks for library functions.

 

 

AC_PROG_INSTALL

 

AC_OUTPUT(Makefile ShowServer/Makefile TestClient/Makefile)


 

 

 

注意:在脚本中变量就只由$引用,不需要“()”。

 

 Makefile.am

 

AUTOMAKE_OPTIONS = foreign

lib_LTLIBRARIES = libSxitCommunicate.la

libSxitCommunicate_la_CPPFLAGS = /
  -DACE_BUILD_SVC_DLL

libSxitCommunicate_la_SOURCES = /
  SxitCommunicate.cpp /
  SxitComm.cpp /
  CommunicateImpt.cpp/
  ImptCommunicateRemote.cpp /
  ImptCommunicateLocal.cpp /
  NetIdManage.cpp /
  SxitPacketHandler.cpp


 

bin_PROGRAMS:生成执行文件

lib_LTLIBRARIES:生成库,根据库后缀名来确定生成什么库(安装)

noinst_LIBRARIES:生成库(不安装)

 

 

编译库:

看GUN Automake手册中的相应段(8.2Building a library)。这里只说明静态库,动态库的命名方式。

对象文件命名为:lib***.o

静态库命名为 lib***.a

动态库的命名为 lib***.so

libtool工具库命名为 lib***.la

 

lib***.la 是a libtool library file,它是一个文本文件,用于libtool

lib***.lo是a libtool object file,它是一个文本文件,用于libtool

 

Automake一般在当前目录下会产生一个 .libs ,这个目录中包含生成的对象文件和库文件。

 

 

编译选项:

 

      -static:生成静态库
           On systems that support dynamic linking, this prevents linking with the
           shared libraries.  On other systems, this option has no effect.

       -shared:生成动态库
           Produce a shared object which can then be linked with other objects to
           form an executable.  Not all systems support this option.  For pre-
           dictable results, you must also specify the same set of options that
           were used to generate code (-fpic, -fPIC, or model suboptions) when you
           specify this option.[1]

       -shared-libgcc
       -static-libgcc
           On systems that provide libgcc as a shared library, these options force
           the use of either the shared or static version respectively.  If no
           shared version of libgcc was built when the compiler was configured,
           these options have no effect.

           There are several situations in which an application should use the
           shared libgcc instead of the static version.  The most common of these
           is when the application wishes to throw and catch exceptions across dif-
           ferent shared libraries.  In that case, each of the libraries as well as
           the application itself should use the shared libgcc.

           Therefore, the G++ and GCJ drivers automatically add -shared-libgcc
           whenever you build a shared library or a main executable, because C++
           and Java programs typically use exceptions, so this is the right thing
           to do.

           If, instead, you use the GCC driver to create shared libraries, you may
           find that they will not always be linked with the shared libgcc.  If GCC
           finds, at its configuration time, that you have a non-GNU linker or a
           GNU linker that does not support option --eh-frame-hdr, it will link the
           shared version of libgcc into shared libraries by default.  Otherwise,
           it will take advantage of the linker and optimize away the linking with
           the shared version of libgcc, linking with the static version of libgcc
           by default.  This allows exceptions to propagate through such shared
           libraries, without incurring relocation costs at library load time.

           However, if a library or main executable is supposed to throw or catch
           exceptions, you must link it using the G++ or GCJ driver, as appropriate
           for the languages used in the program, or using the option
           -shared-libgcc, such that it is linked with the shared libgcc.

 

 

 

3.1 编译安装

编译和安装的规则是绑定在一起的,通过同一条语句同时指定了编译和安装的处理方式,具体的格式为:安装目录_编译类型=编译目标

3.1.1【安装目录】

例如:bin_PROGRAMS = hello subdir/goodbye,其中安装目录是bin,编译类型是PROGRAMS,编译目标是两个程序hello, goodbye.

常用缺省的安装目录如下

目录

Makefile.am中的变量

使用方式

prefix

/usr/local

安装目录,通过--prefix指定

exec_prefix

${prefix}

同prefix

bindir

${exec_prefix}/bin

bin_编译类型

libdir

${exec_prefix}/lib

lib_编译类型

includedir

${prefix}/include

include_编译类型

noinstdir

noinst_编译类型,特殊的目录,表示编译目标不安装。

除了常用的缺省目录外,有时候我们还需要自定义目录,例如日志目录log,配置目录config,这种目录可以通过自定义目录方式定义,然后按照缺省目录的使用方式使用即可。例如:自定义config目录的方式如下:

configdir=${prefix}/log  => 定义一个自定义的目录名称config,注意dir后缀是固定的

config_DATA=config/test.ini  => 使用自定义的目录config,必须要有这句,否则目录不会创建, =号后面如果有对应的文件,安装时会将对应的文件拷贝到config目录下。

 

3.1.2【编译类型】

常见编译类型如下,没有自定义编译类型

类型

说明

使用方式

PROGRAMS

可执行程序

bin_PROGRAMS

LIBRARIES

库文件

lib_LIBRARIES

LTLIBRARIES (Libtool libraries)

libtool库文件

lib_LTLIBRARIES

HEADERS

头文件

include_HEADERS

SCRIPTS

脚本文件,有可执行权限

test_SCRIPTS(需要自定义test目录)

DATA

数据文件,无可执行权限

conf_DATA(需要自定义conf目录)

 

3.1.3【编译目标】

编译目标其实就是编译类型对应的具体文件,其中需要make生成的文件主要有如下几个:可执行程序_PROGRAMS,普通库文件_LIBRARIES,libtool库文件_LTLIBRARIES,其它类型对应的编译目标不需要编译,源文件就是目标文件。

Ø  标准的编译配置

如果你熟悉gcc的编译命令写法,那么Automake的Makefile.am编译过程就很好写了。因为Automake只是将写在一行gcc命令里的各个不同部分的信息分开定义而已。我们来看具体是如何定义的:

_SOURCES:对应gcc命令中的源代码文件

_LIBADD:编译链接库时需要链接的其它库,对应gcc命令中的*.a, *.so等文件

_LDADD:编译链接程序时需要链接的其他库,对应gcc命令中的*.a, *.so等文件

_LDFLAGS:链接选项,对应gcc命令中的-L, -l, -shared, -fpic等选项

_LIBTOOLFLAGS:libtool编译时的选项

**FLAGS(例如_CFLAGS/_CXXFLAGS):编译选项,对应gcc命令中的-O2, -g, -I等选项

_DEPENDENCIES:编译链接库时需要的依赖条件,可以是文件,也可以是规则,在规则中可以定义自定义脚本

 

举例如下:

#不同的编译类型只是第一句不一样,后面的编译配置都是一样的

bin_PROGRAMS= myproject

myproject_SOURCES = main.c

myproject_LDADD   = ./utils/libutils.a ./module1/libmodule1.a ./core1/libcore.a

myproject_LDFLAGS = -L/home/test/local -lmemcached

myproject_CFLAGS  = -I./core1/ -I./module1/ -I./utils/ -O2 -g

myproject_DEPENDENCIES=../lib

../lib:

       mkdir -p ../lib

 

Ø  如何编译可执行程序

对于大型项目来说,代码基本上都是分目录存放的,如果是直接写makefile文件,一般都是将所有源文件首先编译成*.o的文件,再链接成最终的二进制文件。但在Automake里面这样是行不通的,因为你只要仔细看编译类型表格就会发现,并没有一种编译类型能够编译*.o文件,无法像常规makefile那样来编写,所以就需要采取一些技巧。

其实这个技巧也很简单:将非main函数所在目录的文件编译成静态链接库,然后采用链接静态库的方式编译可执行程序。

样例如下:

=================根目录Makefile.am======================

#对应Makefile.am原则2

SUBDIRS = tools common worker

 

=================tool目录Makefile.am======================

#只是为了编译而生成的.a库文件,没有必要安装, 所以是noinst

noinst_LIBRARIES=libtools.a

libtools_a_SOURCES=./urlcode.h /

                   ./stringtools.cpp /

                   ./stringtools.h /

                   ./urlcode.c

 

===============common目录Makefile.am======================

#只是为了编译而生成的.a库文件,没有必要安装, 所以是noinst

noinst_LIBRARIES=libcommon.a

libcommon_a_SOURCES=./iniparser.c /

                    (省略很多文件, 实际使用时要一一填写)

                    ./exception.h /

 

==============worker目录Makefile.am============================

bin_PROGRAMS=worker

worker_SOURCES=./workeralgorithm.cpp /

                ./worker.cpp /

                (省略很多文件, 实际使用时要一一填写)

               ./worker.h

#通过_LDADD告诉Automake需要链接哪些库

worker_LDADD=../tools/libtools.a ../common/libcommon.a

 

Ø  如何编译静态库

Automake天然支持编译静态库,只需要将编译类型指定为_LIBRARIES即可。

 

Ø  如何编译动态库

需要注意的是:_LIBRARIES只支持静态库(即*.a文件),而不支持编译动态库(*.so)文件,要编译动态链接库,需要使用_PROGRAMS。除此之外,还需要采用自定义目录的方式避开Automake的两个隐含的限制:

1)      如果使用bin_PROGRAMS, 则库文件会安装到bin目录下,这个不符合我们对动态库的要求;

2)      automake不允许用lib_ PROGRAMS

下面假设将utils编译成so,采用自定义目录的方式,修改Makefile.am如下:

mylibdir=$libdir         #$libdir其实就是lib目录,请参考【安装目录】表格

mylib_PROGRAMS= libutils.so

libutils_so_SOURCES = utils.c utils.h

libutils_so_LDFLAGS = -shared –fpic  #这个就是gcc编译动态库的选项

 

Ø  如何编译libtool库

对于跨平台可移植的库来说,推荐使用libtool编译,而且Automake内置了libtool的支持,只需要将编译类型修改为_LTLIBRARIES即可。

需要注意的是:如果要使用libtool编译,需要在configure.ac中添加LT_INIT宏,同时注释掉AC_PROG_RANLIB,因为使用了LT_INIT后,AC_PROG_RANLIB就没有作用了。

 

编译时自定义脚本:

automake提供编译时用户自定义清理规则:

clean-local

 

3.2 打包

make dist  #只打包

或者

make distcheck      #打包并对打的包解压进行编译检查,看是否出错

Automake缺省情况下会自动打包,自动打包包含如下内容:

1)      所有源文件

2)      所有Makefile.am/Makefile.in文件

3)      configure读取的文件

4)      Makefile.am’s (using include) 和configure.ac’ (using m4_include)包含的文件

5)      缺省的文件,例如README, ChangeLog, NEWS, AUTHORS

 

如果除了这些缺省的文件外,你还想将其它文件打包,有如下两种方法:

(1)   粗粒度方式:通过EXTRA_DIST来指定,例如:

EXTRA_DIST=conf/config.ini  test/test.php  tools/initialize.sh

(2)   细粒度方式:在“安装目录_编译类型=编译目标”前添加dist(表示需要打包),或者nodist(不需要打包),例如:

#将data_DATA= distribute-this打包

dist_data_DATA = distribute-this

 

#foo_ SOURCES不打包

bin_PROGRAMS = foo

nodist_foo_SOURCES = do-not-distribute.c

 

 

安装时自定义脚本:

automake提供两个规则供用户在完装完后自定义脚本:

install-exec-hook

install-data-hook

 

提供相应的反安装自定义脚本规则:

uninstall-hook

 

生成过程:http://www.ibm.com/developerworks/cn/linux/l-makefile/

工具简介

所必须的软件:autoconf/automake/m4/perl/libtool(其中libtool非必须)。

autoconf是一个用于生成可以自动地配置软件源码包,用以适应多种UNIX类系统的shell脚本工具,其中autoconf需要用到 m4,便于生成脚本。automake是一个从Makefile.am文件自动生成Makefile.in的工具。为了生成Makefile.in,automake还需用到perl,由于automake创建的发布完全遵循GNU标准,所以在创建中不需要perl。libtool是一款方便生成各种程序库的工具。

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

1) flat指的是所有文件都位于同一个目录中。

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

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

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

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

就是所有源文件及自己写的头文件位于当前目录的一个子目录中,而当前目录里没有任何源文件。 GNU cpio和GNU tar就是这一类。

flat类型是最简单的,deep类型是最复杂的。不难看出,我们的模拟需求正是基于第三类deep型,也就是说我们要做挑战性的事情:)。注:我们的测试程序是基于多线程的简单程序。

 
 

 

首先进入 project 目录,在该目录下运行一系列命令,创建和修改几个文件,就可以生成符合该平台的Makefile文件,操作过程如下:

1) 运行autoscan命令

2) 将configure.scan 文件重命名为configure.in,并修改configure.in文件

3) 在project目录下新建Makefile.am文件,并在core和shell目录下也新建makefile.am文件

4) 在project目录下新建NEWS、 README、 ChangeLog 、AUTHORS文件

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

6) 运行aclocal命令

7) 运行autoconf命令

8) 运行automake -a命令

9) 运行./confiugre脚本

可以通过图2看出产生Makefile的流程,如图所示:


图 2生成Makefile流程图

 

 

 

 

在linux下编译c/c++程序出错:

显示代码打印
 $ automake --add-missing  

 configure.in:18: required file `build/ltmain.sh' not found  


解决方案(libtoolize配置即可):


显示代码打印
 $libtoolize --version 

 -libtoolize (GNU libtool) 1.4.2  

 $libtoolize --automake --copy --debug --force

 

你可能感兴趣的:(autoconf和automake生成makefile)