自動生成項目的Makefile文件
理論基礎
跟我一起寫 Makefile: http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=408225
步驟
- 寫好Makefile.am
- 運行 autoscan , 自動創建兩個文件: autoscan.log configure.scan
- 將configure.scan 命名為configure.ac,修改某些內容,具體怎么修改后面再講
- 運行aclocal,生成一個“aclocal.m4”文件和一個緩沖文件夾autom4te.cache,該文件主要處理本地的宏定義
- 運行 autoconf,目的是生成 configure
- 運行 autoheader,它負責生成config.h.in文件。該工具通常會從“acconfig.h”文件中復制用戶附加的符號定義
- 運行automake,生成Makefile.in
- 運行configure,通過運行自動配置設置文件configure,把Makefile.in變成了最終的Makefile。
注意到,在前面介紹的步驟中,只有兩處需要對文件內容進行修改:Makefile.am和configure.ac。
編寫Makefile.am
假如安裝目錄如下:
. ├── echo_server # 打包生成動態鏈接庫(so文件) ├── etc # 配置文件 ├── script # 啟動、停止等腳本文件 ├── src # 源文件 └── tools # 工具文件
主目錄的Makefile.am:
# Process this file with automake to produce Makefile.in SUBDIRS = etc src script tools echo_server DIST_SUBDIRS = etc src script tools echo_server
etc目錄的Makefile.am:
# Makefile.am不能有空格,必須是tab才行,這個Makefile.am主要作用是把framework.json這個配置文件安裝到相應的目錄中 # Process this file with automake to produce Makefile.in DEFAULT_CONFIG_DIR = $(sysconfdir) # more configs can be separated by a space DEFAULT_GLB_CONFIG_DIR = $(sysconfdir)/glb FRAMEWORK_CONFS = framework.json install-data-local: @if test ! -d $(DESTDIR)$(DEFAULT_CONFIG_DIR); then \ $(mkinstalldirs) $(DESTDIR)$(DEFAULT_CONFIG_DIR); \ fi @if test ! -d $(DESTDIR)$(DEFAULT_GLB_CONFIG_DIR); then \ $(mkinstalldirs) $(DESTDIR)$(DEFAULT_GLB_CONFIG_DIR); \ fi $(INSTALL_DATA) $(srcdir)/$(FRAMEWORK_CONFS) $(DESTDIR)$(DEFAULT_GLB_CONFIG_DIR)/$(FRAMEWORK_CONFS);
echo_server目錄的Makefile.am:
# Process this file with automake to produce Makefile.in CXX = g++ -std=c++0x LIBS = -ljsoncpp -lrt -lpthread -levent # 依賴的庫 lib_LTLIBRARIES = libecho_server.la # 動態鏈接庫名稱 libecho_server_la_SOURCES = \ # 生成動態鏈接庫的源文件 echo.cc libecho_server_la_LIBADD = \ # 依賴於src/libframework_tool.so $(top_srcdir)/src/libframework_tool.la # $(top_srcdir)實際就是主目錄 # $(prefix)這個是從./configure --prefix=/home/yjr/framework中傳進來 AM_CPPFLAGS = \ -I$(prefix)/modules/include \ -I$(top_srcdir)/src AM_CXXFLAGS = -Wall -Wextra -pedantic AM_LDFLAGS = \ # 安裝目錄 -L$(prefix)/modules/lib \ # 動態鏈接庫將會安裝到$(prefix)/modules/lib -I$(top_srcdir)/src # 依賴的源文件 clean-local: # 執行make clean時,執行的命令 $(RM) -r genpy # 執行make clean時,刪除genpy這個目錄
src下Makefile.am:
# Process this file with automake to produce Makefile.in CXX = g++ -std=c++0x LIBS = -ljsoncpp -lpthread -levent -DUSE_JEMALLOC -ljemalloc -ldl -L$(prefix)/modules/lib -I$(prefix)/modules/include # 依賴的庫 lib_LTLIBRARIES = libframework_tool.la # 生成動態鏈接庫 libframework_tool_la_SOURCES = \ logging/debug.cc \ base/CUtil.cc \ config/config_module.cc libframework_tool_la_LIBADD = \ $(prefix)/modules/lib/libevent.la noinst_LTLIBRARIES = libdfrpcif.la # 生成庫,但無需安裝 nodist_libdfrpcif_la_SOURCES = \ protocol/rpc_handler.cc \ protocol/rpc_types.cc \ base/set_proc_title.c libdfrpcif_la_LIBADD = \ $(prefix)/modules/lib/libevent.la sbin_PROGRAMS = framework framework_gdb # 生成兩個bin文件,如果生成一個,則把其中一個去掉即可 framework_SOURCES = \ # 第一個bin文件,主文件 main.cc framework_LDADD = \ # 依賴的第三方庫 -lboost_system -lboost_filesystem -ldl -L$(prefix)/modules/lib\ libdfrpcif.la \ libframework_tool.la framework_gdb_SOURCES = \ # 第二個bin文件 main.cc framework_gdb_LDADD = \ -lboost_system -lboost_filesystem -ldl -L$(prefix)/modules/lib\ libdfrpcif.la \ libframework_tool.la framework_gdb_LDFLAGS = -g -Ddebug include_HEADERS = \ # 需要安裝的頭文件 framework.h base_includedir = $(includedir)/base # 需要安裝的頭文件 base_include_HEADERS = \ base/CUtil.h config_includedir = $(includedir)/config # 需要安裝的頭文件 config_include_HEADERS = \ config/config_module.h logging_includedir = $(includedir)/logging # 需要安裝的頭文件 logging_include_HEADERS = \ logging/debug.h AM_CPPFLAGS = \ $(BOOST_CPPFLAGS) \ $(LIBEVENT_CPPFLAGS) \ -I$(top_srcdir)/src \ -I$(top_srcdir)/src/base \ -I$(top_srcdir)/src/config \ -I$(top_srcdir)/src/debug \ -I$(top_srcdir)/src/protocol \ -I$(prefix)/modules/include AM_CXXFLAGS = -Wall -Wextra -pedantic AM_LDFLAGS = $(BOOST_LDFLAGS) $(LIBEVENT_LDFLAGS) clean-local: $(RM) -r protocol/cpp install-exec-hook: # 安裝可執行文件 $(INSTALL) $(top_srcdir)/script/start_server.sh $(DESTDIR)$(sbindir)/start_server.sh $(INSTALL) $(top_srcdir)/script/stop_server.sh $(DESTDIR)$(sbindir)/stop_server.sh
其它的就不再細說
編寫configure.ac
AC_INIT([df_framework], [1.0], [http://www.yejinru.com]) AC_CONFIG_SRCDIR([src/main.cc]) # main函數文件 AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([-Wall -Werror foreign]) AC_PROG_LIBTOOL AC_CONFIG_FILES([Makefile # 包含有Makefile文件的目錄 etc/Makefile src/Makefile script/Makefile tools/Makefile])
除了前面修改的內容以外,還可以增加第三方庫的安裝檢查。比如判斷boost_filesystem是否已經安裝,可在configure.ac中增加:
# FIXME: Replace `main' with a function in `-lboost_filesystem': AC_CHECK_LIB([boost_filesystem], [main])
假如我們想在安裝前執行某個shell腳本,我們也可以在configure.ac中增加相關命令。
cd src/protocol && ./update_proto.sh && cd -
注意
1. 如果在confiugre.ac中定義了宏AC_PROG_LIBTOOL,
1)automake時可能提示提示“required file `build/ltmain.sh' not found”。可運行如下命令自動copy到當前工程:
libtoolize --automake --copy --debug --force
2) 如果出現如下提示:
configure.ac: required file `./install-sh' not found
configure.ac: required file `./missing' not found
Makefile.am: required file `./depcomp' not found
可使用命令automake --add-missing,或將/usr/share/automake-1.X/目錄下的depcomp等文件拷貝到本目錄下
2. 如果引用第三方的庫需要先解壓和編譯,也可以將對應的configure & make & make install寫在configure.ac中