天天看点

自动生成Linux下Makefile全攻略(下)

    下面再来看看多个源文件的例子。

     如何写用code1.c, code2.c生成 prog1的configure.in和Makefile.am。首先建立一个项目文件夹testproj。在testproj下建立dir1目录。

    [[email protected] kang]$ mkdir testproj

    [[email protected] kang]$ mkdir dir1

    然后在dir1目录中分别建立code1.c, code1.h, code2.c, code2.h,下面源代码都只由几个简单的语句组成,以便说明问题。

   下面是code1.h:

    #include <stdlib.h>

    void foo_a();

    下面是code1.c:

    #include "code1.h"

    void foo_a()

    {

        printf("This is code1./n");

    }

    下面是code2.h:

    #include <stdlib.h>

    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了。

首先在testproj目录下建立configure.in文件:

    #指定项目的一个源文件

    AC_INIT(dir1/code2.c)

    #指定项目名称和版本号

    AM_INIT_AUTOMAKE(prog1, 0.0.1)

    #检查编译器

    AC_PROG_CC

    #输出Makefile文件

    AC_OUTPUT(Makefile dir1/Makefile) 

    同时建立testproj目录下的Makefile.am文件,这个文件很简单,就一句话:

    SUBDIRS=dir1

    然后建立dir1目录下的Makefile.am文件,这才是真正起作用的Makefile.am文件: 

    bin_PROGRAMS=prog1

    prog1_SOURCES=code1.c code2.c 

    完成之后,为了方便操作,再写一个autogen.sh文件,保存在testproj目录下。 

    #!/bin/sh

    aclocal

    automake --add-missing

    autoconf 

    ./autogen.sh即可在testproj目录下生成configure和makefile文件,同时在dir1目录下也会生成一个makefile文件。现在在testproj目录下执行make,屏幕将显示如下信息: 

    [[email protected] testproj]$ make

    Making all in dir1

    make[1]: Entering directory `/home/kang/testproj/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/kang/testproj/dir1'

    make[1]: Entering directory `/home/kang/testproj'

    make[1]: Nothing to be done for `all-am'.

    make[1]: Leaving directory `/home/kang/testproj' 

    进入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: 

    #include <stdlib.h>

    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两个程序。

     那么,两个处在不同子目录下的文件如何共同生成一可执行文件呢?一般互相引用的源程序都是放在同一个目录下的,如果要放在不同的目录,可以把要引用的源文件编译成静态库文件。为便于说明问题,准备了如下文件:

    在testproj目录下新建dir2目录,保存code4.h和code4.c文件。

    下面是code4.h:

    #include <stdlib.h>

    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();

    } 

    修改testproj目录下的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) 

    同时修改testproj目录下的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就可以了。

    补充问答。

    问题1:如何指定特定的编译器(AC_PROG_CC只会检查C编译器?)?

    答:首先在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= 

    这样用自己定义的编译器和编译标志取代系统定义的编译器和编译标志。

    问题2:因为有部分程序不能公开发布,所以我想将它们生成库,(*.la, 通过libtool 生成),但我解开生成的压缩文件,发现库文件没在压缩文件里面,所以make的时候会有些函数找不到,产生错误。请问如何能让带库文件的文件夹也一起包括的压缩文件里去呢?

    答:如果代码中用了库文件,要先编译安装库文件,再编译代码。你可以把编译成库文件的代码独立出来单独打包,这样也便于管理。前面给的例子中库文件是只编译不安装的。下面给一个动态库安装的例子。

     问题3:我做的Makefile安装时默认安装在/usr/local/bin底下,而我想安装在/usr/sbin下,不知道该怎么改?

    答:这个问题不需要修改configure.in或者Makefile.am文件。用./configure --help可以看到有一个bindir参数可以指定可执行文件的安装目录。你只需要执行./configure --bindir=/usr/sbin就可以了。

继续阅读