手寫 Makefile 既繁瑣又易出錯,且難以適應不同平台的編譯環境。GNU Build System(Autotools)提供 Autoconf(生成 configure 腳本)與 Automake(生成符合 GNU 標準的 Makefile.in)雙工具鏈,實現「./configure && make && make install」的標準化構建流程。本文以經典 helloworld 為例,手把手演示從零構建完整構建系統。
開發者編寫
├── configure.ac (原 configure.in) ──autoconf──→ configure
└── Makefile.am ──automake──→ Makefile.in
└──configure──→ Makefile
用戶執行
./configure → 檢測環境、生成 Makefile
make → 編譯鏈接
make install → 安裝到系統目錄
# Fedora / CentOS / RHEL
dnf install autoconf automake libtool make gcc gcc-c++
# Debian / Ubuntu
apt-get install autoconf automake libtool build-essential
mkdir -p helloworld/src
cd helloworld
#include <stdio.h>
int main(int argc, char **argv) {
printf("Hello, Linux World!\n");
return 0;
}
autoscan
mv configure.scan configure.ac
編輯 configure.ac,保留核心宏:
# configure.ac
AC_INIT([helloworld], [1.0], [bug-report@example.com])
AM_INIT_AUTOMAKE([foreign -Wall -Werror])
AC_PROG_CC
AC_CONFIG_FILES([Makefile src/Makefile])
AC_OUTPUT
AC_INIT:包名、版本、報錯郵箱。AM_INIT_AUTOMAKE:初始化 Automake,foreign 表示非標準 GNU 目錄結構(無 COPYING、INSTALL 等),-Wall -Werror 開啟警告。AC_PROG_CC:檢測 C 編譯器。AC_CONFIG_FILES:指定要生成的 Makefile 列表。# Makefile.am
SUBDIRS = src
EXTRA_DIST = README.md
# src/Makefile.am
bin_PROGRAMS = helloworld
helloworld_SOURCES = helloworld.c
# 可選:helloworld_LDADD = -lm # 鏈接數學庫
bin_PROGRAMS:安裝到 bindir(默認 /usr/local/bin)的可執行文件。_SOURCES:對應程序的源文件列表,Automake 自動推導依賴並生成編譯規則。aclocal # 生成 aclocal.m4,收集宏定義
autoconf # 由 configure.ac 生成 configure
automake --add-missing --copy # 生成 Makefile.in,補全 install-sh、depcomp 等輔助腳本
此時目錄結構:
helloworld/
├── configure.ac
├── Makefile.am
├── configure
├── Makefile.in
├── aclocal.m4
├── install-sh
├── depcomp
├── missing
└── src/
├── Makefile.am
├── Makefile.in
└── helloworld.c
./configure
# 輸出:checking for gcc... gcc ... checking for C compiler default output file name... a.out ...
make
# 輸出:gcc -DPACKAGE_NAME=\"helloworld\" ... -o helloworld helloworld.c
./helloworld
# Hello, Linux World!
make install
# 安裝至 /usr/local/bin/helloworld
| 需求 | configure.ac 宏 | 說明 |
|---|---|---|
| 檢測庫函數 | AC_CHECK_LIB([m], [sin]) | 檢測 libm 是否有 sin,需在 Makefile.am 中 helloworld_LDADD = -lm |
| 檢測頭文件 | AC_CHECK_HEADERS([stdlib.h string.h]) | 定義 HAVE_STDLIB_H 等宏供 config.h 使用 |
| 生成 config.h | AC_CONFIG_HEADERS([config.h]) | 源碼中 #include "config.h" 獲取編譯時配置 |
| 條件編譯 | AM_CONDITIONAL([USE_FOO], [test "$use_foo" = "yes"]) | Makefile.am 中 if USE_FOO ... endif |
| 指定安裝前綴 | ./configure --prefix=/opt/myapp | 用戶自定義安裝路徑 |
| 交叉編譯 | ./configure --host=arm-linux-gnueabihf | 指定目標三元組 |
automake: error: no 'Makefile.am' found:確認在正確目錄執行,且文件名大小寫正確。configure: error: cannot run C compiled programs:交叉編譯時需 --host 並確保交叉工具鏈在 PATH 中。depcomp 生成 .deps/*.Po,確保 make 時自動重編譯。LD_LIBRARY_PATH 或 rpath (helloworld_LDFLAGS = -Wl,-rpath,'$$ORIGIN/../lib')。make -j$(nproc) 正常工作需正確聲明依賴;Automake 自動處理源文件間依賴,自定義規則需顯式聲明。但 Autotools 仍是 GNU 專案、許多老牌開源庫(glibc、coreutils、GCC 等)的標準,理解其原理有助於維護現有項目、閱讀源碼構建邏輯。
通過 configure.ac + Makefile.am 雙文件驅動,Autotools 將複雜的跨平台構建細節封裝為標準化流程。掌握核心宏、目錄佈局、依賴聲明,即可為項目賦予專業級構建能力,讓用戶享受開箱即用的 ./configure && make && make install 體驗。