如何自动生成Makefile文件

来源:互联网 发布:网络用语 刚 编辑:程序博客网 时间:2024/05/27 14:13

1、概述

什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员,makefile还是要懂。这就好像现在有这么多的HTML的编辑器,但如果你想成为一个专业人士,你还是要了解HTML的标识的含义。特别在Unix下的软件编译,你就不能不自己写makefile了,会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。因为,makefile关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。 makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。

我相信所有在Unix/Linux下编写过C/C++程序都遇到或使用过Makefile,使用make编译程序相当简单,但是使用make来开发程序却不那么简单。对于一个程序,Makefile小则几百行多则上万行,这对于程序员来说是一件相当痛苦的事情。为此GNU提供Autoconf、Automake两个软件来自动生成Makefile文件,这个程序员提供了很大的方便。

 

2、准备工作

首先要确认已安装一下软件:

a)      GNU autoconf

b)      GNU automake

c)      GNU m4

d)      GNU libtool

 

3、一个简单的例子

a)创建目录

mkdir hello

cd hello/

mkdir src

b)在src目录编写源代码hello.c

源代码如下:

#include <stdio.h>

 

int main(int argc , char **argv)

{

         printf("Hello,world!\n");

         return0;

}

c)编写Makefile.am文件

在src目录下编写Makefile.am文件:

AUTOMAKE_OPTIONS = foreign

bin_PROGRAMS     = hello

hello_SOURCES    = hello.c

hello_LDADD      = -lpthread (这里只是为了测试,实际不需要)

退到hello目录下编写Makefile.am文件:

AUTOMAKE_OPTIONS=foreign

SUBDIRS = src

e)      autoscan并修改configure.in

执行autoscan命令,生成configure.scan文件,将其更名为configure.in,并修改其内容:

#                                              -*- Autoconf -*-

# Process this file with autoconf toproduce a configure script.

 

AC_PREREQ([2.68])

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

AM_INIT_AUTOMAKE(hello,1.0)

AC_CONFIG_SRCDIR([src/hello.c])

#AC_CONFIG_HEADERS([config.h])

 

# Checks for programs.

AC_PROG_CC

 

# Checks for libraries.

# FIXME: Replace `main' with a function in`-lpthread':

AC_CHECK_LIB([pthread], [main])

 

# Checks for header files.

 

# Checks for typedefs, structures, andcompiler characteristics.

 

# Checks for library functions.

 

#AC_CONFIG_FILES([Makefile

#                 src/Makefile])

AC_OUTPUT(Makefile

                src/Makefile)

f)       aclocal

生成aclocal.m4和autom4te.cache文件。

g)      autoconf

根据 configure.in和aclocal.m4生成configure文件

h)      automake --add-missing

通过Makefile.am文件生成Makefile.in文件,并生成install-sh,depcomp,INSTALL,missing等文件。

i)        ./configure

通过Makefile.in文件生成Makefile文件。

解释:

AM_INIT_AUTOMAKE([FULL-PACKAGE-NAME],[VERSION], [BUG-REPORT-ADRESS]):

这个是使用Automake 所必备的宏,FULL-PACKAGE-NAME 是所要产生软件的名称,VERSION 是版本编号,BUG-REPORT-ADRESS反馈地址。

AC_PROG_CC:

检查系统可用的C 编译器,若源代码是用C 写的就需要这个宏

AC_OUTPUT(file):

设置configure 所要产生的文件,若是Makefile ,configure 便会把它检查出来的结果填充到Makefile.in 文件后产生合适的Makefile。

AUTOMAKE_OPTIONS:

设置Automake 的选项。Automake 主要是帮助开发GNU 软件的人员来维护软件,所以在执行Automake 时,会检查目录下是否存在标准GNU 软件中应具备的文件,例如'NEWS'、'AUTHOR'、'ChangeLog'、’README’ 等文件。设置为foreign 时,Automake 会改用一般软件的标准来检查。

bin_PROGRAMS:

定义要产生的执行文件名。如果要产生多个执行文件,每个文件名用空白符隔开。

hello_SOURCES:

生成这个可执行文件所需要的源文件。

hello_LDADD:

链接库文件。

 

4、深度了解如何生成Makefile文件

a)      autoscan (autoconf)

扫描源代码以搜寻普通的可移植性问题,比如检查编译器,库,头文件等,生成文件configure.scan,它是configure.ac的一个雏形。

your source files --> [autoscan*] -->[configure.scan] --> configure.ac

b)      aclocal (automake)

根据已经安装的宏,用户定义宏和acinclude.m4文件中的宏将configure.ac文件所需要的宏集中定义到文件 aclocal.m4中。

         aclocal是一个perl 脚本程序,它的定义是:“aclocal- create aclocal.m4 by scanning configure.ac”

c)      autoheader(autoconf)

根据configure.ac中的某些宏,比如cpp宏定义,运行m4,声称config.h.in

d)      automake

automake将Makefile.am中定义的结构建立Makefile.in,然 后configure脚本将生成的Makefile.in文件转换 为Makefile。如果在configure.ac中定义了一些特殊的宏,比如AC_PROG_LIBTOOL,它会调用libtoolize,否则它 会自己产生config.guess和config.sub

