為什么linux下要先./configure再make make install?


一:


許多讀者都知道在linux系統中安裝軟件的其中一種:源碼安裝的方法是,先輸入./configure,然后輸入make,最后make install。或許有人留意到沒有,這些軟件的根目錄中開始是沒有Makefile的,在執行了./configure后會生成了很多奇怪名字的文件,當然./configure命令就是執行當前目錄的名為configure的腳本,這篇文章就是簡單的說說為什么要這樣子。

二:


實際操作可以讓我們得到更深刻的理解。
假設我們寫一個簡單的程序poke,它用到utime系統調用來更改文件的訪問和修改時間,這個程序必須具備高度的可移植性
First Try
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<utime.h>

int main(argc,argv)
int argc;
char **argv;
{
if(argc !=2)
{
fprintf(stderr,"Usage:poke file \n");
exit(1);
}

if(utime(argv[1],NULL)<0)
{
perror("utime");
exit(1);
}

exit(0);
}
簡單的Makefile如下:
CC=gcc
CFLAGS=-g -O2

all:poke

poke:poke.o
    $(CC) -o poke $(CFLAGS) $(LDFLAGS) poke.o
目前為止,一個make命令就可以生成poke的可執行文件,so far,so good!不幸的是,這里有幾個問題值得深究:
在比較old的BSD4.3派生的unix系統,utime系統調用並不能接受第二個參數NULL,它們需要的是一個struct utimbuf的結構體指針。再追溯到更古老的系統,它們甚至沒有定義這個struct,需要傳遞兩個long型的參數。
另外一個問題是stdlib.h是ANSI C所用,老一點的系統也沒有這份copy。我們把它包含進來是為了得到exit函數的聲明。
在上面的Makefile中,我們甚至都沒有提供安裝的方法,當然作為例子可能不需要這樣做,但實際上我們需要在Makefile里面install跟clean兩個偽目標。

Second Try
為了解決上面的問題,我們用預處理命令的宏修改了poke.c文件如下:
#include <stdio.h>


#ifdef STDC_HEADERS


#include <stdlib.h>


#endif


#include <sys/types.h>


#ifdef HAVE_UTIME_H


#include <utime.h>


#endif


#ifndef HAVE_UTIME_NULL


#include <time.h>


#ifndef HAVE_STRUCT_UTIMBUF


struct utimbuf


{


long actime;


long modtime;


};


#endif


static int
utime_now (file)


char *file;


{


struct utimbuf now;


now.actime = now.modtime = time (NULL);


return utime (file, &now);


}


#define utime(f, p) utime_now (f)


#endif /* HAVE_UTIME_NULL */


int


main (argc, argv)


int argc;


char **argv;


{


if (argc != 2)


{


fprintf (stderr, "Usage: poke file\n");


exit (1);


}


if (utime (argv[1], NULL) < 0)


{


perror ("utime");


exit (1);


}


exit (0);


}
下面是相應的Makefile,我們添加了預處理標志以及install和clean兩個偽目標。
# Set this to your installation directory.


bindir = /usr/local/bin


# Uncomment this if you have the standard ANSI/ISO C header files.


# STDC_HDRS = -DSTDC_HEADERS


# Uncomment this if you have utime.h.


# UTIME_H = -DHAVE_UTIME_H


# Uncomment this if utime (FILE, NULL) works on your system.


# UTIME_NULL = -DHAVE_UTIME_NULL
# Uncomment this if struct utimbuf is defined in utime.h.


# UTIMBUF = -DHAVE_STRUCT_UTIMBUF


CC = gcc


CFLAGS = -g -O2


ALL_CFLAGS = $(STDC_HDRS) $(UTIME_H) $(UTIME_NULL) $(UTIMBUF) $(CFLAGS)


all: poke


poke: poke.o


$(CC) -o poke $(ALL_CFLAGS) $(LDFLAGS) poke.o


.c.o:


$(CC) -c $(ALL_CFLAGS) poke.c


