有時候需要直接寫 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
- 2.1 What a Rule Looks Like
target ... : prerequisites ... recipe ...
- 當 prerequisites 有修改時,執行 recipe 生成 target。
- 10.5.3 Automatic Variables
all: a.txt b.txt b.txt @echo $@ @echo $< @echo $^ @echo $+
$ make all a.txt a.txt b.txt a.txt b.txt b.txt
-
- 強制跳離 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 內容不變情況下被重建。
- 第一次下 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
- 即使 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
- DEPENDENCIES 不變。STAMP-FILE 規則對應的命令不會被執行。
$ make
FILE: DEPENDENCIES echo "haha" > FILE.tmp ./move-if-change FILE.tmp FILE
- 第一次下 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
- 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
- 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 export
再 make dist
。
加速編譯
-
- 預編頭檔,就是經過前處理器處理過後的頭檔,以二進制格式儲存的檔案,供後來編譯時使用,加快編譯速度。一般做法,是創建一個包含所有較少變動頭檔的頭檔 (pch.h)。其餘檔案將 pch.h 做為第一個頭檔引入。
-
- GCC 單獨對頭檔 (*.h) 編譯,即可得到預編頭檔 (*.h.gch)。
-
-
-
- Ninja 有 Windows 版本。