有時候需要直接寫 Makefile,請見 make。底下是通用的起始腳本,它負責呼叫所有相關的工具。

autogen.sh
dir=`echo "$0" | sed 's,[^/]*$,,'`
test "x${dir}" = "x" && dir='.'
 
if test "x`cd "${dir}" 2>/dev/null && pwd`" != "x`pwd`"
then
    echo "This script must be executed directly from the source directory."
    exit 1
fi
 
rm -f config.cache acconfig.h
 
echo "- libtoolize."            && \
libtoolize --force              && \
echo "- aclocal."               && \
aclocal                         && \
echo "- autoconf."              && \
autoconf                        && \
echo "- autoheader."            && \
autoheader                      && \
echo "- automake."              && \
automake --add-missing --gnu    && \
echo                            && \
#./configure "$@"               && exit 0
 
exit 1

Makefile

Make

FILE: STAMP-FILE; @true
STAMP-FILE: DEPENDENCIES
        echo "haha" > FILE.tmp
        ./move-if-change FILE.tmp FILE
        touch $@

下載 GCC 源代碼以取得 move-if-change 腳本。STAMP-FILE 的寫法是希望只有在 FILE 內容有被修改的情況下 (即使 DEPENDENCIES 有更動),依賴於 FILE 的目標才會被重建 1)。STAMP-FILE 基本上是多加一個間接層,如此既不會多做不必要的工作,也不會使得依賴於 FILE 的目標在 DEPENDENCIES 有更動,但 FILE 內容不變情況下被重建。

  1. 第一次下 make,生成 FILE 和 STAMP-FILE。
    $ make
    echo "haha" > FILE.tmp
    ./move-if-change FILE.tmp FILE
    touch STAMP-FILE
    $ ls -ls
    total 12
    0 -rw-r--r-- 1 chenwj parallel    0 Jan 17 16:25 DEPENDENCIES
    4 -rw-r--r-- 1 chenwj parallel    5 Jan 17 16:43 FILE
    4 -rw-r--r-- 1 chenwj parallel  145 Jan 17 16:37 Makefile
    0 -rw-r--r-- 1 chenwj parallel    0 Jan 17 16:43 STAMP-FILE
    4 -rwxr-xr-x 1 chenwj parallel 2648 Jan 17 15:08 move-if-change
  2. 即使 DEPENDENCIES 有更動,FILE.tmp 和 FILE 內容一樣。如此 FILE 不會被替換,其時間戳不變。依賴於 FILE 的目標不會被重建。
    $ touch DEPENDENCIES; make
    echo "haha" > FILE.tmp
    ./move-if-change FILE.tmp FILE
    touch STAMP-FILE
    $ ls -ls
    total 12
    0 -rw-r--r-- 1 chenwj parallel    0 Jan 17 16:44 DEPENDENCIES
    4 -rw-r--r-- 1 chenwj parallel    5 Jan 17 16:43 FILE
    4 -rw-r--r-- 1 chenwj parallel  145 Jan 17 16:37 Makefile
    0 -rw-r--r-- 1 chenwj parallel    0 Jan 17 16:44 STAMP-FILE
    4 -rwxr-xr-x 1 chenwj parallel 2648 Jan 17 15:08 move-if-change
  3. DEPENDENCIES 不變。STAMP-FILE 規則對應的命令不會被執行。
    $ make
FILE: DEPENDENCIES
        echo "haha" > FILE.tmp
        ./move-if-change FILE.tmp FILE
  1. 第一次下 make,生成 FILE。
    $ make
    echo "haha" > FILE.tmp
    ./move-if-change FILE.tmp FILE
    $ ls -ls
    total 12
    0 -rw-r--r-- 1 chenwj parallel    0 Jan 17 16:44 DEPENDENCIES
    4 -rw-r--r-- 1 chenwj parallel    5 Jan 17 16:47 FILE
    4 -rw-r--r-- 1 chenwj parallel  106 Jan 17 16:47 Makefile
    4 -rwxr-xr-x 1 chenwj parallel 2648 Jan 17 15:08 move-if-change
  2. DEPENDENCIES 有更動,FILE.tmp 和 FILE 內容一樣。如此 FILE 不會被替換,其時間戳不變。依賴於 FILE 的目標不會被重建。
    $ touch DEPENDENCIES; make
    echo "haha" > FILE.tmp
    ./move-if-change FILE.tmp FILE
    $ ls -ls
    total 12
    0 -rw-r--r-- 1 chenwj parallel    0 Jan 17 16:47 DEPENDENCIES
    4 -rw-r--r-- 1 chenwj parallel    5 Jan 17 16:47 FILE
    4 -rw-r--r-- 1 chenwj parallel  106 Jan 17 16:47 Makefile
    4 -rwxr-xr-x 1 chenwj parallel 2648 Jan 17 15:08 move-if-change
  3. DEPENDENCIES 不變。FILE 規則對應的命令仍然會被執行 (多做不必要的工作),這是因為 FILE 的時間戳比 DEPENDENCIES 舊。如果在這條規則最後加上 touch $@,FILE 的時間戳會被更新,這樣 FILE 規則對應的命令就不會被執行。但是這樣依賴於 FILE 的目標就會被重建,即使 FILE 內容不變。
    $ make
    echo "haha" > FILE.tmp
    ./move-if-change FILE.tmp FILE
    $ ls -ls
    total 12
    0 -rw-r--r-- 1 chenwj parallel    0 Jan 17 16:47 DEPENDENCIES
    4 -rw-r--r-- 1 chenwj parallel    5 Jan 17 16:47 FILE
    4 -rw-r--r-- 1 chenwj parallel  106 Jan 17 16:47 Makefile
    4 -rwxr-xr-x 1 chenwj parallel 2648 Jan 17 15:08 move-if-change

編寫 configure.ac

編寫 Makefile.am

建置程式

建置共享函式庫

Makefile.am
# 最终调用者所使用的动态库函数声明文件, 执行 make install 会将其在 prefix 目录下的 include 中
include_HEADERS = myexpfunc.h
 
lib_LTLIBRARIES= libfoo.la
 
# 可以指定下版本号,这样会生成 libfoo.so.1.0.1 然后 make install 后会自动创建符号链接 libfoo.so -> libfoo.so.1.0.1
libfoo_la_LDFLAGS = -version-info 1:0:1
 
# 生成 .so
libfoo_la_LDFLAGS += -module
 
# 生成共享函式庫所需的源文件
libfoo_la_SOURCES = src1.c src2.c
 
# 本动态库的第三方依赖库, 比如 openssl 可以写为: -L/my_openssl_lib -lcrypto, 如果不依赖可以不写, 具体依赖目录可以在 configure.in 中编写 -with 参数指定
 
libfoo_la_LIBADD =  
 
# 本动态库的第三方依赖头文件目录, 比如 openssl 可以写为: -Imy_openssl_inc, 如果不依赖可以不写, 具体依赖目录可以在 configure.in 中编写 --with 参数指定
 
INCLUDES= 
 
# 生成一个 libfoo 的测试程序,如果不需要则不必写, 最终 make install 会 cp 到 prefix 目录的 bin 下, 如果不想安装则写为 noinst_PROGRAMS
bin_PROGRAMS=footest
 
footest_SOURCES = footest.c 
 
footest_LDADD= ./libfoo.la

建置文件

小技巧

使用 make dist 打包時,若不想包含 svn 文件,可以利用 dist-hook2)

EXTRA_DIST = doc
     
dist-hook:
  rm -rf `find $(distdir)/doc -name CVS`
  find ./ -name  .svn -exec rm -rf ';' '{'

但是正規做法是先 svn exportmake dist

加速編譯

參考資料

外部連結

登录