如何寫用code1.c, code2.c生成 prog1的configure.in和Makefile.am。首先建立一個項目文件夾testproj。在testproj下建立dir1目錄。
[kang@node16 kang]$ mkdir testproj
[kang@node16 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_CONFIG_FILES(Makefile dir1/Makefile)
AC_OUTPUT
同時建立testproj目錄下的Makefile.am文件,這個文件很簡單,就一句話:
SUBDIRS=dir1
然後建立dir1目錄下的Makefile.am文件,這纔是真正起作用的Makefile.am文件:
bin_PROGRAMS=prog1
prog1_SOURCES=code1.c code2.c
完成之後,爲了方便操作,再寫一個autogen.sh文件,保存在testproj目錄下。
#!/bin/sh
touch NEWS README AUTHORS ChangeLog
aclocal
automake --add-missing
autoconf
./autogen.sh即可在testproj目錄下生成configure和makefile文件,同時在dir1目錄下也會生成一個makefile文件。現在在testproj目錄下執行make,屏幕將顯示如下信息:
[kang@node16 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就可以了。