先来举一个简单的例子吧。如何写用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:
下面是code1.c:
#include "code1.h"
void foo_a()
{
printf("This is code1.\n");
}
下面是code2.h:
下面是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文件,这个文件很简单,就一句话:
然后建立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。
即可在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都是在这个基础上扩充的。
在此基础上,如果要同时实现code1.c, code2.c生成 prog1, 而 code3.c生成prog2。由于code1.c,code2.c,code3.c都在同一个目录,只要改写dir1目录下的Makefile.am就可以了。
为了便于说明问题,首先要在dir1目录下增加一个code3.h 和code3.c文件。
下面是code3.h:
下面是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。应该很容易的。
十分感谢精灵王详尽的解释,现在已经清楚多了。还有三个问题需要确认。
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编译器?
再次感谢!
先回答第1个问题。一般互相引用的源程序都是放在同一个目录下的,如果要放在不同的目录,可以把要引用的源文件编译成静态库文件。
为便于说明问题,准备了如下文件:
在tt目录下新建dir2目录,保存code4.h和code4.c文件。
下面是code4.h:
下面是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文件。
在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就可以了。
关于第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的文件。只要你从网上下载并编译过软件的源代码,对于这个应该不会陌生。当然从技术的角度
来说,项目名称和项目版本号可以随便取,但为了管理上的方便,一般都有规范可循。
第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文件。然后再加上下面这部分:
这样用自己定义的编译器和编译标志取代系统定义的编译器和编译标志。
由于我没有mpicc编译器,没有办法亲自做试验。可能使用mpicc还有其它的要求,直接照做不一定行得通。但解决问题的思想应该就是这样了,希望你能举一反三。
阅读(717) | 评论(0) | 转发(0) |