install: poke


cp poke $(bindir)/poke


clean:


rm poke poke.o

從Makefile可以知道,編譯安裝poke這個軟件的用戶必須知道自己的系統中utime系統調用是怎么樣工作的,然后把Makefile中對應的預處理標志選擇上,這又是一個頭疼的問題。
Third Try
作為第三次嘗試,我們用autoconf和automake工具自動檢查配置工具生成Makefile,我們寫一個
configure.in的腳本去檢測當前系統的配置特性,而不需要用戶自己編輯Makefile。
poke.c需要包含config后的頭文件config.h
#include "config.h"
1)configure.in腳本

AC_INIT(poke.c)


AM_INIT_AUTOMAKE(poke, 1.0)


AM_CONFIG_HEADER(config.h:config.in)


AC_PROG_CC


AC_HEADER_STDC
AC_CHECK_HEADERS(utime.h)


AC_EGREP_HEADER(utimbuf, utime.h, AC_DEFINE(HAVE_STRUCT_UTIMBUF))


AC_FUNC_UTIME_NULL


AC_OUTPUT(Makefile)

‘AC_HEADER_STDC’


檢查標准的C頭文件.


‘AC_CHECK_HEADERS’


檢查指定的頭文件是否存在。


‘AC_EGREP_HEADER’


檢查特定頭文件里面是否包含特定的字串, in this case checking


for ‘utimbuf’ in ‘utime.h’.


‘AC_FUNC_UTIME_NULL’


Check whether ‘utime’ accepts a NULL second argument to set the ?le change


time to the current time.
2
)Makefile.am腳本
bin_PROGRAMS = poke


poke_SOURCES = poke.c
bin_PROGRAMS表明構建一個名為poke的程序,它應當安裝在binary目錄,己前面提到的bindir目錄;


poke_SOURCES表明poke可執行程序需要源文件為poke.c

3)acconfig.h腳本

/* Name of package. */


#undef PACKAGE


/* Version of package. */


#undef VERSION


/* Whether utime.h defines struct utimbuf. */


#undef HAVE_STRUCT_UTIMBUF

4)
運行如下命令自動生成其他必備的文件(你的電腦上應該有autoconf/automake/m4/perl/libtool)
panasonic@panasonic-linux:~/devel/poke3> autoscan
configure.in: warning: missing AC_CHECK_FUNCS([utime]) wanted by: poke.c:17
這里autoscan提醒我們configure.in應該加上檢查utime函數的選項

panasonic@panasonic-linux:~/devel/poke3> aclocal
panasonic@panasonic-linux:~/devel/poke3> autoconf
panasonic@panasonic-linux:~/devel/poke3> automake -a
Makefile.am: required file `./NEWS' not found
Makefile.am: required file `./README' not found
Makefile.am: required file `./AUTHORS' not found
Makefile.am: required file `./ChangeLog' not found

automake -a
參數是--add-missing,意思是automake會自動添加它運行所需文件到當前工程,上面提示當前目錄下找不到Makefile.am所需四個文件,NEWS/README/AUTHORS/ChangeLog,作為例子我們暫時忽略它們,加上--foreign選項
panasonic@panasonic-linux:~/devel/poke3> automake -a --foreign
5
)當前目錄已經產生了好多文件
? ‘aclocal.m4’


? ‘configure’


? ‘config.in’


? ‘Makefile.in’


? ‘stamp-h.in’
然后我們運行./configure腳本
panasonic@panasonic-linux:~/devel/poke3> ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for gcc... gcc
checking for C compiler default output file name... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables... 
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking for style of include used by make... GNU
checking dependency style of gcc... gcc3
checking how to run the C preprocessor... gcc -E
checking for grep that handles long lines and -e... /usr/bin/grep
checking for egrep... /usr/bin/grep -E
checking for ANSI C header files... yes
checking for sys/types.h... yes
checking for sys/stat.h... yes
checking for stdlib.h... yes
checking for string.h... yes
checking for memory.h... yes
checking for strings.h... yes
checking for inttypes.h... yes
checking for stdint.h... yes
checking for unistd.h... yes
checking utime.h usability... yes
checking utime.h presence... yes
checking for utime.h... yes
checking for utime.h... (cached) yes
checking whether utime accepts a null argument... yes
configure: creating ./config.status
config.status: creating Makefile
config.status: creating config.h
config.status: executing depfiles commands
最后產生我們需要的Makefile和config.h
然后運行make,make install就會生成可執行文件然后安裝。

autoconf和automake過程關系如下圖:



三:構建過程中各種文件
6)程序開發者需要寫以下幾個腳本
1configure.in
這是配置腳本,包含autoconf的可執行宏。當然它也可以包含shell命令。這個腳本包含為可移植服務的特性檢測,文件的最后AC_OUTPUT宏列舉了當用戶運行configure腳本需要創建的文件,一般是Makefile。

2Makefile.am
這是automake的輸入文件。它描述了代碼是如何構建的。它由automake的變量組成,當然它也可能包含Makefile的目標。這個文件僅是automake需要,新一點的工具可以允許開發者直接寫Makefile.in文件。

3acconfig.h
當configure腳本用AM_CONFIG_HEADER或者AC_CONFIG_HEADER產生了帶可移植特性的頭文件時,這個文件用來描述那些autoheader命令識別不了宏。通常在configure.in任何一個AC_DEFINE宏都會在這個文件有一行。

4acinclude.m4
這個文件不是必須的。它定義了本地autoconf宏,這些宏可能用在configure.in里面。如果你不需要任何本地的autoconf宏,你就不需要這個文件,因為你可以把這些需要直接放在configure.in文件里。新一點的工具可能會忽略這個文件,取代的是m4的文件夾,然后在Makefile.am用ACLOCAL_AMFLAGS=-I m4使得aclocal檢查里面是否有宏定義。


7)開發文件
1configure
這是稍后用來構建package的配置腳本。它是autoconf從configure.in 和aclocal.m4產生的,同時它也是一個shell腳本

2Makefile.in
這是configure腳本生成Makefile的高一級文件,它是由automake從Makefile.am文件產生的。如果你沒有用到automake,那你就必須自己來寫這個文件。

3aclocal.m4
它由aclocal程序產生,基於configure.in和acinclude.m4的內容。它包含了autoconf定義的宏,用來產生configure。這些autoconf的宏可能定義在acinclude.m4文件里面,也可能定義在automake或者libtool或者gettext里面。

4configin
這個文件基於acconfig.h和configure.in,有autoheade產生。在構建時,configure腳本會在它里面定義一些宏來創建config.h,config.h是用來包含進你的應用程序的。它允許你的程序使用預處理條件以便改變你的程序動作適應當前的系統。這個文件也可能名為
config.h.in
5、
stamp.h-in
automake產生的,它總是包含timestamp字串,它用來標識文件的時間戳以指明config.in是否是最新的。


8)構建文件
1config.status
安裝一個軟件第一步驟運行configure腳本,然后它會產生config.status,這也是一個shell腳本。當automake使用Makefile.in產生Makefile時會包含自動運行config.status的規則。

2Makefile
make會讀入然后產生program,config.status運行時候會將Makefile.in翻譯成
Makefile
3、
config.h
這個文件定義了c預處理宏,以便適應不同的移植要求,config.status也會把configin翻譯成
config.h
4、
config.cache
configure腳本運行時緩存,可以加速構建過程。

5stamp.h
跟stamp-h.in類似。


9)支持文件
1、ABOUT-NLS;2、ansi2knr.c;3、ansi2knr.1;4、config.guess;5、config.sub;6

.....


這里傳上文章的練習示例代碼包,請大家一起練習學習。


http://space.ednchina.com/Upload/2009/11/16/4215f1e1-60d5-4d00-ae83-6c7872802972.zip


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM