有時候需要直接寫 Makefile,請見 [[wp>Make_(software)|make]]。底下是通用的起始腳本,它負責呼叫所有相關的工具。
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 ======
* [[https://www.gnu.org/software/make/manual/make.html|GNU make]]
* [[http://www.opensourceforu.com/2012/06/gnu-make-in-detail-for-beginners/|GNU Make in Detail for Beginners]]
* [[http://tetralet.luna.com.tw/?op=ViewArticle&articleId=185|Makefile 語法簡介]]
* [[http://lalakiwe.sg1006.myweb.hinet.net/Documents/Makefile/MakefileTotal.pdf|Makefile 總述]]
* [[wp>Make (software)]]
* [[http://stackoverflow.com/questions/18136918/how-to-get-current-directory-of-your-makefile|How to get current directory of your makefile?]]
* [[https://www.gnu.org/software/make/manual/html_node/Using-Variables.html|6 How to Use Variables]]
* [[http://www.gnu.org/software/make/manual/make.html#Target%5F002dspecific|6.11 Target-specific Variable Values]]
* [[http://stackoverflow.com/questions/1440468/set-debugging-macro-conditionally-with-make|Set debugging macro conditionally with make]]
* [[http://stackoverflow.com/questions/1079832/how-can-i-configure-my-makefile-for-debug-and-release-builds|How can I configure my makefile for debug and release builds?]]
* [[https://www.gnu.org/software/make/manual/html_node/Rule-Introduction.html|2.1 What a Rule Looks Like]]
target ... : prerequisites ...
recipe
...
* 當 prerequisites 有修改時,執行 recipe 生成 target。
* [[https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html|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
* [[https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html|4.6 Phony Targets]]
* [[http://stackoverflow.com/questions/1864385/how-to-force-an-error-in-a-gnumake-file|How to force an error in a gnumake file]]
* [[http://www.gnu.org/savannah-checkouts/gnu/make/manual/html_node/Make-Control-Functions.html|8.12 Functions That Control Make]]
* 強制跳離 Makefile 執行。
* [[http://oreilly.com/catalog/make3/book/index.csp|Managing Projects with GNU Make]]
====== Make ======
* [[http://www.technovelty.org/linux/tips/make-stamp.html|The stamp idiom with make]]
* [[http://gcc.gnu.org/ml/gcc/2012-01/msg00090.html|Re: struggling with make inside GCC MELT]]
* [[http://www.hellogcc.org/archives/635|邮件列表解读之STAMP-FILE]]
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 的目標才會被重建 [(http://people.cs.nctu.edu.tw/~chenwj/log/UNIX/EricFisher-2012-01-17.txt)]。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
* [[http://www.study-area.org/cyril/opentools/opentools/makefile.html|Chapter 5. Makefile撰寫]]
* [[http://www.makelinux.net/make3/main|Managing Projects with GNU make]]
====== 編寫 configure.ac ======
[[http://www.flameeyes.eu/autotools-mythbuster/autoconf/arguments.html|Adding Options]]
====== 編寫 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
===== 建置文件 =====
* [[http://boris.lk.net/unix/2_manpages.pdf|How to Read and Write Manual Pages]]
* [[wp>Man page]]
===== 小技巧 =====
使用 ''make dist'' 打包時,若不想包含 svn 文件,可以利用 [[http://www.gnu.org/s/hello/manual/automake/The-dist-Hook.html|dist-hook]][(http://lists.gnu.org/archive/html/automake/2000-12/msg00007.html)]。
EXTRA_DIST = doc
dist-hook:
rm -rf `find $(distdir)/doc -name CVS`
find ./ -name .svn -exec rm -rf ';' '{'
但是正規做法是先 ''svn export'' 再 ''make dist''。
====== 加速編譯 ======
* [[http://voices.canonical.com/jussi.pakkanen/2012/10/01/building-cc-what-really-happens-and-why-does-it-take-so-long/|Building C/C++: what really happens and why does it take so long]]
* [[http://stackoverflow.com/questions/318398/why-does-c-compilation-take-so-long|Why does C++ compilation take so long?]]
* [[http://www.math-linux.com/linux/tip-of-the-day/article/speedup-gnu-make-build-and-compilation-process|Speedup GNU make build and compilation process]]
* [[wp>Precompiled header]]
* 預編頭檔,就是經過前處理器處理過後的頭檔,以二進制格式儲存的檔案,供後來編譯時使用,加快編譯速度。一般做法,是創建一個包含所有較少變動頭檔的頭檔 (pch.h)。其餘檔案將 pch.h 做為第一個頭檔引入。
* [[https://msdn.microsoft.com/en-us/library/szfdksca.aspx|Creating Precompiled Header Files]]
* [[https://gcc.gnu.org/onlinedocs/gcc/Precompiled-Headers.html|3.20 Using Precompiled Headers]]
* GCC 單獨對頭檔 (*.h) 編譯,即可得到預編頭檔 (*.h.gch)。
* [[http://stackoverflow.com/questions/12437955/gcc-and-precompiled-headers|GCC and Precompiled Headers]]
* [[https://ccache.samba.org/|ccache]]
* [[http://fcamel-life.blogspot.tw/2013/08/ccache.html|以安裝 ccache 為例, 說明如何使用系統工具除錯]]
* [[https://github.com/distcc|distcc]]
* [[http://kuoe0.logdown.com/posts/2015/01/29/distcc-ubuntu-help-os-x-compilers|distcc - 讓 Ubuntu 幫 OS X 編譯程式]]
* [[https://martine.github.io/ninja/|Ninja]]
* Ninja 有 Windows 版本。
====== 參考資料 ======
* [[http://www.openismus.com/documents/linux/building_libraries/building_libraries.shtml#directorystructure|Building C/C++ libraries with Automake and Autoconf]]
====== 外部連結 ======
* [[http://www.gnu.org/software/automake/|Automake]]
* [[http://sources.redhat.com/autobook/|Autobook]]
* [[http://www.csie.nctu.edu.tw/~cwj/book/Makefile.pdf|跟我一起写 Makefile]]