Linux安裝軟件有一種方式就是通過源碼安裝,源碼通常是一個壓縮包,打開壓縮包,經常會看到一個叫configure的文件,而不見makefile文件。通常我們在自己的電腦寫應用的時候都是通過makefile來生成可執行的文件,但是為什么源碼里面沒有呢。實際上,編譯器在開始工作前要知道當前的系統環境,比如安裝的位置要在哪里、要依賴什么組件等等,由於每台電腦的環境不一樣,可以通過configure配置文件指定編譯參數。運行這個腳本就可以獲知編譯參數,編譯器就可以靈活地實現針對你個人電腦的“私人定制”,這也是linux源碼安裝的一個優勢。用戶也可以自定義參數,比如假設我們要自定義安裝目錄,可以./configure --prefix=/usr/local/apache2。又比如假如要動態庫和靜態庫一起編譯,使用./config shared --prefix=/usr/local --openssldir=/usr/local/ssl,假如我們要加入一些模塊支持(如mysql),使用
./configure --prefix=/www --with-mysql
configure通常是由autoconf這個工具生成的,下載:
sudo apt-get install autoconf
autoconf:只是autotools系列工具中的一個,運行之后可對configure.in腳本配置文件進行處理進而生成configure可執行文件,其他還包括了-----
aclocal:生成一個名稱為aclocal.m4的用於處理本地宏定義的文件
autoscan:在給定目錄以及其子目錄樹中檢測源文件,若沒有給定目錄,就是在當前目錄及其子目錄樹中檢查。
autoheader:負責生成config.in文件,該工具通常從“acconfig.h”文件中復制用戶附加的符號定義。
automake:它要用到的腳本配置文件是makefile.am,用戶需要自己創建相應的文件,然后利用automake工具轉換成makefile.in,此時運行configure自動配置設置文件就可將該.in文件生成makefile文件
網上摘取的一種圖,解釋了這套工具的工作流程:
運行autoscan,它會自動搜尋指定目錄(默認是當前或者當前目錄的子目錄)的源文件,並且創建configure.scan文件
autoscan會嘗試讀入”configure.ac”(同configure.in的配置文件)文件,此時沒有創建該配置文件,於是它會自動生成“configure.in”的原型文件“configure.scan”,該文件和源文件是在同一個目錄下的,用戶可以通過cat命令查看:
AC_PREREQ(2.61)
AC_INIT(hello, 1.0)
AM_INIT_AUTOMAKE(hello, 1.0)
AC_CONFIG_SRCDIR([hello.c])
AC_CONFIG_HEADER([config.h])
# Checks for programs.
AC_PROG_CC
# Checks for libraries.
# Checks for header files.
AC_CHECK_HEADERS([sys/time.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_HEADER_TIME
# Checks for library functions.
AC_CHECK_FUNCS([gettimeofday])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
解釋-----
AC_PREREQ:這個宏用於聲明本文件要求的autoconf版本
AC_INIT:總是configure.in中的第一個宏,可以拓展為許多可由其他configure腳本共享的模板文件代碼,這些代碼解析傳到configure的命令行參數。這個宏的一個參數是一個文件名,這個文件應該在源代碼目錄中,用於健全性檢查,以保證configure腳本已正確定位源文件目錄
AM_INIT_AUTOMAKE:automake必備的宏,使automake自動生成Makefile
AC_CONFIG_SRCDIR:檢查所指定的源文件是否存在,以及源代碼目錄的有效性。
AC_CHECK_HEADERS:用於生產config.h文件供autoheader使用
AC_CONFIG_FILES:用於生成相應的Makefile
AC_PROG_CC:使配置腳本搜索C編譯器並使用其名稱定義變量CC。 Automake生成的src / Makefile.in文件使用變量CC構建hello,因此當配置從src / Makefile.in創建src / Makefile時,它將使用它找到的值定義CC。如果要求Automake創建一個使用CC的Makefile.in,但是configure.ac沒有定義它,它會建議你添加一個調用AC_PROG_CC
AC_OUTPUT:是一個關閉命令,實際上產生腳本的一部分,負責創建用AC_CONFIG_HEADERS和AC_CONFIG_FILES注冊的文件
AC_CHECK_FUNCS:檢查C標准庫中是否存在函數。 如果找到,則定義預處理器宏HAVE_ [function]。它生成一個測試程序,聲明一個具有相同名稱的函數,然后編譯並鏈接它。更改函數名稱中的幾個字符(使測試失敗)並檢查config.log,當測試程序失敗時,您將看到測試程序的源代碼。假如缺失這個宏,會遇到下面的警告:
configure.ac: warning: missing AC_CHECK_FUNCS(gettimeofday)
這是autoscan告訴你,因為gettimeofday是一個潛在的可移植性問題,你應該有一個配置檢查它。所以你需要做的是添加 AC_CHECK_FUNCS(gettimeofday) 配置.ac,重新運行autoreconf,然后裝飾你的C代碼 #ifdef HAVE_GETTIMEOFDAY ,這是一般的過程
AC_HEADER_TIME:這個不是必要宏,當源代碼中有依賴於time.h和sys/time.h時,則定義TIME_WITH_SYS_TIME,這個宏在使用例如struct timeval和struct tm的程序中很有用,它最好結合HAVE_SYS_TIME_H一起使用,可以使用AC_CHECK_HEADERS檢查它
你的c程序就可以添加下面的一段:
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# if HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
環境:ubuntu14.04
編輯一個文件,命名為hello.c
#include<stdio.h>
#include<sys/time.h>
int main(int argc,char *argv)
{
float sec;
struct timeval time;
gettimeofday(&time,NULL);
sec=time.tv_sec;
sec+=time.tv_usec/1000000.0;
printf("hello-world\n sec=%e\n",sec);
return 0;
}
執行autoscan(如果是sudo權限執行新生成的兩個文件所有者和所屬組都是root,不能編輯),生成兩個文件:
其中autoscan.log顯示一個宏被請求的信息日志
configure.scan原文件內容:
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
AC_CONFIG_SRCDIR([hello.c])
AC_CONFIG_HEADERS([config.h])
# Checks for programs.
AC_PROG_CC
# Checks for libraries.
# Checks for header files.
AC_CHECK_HEADERS([sys/time.h])
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
AC_CHECK_FUNCS([gettimeofday])
AC_OUTPUT
修改一下
紅色部分改為AC_INIT(hello, 1.0)
並且在AC_CONFIG_SRCDIR([hello.c])之后加上
AM_INIT_AUTOMAKE(hello, 1.0)
AC_OUTPUT之前加上
AC_CONFIG_FILES([Makefile])
修改完后執行mv configure.scan configure.ac
舊版本的autoconf編譯是用configure.in,但是現在推薦使用configure.ac。另外注意configure.ac中的宏最好是單獨成行的,AC_INIT必須在check之前調用,而AC_OUTPUT必須在結尾調用,某些宏在運行的時候會檢查一些另外宏是否已經先運行。
宏的順序一般是這樣的:
AC_INIT
測試程序
測試函數庫
測試頭文件
測試類型定義
測試結構
測試編譯器特性
測試庫函數
測試系統調用
AC_OUTPUT
該文件包含autoconf宏的調用,其實configure.ac里面的內容也可以包含shell指令
執行aclocal,此時會生成一個叫aclocal.m4的新文件(告訴autoconf如何找到新的宏)
執行autoconf或autoconf --install
假如遇到錯誤:
試試:
解決:
sudo apt-get install libtool
然后再autoconf
執行autoheader,會生成一個config.h.in文件
創建一個腳本配置文件Makefile.am
AUTOMAKE_OPTIONS=foreign
bin_PROGRAMS=hello
hello_SOURCES=hello.c
說明:AUTOMAKE_OPTIONS為設置automake的選項。GNU對自己發布的軟件有嚴格的規范,例如必須附帶許可證聲明文件COPYING等,否則automake執行時會報錯。automake提供了3種軟件等級:foreign、gnu和gnits,默認為gnu。這里使用foreign,只檢測必須的文件
bin_PROGRAMS定義要生成的可執行文件名。如果要產生多個可執行文件,每個可執行文件的文件名要用空格隔開 .對於可執行文件和靜態庫類型,如果只想編譯,不想安裝到系統中,可以用noinst_PROGRAMS代替bin_PROGRAMS,noinst_LIBRARIES代替lib_LIBRARIES。
hello_SOURCES用於定義“hello”這個可執行程序所需要的依賴文件,如果有多個,要全部列出來,用空格隔開。如果要生成多個執行程序,那么要定義多個filename_SOURCES
然后執行automake -a,自動添加一些腳本並生成configure.in文件
如果遇到警告:
configure.ac:7: warning: AM_INIT_AUTOMAKE: two- and three-arguments forms are deprecated. For more info, see:
configure.ac:7: http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_005fINIT_005fAUTOMAKE-invocation
configure.ac:12: installing './compile'
configure.ac:7: installing './install-sh'
configure.ac:7: installing './missing'
Makefile.am: installing './depcomp'
現在AM_INIT_AUTOMAKE只需要引入一個參數
一個空格分隔的automake選項列表應該應用到項目樹中的每個Makefile.am,效果如同每個選項在AUTOMAKE_OPTIONS中列出。
之前使用的AM_INIT_AUTOMAKE是一種比較老舊的配置:
AM_INIT_AUTOMAKE(PACKAGE,VERSION,[NO-DEFINE])
在這種形式中,有兩個必需要的參數:PACKAGE,VERSION
包和版本已經可以從autoconf的AC_INIT宏獲得。但是和AC_INIT調用發生的情況不同,此時AM_INIT_AUTOMAKE調用支持包和版本參數中的shell變量擴展(否則分別為通過AC_INIT調用定義的PACKAGE_TARNAME和PACKAGE_VERSION),也就是AM_INIT_AUTOMAKE支持Makefile中引入shell指令
解決:編輯configure.ac
方法1:將AM_INIT_AUTOMAKE的參數取消
方法2:默認情況下,這個宏AC_DEFINE的PACKAGE和VERSION。這可以通過傳遞no-define選項來避免
AM_INIT_AUTOMAKE([no-define ...])
不過這樣也不是最穩妥的,鏈接的文章后面提到
如果您從早期版本的Automake升級configure.ac,將包和版本參數從AM_INIT_AUTOMAKE直接移動到AC_INIT並不總是正確的,如上例所示。 AC_INIT的第一個參數應該是程序包的名稱(例如“GNU Automake”),而不是您傳遞給AM_INIT_AUTOMAKE的tarball名稱(例如“automake”)。 Autoconf嘗試從軟件包名稱派生tarball名稱,該名稱應該適用於大多數但不是所有軟件包名稱。 (如果它不適用於你,你可以使用AC_INIT的四參數形式明確地提供tarball名稱)。
然后執行./configure
它將makefile.in文件生成Makefile文件
最后執行make,生成了可執行文件hello
資料:
GNU Autoconf, Automake and Libtool(http://www.shlomifish.org/lecture/Autotools/slides/)
automake(http://www.gnu.org/software/automake/manual/automake.html#index-AC_005fINIT)
autoconf(https://www.gnu.org/software/autoconf/manual/autoconf.html#Shell-Script-Compiler)
GNU Document(http://www.delorie.com/gnu/docs/)
使用autotools生成makefile文件入門(http://www.cnblogs.com/flatfoosie/archive/2010/12/21/1912946.html)
Makefile學習與進階之Makefile.am和$$(M)的意思(http://www.cnblogs.com/zmlctt/p/4161547.html)
GNU AutoMake的中文翻譯(http://blog.csdn.net/brace/article/details/726168)
Autoconf學習---編寫configure腳本(http://www.cnblogs.com/flyfish10000/articles/1986054.html)
例解autoconf和automake生成makefile文件(https://www.ibm.com/developerworks/cn/linux/l-makefile/)
configure.ac(configure.in)詳解(http://www.ivpeng.com/pblog/configure-ac.html)
Makefile.am規則和實例詳解(http://www.ivpeng.com/pblog/makefile-am.html)