2007年2月20日 星期二

autoconf手冊(三)

[本文轉載來源為:http://doc.sheup.com/linux/linux403.htm]

對普通函數的檢查
這些宏被用於尋找沒有包括在特定函數測試宏中的函數。如果函數可能出現下除了缺省C庫以外的庫中,就要首先為這些庫調用AC_CHECK_LIB。如果你除了需要檢查函數是否存在之外,還要檢查函數的行為,你就不得不為此而編寫你自己的測試(參見編寫測試)。
宏︰ AC_CHECK_FUNC (function, [action-if-found [, action-if-not-found]])
如果可以使用C函數function,就營運shell命令action-if-found,否則營運 action-if-not-found。如果你只希望在函數可用的時候定義一個符號,就考慮使用 AC_CHECK_FUNCS。由於C++比C更加標準化,即使在調用了AC_LANG_CPLUSPLUS 的時候,本宏仍然用C的連接模式對函數進行檢查。(關於為測試選擇語言的詳情,請參見 對語言的選擇)
宏︰ AC_CHECK_FUNCS (function... [, action-if-found [, action-if-not-found]])
對於每個在以空格分隔的函數清單function中出現的函數,如果可用,就定義HAVE_function (全部大寫)。如果給出了action-if-found,它就是在找到一個函數的時候執行的附加的shell代碼。你可以給出 ``break''以便在找到第一個匹配的時候跳出循環。如果給出了action-if-not-found,它就在找不到某個函數的時候執行。
宏︰ AC_REPLACE_FUNCS (function...)
本宏的功能就類似於以將``function.o''添加到輸出變量LIBOBJS的shell 代碼為參數action-if-not-found,調用AC_CHECK_FUNCS。你可以透過用 ``#ifndef HAVE_function''包圍你為函數提供的替代版本的原型來聲明函數。如果系統含有該函數,它可能在一個你應該引入的頭檔案中進行聲明,所以你不應該重新聲明它,以避免聲明衝突。

頭檔案
下列宏檢查某些C頭檔案是否存在。如果沒有為你需要檢查的頭檔案定義特定的宏,而且你不需要檢查它的任何特殊屬性,那麼你就可以使用一個通用的頭檔案檢查宏。

對特定頭檔案的檢查
這些宏檢查特定的系統頭檔案--它們是否存在,以及在某些情況下它們是否定義了特定的符號。
宏︰ AC_DECL_SYS_SIGLIST
如果在系統頭檔案,``signal.h''或者``unistd.h'',中定義了變量sys_siglist,就定義SYS_SIGLIST_DECLARED。
宏︰ AC_DIR_HEADER
類似於調用AC_HEADER_DIRENT和AC_FUNC_CLOSEDIR_VOID,但為了指明找到了哪個頭檔案而定義了不同的一組C預處理器宏。本宏和它定義的名字是過時的。它定義的名字是︰

``dirent.h''
DIRENT
``sys/ndir.h''
SYSNDIR
``sys/dir.h''
SYSDIR
``ndir.h''
NDIR
此外,如果closedir不能返回一個有意義的值,就定義VOID_CLOSEDIR。

宏︰ AC_HEADER_DIRENT
對下列頭檔案進行檢查,並且為第一個找到的頭檔案定義``DIR'',以及列出的C預處理器宏︰

``dirent.h''
HAVE_DIRENT_H
``sys/ndir.h''
HAVE_SYS_NDIR_H
``sys/dir.h''
HAVE_SYS_DIR_H
``ndir.h''
HAVE_NDIR_H
源代碼中的目錄庫聲明應該以類似於下面的模式給出︰

#if HAVE_DIRENT_H
# include
# define NAMLEN(dirent) strlen((dirent)->d_name)
#else
# define dirent direct
# define NAMLEN(dirent) (dirent)->d_namlen
# if HAVE_SYS_NDIR_H
# include
# endif
# if HAVE_SYS_DIR_H
# include
# endif
# if HAVE_NDIR_H
# include
# endif
#endif

使用上述聲明,程式應該把變量定義成類型struct dirent,而不是struct direct,並且應該透過把指向struct direct的指標傳遞給宏NAMLEN來獲得目錄項的名稱的長度。

本宏還為SCO Xenix檢查庫``dir''和``x''。

宏︰ AC_HEADER_MAJOR
如果``sys/types.h''沒有定義major、minor和makedev,但``sys/mkdev.h''定義了它們,就定義MAJOR_IN_MKDEV;否則,如果``sys/sysmacros.h''定義了它們,就定義MAJOR_IN_SYSMACROS。
宏︰ AC_HEADER_STDC
如果含有標準C(ANSI C)頭檔案,就定義STDC_HEADERS。特別地,本宏檢查``stdlib.h''、``stdarg.h''、``string.h''和``float.h'';如果系統含有這些頭檔案,它可能也含有其他的標準C頭檔案。本宏還檢查``string.h''是否定義了memchr (並據此對其他mem函數做出假定),``stdlib.h''是否定義了free(並據此對malloc和其他相關函數做出假定),以及``ctype.h''宏是否按照標準C的要求而可以用於被設定了高位的字符。

因為許多含有GCC的系統並不含有標準C頭檔案,所以用STDC_HEADERS而不是__STDC__ 來決定系統是否含有服從標準(ANSI-compliant)的頭檔案(以及可能的C庫函數)。

在沒有標準C頭檔案的系統上,變種太多,以至於可能沒有簡單的模式對你所使用的函數進行定義以使得它們與系統頭檔案聲明的函數完全相同。某些系統包含了ANSI和BSD函數的混合;某些基本上是標準(ANSI)的,但缺少``memmove'';有些系統在``string.h''或者``strings.h''中以宏的模式定義了BSD函數;有些系統除了含有``string.h''之外,只含有BSD函數;某些系統在``memory.h'' 中定義內存函數,有些在``string.h''中定義;等等。對於一個字元串函數和一個內存函數的檢查可能就夠了;如果庫含有這些函數的標準版,那麼它就可能含有其他大部分函數。如果你在``configure.in'' 中安放了如下代碼︰

AC_HEADER_STDC
AC_CHECK_FUNCS(strchr memcpy)

那麼,在你的代碼中,你就可以像下面那樣放置聲明︰
#if STDC_HEADERS
# include
#else
# ifndef HAVE_STRCHR
# define strchr index
# define strrchr rindex
# endif
char *strchr (), *strrchr ();
# ifndef HAVE_MEMCPY
# define memcpy(d, s, n) bcopy ((s), (d), (n))
# define memmove(d, s, n) bcopy ((s), (d), (n))
# endif
#endif

如果你使用沒有等價的BSD版的函數,諸如memchr、memset、strtok 或者strspn,那麼僅僅使用宏就不夠了;你必須為每個函數提供一個實現。以memchr為例,一種僅僅在需要的時候(因為系統C庫中的函數可能經過了手工優化)與你的實現協作的簡單模式是把實現放入 ``memchr.c''並且使用``AC_REPLACE_FUNCS(memchr)''。

宏︰ AC_HEADER_SYS_WAIT
如果``sys/wait.h''存在並且它和POSIX.1相兼容,就定義HAVE_SYS_WAIT_H。如果``sys/wait.h''不存在,或者如果它使用老式BSD union wait,而不是 int來儲存狀態值,就可能出現不兼容。如果``sys/wait.h''不與POSIX.1兼容,那就不是引入該頭檔案,而是按照它們的常見解釋定義POSIX.1宏。下面是一個例子︰

#include
#if HAVE_SYS_WAIT_H
# include
#endif
#ifndef WEXITSTATUS
# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
#endif
#ifndef WIFEXITED
# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
#endif
宏︰ AC_MEMORY_H
在``string.h''中,如果沒有定義memcpy, memcmp等函數,並且``memory.h'' 存在,就定義NEED_MEMORY_H。本宏已經過時;可以用AC_CHECK_HEADERS(memory.h)來代替。參見為AC_HEADER_STDC提供的例子。
宏︰ AC_UNISTD_H
如果系統含有``unistd.h'',就定義HAVE_UNISTD_H。本宏已經過時;可以用 ``AC_CHECK_HEADERS(unistd.h)''來代替。

檢查系統是否支援POSIX.1的模式是︰

#if HAVE_UNISTD_H
# include
# include
#endif

#ifdef _POSIX_VERSION
/* Code for POSIX.1 systems. */
#endif

在POSIX.1系統中包含了``unistd.h''的時候定義_POSIX_VERSION。如果系統中沒有``unistd.h'',那麼該系統就一定不是POSIX.1系統。但是,有些非POSIX.1(non-POSIX.1)系統也含有``unistd.h''。

宏︰ AC_USG
如果系統並不含有``strings.h''、rindex、bzero等頭檔案或函數,就定義USG。定義USG就隱含地表明了系統含有``string.h''、strrchr、memset等頭檔案或函數。

符號USG已經過時了。作為本宏的替代,參見為AC_HEADER_STDC提供的例子。
對普通頭檔案的檢查
這些宏被用於尋找沒有包括在特定測試宏中的系統頭檔案。如果你除了檢查頭檔案是否存在之外還要檢查它的內容,你就不得不為此而編寫你自己的測試(參見編寫測試)。
宏︰ AC_CHECK_HEADER (header-file, [action-if-found [, action-if-not-found]])
如果系統頭檔案header-file存在,就執行shell命令action-if-found,否則執行action-if-not-found。如果你只需要在可以使用頭檔案的時候定義一個符號,就考慮使用 AC_CHECK_HEADERS。
宏︰ AC_CHECK_HEADERS (header-file... [, action-if-found [, action-if-not-found]])
對於每個在以空格分隔的參數清單header-file出現的頭檔案,如果存在,就定義 HAVE_header-file(全部大寫)。如果給出了action-if-found,它就是在找到一個頭檔案的時候執行的附加shell代碼。你可以把``break''作為它的值以便在第一次匹配的時候跳出循環。如果給出了action-if-not-found,它就在找不到某個頭檔案的時候被執行。

架構
以下的宏檢查某些架構或者某些架構成員。為了檢查沒有在此給出的架構,使用AC_EGREP_CPP (參見檢驗聲明)或者使用AC_TRY_COMPILE (參見檢驗語法)。
宏︰ AC_HEADER_STAT
如果在``sys/stat.h''中定義的S_ISDIR、S_ISREG等宏不能正確地工作(返回錯誤的正數),就定義STAT_MACROS_BROKEN。這種情況出現下Tektronix UTekV、 Amdahl UTS和Motorola System V/88上。
宏︰ AC_HEADER_TIME
如果程式可能要同時引入``time.h''和``sys/time.h'',就定義TIME_WITH_SYS_TIME。在一些老式系統中,``sys/time.h''引入了``time.h'',但``time.h''沒有用多個包含保護起來,所以程式不應該顯式地同時包含這兩個檔案。例如,本宏在既使用struct timeval或 struct timezone,又使用struct tm程式中有用。它最好和 HAVE_SYS_TIME_H一起使用,該宏可以透過調用AC_CHECK_HEADERS(sys/time.h)來檢查。

#if TIME_WITH_SYS_TIME
# include
# include
#else
# if HAVE_SYS_TIME_H
# include
# else
# include
# endif
#endif
宏︰ AC_STRUCT_ST_BLKSIZE
如果struct stat包含一個st_blksize成員,就定義HAVE_ST_BLKSIZE。
宏︰ AC_STRUCT_ST_BLOCKS
如果struct stat包含一個st_blocks成員,就定義HAVE_ST_BLOCKS。否則,就把``fileblocks.o''添加到輸出變量LIBOBJS中。
宏︰ AC_STRUCT_ST_RDEV
如果struct stat包含一個st_rdev成員,就定義HAVE_ST_RDEV。
宏︰ AC_STRUCT_TM
如果``time.h''沒有定義struct tm,就定義TM_IN_SYS_TIME,它意味著引入``sys/time.h''將得到一個定義得更好的struct tm。
宏︰ AC_STRUCT_TIMEZONE
確定如何獲取當前的時區。如果struct tm有tm_zone成員,就定義HAVE_TM_ZONE。否則,如果找到了外部數組tzname,就定義HAVE_TZNAME。

類型定義
以下的宏檢查C typedefs。如果沒有為你需要檢查的typedef定義特定的宏,並且你不需要檢查該類型的任何特殊的特徵,那麼你可以使用一個普通的typedef檢查宏。

對特定類型定義的檢查
這些宏檢查在``sys/types.h''和``stdlib.h''(如果它存在)中定義的特定的C typedef。
宏︰ AC_TYPE_GETGROUPS
把GETGROUPS_T定義成getgroups的數組參數的基類型gid_t或者int。
宏︰ AC_TYPE_MODE_T
如果沒有定義mode_t,就把mode_t定義成int。
宏︰ AC_TYPE_OFF_T
如果沒有定義off_t,就把off_t定義成long。
宏︰ AC_TYPE_PID_T
如果沒有定義pid_t,就把pid_t定義成int。
宏︰ AC_TYPE_SIGNAL
如果``signal.h''把signal聲明成一個指向返回值為void的函數的指標,就把RETSIGTYPE定義成void;否則,就把它定義成int。

把信號處理器(signal handler)的返回值類型定義為RETSIGTYPE︰

RETSIGTYPE
hup_handler ()
{
...
}
宏︰ AC_TYPE_SIZE_T
如果沒有定義size_t,就把size_t定義成unsigned。
宏︰ AC_TYPE_UID_T
如果沒有定義uid_t,就把uid_t定義成int並且把 gid_t定義成int。

對普通類型定義的檢查
本宏用於檢查沒有包括在特定類型測試宏中的typedef。
宏︰ AC_CHECK_TYPE (type, default)
如果``sys/types.h''或者``stdlib.h''或者``stddef.h''存在,而類型 type沒有在它們之中被定義,就把type定義成C(或者C++)預定義類型 default;例如,``short''或者``unsigned''。

C編譯器的特徵
下列宏檢查C編譯器或者機器架構的特徵。為了檢查沒有在此列出的特徵,使用AC_TRY_COMPILE (參見檢驗語法)或者AC_TRY_RUN (參見檢查營運時的特徵)
宏︰ AC_C_BIGENDIAN
如果字(word)按照最高位在前的模式儲存(比如Motorola和SPARC,但不包括Intel和VAX,CPUS),就定義 WORDS_BIGENDIAN。
宏︰ AC_C_CONST
如果C編譯器不能完全支援關鍵字const,就把const定義成空。有些編譯器並不定義 __STDC__,但支援const;有些編譯器定義__STDC__,但不能完全支援 const。程式可以假定所有C編譯器都支援const,並直接使用它;對於那些不能完全支援const的編譯器,``Makefile''或者配置頭檔案將把const定義為空。
宏︰ AC_C_INLINE
如果C編譯器支援關鍵字inline,就什麼也不作。如果C編譯器可以接受__inline__或者__inline,就把inline定義成可接受的關鍵字,否則就把inline定義為空。
宏︰ AC_C_CHAR_UNSIGNED
除非C編譯器預定義了__CHAR_UNSIGNED__,如果C類型char是無符號的,就定義 __CHAR_UNSIGNED__。
宏︰ AC_C_LONG_DOUBLE
如果C編譯器支援long double類型,就定義HAVE_LONG_DOUBLE。有些C編譯器並不定義__STDC__但支援long double類型;有些編譯器定義 __STDC__但不支援long double。
宏︰ AC_C_STRINGIZE
如果C預處理器支援字元串化操作符(stringizing operator),就定義HAVE_STRINGIZE。字元串化操作符是 ``#''並且它在宏定義中以如下模式出現︰

#define x(y) #y
宏︰ AC_CHECK_SIZEOF (type [, cross-size])
把SIZEOF_uctype定義為C(或C++)預定義類型type的,以位元組為單位的大小,例如``int'' or ``char *''。如果編譯器不能識別``type'',它就被定義為0。 uctype就是把type中所有小寫字母轉化為大寫字母,空格轉化成下劃線,星號轉化成``P'' 而得到的名字。在交叉編譯中,如果給出了cross-size,就使用它,否則configure就生成一個錯誤並且退出。

例如,調用
AC_CHECK_SIZEOF(int *)

在DEC Alpha AXP系統中,把SIZEOF_INT_P定義為8。

宏︰ AC_INT_16_BITS
如果C類型int是16為寬,就定義INT_16_BITS。本宏已經過時;更常見的模式是用 ``AC_CHECK_SIZEOF(int)''來代替。
宏︰ AC_LONG_64_BITS
如果C類型long int是64位寬,就定義LONG_64_BITS。本宏已經過時;更常見的模式是用``AC_CHECK_SIZEOF(long)''來代替。

Fortran 77編譯器的特徵
下列的宏檢查Fortran 77編譯器的特徵。為了檢查沒有在此列出的特徵,使用AC_TRY_COMPILE (參見檢驗語法)或者AC_TRY_RUN (參見檢驗營運時的特徵),但首先必須確認當前語言被設定成 Fortran 77 AC_LANG_FORTRAN77(參見對語言的選擇)。
宏︰ AC_F77_LIBRARY_LDFLAGS
為成功地連接Fotran 77或者共享庫而必須的Fortran 77內置函數(intrinsic)和營運庫確定連接選項(例如,``-L''和``-l'')。輸出變量FLIBS被定義為這些選項。

本宏的目的是用於那些需要把C++和Fortran 77源代碼混合到一個程式或者共享庫中的情況(參見GNU Automake中的``Mixing Fortran 77 With C and C++''節)。

例如,如果來自C++和Fortran 77編譯器的目標檔案必須被連接到一起,那麼必須用C++編譯器/連接器來連接(因為有些C++特定的任務要在連接時完成,這樣的任務有調用全局構造函數、模板的實例化、啟動例外(exception)支援,等等)。

然而,Fortran 77內置函數和營運庫也必須被連接,但C++編譯器/連接器在缺省情況下不知道如何添加這些 Fortran 77庫。因此,就創建AC_F77_LIBRARY_LDFLAGS宏以確認這些Fortran 77庫。
系統服務
下列宏檢查作業系統服務或者作業系統能力。
宏︰ AC_CYGWIN
檢查Cygwin環境。如果存在,就把shell變量CYGWIN設定成``yes''。如果不存在,就把CYGWIN設定成空字元串。
宏︰ AC_EXEEXT
根據編譯器的輸出,定義替換變量EXEEXT,但不包括.c、.o和.obj檔案。對於Unix來說典型的值為空,對Win32來說典型的值為``.exe''或者``.EXE''。
宏︰ AC_OBJEXT
根據編譯器的輸出,定義替換變量OBJEXT,但不包括.c檔案。對於Unix來說典型的值為``.o'',對Win32來說典型的值為``.obj''。
宏︰ AC_MINGW32
檢查MingW32編譯環境。如果存在,就把shell變量MINGW32設定成``yes''。如果不存在,就把MINGW32設定成空。
宏︰ AC_PATH_X
試圖找到X Window系統的頭檔案和庫檔案。如果用戶給出了命令行選項``--x-includes=dir''和 ``--x-libraries=dir'',就使用這些目錄。如果沒有給出任一個選項,或者都沒有給出,就透過營運xmkmf以處理一個測試``Imakefile'',並且檢查它所生成的``Makefile'',來得到沒有給出的目錄。如果這失敗了(比如說,xmkmf不存在),就在它們通常存在的幾個目錄中尋找。如果任何一種方法成功了,就把shell變量x_includes和x_libraries設定成相應的位置,除非這些目錄就在編譯器搜索的缺省目錄中。
如果兩種方法都失敗了,或者用戶給出命令行選項``--without-x'',就把shell變量no_x 設定成``yes'';否則就把它設定成空字元串。

宏︰ AC_PATH_XTRA
AC_PATH_X的增強版。它把X需要的C編譯器選項添加到輸出變量X_CFLAGS,並且把 X的連接選項添加到X_LIBS。如果不能使用X系統,就把``-DX_DISPLAY_MISSING'' 設定成X_CFLAGS。
本宏還檢查在某些系統中為了編譯X程式而需要的特殊庫。它把所有系統需要的庫添加到輸出變量X_EXTRA_LIBS。並且它檢查需要在``-lX11''之前被連接的特殊X11R6庫,並且把找到的所有庫添加到輸出變量X_PRE_LIBS。
宏︰ AC_SYS_INTERPRETER
檢查系統是否支援以形式為``#! /bin/csh''的行開頭的腳本選擇執行該腳本的解釋器。在營運本宏之後,configure.in中的shell代碼就可以檢查shell變量interpval;如果系統支援``#!'',interpval將被設定成``yes'',如果不支援就設定成``no''。
宏︰ AC_SYS_LONG_FILE_NAMES
如果系統支援長於14個字符的檔案名,就定義HAVE_LONG_FILE_NAMES。
宏︰ AC_SYS_RESTARTABLE_SYSCALLS
如果系統自動地重新啟動被信號所中斷的系統調用,就定義HAVE_RESTARTABLE_SYSCALLS。

UNIX變種
下列宏檢查對於有些程式來說需要特殊處理的一些作業系統,這是因為它們的頭檔案或庫檔案中含有特別怪異的東西。這些宏不討人喜歡;它們將根據它們所支援的函數或者它們提供的環境,被更加系統化的方法所代替。
宏︰ AC_AIX
如果在AIX系統中,就定義_ALL_SOURCE。允許使用一些BSD函數。應該在所有營運C編譯器的宏之前調用本宏。
宏︰ AC_DYNIX_SEQ
如果在Dynix/PTX (Sequent UNIX)系統中,就把``-lseq''添加到輸出變量LIBS中。本宏已經過時;用AC_FUNC_GETMNTENT來代替。
宏︰ AC_IRIX_SUN
如果在IRIX(Silicon Graphics UNIX)系統中,就把``-lsun''添加到輸出變量LIBS中。本宏已經過時。如果你用本宏來獲取getmntent,就用AC_FUNC_GETMNTENT來代替。如果你為了密碼(password)和組函數的NIS版本而使用本宏,就用``AC_CHECK_LIB(sun, getpwnam)''來代替。
宏︰ AC_ISC_POSIX
如果在POSIX化(POSIXized) ISC UNIX系統中,就定義_POSIX_SOURCE,並且把``-posix'' (對於GNU C編譯器)或者``-Xp''(對於其他C編譯器)添加到輸出變量CC中。本宏允許使用 POSIX工具。必須在調用AC_PROG_CC之後,在調用其他任何營運C編譯器的宏之前,調用本宏。
宏︰ AC_MINIX
如果在Minix系統中,就定義_MINIX和_POSIX_SOURCE,並且把_POSIX_1_SOURCE 定義成2。本宏允許使用POSIX工具。應該在所有營運C編譯器的宏之前調用本宏。
宏︰ AC_SCO_INTL
如果在SCO UNIX系統中,就把``-lintl''添加到輸出變量LIBS。本宏已經過時;用AC_FUNC_STRFTIME來代替。
宏︰ AC_XENIX_DIR
如果在Xenix系統中,就把``-lx''添加到輸出變量LIBS。還有,如果使用了``dirent.h'',就把``-ldir''添加到LIBS。本宏已經過時;用AC_HEADER_DIRENT來代替。

沒有留言: