2021年5月10日 星期一

從一個.c檔案開始的auto makefile

這是一個最基本能自動產生makefile的範例。在專案根目錄下準備好所有的*.c、*.h

整個Autotools的流程圖:

取自http://en.wikipedia.org/wiki/GNU_build_system

1.執行autoscan自動產生configure.scan

手動重新命名為configure.ac,修改configure.ac內容:

#                                               -*- Autoconf -*-

# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.69])

AC_INIT([hello], [0.1.0])

AM_INIT_AUTOMAKE([subdir-objects])

#AM_INIT_AUTOMAKE([1.12 -Wall -Wno-portability subdir-objects foreign])

AC_CONFIG_SRCDIR([src/hello.c])

AC_CONFIG_HEADERS([config.h])

# Checks for programs.

AC_PROG_CC

# Checks for libraries.

GLIB_REQ=2.48

PACKAGES_PUBLIC="glib-2.0 >= $GLIB_REQ gio-2.0 >= $GLIB_REQ gobject-2.0 >= $GLIB_REQ" 

PKG_CHECK_MODULES(GLIB, [$PACKAGES_PUBLIC) 

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_CONFIG_FILES([Makefile])

AC_OUTPUT

參數說明:

AC_CONFIG_SRCDIR

autoconf 會檢查此檔案來確認該目錄是否存在。在此可任意使用該目錄中的某個檔案作為代表。

AM_INIT_AUTOMAKE

為要傳給 automake 的參數。這些參數會放在 AUTOMAKE_OPTIONS 裡傳給所有的 Makefile.am 檔。在執行automake時,它會檢查目錄下是否存在標準GNU軟件包中應具備的各種文件,例如AUTHORS、ChangeLog、NEWS等文件。將其設置成foreign時,automake會改用一般軟件包的標準來檢查。

AC_CONFIG_HEADERS

它會收集在原始程式碼裡使用 #define 所定義的前置處理常數,並寫入指定的檔案中,(在此為 config.h),以便於讓 autoheader 處理。一般而言應該不要去更改這個設定值。

PKG_CHECK_MODULES(GLIB, [$PACKAGES_PUBLIC)  

其中的大寫GLIB是自己取的變數名字,自己取名的變數PACKAGES_PUBLIC裡放的是函式庫的名字(得到函式庫名字的方法:pkg-config --list-all),後面的>=是版本檢查,可省略。這樣Autotools就會自己執行pkg-config去取得相關的CFLAGS跟LIBS參數,作用跟以下兩行一樣:

pkg-config GLIB --cflags

pkg-config GLIB --libs

只不過PKG_CHECK_MODULES這個巨集會自動產生GLIB_CFLAGS跟GLIB_LIBS這兩個對應的變數。

不管什麼時候,您在 configure.ac 加入一個巨集時,接著必須執行 aclocal 和 autoconf,因為 aclocal 會掃描 configure.in 然後找出它必須提供的巨集。


2.手動新增Makefile.am

在主目錄下的 Makefile.am:

bin_PROGRAMS=hello 

hello_CFLAGS  = $(GTK_CFLAGS) $(GLIB_CFLAGS)

hello_LDADD   = $(GTK_LIBS) $(INTLLIBS) $(GLIB_LIBS)

hello_SOURCES = src/hello.c

參數說明: 

bin_PROGRAMS 指的是要產生的執行檔名。在此為 hello

hello_CFLAGS 指定了在產生 hello 這個執行檔時的 CFLAGS 參數。

hello_LDADD 指定了在產生 hello 這個執行檔時要連結的 函式庫。而其中的 $(INTLLIBS) 則是用於 L10N。

hello_SOURCES 是 指在產生 hello 這個執行檔時所需要的檔案。

在configure.ac中的PKG_CHECK_MODULES(GLIB, [$PACKAGES_PUBLIC) ,第一個參數自己取名為GLIB,接著要在Makefile.am自己分別取名GLIB_CFLAGS、GLIB_LIBS這兩個變數名才會被認得。

執行 aclocal 產生aclocal.m4

aclocal根據configure.ac文件的內容,自動生成aclocal.m4文件


執行 autoheader產生 config.h.in

如果在程式碼中有用到 #define 語法的話,則必須額外下達這個指令。它會根據 configure.ac 的內容並搭配 aclocal.m4、acsite.m4 而產生 config.h.in 檔案。


執行 automake --add-missing --copy --foreign 產生Makefile.in

automake 參考 configure.ac 及 Makefile.am 的內容來自動產生Makefile.in


執行 autoconf 產生configure

autoconf需要GNU m4巨集處理器來處理aclocal.m4,生成configure腳本


執行./configure產生makefile

利用 configure 所產生的 Makefile 檔有幾個預設的目標可供使用,其中幾個簡述如下:

make all
產生我們設定的目標,即此範例中的執行檔。只打 make 也可以,此時會開始編譯原始碼,然後連結,並且產生執行檔。

make clean
清除之前所編譯的執行檔及目的檔 (object file, *.o)。

make distclean
除了清除執行檔和目的檔外,也把 configure 所產生的 Makefile 也清除掉。

make install
將程式安裝至系統中。如果原始碼編譯無誤,且執行結果正確,便可以把程式安裝至系統預設的執行檔存放路徑。如果我們用 bin_PROGRAMS 巨集的話,程式會被安裝至 /usr/local/bin 這個目錄。

make dist
將程式和相關的檔案包裝成一個壓縮檔以供散播 (distribution) 。執行完在目錄下會產生一個以 PACKAGE-VERSION.tar.gz 為名稱的檔案。PACKAGE 和 VERSION 這兩個變數是根據 configure.in 檔中 AM_INIT_AUTOMAKE(PACKAGE, VERSION) 的定義。在此範例中會產生 'hello-1.0.tar.gz' 的檔案。

make distcheck
和 make dist 類似,但是加入檢查包裝後的壓縮檔是否正常。這個目標除了把程式和相關檔案包裝成 tar.gz 檔外,還會自動把這個壓縮檔解開,執行 configure,並且進行 make all 的動作,確認編譯無誤後,會顯示這個 tar.gz 檔已經準備好可供散播了。這個檢查非常有用,檢查過關的套件,基本上可以給任何一個具備 GNU 發展環境的人去重新編譯。就 hello-1.tar.gz 這個範例而言,除了在 Red Hat Linux 上,在 FreeBSD 2.2.x 版也可以正確地重新編譯。

 

執行make產生hello執行檔

最後就可以用./hello來執行程式了!

Q:What is the difference between LDADD and LIBADD?
A:Use the LIBADD primary for libraries, and LDADD for executables.

下載automake

REF

https://www.gnu.org/software/automake/manual/automake.html#index-AM_005fINIT_005fAUTOMAKE

https://www.cntofu.com/book/46/gunmake/autotools.md

http://riverhippo.blogspot.com/2010/03/gnu-autotools-share-library.html

http://markuskimius.wikidot.com/programming:tut:autotools/

https://gohalo.me/post/linux-autotools-auto-compile-introduce.html

沒有留言:

張貼留言