您的位置:首页 > 其它

自动生成Makefile的全过程详解

2018-01-30 10:49 405 查看

相信每个学习Linux的人都知道Makefile,这是一个很有用的东西,但是编写它是比较复杂,今天介绍一个它的自动生成工具,autotools的使用。很多GNULinux的的软件都是用它生成Makefile的,包括我们非常熟悉的Linux内核源代码。

  1、准备:

  需要工具

  autoscan

  aclocal

  autoheader 

  automake

  autoconf

  auto make 

  在终端敲入命令,哪个没有安装哪个,一般是第一个autoscan没有,其它的我用的Ubuntu10.04下全部都有

(不同发行版本对于自动生成makefile有些不一样,此文Ubuntu10.04 Ubuntu12.04适用)

  2、测试程序编写:

     建立目录:mkdir include src

     编写程序:include/str.h

[cpp] view
plaincopy

#include <stdio.h>  

int str(char *string);  

    编写程序:src/str.c

[cpp] view
plaincopy

#include "str.h"  

//print string  

int str(char *string){  

        printf("\n----PRINT STRING----\n\"%s\"\n",string);  

        return 0;  

}  

  

//interface of this program  

int main(int argc , char **argv){  

        char str_read[1024];  

        printf("Please INPUT something end by [ENTER]\n");  

        scanf("%s",str_read);  

        return str(str_read );  

}  

  

       

  3、生成configure.ac

    configure.ac是automake的输入文件,所以必须先生成该文件。

    执行命令:

[cpp] view
plaincopy

[root@localhost str]# ls  

include  src  

[root@localhost str]# autoscan  

autom4te: configure.ac: no such file or directory  

autoscan: /usr/bin/autom4te failed with exit status: 1  

[root@localhost str]# ls  

autoscan.log  configure.scan  include  src  

[root@localhost str]# cp configure.scan configure.ac   

    修改 configure.ac 

[cpp] view
plaincopy

#                                               -*- Autoconf -*-  

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

  

AC_PREREQ(2.59)  

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

AC_CONFIG_SRCDIR([include/str.h])  

AC_CONFIG_HEADER([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  

修改

[cpp] view
plaincopy

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

改为:

[cpp] view
plaincopy

AC_INIT(str,0.0.1, [bug@sounos.org])  

其中:FULL-PACKAGE-NAME 为程序名称,VERSION为当前版本, BUG-REPORT-ADDRESS为bug汇报地址

然后添加两句话:

    AM_INIT_AUTOMAKE

    AC_CONFIG_FILES([Makefile])

结果如下:(两句话不是在一起的)

[cpp] view
plaincopy

#                                               -*- Autoconf -*-  

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

  

AC_PREREQ(2.59)  

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

AC_INIT(str, 0.0.1, [bug@sounos.org])  

AM_INIT_AUTOMAKE  

AC_CONFIG_SRCDIR([include/str.h])  

AC_CONFIG_HEADER([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_CONFIG_FILES([Makefile])  

AC_OUTPUT  

4、执行aclocal

[cpp] view
plaincopy

[root@localhost str]# aclocal  

/usr/share/aclocal/libfame.m4:6: warning: underquoted definition of AM_PATH_LIBFAME  

  run info '(automake)Extending aclocal'  

  or see http://sources.redhat.com/automake/automake.html#Extending-aclocal  

5、制作Makefile.am

[cpp] view
plaincopy

[root@localhost str]# vi Makefile.am  

#Makefile.am  

bin_PROGRAMS    = str  

str_SOURCES     = include/str.h src/str.c  

str_CPPFLAGS    = -I include/  

automake 这个命令需要用到这个配置文件。各个选项意思比较直观,不多说。

6、autoheader

[cpp] view
plaincopy

[root@localhost str]# autoheader  

7、automake必须文件:

[cpp] view
plaincopy

*  install-sh  

* missing  

* INSTALL  

* NEWS  

* README  

* AUTHORS  

* ChangeLog  

* COPYING  

* depcomp   

其中,以下文件在执行automake -a的时候会自动生成

[cpp] view
plaincopy

* install-sh  

* missing  

* INSTALL  

* COPYING  

* depcomp   

所以,接下来手动生成剩下的文件

[cpp] view
plaincopy

[root@localhost str]# touch NEWS README AUTHORS ChangeLog  

8、执行automake -a

[cpp] view
plaincopy

[root@localhost str]# automake -a  

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

configure.ac: installing `./missing'  

Makefile.am: installing `./INSTALL'  

Makefile.am: installing `./COPYING'  

Makefile.am: installing `./compile'  

Makefile.am: installing `./depcomp'  

9、autoconf

[cpp] view
plaincopy

[root@localhost str]# autoconf  

[root@localhost str]# ls  

aclocal.m4      autoscan.log  config.h.in   configure.scan  include     Makefile.am  NEWS  

AUTHORS         ChangeLog     configure     COPYING         INSTALL     Makefile.in  README  

autom4te.cache  compile       configure.ac  depcomp         install-sh  missing      src  

10、执行测试:
      执行./configure

[cpp] view
plaincopy

[root@localhost str]# ./configure --prefix=/u  

checking for a BSD-compatible install... /usr/bin/install -c  

checking whether build environment is sane... yes  

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 ANSI C... 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: creating config.h  

config.status: config.h is unchanged  

config.status: executing depfiles commands  

执行 make

[cpp] view
plaincopy

[root@localhost str]# make  

make  all-am  

make[1]: Entering directory `/data/devel/c/str'  

if gcc -DHAVE_CONFIG_H -I. -I. -I.  -I include/   -g -O2 -MT str-str.o -MD -MP -MF ".deps/str-str.Tpo" -c -o str-str.o `test -f 'src/str.c' || echo './'`src/str.c; \  

then mv -f ".deps/str-str.Tpo" ".deps/str-str.Po"; else rm -f ".deps/str-str.Tpo"; exit 1; fi  

gcc  -g -O2   -o str  str-str.o  

make[1]: Leaving directory `/data/devel/c/str'  

此时已经生成了 str(可执行文件名字在前面设置Makefile.am的参数时候去顶)这个,可以通过./str直接看到运行结果

[cpp] view
plaincopy

[root@localhost str]# ./str  

Please INPUT something end by [ENTER]  

abcksdhfklsdklfdjlkfd  

  

----PRINT STRING----  

"abcksdhfklsdklfdjlkfd"  

不过这里我们都做一步,把它安装到系统里面,这样我们只要在终端输入str就可以运行程序了。

 执行 make install:

[cpp] view
plaincopy

[root@localhost str]# make install  

make[1]: Entering directory `/data/devel/c/str'  

test -z "/u/bin" || mkdir -p -- "/u/bin"  

  /usr/bin/install -c 'str' '/u/bin/str'  

make[1]: Nothing to be done for `install-data-am'.  

make[1]: Leaving directory `/data/devel/c/str'       

接下来你可以make clean 清除安装的那些.o 文件了。

这样生成了一个自动的Makefile。

四、深入浅出

针对上面提到的各个命令,我们再做些详细的介绍。

1、 autoscan

autoscan是用来扫描源代码目录生成configure.scan文件的。autoscan可以用目录名做为参数,但如果你不使用参数的话,那么 autoscan将认为使用的是当前目录。autoscan将扫描你所指定目录中的源文件,并创建configure.scan文件。

2、 configure.scan

configure.scan包含了系统配置的基本选项,里面都是一些宏定义。我们需要将它改名为configure.ac

3、 aclocal

aclocal是一个perl 脚本程序。aclocal根据configure.in文件的内容,自动生成aclocal.m4文件。aclocal的定义是:“aclocal - create aclocal.m4 by scanning configure.ac”。

4、 autoconf

autoconf是用来产生configure文件的。configure是一个脚本,它能设置源程序来适应各种不同的操作系统平台,并且根据不同的系统来产生合适的Makefile,从而可以使你的源代码能在不同的操作系统平台上被编译出来。

configure.ac文件的内容是一些宏,这些宏经过autoconf 处理后会变成检查系统特性、环境变量、软件必须的参数的shell脚本。configure.ac文件中的宏的顺序并没有规定,但是你必须在所有宏的最前 面和最后面分别加上AC_INIT宏和AC_OUTPUT宏。

在configure.ac中:

#号表示注释,这个宏后面的内容将被忽略。

+++++++++++Fedora Core release 1  好像是这样++++++++++
AC_INIT(FILE)
这个宏用来检查源代码所在的路径。
AM_INIT_AUTOMAKE(PACKAGE, VERSION) 
这个宏是必须的,它描述了我们将要生成的软件包的名字及其版本号:PACKAGE是软件包的名字,VERSION是版本号。当你使用make dist命令时,它会给你生成一个类似helloworld-1.0.tar.gz的软件发行包,其中就有对应的软件包的名字和版本号。
++++++++ubuntu 12.04 好像是这样+++++++++++
AC_INIT([FULL-PACKAGE-NAME],[VERSION],[BUG-REPORT-ADDRESS])
其中:FULL-PACKAGE-NAME 为程序名称,VERSION为当前版本, BUG-REPORT-ADDRESS为bug汇报地址
+++++++++++++++++++++

AC_PROG_CC

这个宏将检查系统所用的C编译器。

AC_OUTPUT          //Fedora Core release 1  版本为  AC_OUTPUT(FILE)
         这个宏是我们要输出的Makefile的名字。

我们在使用automake时,实际上还需要用到其他的一些宏,但我们可以用aclocal 来帮我们自动产生。执行aclocal后我们会得到aclocal.m4文件。

产生了configure.in和aclocal.m4 两个宏文件后,我们就可以使用autoconf来产生configure文件了。

5、 Makefile.am

Makefile.am是用来生成Makefile.in的,需要你手工书写。Makefile.am中定义了一些内容:

AUTOMAKE_OPTIONS

这个是automake的选项。在执行automake时,它会检查目录下是否存在标准GNU软件包中应具备的各种文件,例如AUTHORS、ChangeLog、NEWS等文件。我们将其设置成foreign时,automake会改用一般软件包的标准来检查。

bin_PROGRAMS

这个是指定我们所要产生的可执行文件的文件名。如果你要产生多个可执行文件,那么在各个名字间用空格隔开。

helloworld_SOURCES

这个是指定产生“helloworld”时所需要的源代码。如果它用到了多个源文件,那么请使用空格符号将它们隔开。比如需要 helloworld.h,helloworld.c那么请写成helloworld_SOURCES= helloworld.h helloworld.c。

如果你在bin_PROGRAMS定义了多个可执行文件,则对应每个可执行文件都要定义相对的filename_SOURCES。

6、 automake

我们使用automake --add-missing来产生Makefile.in。

选项--add-missing的定义是“add missing standard files to package”,它会让automake加入一个标准的软件包所必须的一些文件。

我们用automake产生出来的Makefile.in文件是符合GNU Makefile惯例的,接下来我们只要执行configure这个shell 脚本就可以产生合适的 Makefile 文件了。

7、 Makefile

在符合GNU Makefiel惯例的Makefile中,包含了一些基本的预先定义的操作:

make

根据Makefile编译源代码,连接,生成目标文件,可执行文件。

make clean

清除上次的make命令所产生的object文件(后缀为“.o”的文件)及可执行文件。

make install

将编译成功的可执行文件安装到系统目录中,一般为/usr/local/bin目录。

make dist

产生发布软件包文件(即distribution package)。这个命令将会将可执行文件及相关文件打包成一个tar.gz压缩的文件用来作为发布软件的软件包。

它会在当前目录下生成一个名字类似“PACKAGE-VERSION.tar.gz”的文件。PACKAGE和VERSION,是我们在configure.in中定义的AM_INIT_AUTOMAKE(PACKAGE, VERSION)。

make distcheck

生成发布软件包并对其进行测试检查,以确定发布包的正确性。这个操作将自动把压缩包文件解开,然后执行configure命令,并且执行make,来确认编译不出现错误,最后提示你软件包已经准备好,可以发布了。

===============================================
helloworld-1.0.tar.gz is ready for distribution
===============================================
make distclean

类似make clean,但同时也将configure生成的文件全部删除掉,包括Makefile。

五、结束语

通过上面的介绍,你应该可以很容易地生成一个你自己的符合GNU惯例的Makefile文件及对应的项目文件。

如果你想写出更复杂的且符合惯例的Makefile,你可以参考一些开放代码的项目中的configure.in和Makefile.am文件,比如:嵌入式数据库sqlite,单元测试cppunit。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: