最近须要在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)增长该句是为了屏蔽掉无输入的情形(跟随功能而言)。