建議閱讀GNU Automake 官方文檔,系統學習 automake 的用法。
---------------------------------------------------------------------------------------------(以下內容僅供參考)
一般而言,對於小項目或玩具程序,手動編寫 Makefile 即可。但對於大型項目,手動編寫維護 Makefile 成為一件費時費力的無聊工作。
本文介紹 autotools 工具集自動生成符合 Linux 規范的 Makefile 文件。
如果讀者沒有安裝 autotools 工具集,安裝命令如下,
$ sudo apt-get install automake
安裝完成之后,會有如下工具可用,
aclocal
autoscan
autoconf
autoheader
automake
一般大型項目,代碼組織結構分為兩種,一種是所有文件都在同一個目錄下的 flat 結構,另一種是按層次組織的多文件夾形式。先來看第一種,
flat 結構的項目使用 autotools 工具集
本篇測試代碼如下,
入口代碼 int_arithmetic.c
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include "sum.h" #include "sub.h" #include "mul.h" #include "div.h" int main() { printf("======== < Integer Arithmethic > ========\n"); int x, y; printf("Enter two integer: "); scanf("%d%d", &x, &y); int sm = sum(x, y); printf("sum is: %d\n", sm); int sb = sub(x, y); printf("sub is: %d\n", sb); int ml = mul(x, y); printf("mul is: %d\n", ml); int dv = divide(x, y); printf("div is: %d\n", dv); return 0; }
輔助代碼,頭文件,
sum.h
#ifndef SUM_H_ #define SUM_H_ int sum(int x, int y); #endif
sub.h
#ifndef SUB_H_ #define SUB_H_ int sub(int x, int y); #endif
mul.h
#ifndef MUL_H_ #define MUL_H_ int mul(int x, int y); #endif
div.h
#ifndef DIV_H_ #define DIV_H_ int divide(int x, int y); #endif
輔助代碼,實現文件,
sum.c
#include "sum.h" int sum(int x, int y) { return x + y; }
sub.c
#include "sub.h" int sub(int x, int y) { return x - y; }
mul.c
#include "mul.h" int mul(int x, int y) { return x * y; }
div.c
#include "div.h" #include <stdio.h> int divide(int x, int y) { if(x % y != 0) printf("\nWarning: Integer Division May Have Accuracy Loss.\n"); return x / y; }
1) 在項目目錄下,運行 autoscan 命令,生成 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([int_arithmetic.c]) AC_CONFIG_HEADERS([config.h]) # Checks for programs. AC_PROG_CC # Checks for libraries. # Checks for header files. AC_CHECK_HEADERS([stdlib.h unistd.h]) # Checks for typedefs, structures, and compiler characteristics. # Checks for library functions. AC_OUTPUT
重命名 configure.scan 為 configure.ac ,並修改其內容為,
# -*- 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_INIT(int_arithmetic, 0.1, ggao@micron.com) AM_INIT_AUTOMAKE(int_arithmetic, 0.1) AC_CONFIG_SRCDIR([int_arithmetic.c]) AC_CONFIG_HEADERS([config.h]) # Checks for programs. AC_PROG_CC # Checks for libraries. # Checks for header files. AC_CHECK_HEADERS([stdlib.h unistd.h]) # Checks for typedefs, structures, and compiler characteristics. # Checks for library functions. AC_CONFIG_FILES([Makefile]) AC_OUTPUT
上述 configure.ac 中宏定義意義如下,
AC_PREREQ : 聲明 autoconf 的版本號
AC_INIT : 聲明軟件名稱,版本號及 bug report 地址
AM_INIT_AUTOMAKE : automake 需要的信息,參數為軟件名和版本號
AC_CONFIG_SRCDIR : autoscan 偵測的源文件名,用來確定目錄的有效性
AC_CONFIG_HEADERS : autoscan 定義要生成的頭文件,后續 autoheader 要使用
AC_PROG_CC : 指定編譯器,默認為 gcc
AC_CHECK_HEADERS : autoscan 偵測到的頭文件
AC_CONFIG_FILES : 指定生成 Makefile,如果是多目錄結構,可指定生成多個Makefile,以空格分隔,例如,AC_CONFIG_FILES([Makefile src/Makefile])
AC_OUTPUT : autoscan 輸出
2) 運行 aclocal,根據 configure.ac 生成 aclocal.m4 文件,該文件主要處理各種宏定義
3) 運行 autoconf,將 configure.ac 中的宏展開,生成 configure 腳本,這過程中可能會用到 aclocal.m4
4) 執行 autoheader,生成 config.h.in 文件,該命令通常會從 "acconfig.h” 文件中復制用戶附加的符號定義。該例子中沒有附加的符號定義, 所以不需要創建 "acconfig.h” 文件
5) 創建 Makefile.am 文件,automake工具會根據 configure.in 中的參量把 Makefile.am 轉換成 Makefile.in 文件,最終通過 Makefile.in 生成 Makefile
AUTOMAKE_OPTIONS=foreign bin_PROGRAMS=int_arithmetic int_arithmetic_SOURCES=int_arithmetic.c sum.c sub.c mul.c div.c
include_HEADERS=sum.h sub.h mul.h div.h
對上述 makefile.am 中各標簽的解釋,
AUTOMAKE_OPTIONS : 由於 GNU 對自己發布的軟件有嚴格的規范, 比如必須附帶許可證聲明文件 COPYING 等,否則 automake 執行時會報錯。
automake 提供了3中軟件等級: foreign, gnu, gnits, 默認級別是gnu, 在本例中,使用 foreign 等級,它只檢測必須的文件。
bin_PROGRAMS : 要生成的可執行文件名稱,如果要生成多個可執行文件,用空格隔開。
int_arithmetic_SOURCES : 可執行文件依賴的所有源文件。
6) 手動添加必要的文件 NEWS,README,AUTHORS,ChangeLog
7) 執行 automake --add-missing ,該命令生成 Makefile.in 文件。使用選項 "--add-missing" 可以讓 automake 自動添加一些必需的腳本文件。
8) 執行 ./configure 生成 Makefile
====>>> 至此 Makefile 生成完畢。
如果要繼續安裝,
9) $ make
10) $ sudo make install 即可將可執行文件安裝在 /usr/local/bin/ 目錄下,以后就可以直接使用啦
11) $ sudo make uninstall 即可將安裝的可執行文件從 /usr/local/bin 目錄下移除
如果要發布你的軟件,
12) $ make dist 即可打包生成 xxx-version.tar.gz 文件
如果要清理中間文件,
13) make clean
14) make distclean
層次結構的項目使用 autotools 工具集
當前項目層次結構如下圖,
主入口函數 int_arithmetic.c
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include "include/sum.h" #include "include/sub.h" #include "include/mul.h" #include "include/div.h" int main() { printf("======== < Integer Arithmethic > ========\n"); int x, y; printf("Enter two integer: "); scanf("%d%d", &x, &y); int sm = sum(x, y); printf("sum is: %d\n", sm); int sb = sub(x, y); printf("sub is: %d\n", sb); int ml = mul(x, y); printf("mul is: %d\n", ml); int dv = divide(x, y); printf("div is: %d\n", dv); return 0; }
頭文件,
sum.h
#ifndef SUM_H_ #define SUM_H_ int sum(int x, int y); #endif
sub.h
#ifndef SUB_H_ #define SUB_H_ int sub(int x, int y); #endif
mul.h
#ifndef MUL_H_ #define MUL_H_ int mul(int x, int y); #endif
div.h
#ifndef DIV_H_ #define DIV_H_ int divide(int x, int y); #endif
實現文件,
sum.c
#include "../include/sum.h" int sum(int x, int y) { return x + y; }
sub.c
#include "../include/sub.h" int sub(int x, int y) { return x - y; }
mul.c
#include "../include/mul.h" int mul(int x, int y) { return x * y; }
div.c
#include "../include/div.h" #include <stdio.h> int divide(int x, int y) { if(x % y != 0) printf("\nWarning: Integer Division May Have Accuracy Loss.\n"); return x / y; }
1) 在項目頂層目錄,建立文件 Makefile.am, 內容如下,
AUTOMAKE_OPTIONS=foreign # 軟件等級 SUBDIRS=src # 先掃描子目錄 bin_PROGRAMS=int_arithmetic # 軟件生成后的可執行文件名稱 int_arithmetic_SOURCES=int_arithmetic.c # 當前目錄源文件 int_arithmetic_LDADD=src/libsrc.a # 靜態連接方式,連接 src 下生成的 libsrc.a 文件 #LIBS = -l xxx -l xxx # 添加必要的庫
在 src 目錄,建立文件 Makefile.am,內容如下,
noinst_LIBRARIES=libsrc.a # 生成的靜態庫文件名稱,noinst加上之后是只編譯,不安裝到系統中 libsrc_a_SOURCES=sum.c sub.c mul.c div.c # 這個靜態庫文件需要用到的依賴 include_HEADERS=../include/sum.h ../include/sub.h ../include/mul.h ../include/div.h # 導入需要依賴的頭文件
2) 執行 autoscan 生成 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([int_arithmetic.c]) AC_CONFIG_HEADERS([config.h]) # Checks for programs. AC_PROG_CC # Checks for libraries. # Checks for header files. AC_CHECK_HEADERS([stdlib.h unistd.h]) # Checks for typedefs, structures, and compiler characteristics. # Checks for library functions. AC_CONFIG_FILES([Makefile src/Makefile]) AC_OUTPUT
重命名 configure.scan 為 configure.ac 並修改如下,
# -*- 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_INIT(int_arithmetic, 0.1, ggao@micron.com) AM_INIT_AUTOMAKE(int_arithmetic, 0.1) # Generate static lib AC_PROG_RANLIB AC_CONFIG_SRCDIR([int_arithmetic.c]) AC_CONFIG_HEADERS([config.h]) # Checks for programs. AC_PROG_CC # Checks for libraries. # Checks for header files. AC_CHECK_HEADERS([stdlib.h unistd.h]) # Checks for typedefs, structures, and compiler characteristics. # Checks for library functions. AC_CONFIG_FILES([Makefile src/Makefile]) AC_OUTPUT
3) 執行 aclocal
4) 運行 autoconf
5) 運行 autoheader
6) 手動添加必要的文件 NEWS,README,AUTHORS,ChangeLog
7) 執行 automake --add-missing
8) 執行 ./configure 生存 Makefile
====>>> 至此 Makefile 生成完畢。
如果要繼續安裝,
9) $ make
10) $ sudo make install 即可將可執行文件安裝在 /usr/local/bin/ 目錄下,以后就可以直接使用啦
11) $ sudo make uninstall 即可將安裝的可執行文件從 /usr/local/bin 目錄下移除
如果要發布你的軟件,
12) $ make dist 即可打包生成 xxx-version.tar.gz 文件
如果要清理中間文件,
13) make clean
14) make distclean
====>>> 感謝原創作者的分享 http://blog.csdn.net/initphp/article/details/43705765
完。