关于automake 和 autoconf 的例子网上有很多,但是里面应用的例子都过于简单,基本上都是"hello world", 大家是否有比较复杂的例子提供供学习。我现在有个比较大的项目,有20多个C 源文件和头文件,又放在不同的目录下,最后安装后要生成好几个可执行文件,这样我就不知道Makefile.am 和 configure.in 怎么写, 比如说 AC_INIT 宏?
回复于:2004-10-02 10:55:53
configure.in写一个就够了,Makefile.am要在不同的目录下分别写。 这些东东都是要实际操作才能理解的。能不能把你的情况说详细一些。
回复于:2004-10-02 23:27:19
感谢你的回答。我再讲我的例子说的详细些(举例)。现在我有两个子目录,dir1 和 dir2, 在子目录dir1 下有源文件 code1.c, code1.h, code2.c, code2.h, code3.c, code3.h, 在子目录dir2下同样有几个源文件,code4.c, code4.h, code5.c, code5.h, code6.c, code6.h。最后我希望在bin目录下生成几个可执行文件,比如 code1.c, code2.c 生成 prog1, 而 code3.c 生成prog2, code4.c 和 code5.c 生成 prog3。 更复杂一点的是在不同子目录下的程序互相关联,比如 code2.c 中需要用到 code6.c 中的函数。还有在不同目录下的两个文件生成一个可执行文件,如 code2.c 和 code6.c 生成 prog4。
还有一个问题,是否可以指定编译器。通常在linux下就用 gcc, 但是有些程序需要特殊的编译器,比如mpicc (编译mpi 函数)。这如何在configure.in 文件中指定?
谢谢指教。
回复于:2004-10-03 10:57:49
我们在SourceForge上发布的项目CORBA Component Model实现StarCCM有几十万行代码。支持Win+VC nmake和linux、solaris。原代码中有configure.in和Makefile.in(没有Makefile.am,我们自己写的Makfile.in),可以看到,StarCCM中如何使用.m4;如何在一个大项目中包含几个项目。 网址:
回复于:2004-10-03 11:40:35
引用:原帖由 "wubulen"]感谢你的回答。我再讲我的例子说的详细些(举例)。现在我有两个子目录,dir1 和 dir2, 在子目录dir1 下有源文件 code1.c, code1.h, code2.c, code2.h, code3.c, code3.h, 在子目录dir2下同样有几个源文件,code4.c,.......... 发表:
bin目录是那个目录,是你的程序安装的目录吗?如果我估计得不错的话,应该是/usr/bin,或者是/usr/local/bin吧。 prog1应该是一个可以单独执行的程序吧。不需要调用自己编写的动态库文件吗?
回复于:2004-10-03 17:39:25
先来举一个简单的例子吧。如何写用code1.c, code2.c生成 prog1的configure.in和Makefile.am。 首先建立一个项目文件夹tt。在tt下建立dir1目录。
[kj501@s2023 dir1]$ mkdir tt
[kj501@s2023 dir1]$ mkdir tt/dir1
然后在dir1目录中分别建立code1.c, code1.h, code2.c, code2.h,由于楼主没有给出源代码,我自己写了几个简单的语句,以便说明问题。 下面是code1.h:
#include ;
void foo_a();
下面是code1.c:
#include "code1.h"
void foo_a()
{
printf("This is code1.\n");
}
下面是code2.h:
#include ;
void foo_b();
下面是code2.c,这里让code.c作为prog1的入口点:
#include "code1.h"
#include "code2.h"
void foo_b()
{
printf("This is code2.\n");
}
int main()
{
foo_a();
foo_b();
}
建立好这几个文件之后,下面就可以正式建立configure.in和Makefile.am了。 首先在tt目录下建立configure.in文件:
#指定项目的一个源文件
AC_INIT(dir1/code2.c)
#指定项目名称和版本号
AM_INIT_AUTOMAKE(prog1, 0.0.1)
#检查编译器
AC_PROG_CC
#输出Makefile文件
AC_OUTPUT(Makefile
dir1/Makefile
)
同时建立tt目录下的Makefile.am文件,这个文件很简单,就一句话:
SUBDIRS=dir1
然后建立dir1目录下的Makefile.am文件,这才是真正起作用的Makefile.am文件:
bin_PROGRAMS=prog1
prog1_SOURCES=code1.c code2.c
完成之后,为了方便操作,再写一个autogen.sh文件,保存在tt目录下。
#!/bin/sh
aclocal
automake --add-missing
autoconf
存盘之后,用chmod +x改成可执行文件。然后执行autogen.sh。
./autogen.sh
即可在tt目录下生成configure和makefile文件,同时在dir1目录下也会生成一个makefile文件。现在在tt目录下执行make,屏幕将显示如下信息:
[kj501@s2023 tt]$ make
Making all in dir1
make[1]: Entering directory `/home/kj501/program/c/tt/dir1'
gcc -DPACKAGE=\"prog1\" -DVERSION=\"0.0.1\" -I. -I. -g -O2 -c code1.c
code1.c:6:2: warning: no newline at end of file
gcc -DPACKAGE=\"prog1\" -DVERSION=\"0.0.1\" -I. -I. -g -O2 -c code2.c
code2.c:13:2: warning: no newline at end of file
gcc -g -O2 -o prog1 code1.o code2.o
make[1]: Leaving directory `/home/kj501/program/c/tt/dir1'
make[1]: Entering directory `/home/kj501/program/c/tt'
make[1]: Nothing to be done for `all-am'.
make[1]: Leaving directory `/home/kj501/program/c/tt'
进入dir1目录,就可以看到生成的prog1程序。如果再执行make install,prog1将被安装到缺省的/usr/local/bin目录下去。 这就是一个最简单的configure.in和Makefile.am的编写情况。你如果不熟悉,最好自己动手做一遍,复杂的configure.in和Makefile.am都是在这个基础上扩充的。
回复于:2004-10-03 17:57:56
在此基础上,如果要同时实现code1.c, code2.c生成 prog1, 而 code3.c生成prog2。由于code1.c,code2.c,code3.c都在同一个目录,只要改写dir1目录下的Makefile.am就可以了。 为了便于说明问题,首先要在dir1目录下增加一个code3.h 和code3.c文件。 下面是code3.h:
#include ;
void foo_c();
下面是code3.c:
#include "code3.h"
void foo_c()
{
printf("This is code3.\n");
}
int main()
{
foo_c();
}
然后修改dir1目录下的Makefile.am文件:
bin_PROGRAMS=prog1 prog2
prog1_SOURCES=code1.c code2.c
prog2_SOURCES=code3.c
再重新执行一次autogen.sh。make之后,在dir1目录下就会同时存在prog1和prog2两个程序。 你先体会一下吧。然后自己做做用code4.c和 code5.c生成 prog3。应该很容易的。
回复于:2004-10-03 19:46:03
十分感谢精灵王详尽的解释,现在已经清楚多了。还有三个问题需要确认。
1。两个处在不同子目录下的文件共同生成一可执行文件,那需要在两个子目录下都写Makefile.am吗,还是只要在带main的那个文件的目录下写?
2。在同一个目录下的文件生成几个可执行文件,configure.in写法问题。code1.c, code2.c(带main) 生成prog1,code3.c生成prog2.
AC_INIT(dir1/code2.c dir1/code3.c)
AM_INIT_AUTOMAKE(prog,0.0.1) #prog 这个名字可以随便取?
3。关于编译器的问题,如何指定特定的编译器, AC_PROG_CC只会检查C编译器?
再次感谢!
回复于:2004-10-04 12:08:45
先回答第1个问题。一般互相引用的源程序都是放在同一个目录下的,如果要放在不同的目录,可以把要引用的源文件编译成静态库文件。 为便于说明问题,准备了如下文件: 在tt目录下新建dir2目录,保存code4.h和code4.c文件。 下面是code4.h:
#include ;
void foo_d();
下面是code4.c:
#include "code1.h"
#include "code4.h"
void foo_d()
{
printf("This is code4.\n");
}
int main()
{
foo_a();
foo_d();
}
dir1目录下的code1.h和code1.c和上面的一样,我就不写了。 修改tt目录下的configure.in文件。
#指定项目的一个源文件
AC_INIT(dir2/code4.c)
#指定项目名称和版本号
AM_INIT_AUTOMAKE(myproject, 0.0.1)
#检查编译器
AC_PROG_CC
#检查ranlib
AC_PROG_RANLIB
#输出Makefile文件
AC_OUTPUT(Makefile
dir1/Makefile
dir2/Makefile
)
同时修改tt目录下的Makefile.am文件。
SUBDIRS = dir1 dir2
在dir1目录下修改Makefile.am文件。这时是将code1.c编译成一个不安装(noinst)的静态库文件。
noinst_LIBRARIES=libcode1.a
libcode1_a_SOURCES=code1.c
在dir2目录下添加一个Makefile.am文件。
INCLUDES= -I../dir1
bin_PROGRAMS=prog4
prog4_SOURCES=code4.c
prog4_LDADD=../dir1/libcode1.a
然后执行autogen.sh就可以了。
回复于:2004-10-04 17:10:26
关于第2个问题,我举的第2个例子正是说明这个问题,不过看来有些地方你没有理解。 AC_INIT(dir1/code2.c)写一个要检查的源文件就够了。多写是没有用的。不信你可以作一下试验。 只要把AC_INIT改为AC_INIT(dir1/code2.c,dir1/vvv.c),这个vvv.c文件是不存在的,但执行configure时,一样不会报错。但这个要检查的文件应该是程序的主文件,少了它,程序将无法运行。 AM_INIT_AUTOMAKE(package, version)是项目文件打包时的名字。比如说,AM_INIT_AUTOMAKE(mypro, 0.0.1),如果项目要发布源代码,这时打包就可以执行一个make dist,会自动生成一个mypro-0.0.1.tar.gz的文件。只要你从网上下载并编译过软件的源代码,对于这个应该不会陌生。当然从技术的角度来说,项目名称和项目版本号可以随便取,但为了管理上的方便,一般都有规范可循。
回复于:2004-10-04 17:32:28
第3个问题我也没有碰到过,我得想一下才能答复你。
回复于:2004-10-04 20:53:47
谢谢精灵网,你的回答使我清楚多了,我会自己实践一下的。:-)
回复于:2004-10-05 17:43:44
第3个问题我看可以你可以用这个办法解决。 首先在configure.in中加上对特殊编译器的检查,如果检查不到,则configure时会停止并给出“Couldn't find mpicc.”的出错信息:
#检查mpicc编译器
AC_CHECK_PROG(MPICC,mpicc,yes,no)
if test "$MPICC" = no; then
AC_MSG_ERROR([Couldn't find mpicc.])
fi
然后把需要用mpicc编译的源程序放在一个目录下面。在这个目录中先用上面的方法写Makefile.am文件。然后再加上下面这部分:
CC=mipcc
CFLAGS=
这样用自己定义的编译器和编译标志取代系统定义的编译器和编译标志。 由于我没有mpicc编译器,没有办法亲自做试验。可能使用mpicc还有其它的要求,直接照做不一定行得通。但解决问题的思想应该就是这样了,希望你能举一反三。
回复于:2004-10-05 17:55:05
回复于:2004-10-06 10:51:09
:)
回复于:2004-10-06 20:28:24
非常感谢kj501,我也正在摸索autoconf的用法,帮了大忙了 :em02:
回复于:2004-10-09 09:45:22
回复于:2004-10-21 04:27:00
关于这个主题我经过实践尝试,终于得到了正确的结果。但是还有一个问题,是在我发布程序时产生的(make dist)。 因为有部分程序不能公开发布,所以我想将它们生成库,(*.la, 通过libtool 生成),但我解开生成的压缩文件,发现库文件没在压缩文件里面,所以make的时候会有些函数找不到,产生错误。 请问如何能让带库文件的文件夹也一起包括的压缩文件里去呢?
回复于:2004-10-21 11:55:53
如果代码中用了库文件,要先编译安装库文件,再编译代码。你可以把编译成库文件的代码独立出来单独打包,这样也便于管理。我前面给的例子中库文件是只编译不安装的。我明天给一个动态库安装的例子出来。
回复于:2004-10-21 12:07:13
值得收藏,思路非常清晰的教材啊
回复于:2004-10-21 12:55:47
太棒了,goodgoodstudy to kj501, daydayup!
回复于:2004-10-21 19:16:42
我做的Makefile安装时默认安装在/usr/local/bin底下, 而我想安装在/usr/sbin下,不知道该怎么改?
先谢谢了!!
回复于:2004-10-21 21:49:37
这个问题不需要修改configure.in或者Makefile.am文件。用./configure --help可以看到有一个bindir参数可以指定可执行文件的安装目录。你只需要执行./configure --bindir=/usr/sbin就可以了。
回复于:2004-10-21 21:59:15
老兄,你可来了,帮帮忙,这个问题搞了一天了,还是没结果!!
回复于:2004-10-21 22:00:13
谢谢,我试试看!
回复于:2004-10-21 22:09:27
本人才学疏浅,惭愧惭愧!!
以后多多学习才是!! :em02: :em02:
回复于:2004-10-22 19:23:51
上面的问题已经解决,但又有个新的问题:
我的程序是这样的: mailrelay目录下有两个文件夹,poprelay和sendmailrelay.
在poprelay下的process.c中使用了crypt()函数,它要求gcc编译时加-lcrypt参数,但默认情况下编译时没有加-lcrypt,所以编译就通不过.
请问我该怎样做才能编译自动加上-lcrpty参数??
我自己瞎捉摸了一下,在configure.in文件加了这么一行: 引用:CFLAGS=-lcrypt
不知对不对???
回复于:2004-10-23 11:01:40
当然不对啦。要是对了,你也不没有必要问这个问题了。 应该是在Makefile.am中写
LIBS = -lcrypt
我觉得你对configure.in和Makefile.am的作用不清楚。configure.in是用来生成configure的,主要用于检查系统的编译环境。至于编译的各项参数,是由Makefile.am生成的Makefile决定的。建议你在网上找点资料仔细看看。
回复于:2004-10-24 11:04:15
谢谢你,那我就在网上找一些资料学习一下,我也看过一些关于automake,autoconf的文档,就是大部分看不太懂,呵呵! 以后还要不断学习才是啊,现在对这方面的动西,我是太死板了,其实主要原因还是没理解.还望以后多多指教!! :D :D :D
回复于:2004-12-02 03:04:45
隔了很长时间,现在又回到这个主题上。我安装了动态库,在lib目录下,可是通过make dist 还是不能将库文件(*.la) 打进包里。是否可以将库文件打到包里呢?因为有些源程序不能发布,所以必须有库文件。
回复于:2004-12-02 11:44:56
如果要发布编译好的二进制可执行程序,可以采用rpm包的形式。
回复于:2004-12-03 16:28:29
值得收藏,多谢kj501,辛苦了。
回复于:2004-12-11 20:51:48
kj501的回答很耐心哈,很喜欢这种step by step的例子。 喜欢这种细致讨论的气氛。 收藏!
回复于:2006-06-15 23:35:20
以前是看开源代码才悟出来的,有点想看很晚的感觉
回复于:2006-11-15 03:12:36
在发布程序的时候如果把库文件加进去呢?
回复于:2007-01-31 23:14:41
真是热心人呀,好人
|