有時候需要直接寫 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]]