kj501 回复于:2004-10-02 10:55:53 |
configure.in写一个就够了,Makefile.am要在不同的目录下分别写。
这些东东都是要实际操作才能理解的。能不能把你的情况说详细一些。 |
wubulen 回复于: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 文件中指定? 谢谢指教。 |
mep 回复于: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;如何在一个大项目中包含几个项目。
网址:http://sf.net/projects/starccm/ |
kj501 回复于:2004-10-03 11:40:35 |
[quote:656c0e17e3="wubulen"]感谢你的回答。我再讲我的例子说的详细些(举例)。现在我有两个子目录,dir1 和 dir2, 在子目录dir1 下有源文件 code1.c, code1.h, code2.c, code2.h, code3.c, code3.h, 在子目录dir2下同样有几个源文件,code4.c,..........[/quote:656c0e17e3]
bin目录是那个目录,是你的程序安装的目录吗?如果我估计得不错的话,应该是/usr/bin,或者是/usr/local/bin吧。 prog1应该是一个可以单独执行的程序吧。不需要调用自己编写的动态库文件吗? |
kj501 回复于:2004-10-03 17:39:25 |
先来举一个简单的例子吧。如何写用code1.c, code2.c生成 prog1的configure.in和Makefile.am。
首先建立一个项目文件夹tt。在tt下建立dir1目录。 [code:1:78df12705f] [kj501@s2023 dir1]$ mkdir tt [kj501@s2023 dir1]$ mkdir tt/dir1 [/code:1:78df12705f] 然后在dir1目录中分别建立code1.c, code1.h, code2.c, code2.h,由于楼主没有给出源代码,我自己写了几个简单的语句,以便说明问题。 下面是code1.h: [code:1:78df12705f] #include <stdlib.h> void foo_a(); [/code:1:78df12705f] 下面是code1.c: [code:1:78df12705f] #include "code1.h" void foo_a() { printf("This is code1.\n"); } [/code:1:78df12705f] 下面是code2.h: [code:1:78df12705f] #include <stdlib.h> void foo_b(); [/code:1:78df12705f] 下面是code2.c,这里让code.c作为prog1的入口点: [code:1:78df12705f] #include "code1.h" #include "code2.h" void foo_b() { printf("This is code2.\n"); } int main() { foo_a(); foo_b(); } [/code:1:78df12705f] 建立好这几个文件之后,下面就可以正式建立configure.in和Makefile.am了。 首先在tt目录下建立configure.in文件: [code:1:78df12705f] #指定项目的一个源文件 AC_INIT(dir1/code2.c) #指定项目名称和版本号 AM_INIT_AUTOMAKE(prog1, 0.0.1) #检查编译器 AC_PROG_CC #输出Makefile文件 AC_OUTPUT(Makefile dir1/Makefile ) [/code:1:78df12705f] 同时建立tt目录下的Makefile.am文件,这个文件很简单,就一句话: [code:1:78df12705f] SUBDIRS=dir1 [/code:1:78df12705f] 然后建立dir1目录下的Makefile.am文件,这才是真正起作用的Makefile.am文件: [code:1:78df12705f] bin_PROGRAMS=prog1 prog1_SOURCES=code1.c code2.c [/code:1:78df12705f] 完成之后,为了方便操作,再写一个autogen.sh文件,保存在tt目录下。 [code:1:78df12705f] #!/bin/sh aclocal automake --add-missing autoconf [/code:1:78df12705f] 存盘之后,用chmod +x改成可执行文件。然后执行autogen.sh。 [code:1:78df12705f] ./autogen.sh [/code:1:78df12705f] 即可在tt目录下生成configure和makefile文件,同时在dir1目录下也会生成一个makefile文件。现在在tt目录下执行make,屏幕将显示如下信息: [code:1:78df12705f] [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' [/code:1:78df12705f] 进入dir1目录,就可以看到生成的prog1程序。如果再执行make install,prog1将被安装到缺省的/usr/local/bin目录下去。 这就是一个最简单的configure.in和Makefile.am的编写情况。你如果不熟悉,最好自己动手做一遍,复杂的configure.in和Makefile.am都是在这个基础上扩充的。 |
kj501 回复于: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: [code:1:4ecf204e74] #include <stdlib.h> void foo_c(); [/code:1:4ecf204e74] 下面是code3.c: [code:1:4ecf204e74] #include "code3.h" void foo_c() { printf("This is code3.\n"); } int main() { foo_c(); } [/code:1:4ecf204e74] 然后修改dir1目录下的Makefile.am文件: [code:1:4ecf204e74] bin_PROGRAMS=prog1 prog2 prog1_SOURCES=code1.c code2.c prog2_SOURCES=code3.c [/code:1:4ecf204e74] 再重新执行一次autogen.sh。make之后,在dir1目录下就会同时存在prog1和prog2两个程序。 你先体会一下吧。然后自己做做用code4.c和 code5.c生成 prog3。应该很容易的。 |
wubulen 回复于: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编译器? 再次感谢! |
kj501 回复于:2004-10-04 12:08:45 |
先回答第1个问题。一般互相引用的源程序都是放在同一个目录下的,如果要放在不同的目录,可以把要引用的源文件编译成静态库文件。
为便于说明问题,准备了如下文件: 在tt目录下新建dir2目录,保存code4.h和code4.c文件。 下面是code4.h: [code:1:1d78027594] #include <stdlib.h> void foo_d(); [/code:1:1d78027594] 下面是code4.c: [code:1:1d78027594] #include "code1.h" #include "code4.h" void foo_d() { printf("This is code4.\n"); } int main() { foo_a(); foo_d(); } [/code:1:1d78027594] dir1目录下的code1.h和code1.c和上面的一样,我就不写了。 修改tt目录下的configure.in文件。 [code:1:1d78027594] #指定项目的一个源文件 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 ) [/code:1:1d78027594] 同时修改tt目录下的Makefile.am文件。 [code:1:1d78027594] SUBDIRS = dir1 dir2 [/code:1:1d78027594] 在dir1目录下修改Makefile.am文件。这时是将code1.c编译成一个不安装(noinst)的静态库文件。 [code:1:1d78027594] noinst_LIBRARIES=libcode1.a libcode1_a_SOURCES=code1.c [/code:1:1d78027594] 在dir2目录下添加一个Makefile.am文件。 [code:1:1d78027594] INCLUDES= -I../dir1 bin_PROGRAMS=prog4 prog4_SOURCES=code4.c prog4_LDADD=../dir1/libcode1.a [/code:1:1d78027594] 然后执行autogen.sh就可以了。 |
kj501 回复于: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的文件。只要你从网上下载并编译过软件的源代码,对于这个应该不会陌生。当然从技术的角度来说,项目名称和项目版本号可以随便取,但为了管理上的方便,一般都有规范可循。 |
kj501 回复于:2004-10-04 17:32:28 |
第3个问题我也没有碰到过,我得想一下才能答复你。 |
wubulen 回复于:2004-10-04 20:53:47 |
谢谢精灵网,你的回答使我清楚多了,我会自己实践一下的。:-) |
kj501 回复于:2004-10-05 17:43:44 |
第3个问题我看可以你可以用这个办法解决。
首先在configure.in中加上对特殊编译器的检查,如果检查不到,则configure时会停止并给出“Couldn't find mpicc.”的出错信息: [code:1:f1442f64d8] #检查mpicc编译器 AC_CHECK_PROG(MPICC,mpicc,yes,no) if test "$MPICC" = no; then AC_MSG_ERROR([Couldn't find mpicc.]) fi [/code:1:f1442f64d8] 然后把需要用mpicc编译的源程序放在一个目录下面。在这个目录中先用上面的方法写Makefile.am文件。然后再加上下面这部分: [code:1:f1442f64d8] CC=mipcc CFLAGS= [/code:1:f1442f64d8] 这样用自己定义的编译器和编译标志取代系统定义的编译器和编译标志。 由于我没有mpicc编译器,没有办法亲自做试验。可能使用mpicc还有其它的要求,直接照做不一定行得通。但解决问题的思想应该就是这样了,希望你能举一反三。 |
win_hate 回复于:2004-10-05 17:55:05 |
[img:e414ca7818]http://bbs.chinaunix.net/forum/templates/subSilver/images/good_re.gif[/img:e414ca7818] [img:e414ca7818]http://bbs.chinaunix.net/forum/templates/subSilver/images/good_re.gif[/img:e414ca7818] [img:e414ca7818]http://bbs.chinaunix.net/forum/templates/subSilver/images/good_re.gif[/img:e414ca7818] [img:e414ca7818]http://bbs.chinaunix.net/forum/templates/subSilver/images/good_re.gif[/img:e414ca7818] [img:e414ca7818]http://bbs.chinaunix.net/forum/templates/subSilver/images/good_re.gif[/img:e414ca7818] |
kj501 回复于:2004-10-06 10:51:09 |
:) |
CNL 回复于:2004-10-06 20:28:24 |
非常感谢kj501,我也正在摸索autoconf的用法,帮了大忙了 :em02: |
chrisyan 回复于:2004-10-09 09:45:22 |
http://www.gnu.org/software/autoconf/manual/autoconf-2.57/html_chapter/autoconf_toc.html |
wubulen 回复于:2004-10-21 04:27:00 |
关于这个主题我经过实践尝试,终于得到了正确的结果。但是还有一个问题,是在我发布程序时产生的(make dist)。
因为有部分程序不能公开发布,所以我想将它们生成库,(*.la, 通过libtool 生成),但我解开生成的压缩文件,发现库文件没在压缩文件里面,所以make的时候会有些函数找不到,产生错误。 请问如何能让带库文件的文件夹也一起包括的压缩文件里去呢? |
kj501 回复于:2004-10-21 11:55:53 |
如果代码中用了库文件,要先编译安装库文件,再编译代码。你可以把编译成库文件的代码独立出来单独打包,这样也便于管理。我前面给的例子中库文件是只编译不安装的。我明天给一个动态库安装的例子出来。 |
superdoctor 回复于:2004-10-21 12:07:13 |
值得收藏,思路非常清晰的教材啊 |
stsaofirst 回复于:2004-10-21 12:55:47 |
太棒了,goodgoodstudy to kj501, daydayup! |
daniel-hou 回复于:2004-10-21 19:16:42 |
我做的Makefile安装时默认安装在/usr/local/bin底下, 而我想安装在/usr/sbin下,不知道该怎么改? 先谢谢了!! |
kj501 回复于:2004-10-21 21:49:37 |
这个问题不需要修改configure.in或者Makefile.am文件。用./configure --help可以看到有一个bindir参数可以指定可执行文件的安装目录。你只需要执行./configure --bindir=/usr/sbin就可以了。 |
daniel-hou 回复于:2004-10-21 21:59:15 |
老兄,你可来了,帮帮忙,这个问题搞了一天了,还是没结果!! http://bbs.chinaunix.net/forum/23/20041021/429469.html |
daniel-hou 回复于:2004-10-21 22:00:13 |
谢谢,我试试看! |
daniel-hou 回复于:2004-10-21 22:09:27 |
本人才学疏浅,惭愧惭愧!! 以后多多学习才是!! :em02: :em02: |
daniel-hou 回复于:2004-10-22 19:23:51 |
上面的问题已经解决,但又有个新的问题: 我的程序是这样的: mailrelay目录下有两个文件夹,poprelay和sendmailrelay. 在poprelay下的process.c中使用了crypt()函数,它要求gcc编译时加-lcrypt参数,但默认情况下编译时没有加-lcrypt,所以编译就通不过. 请问我该怎样做才能编译自动加上-lcrpty参数?? 我自己瞎捉摸了一下,在configure.in文件加了这么一行: [quote:580b093323]CFLAGS=-lcrypt[/quote:580b093323] 不知对不对??? |
kj501 回复于:2004-10-23 11:01:40 |
当然不对啦。要是对了,你也不没有必要问这个问题了。
应该是在Makefile.am中写 [code:1:4c199d24c7] LIBS = -lcrypt [/code:1:4c199d24c7] 我觉得你对configure.in和Makefile.am的作用不清楚。configure.in是用来生成configure的,主要用于检查系统的编译环境。至于编译的各项参数,是由Makefile.am生成的Makefile决定的。建议你在网上找点资料仔细看看。 |
daniel-hou 回复于:2004-10-24 11:04:15 |
谢谢你,那我就在网上找一些资料学习一下,我也看过一些关于automake,autoconf的文档,就是大部分看不太懂,呵呵!
以后还要不断学习才是啊,现在对这方面的动西,我是太死板了,其实主要原因还是没理解.还望以后多多指教!! :D :D :D |
wubulen 回复于:2004-12-02 03:04:45 |
隔了很长时间,现在又回到这个主题上。我安装了动态库,在lib目录下,可是通过make dist 还是不能将库文件(*.la) 打进包里。是否可以将库文件打到包里呢?因为有些源程序不能发布,所以必须有库文件。 |
kj501 回复于:2004-12-02 11:44:56 |
如果要发布编译好的二进制可执行程序,可以采用rpm包的形式。 |
yunin 回复于:2004-12-03 16:28:29 |
值得收藏,多谢kj501,辛苦了。 |
simtiger 回复于:2004-12-11 20:51:48 |
kj501的回答很耐心哈,很喜欢这种step by step的例子。
喜欢这种细致讨论的气氛。 收藏! |