Chinaunix首页 | 论坛 | 博客
  • 博客访问: 444614
  • 博文数量: 72
  • 博客积分: 3186
  • 博客等级: 中校
  • 技术积分: 1039
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-07 16:53
文章分类

全部博文(72)

文章存档

2012年(1)

2011年(5)

2010年(10)

2009年(56)

我的朋友

分类: LINUX

2009-04-18 03:24:08

关于automake的实践
今天弄了很久的automake,自动生成Makefile,这样写程序时就会方便很多。之前也花时间看过一次,但当时只是对着一个hello.c的例子试了一遍就过去了,印象并不深刻,过后就忘记了。最近在学minigui时,考贝过来的程序每次都用一个笨办法来编译:直接考到mg-sample文件夹里面的src里,再在Makefile.am里加入所要编译的文件。由于对automake不了解,经常在./configure时出错,又不知道怎么去改,费时费力。这个问题托了好久,终于决心要把它搞定。
要实现的功能:
1.编写的程序用automake 能够成功生成Makefile文件。
2.用automake生成交叉编译的Makefile.

仔细看下这篇文章,有关于这个知识点的详细介绍:http://www.ibm.com/developerworks/cn/linux/l-makefile/

按照文中的步骤进行:注意如图的各文件的依赖关系。

这里举个例子是minigui里的mg-samples-1.3.1/src/helloworld.c
1.建立test目录,将helloworld.c copy进来,然后:

[root@localhost mg-samples-1.3.1]# cd test/   *进入目录
[root@localhost test]# ls                     *可以看到这时只有源文件
helloworld.c
[root@localhost test]# autoscan  
[root@localhost test]# ls   *查看,生成了configure.scan
autoscan.log configure.scan helloworld.c
[root@localhost test]# mv configure.scan configure.in *重命名一下
[root@localhost test]# ls
autoscan.log configure.in helloworld.c
[root@localhost test]# vim configure.in *编辑configure.in

*******************生成的文件内容如下:

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

