最近須要在linux下完成項目編碼,所以記錄一下編碼心得。(選擇ubuntu14.04版本,04表明穩定版本,amd64表明64位,本文使用163源)linux
-------------------------------------------------------------------------------------------ios
計劃:算法
1.完成GNU風格helloworld。ubuntu
2.熟悉libconfig庫,完成參數解析。segmentfault
3.完成單例模式,封裝算法功能數據結構
4.熟悉libevent庫,並添加事件響應。函數
-------------------------------------------------------------------------------------------工具
1.GNU風格,命令行程序hello測試
如何寫一個 GNU 風格的命令行程序: https://segmentfault.com/a/1190000004321899this
Automake的標準工程組織 :http://blog.csdn.net/sufwei/article/details/50515873
本文參考了上述2篇較爲經典的文章,操做步驟以下。
autotools是一系列的編譯工具,可用過一句指令來安裝它們。
>sudo apt-get install autoconf
驗證:which aclocal,which autoscan,which autoconf,which autoheader,which automake。若是都有具體的路徑返回,則安裝成功。
a)創建根文件夾,~/DP/,創建project文件夾存放工程代碼。通常來講,應該添加下面這些目錄文件。
(1) 必選:
m4: 第三方或本身寫的用於configure.in中的宏
doc: 各類文檔
src: 源碼頂層目錄(裏面怎麼細分是本身的事)
config: 放置configure過程當中的一些文件,使得頂層目錄不那麼多文件
>mkdir src doc config m4
編碼文件,configure.ac
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
AC_INIT(Eproxy,1.0,watch_ch@163.com)
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([config])
AM_INIT_AUTOMAKE([foreign -Wall])
AC_PROG_CC
AC_PROG_CXX
PKG_CHECK_MODULES(WHEEL,[glib-2.0])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES(Makefile src/Makefile)
AC_OUTPUT
編碼文件,Makefile.am
ACLOCAL_AMFLAGS=-I m4
SUBDIRS=src
b)在src下,先完成cpp的helloworld編寫和src/Makefile.am編寫(拷貝下參考文中的部分說法)
GNU Autotools 是一個工具集,其中比較重要的工具備 autoconf, aclocal, automake, libtool,此外還有一些輔助工具,例如 autoscan, autoheader 之類。還有一個工具 pkg-config ,雖然它不屬於 GNU Autotools,但也是很是重要。這些工具提供了一些可在 configure.ac 文件中調用的 m4 宏。例如,以 AC_ 爲前綴的宏都是 autoconf 提供的,以 AM_ 爲前綴的宏是 automake 提供的,以 PKG_ 爲前綴的宏是 pkg-config 提供的。因此,要想弄明白這些宏的含義,就使用 info 去查各個工具的手冊。例如,要弄清楚 AC_CONFIG_AUX_DIR,就須要 info autoconf。若是不懂 info 命令的用法,那麼你應該 info info。
既然在 AC_CONFIG_FILES 宏參數中設定未來要經過 configure 腳本生成 Makefile 與 src/Makefile 文件,那麼就必須提供相應的 Makefile.am 與 src/Makefile.am 文件:
eproxyd.cpp
#include<iostream> using namespace std; int main() { cout<<"hello Gnu"; return 0; }
src/Makefile.am
bin_PROGRAMS=eproxyd eproxyd_SOURCES=eproxyd.cpp eproxyd_LDADD = $(WHEEL_LIBS) eproxyd_CFLAGS= $(WHEEL_CFLAGS) eproxyd_CPPFLAGS= $(WHEEL_CFLAGS)
c)到這裏,源碼部分的代碼就已經寫完,接下來須要用automake工具進行編譯了,咱們這裏寫個腳原本快速完成相關工做。
定位到project目錄下,編碼autogen.sh,並更改運行模式,chmod 777 autogen.sh。
#!/bin/sh aclocal autoheader automake --add-missing autoconf
運行以後,執行./configure,並按照要求安裝依賴的工具庫。
例如,我用到了glib-2.0,且是另外一個庫的一部分(glib is a part of : libgtk2.0-dev),我遇到了依賴的錯誤,試了下aptitude(sudo aptitude install libgtk2.0-dev),最後用換源解決的(最初使用了ubuntu14.10版本,然而更新源時遇到很嚴重的問題,update以後變成16.10,且屏幕的最上方的狀態欄每半秒變大縮小一次。重裝64位14.04穩定版解決)。
>sudo apt-get install libgtk2.0-dev
此時,makefile文件便生成出來。在project下執行make,會在src中生成咱們剛纔定義的eproxyd。測試下執行,獲得「hello Gnu」。
2.增長參數解析
接下來咱們就能夠對剛纔的helloworld程序進行擴充了。
其實,在上面的文件configure.ac中,已經存在了一行宏命令 PKG_CHECK_MODULES(WHEEL,[glib-2.0]) ,它表明的意思是,利用pkg工具導入glib-2.0庫。terminal中可用下屬指令查看支持那些庫(我暫時還沒用到)。例如,PKG_CHECK_MODULES(XML, libxml-2.0 >= 2.4) 。
pkg-config --list-all
給工程添加依賴庫有幾種方式,參考http://socol.iteye.com/blog/580416,有pkg,-I-L,貌似還有種pc形式的。(遇到再回來更新)
迴歸話題,我但願個人程序可以支持下面這種調用形式:
src/eproxyd --inport =6666 --outport=6667 --log="~/eplog/"
或
src/eproxyd --i =6666 --o=6667 --l="~/eplog/"
這種狀況下,咱們能夠調用 GLib 庫中的命令行選項解析器來完成。
初步代碼結構以下,eproxyd.cpp
#include<cstdlib> #include<glib.h> #include<iostream> using namespace std; static gint zero_inport = 6660; static gint zero_outport = 6661; static gchar *zero_log="~/log/"; static GOptionEntry eproxyd_entries[]={ {"inport",'i',0,G_OPTION_ARG_INT,&zero_inport,"Set <chunk> as the inport to receive SQLs.","<chunk>"}, {"outport",'o',0,G_OPTION_ARG_INT,&zero_outport,"Set <chunk> as the outport to send encrypted SQLs.","<chunk>"}, {"log",'l',0,G_OPTION_ARG_STRING,&zero_log,"the log file will be stored at <locate>/log","<locate>"}, {NULL} }; bool prepare(int argc,char**argv); bool work(); int main(int argc,char**argv) { bool IsPre = prepare(argc,argv); if(!IsPre){ g_error("prepare fail!"); exit(1); } g_print("Msg: inport=%d,outport=%d,log=%s\n",&zero_inport,&zero_outport,&zero_log); work(); return 0; } bool prepare(int argc,char**argv){ cout<<"prepare"<<endl; GOptionContext *context=g_option_context_new("An integrated proxy to rewrite SQLs."); g_option_context_add_main_entries(context,eproxyd_entries,NULL); GError *error=NULL; if(!g_option_context_parse(context,&argc,&argv,&error)){ g_error("Command line option parser failed:",error->message); return false; } if(argv[1]==NULL) g_error("You should give params! -h for help\n"); g_option_context_free(context); return true; } bool work(){ cout<<"work"<<endl; return true; }
同時,把cpp文件中新增的函數,加入到eproxyd.h中作申明。
#ifndef EPROXYD_H #define EPROXYD_H bool prepare(int argc,char**argv); bool work(); #endif
上面代碼使用到了GLIB中的幾個數據結構,值得注意的是,if(argv[1]==NULL)增長該句是爲了屏蔽掉無輸入的情形(跟隨功能而言)。