下面再來看看多個源檔案的例子。
如何寫用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就可以了。