轉載自 http://blog.csdn.net/scucj/article/details/6079052
收藏
手工寫Makefile是一件很有趣的事情,對於比較大型的項目,如果有工具可以代勞,自然是一件好事。在Linux系統開發環境中,GNU Autotools 無疑就充當了這個重要角色。(在Windows系統的開發環境中,IDE工具,諸如Visual Studio,來管理項目也很方便。)
本文以一個簡單項目爲例子,來講述GNU Autotools的一列工具及其命令的用法。
autotools是系列工具, 它主要由autoconf、automake、perl語言環境和m4等組成;所包含的命令有五個:
(1)aclocal
(2)autoscan
(3)autoconf
(4)autoheader
(5)automake
一、準備源代碼
(1)目錄project包含一個main.c的文件和兩個子目錄lib與include;lib目錄中包含一個test.c,include目錄中包含一個test.h。在系統中,顯示如下:
- [root@localhost project]# ls
- include lib main.c
- [root@localhost project]#
- [root@localhost project]# ls include/
- test.h
- [root@localhost project]# ls lib/
- test.c
- [root@localhost project]#
(2)源代碼如下:
- /* project/main.c */
- #include <stdio.h>
- #include "include/test.h"
- int main()
- {
- printf("main entrance./n");
- test_method();
- return 0;
- }
- /* project/lib/test.c */
- #include <stdio.h>
- #include "../include/test.h"
- void test_method()
- {
- printf("test method./n");
- }
- /* project/include/test.h*/
- void test_method();
二、autotools 使用步驟
2.1 使用autoscan命令,它將掃描工作目錄,生成 configure.scan 文件。
- [root@localhost project]# autoscan
- autom4te: configure.ac: no such file or directory
- autoscan: /usr/bin/autom4te failed with exit status: 1
- [root@localhost project]# ls
- autoscan.log configure.scan include lib main.c
- [root@localhost project]#
2.2 將configure.scan 文件重命名爲configure.ac,並做適當的修改。在 configure.ac 中,# 號開始的行是註釋,其他都是m4 宏命令;configure.ac裏面的宏的主要作用是偵測系統。
- [root@localhost project]mv configure.scan configure.ac
- [root@localhost project]# ls
- autoscan.log configure.ac include lib main.c
- [root@localhost project]#
- [root@localhost project]# cat configure.ac
- # -*- Autoconf -*-
- # Process this file with autoconf to produce a configure script.
- AC_PREREQ(2.59)
- AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)
- AC_CONFIG_SRCDIR([main.c])
- AC_CONFIG_HEADER([config.h])
- # Checks for programs.
- AC_PROG_CC
- # Checks for libraries.
- # Checks for header files.
- # Checks for typedefs, structures, and compiler characteristics.
- # Checks for library functions.
- AC_OUTPUT
- [root@localhost project]#
2.3 對 configure.ac 文件做適當的修改,修改顯示如下[1]:
- [root@localhost project]# cat configure.ac
- # -*- Autoconf -*-
- # Process this file with autoconf to produce a configure script.
- AC_PREREQ(2.59)
- #AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)
- AC_INIT(hello,1.0,[email protected])
- AM_INIT_AUTOMAKE(hello,1.0)
- AC_CONFIG_SRCDIR([main.c])
- AC_CONFIG_HEADER([config.h])
- # Checks for programs.
- AC_PROG_CC
- # Checks for libraries.
- # Checks for header files.
- # Checks for typedefs, structures, and compiler characteristics.
- # Checks for library functions.
- AC_CONFIG_FILES([Makefile])
- AC_OUTPUT
說明:
(1)以“#”號開始的行均爲註釋行。
(2)AC_PREREQ 宏聲明本文要求的 autoconf 版本, 如本例中的版本 2.59。
(3)AC_INIT 宏用來定義軟件的名稱、版本等信息、作者的E-mail等。
(4)AM_INIT_AUTOMAKE是通過手動添加的, 它是automake所必備的宏, FULL-PACKAGE-NAME是軟件名稱,VERSION是軟件版本號。
(5)AC_CONFIG_SCRDIR 宏用來偵測所指定的源碼文件是否存在, 來確定源碼目錄的有效性.。此處爲當前目錄下main.c。
(6)AC_CONFIG_HEADER 宏用於生成config.h文件,以便 autoheader 命令使用。
(7)AC_PROG_CC用來指定編譯器,如果不指定,默認gcc。
(8)AC_OUTPUT 用來設定 configure 所要產生的文件,如果是makefile,configure 會把它檢查出來的結果帶入makefile.in文件產生合適的makefile。使用 Automake 時,還需要一些其他的參數,這些額外的宏用aclocal工具產生。
(9)AC_CONFIG_FILES宏用於生成相應的Makefile文件。
2.4 使用 aclocal 命令,掃描 configure.ac 文件生成 aclocal.m4文件, 該文件主要處理本地的宏定義,它根據已經安裝的宏、用戶定義宏和 acinclude.m4 文件中的宏將 configure.ac 文件需要的宏集中定義到文件 aclocal.m4 中。[2]
- [root@localhost project]# aclocal
- [root@localhost project]# ls
- aclocal.m4 autom4te.cache autoscan.log configure.in include lib main.c
- [root@localhost project]#
2.5 使用 autoconf 命令生成 configure 文件。這個命令將 configure.ac 文件中的宏展開,生成 configure 腳本。這個過程可能要用到aclocal.m4中定義的宏。
- [root@localhost project]# autoconf
- [root@localhost project]# ls
- aclocal.m4 autom4te.cache autoscan.log configure configure.in include lib main.c
2.6 使用 autoheader 命令生成 config.h.in 文件。該命令通常會從 "acconfig.h” 文件中複製用戶附加的符號定義。該例子中沒有附加的符號定義, 所以不需要創建 "acconfig.h” 文件[2].
- [root@localhost project]# autoheader
- [root@localhost project]# ls
- aclocal.m4 autom4te.cache autoscan.log config.h.in configure configure.in include lib main.c
- [root@localhost project]#
2.7 手工創建Makefile.am文件。Automake工具會根據 configure.in 中的參量把 Makefile.am 轉換成 Makefile.in 文件。
- [root@localhost project]# cat Makefile.am
- UTOMAKE_OPTIONS = foreign
- bin_PROGRAMS = hello
- hello_SOURCES = main.c include/test.h lib/test.c
說明:
(1)其中的AUTOMAKE_OPTIONS爲設置automake的選項. 由於GNU對自己發佈的軟件有嚴格的規範, 比如必須附帶許可證聲明文件COPYING等,否則automake執行時會報錯. automake提供了3中軟件等級:foreign, gnu和gnits, 供用戶選擇。默認級別是gnu. 在本例中, 使用了foreign等級, 它只檢測必須的文件。
(2)bin_PROGRAMS定義要產生的執行文件名. 如果要產生多個執行文件, 每個文件名用空格隔開。
(3)hello_SOURCES 定義”hello”這個可執行程序所需的原始文件。如果”hello”這個程序是由多個源文件所產生的, 則必須把它所用到的所有源文件都列出來,並用空格隔開。如果要定義多個可執行程序,那麼需要對每個可執行程序建立對應的file_SOURCES。
2.8 使用 Automake 命令生成 Makefile.in 文件。使用選項 "--add-missing" 可以讓 Automake 自動添加一些必需的腳本文件。
- [root@localhost project]# automake --add-missing
- configure.ac: installing `./install-sh'
- configure.ac: installing `./missing'
- Makefile.am: installing `./INSTALL'
- 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
- Makefile.am: installing `./COPYING'
- Makefile.am: installing `./depcomp'
- [root@localhost project]#
2.8.1 再次使用 automake ——add-missing 運行一次,可以輔助生成幾個必要的文件。
- [root@localhost project]# automake --add-missing
- 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
- [root@localhost project]# ls
- aclocal.m4 autom4te.cache autoscan.log config.h.in config.h.in~ configure configure.ac COPYING depcomp include INSTALL install-sh lib main.c Makefile.am missing
- [root@localhost project]#
2.8.2 在當前目錄創建上面未發現的四個文件,並再次使用 automake ——add-missing 運行一次。
- [root@localhost project]# touch NEWS
- [root@localhost project]# touch README
- [root@localhost project]# touch AUTHORS
- [root@localhost project]# touch ChangeLog
- [root@localhost project]#
- [root@localhost project]# automake --add-missing
- [root@localhost project]# ls
- aclocal.m4 autom4te.cache ChangeLog config.h.in~ config.status configure.ac depcomp INSTALL lib Makefile.am missing README
- AUTHORS autoscan.log config.h.in config.log configure COPYING include install-sh main.c Makefile.in NEWS
- [root@localhost project]#
2.9 使用 configure 命令, 把 Makefile.in 變成最終的 Makefile 文件。
- [root@localhost project]# ./configure
- checking for a BSD-compatible install... /usr/bin/install -c
- checking whether build environment is sane... yes
- 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 ANSI C... none needed
- checking for style of include used by make... GNU
- checking dependency style of gcc... gcc3
- configure: creating ./config.status
- config.status: creating Makefile
- config.status: creating config.h
- config.status: config.h is unchanged
- config.status: executing depfiles commands
- [root@localhost project]# ls
- aclocal.m4 autom4te.cache ChangeLog config.h.in config.log configure COPYING hello INSTALL lib main.o Makefile.am missing README test.o
- AUTHORS autoscan.log config.h config.h.in~ config.status configure.ac depcomp include install-sh main.c Makefile Makefile.in NEWS stamp-h1
- [root@localhost project]#
Makefile文件已經生成成功。
三、Makefile的用法
3.1 make 命令,用來編譯代碼, 默認執行”make all”命令,可以看到生成了"hello"的可執行文件,
- [root@localhost project]# make
- make all-am
- make[1]: Entering directory `/home/chenjie/project'
- gcc -g -O2 -o hello main.o test.o
- make[1]: Leaving directory `/home/chenjie/project'
- [root@localhost project]#
- [root@localhost project]# ls
- aclocal.m4 autom4te.cache ChangeLog config.h.in config.log configure COPYING hello INSTALL lib main.o Makefile.am missing README test.o
- AUTHORS autoscan.log config.h config.h.in~ config.status configure.ac depcomp include install-sh main.c Makefile Makefile.in NEWS stamp-h1
- [root@localhost project]#
3.2 make clean 命令清除編譯時的obj文件,它與 make 命令是對應關係,一個是編譯,一個清除編譯的文件
3.3 運行”./hello”就能看到運行結果:
- [root@localhost project]# ./hello
- main entrance.
- test method.
- [root@localhost project]#
3.4 make install 命令把目標文件安裝到系統中。這一,直接輸入hello, 就可以看到程序的運行結果。
- [root@localhost project]# make install
- make[1]: Entering directory `/home/chenjie/project'
- test -z "/usr/local/bin" || mkdir -p -- "/usr/local/bin"
- /usr/bin/install -c 'hello' '/usr/local/bin/hello'
- make[1]: Nothing to be done for `install-data-am'.
- make[1]: Leaving directory `/home/chenjie/project'
- [root@localhost project]#
- [root@localhost project]# hello
- main entrance.
- test method.
- [root@localhost project]#
3.5 make uninstall 命令把目標文件從系統中卸載。
3.6 make dist 命令將程序和相關的文檔打包爲一個壓縮文檔以供發佈,在本例子中,生成的打包文件名爲:hello-1.0.tar.gz。
- [root@localhost project]# make dist
- { test ! -d hello-1.0 || { find hello-1.0 -type d ! -perm -200 -exec chmod u+w {} ';' && rm -fr hello-1.0; }; }
- mkdir hello-1.0
- find hello-1.0 -type d ! -perm -755 -exec chmod a+rwx,go+rx {} /; -o /
- ! -type d ! -perm -444 -links 1 -exec chmod a+r {} /; -o /
- ! -type d ! -perm -400 -exec chmod a+r {} /; -o /
- ! -type d ! -perm -444 -exec /bin/sh /home/chenjie/project/install-sh -c -m a+r {} {} /; /
- || chmod -R a+r hello-1.0
- tardir=hello-1.0 && /bin/sh /home/chenjie/project/missing --run tar chof - "$tardir" | GZIP=--best gzip -c >hello-1.0.tar.gz
- { test ! -d hello-1.0 || { find hello-1.0 -type d ! -perm -200 -exec chmod u+w {} ';' && rm -fr hello-1.0; }; }
- [root@localhost project]# ls
- aclocal.m4 autom4te.cache ChangeLog config.h.in config.log configure COPYING hello include install-sh main.c Makefile Makefile.in NEWS stamp-h1
- AUTHORS autoscan.log config.h config.h.in~ config.status configure.ac depcomp hello-1.0.tar.gz INSTALL lib main.o Makefile.am missing README test.o
- [root@localhost project]#
四 如何使用已發佈的壓縮文檔
4.1 下載到“hello-1.0.tar.gz”壓縮文檔
4.2 使用“ tar -zxvf hello-1.0.tar.gz ”命令解壓
4.3 使用 “./configure” 命令,主要的作用是對即將安裝的軟件進行配置,檢查當前的環境是否滿足要安裝軟件的依賴關係。
4.4 使用“ make ” 命令編譯源代碼文件生成軟件包。
4.5 使用 “ make install ”命令來安裝編譯後的軟件包。
- [root@localhost chenjie]# ls
- hello-1.0.tar.gz
- [root@localhost chenjie]# tar -zxvf hello-1.0.tar.gz
- [root@localhost chenjie]# ls
- hello-1.0 hello-1.0.tar.gz
- [root@localhost chenjie]# cd hello-1.0
- [root@localhost hello-1.0]# ls
- aclocal.m4 AUTHORS ChangeLog config.h.in configure configure.ac COPYING depcomp include INSTALL install-sh lib main.c Makefile.am Makefile.in missing NEWS README
- [root@localhost hello-1.0]#
- [root@localhost hello-1.0]#
- [root@localhost hello-1.0]# ./configure
- checking for a BSD-compatible install... /usr/bin/install -c
- checking whether build environment is sane... yes
- 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 ANSI C... none needed
- checking for style of include used by make... GNU
- checking dependency style of gcc... gcc3
- configure: creating ./config.status
- config.status: creating Makefile
- config.status: creating config.h
- config.status: executing depfiles commands
- [root@localhost hello-1.0]#
- [root@localhost hello-1.0]# make
- make all-am
- make[1]: Entering directory `/home/chenjie/hello-1.0'
- if gcc -DHAVE_CONFIG_H -I. -I. -I. -g -O2 -MT main.o -MD -MP -MF ".deps/main.Tpo" -c -o main.o main.c; /
- then mv -f ".deps/main.Tpo" ".deps/main.Po"; else rm -f ".deps/main.Tpo"; exit 1; fi
- if gcc -DHAVE_CONFIG_H -I. -I. -I. -g -O2 -MT test.o -MD -MP -MF ".deps/test.Tpo" -c -o test.o `test -f 'lib/test.c' || echo './'`lib/test.c; /
- then mv -f ".deps/test.Tpo" ".deps/test.Po"; else rm -f ".deps/test.Tpo"; exit 1; fi
- gcc -g -O2 -o hello main.o test.o
- make[1]: Leaving directory `/home/chenjie/hello-1.0'
- [root@localhost hello-1.0]#
- [root@localhost hello-1.0]# make install
- make[1]: Entering directory `/home/chenjie/hello-1.0'
- test -z "/usr/local/bin" || mkdir -p -- "/usr/local/bin"
- /usr/bin/install -c 'hello' '/usr/local/bin/hello'
- make[1]: Nothing to be done for `install-data-am'.
- make[1]: Leaving directory `/home/chenjie/hello-1.0'
- [root@localhost hello-1.0]#
- [root@localhost hello-1.0]# hello
- main entrance.
- test method.
五、命令使用的整個流程圖
圖我就不畫了,轉載兩個圖[2][3],對比着看,或許更明白一些。
六、總結
本文描述瞭如果使用GNU Autotools的來管理源代碼,發佈源代碼包,以及獲得源代碼包後如何編譯、安裝。由於這個例子過於簡單,GNU Autotools的用法還未完全描述清楚,主要體現在以下幾點:
(1)在創建 Makefile.am 文件中,描述的很簡單。在實際的項目中,文件關係很複雜,而且還有引用其他動態庫、第三方動態庫等關係。
(2)雖然 makefile 是自動生成的,但是瞭解它的規則是非常重要的。makefile 涉及到的規則本文並未加以描述。
有空的時候再寫一篇blog來描述上述兩個問題。
[1] http://book.chinaitlab.com/linux/777286.html
[2] http://blog.ossxp.com/2010/04/954/