e)      autoconf

将configure.ac中的宏展开,生成configure脚本。这个过程可能要用到aclocal.m4中定义的宏。

f)        ./configure的过程

g)      make过程

5、使用automake及autoconf制作静态库文件

a) 目录结构如下:

example

|——src 目录(存放源代码文件)

       |——hello.c

|——lib 目录(存放用来生成库的文件)

       |——test.c 用来生成静态库libhello.a
|——include 目录(存放程序中使用的头文件)

       |——hello.h

b)      编写各个源文件

hello.h文件:

extern void print(char *);

test.c文件:

#include <stdio.h>

 

void print(char *msg)

{

         printf("%s\n",msg);

}

hello.c文件:

#include "hello.h"

 

int main()

{

         print("helloworld!\n");

         return0;

}

c)      编写各个Makfile.am文件:

Makefile.am文件:

SUBDIRS=lib src

lib/Makefile.am文件:

noinst_LIBRARIES=libhello.a

libhello_a_SOURCES=test.c

src/Makefile.am文件:

INCLUDES=-I ../include

bin_PROGRAMS=hello

hello_SOURCES=hello.c

hello_LDADD=../lib/libhello.a

解释:

SUBDIRS:

表示子目录下也有Makefile.am文件。

noinst_LIBRARIES :

noinst 表示生成的是静态库,不需要makeinstall ,直接制定它的位置和名字就
可以使用。

libhello_a_SOURCES:

表示用来生成静态库的源文件

d)      生成并修改configure.in

执行autoscan,生成configure.scan,将其更名为configure.in,并修改。修改和上面所说基本相同,不同的是添加了一行:AC_PROG_RANLIB。

#                                              -*- Autoconf -*-

# Process this file with autoconf toproduce a configure script.

 

AC_PREREQ([2.68])

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

AC_INIT(hello,1.1,guizhongyun1010@sina.com)

AM_INIT_AUTOMAKE

AC_CONFIG_SRCDIR([src/hello.c])

AC_CONFIG_HEADERS([config.h])

 

# Checks for programs.

AC_PROG_CC

 

# Checks for libraries.

AC_PROG_RANLIB

# Checks for header files.

 

# Checks for typedefs, structures, andcompiler characteristics.

 

# Checks for library functions.

 

#AC_CONFIG_FILES([Makefile

#                lib/Makefile

#                 src/Makefile])

AC_OUTPUT(Makefile

                lib/Makefile

                src/Makefile)

e)      生成configure文件及生成Makefile文件

执行以下命令:

touch NEWS README AUTHORS ChangeLog

autoreconf -fvi

./configure

make

 

6、使用automake及autoconf制作动态库文件

动态库和静态库的区别在于:动态库是在程序装载的时候才加入到程序。

a)      目录结构

example

|——src 目录(存放源代码文件)

       |——hello.c

|——lib 目录(存放用来生成库的文件)

       |——test.c 用来生成静态库libhello.a
|——include 目录(存放程序中使用的头文件)

       |——hello.h

b)      编写各个源文件

hello.h文件:

extern void print(char *);

test.c文件:

#include <stdio.h>

 

void print(char *msg)

{

         printf("%s\n",msg);

}

hello.c文件:

#include "hello.h"

 

int main()

{

         print("helloworld!\n");

         return0;

}

c)      编写各个Makfile.am文件:

Makefile.am文件:

AUTOMAKE_OPTIONS =foreign

SUBDIRS=lib src

lib/Makefile.am文件:

AUTOMAKE_OPTIONS = foreign

lib_LTLIBRARIES  = libhello.la

libhello_la_SOURCES = test.c

src/Makefile.am文件:

AUTOMAKE_OPTIONS = foreign

INCLUDES         = -I../include

bin_PROGRAMS     = hello

hello_SOURCES    = hello.c

hello_LDADD      = -lhello

d)      生成并修改configure.in

执行autoscan,生成configure.scan,将其更名为configure.in,并修改。configure.in大致和上面相同,只是在其中加入了AC_PROG_LIBTOOL,修改后如下:

#                                              -*- Autoconf -*-

# Process this file with autoconf toproduce a configure script.

 

AC_PREREQ([2.68])

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

AC_INIT(hello,1.0,guizhongyun1010@sina.com)

AM_INIT_AUTOMAKE

AC_CONFIG_SRCDIR([src/hello.c])

#AC_CONFIG_HEADERS([config.h])

 

# Checks for programs.

AC_PROG_CC

AC_PROG_LIBTOOL

# Checks for libraries.

 

# Checks for header files.

 

# Checks for typedefs, structures, andcompiler characteristics.

 

# Checks for library functions.

 

AC_CONFIG_FILES([Makefile

                 lib/Makefile

                 src/Makefile])

AC_OUTPUT

e)      生成configure文件及Makefile文件并编译

依次执行以下命令:

aclocal

libtoolize -f -c

autoconf

automake --add-missing

./configure

make

注:libtoolize 提供了一种标准的方式来将libtool 支持加入一个软件包,而GNU libtool 是
一个通用库支持脚本,将使用动态库的复杂性隐藏在统一、可移植的接口中。