AC_PREREQ([2.63])
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
AC_CONFIG_SRCDIR([helloworld.c])
AC_CONFIG_HEADERS([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

******************************修改如下:
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.63])
AC_INIT(helloworld.c,1.0)
AM_INIT_AUTOMAKE(helloworld, 1.0) 重点要加上这一句,最后的输出文件名及版本
AC_CONFIG_SRCDIR([helloworld.c]) 如果有多个源文件,按其默认或只写文件中的任意一个就好了,只是测试
AC_CONFIG_HEADERS([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(Makefile)  这时是最生要输出的文件名,要输出的是Makefile


*****************然后回到终端里:
[root@localhost test]# aclocal
[root@localhost test]# ls    产生aclocal.m4
aclocal.m4 autoscan.log configure.in~
autom4te.cache configure.in helloworld.c
[root@localhost test]# autoconf
[root@localhost test]# ls
aclocal.m4 autoscan.log configure.in helloworld.c
autom4te.cache configure configure.in~
看到生成了configure,这个就是最后要./configure的文件了.但是现在要执行这个命令生成Makefile还需要一个文件:Makefile.am
需要手动编辑

[root@localhost test]# vim Makefile.am

输入如下:
bin_PROGRAMS=helloworld    最生输出的可执行文件名,输出多个则用空格隔开即可
helloworld_SOURCES=helloworld.c 依赖的源文件,有多个源文件用空格隔开,有头文件也写出来。
helloworld_LDADD=-lminigui -lpthread 链接时要的额外函数库名

还有其他参数,参照上面的那篇文章。

[root@localhost test]# automake --add-missing
configure.in:6: installing `./install-sh'
configure.in:6: installing `./missing'

Makefile.am: installing `./INSTALL'
Makefile.am: required file `./NEWS'
not found
Makefile.am: required file `./README' not found
Makefile.am: required file `./AUTHORS'
not found
Makefile.am: required file `./ChangeLog' not found
Makefile.am: installing `./COPYING'

configure.in:8: required file `config.h.in' not found
Makefile.am: installing `./depcomp'


这里直接用automake --add-missing会提示错误,需要这几个文件,可以动touch建立,
[root@localhost test]# touch NEWS README AUTHORS ChangeLog

如果不建立这些文件,则在Makefile的第一行加上Automake_OPTIONS=foreign,如下:


AUTOMAKE_OPTIONS=foreign
bin_PROGRAMS=helloworld
helloworld_SOURCES=helloworld.c
helloworld_LDADD=-lminigui -lpthread
上面还有一个错误为:configure.in:8: required file `config.h.in' not found

是因为在automake之前没有建立config.h.in,运行如下命令即可
[root@localhost test]# autoheader


接着,再次运行
automake --add-missing,可以看到生成了Makefile.in文件
[root@localhost test]# automake --add-missing
[root@localhost test]# ls
aclocal.m4 config.h.in configure.in~ helloworld.c Makefile.am
autom4te.cache configure COPYING INSTALL Makefile.in
autoscan.log configure.in depcomp install-sh missing


然后执行,./configure,即可生成Makefile
[root@localhost test]# ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
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 ISO C89... 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: executing depfiles commands
[root@localhost test]# ls
aclocal.m4 config.h.in configure.in helloworld.c Makefile.am
autom4te.cache config.log configure.in~ INSTALL Makefile.in
autoscan.log config.status COPYING install-sh missing
config.h configure depcomp Makefile stamp-h1
[root@localhost test]# make
make all-am
make[1]: Entering directory `/home/minigui/mg-samples-1.3.1/test'
gcc -g -O2 -o helloworld helloworld.o -lminigui -lpthread
make[1]: Leaving directory `/home/minigui/mg-samples-1.3.1/test'

[root@localhost test]# ls
aclocal.m4 config.log COPYING INSTALL missing
autom4te.cache config.status depcomp install-sh stamp-h1
autoscan.log configure helloworld Makefile
config.h configure.in helloworld.c Makefile.am
config.h.in configure.in~ helloworld.o Makefile.in

可以看到make之后生成了helloworld


这里主要是将最后要链接的两个库名加入进去。同时在Makefile.am中也可以用LDFLAGS加入库的路径,不过上面的例子没有用到,因为按系统默认库就可以生成在PC机上运行的MINIGUI程序。


但是如果要交叉编译,直接用./configure生成Makefile可以运行在arm上的话,还需要指定头文件和库文件。关于c语言的头文件和库文件,最近总算理解了一点,但还是很模糊。我的理解是这样的:

1.头文件,即include中,只是一些函数的声明。

2.c语言的编译是按单个文件进行的,单个文件编译生成“.o”格式的文件,如果a函数要调用b函数的话,那么b函数的定义必须在a的前面。否则,在a函数之前就需要对b函数进行声明。

3.不同文件中。若引用函数库中的b函数,则此时a和b肯定是在不同的文件内的,这样,在a之前需要对b函数进行声明,而对于库函数的声明都全部写在了头文件里,所以a所在的文件中,只需在文件的开始把头文件include进来。比如最常用的#include ,其实就是把stdio.h里的所有内容都复制到a文件的开头,这样,在函数a之前就一定有对b函数的声明了。

4.编译器将各个文件编译成“.o“格式的文件,然后用链接器将所有的.o文件,包括含数库一起,最后链接成目标文件。如上例中的helloworld。

在我的机子上,对于交叉编译,

编译器位于/usr/local/arm/2.95.2/bin,即其中的armv4l-unknown-linux-gcc

链接器是/usr/local/arm/2.95.2/bin/armv4l-unknown-linux-ld

交叉编译好的minigui头文件位于/usr/local/arm/2.95.2/armv4l-unknown-linux/include/,(注意,名为minigui的头文件文件夹位于这个目录下,文件夹下有如window.h等多个minigui头文件在minigui文件夹内)

库函数位于/usr/local/arm/2.95.2/armv4l-unknown-linux/lib/ 内


交叉编译时用如下命令:(交叉编译器的环境变量已经添加,如果没有添加则需要绝对路径)

./configure --build=i686-linux --host=arm --target=arm CC=armv4l-unknown-linux-gcc LD=arm-unknown-linux-ld CFLAGS=-I/usr/local/arm/2.95.2/armv4l-unknown-linux/include/ LDFLAGS=-L/usr/local/arm/2.95.2/armv4l-unknown-linux/lib  

这样生成了Makefile,以后直接make就可以生成arm下的二进制执行文件了。


一个晚上,也就弄了这么多。一个问题,多动手实践,有时候可能一时没有查找具体例子,自己动手试几下也就出来了。

阅读(6400) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~