转自 http://my.huhoo.net/archives/2009/08/post_39.html
项目框架设计模式
目的
- 解决多人开发过程中协作的问题;
- 解决配置文件规范;
- 解决项目源码包和二进制打包的问题;
- 解决文档规范;
目录
|
目的
- 解决多人开发过程中协作的问题;
- 解决配置文件规范;
- 解决项目源码包和二进制打包的问题;
- 解决文档规范;
框架
- 结合git和autoconf,可以达到多人的协作开发模式;
- 上图中利用autoconf的开发模式,能有效的达到各项的“产出”,具体介绍可浏览autoconf介绍,如果多个人进行开发,可以选择svn或者git,这里有一个大概介绍git的开发模式图:
常约定
- 在了解大概的模式之后,我们还要了解经常在一些开发和项目中的约定(常约定)。
配置文件
- 在实际的工程项目中,我们一般使用以下几种类型的配置文件:
- unixconfig常用于在unix环境中读取配置信息的一种格式,这种格式被众多开源程序所用,是最广泛的一种配置文件类型;
- libconfig是基于自定义的一套数据结构格式,数据结构可以很复杂,也是开源程序经常使用一种方式,最近cnangel做了针对perl读写的模块,这样可以兼容perl语言、C/C++语言;
- xml格式是一种常见的数据结构,但也常用于作配置文件,一般在java工程中经常使用,c/c++并不常见;
- yaml是一种包含xml等子集的数据格式,在yaml官方网站有yaml的标准规范,且yaml支持多种语言,但是c/c++库提供的库并不是很适合做配置文件,所以此配置类型往往用于脚本;
- unixconfig常用于在unix环境中读取配置信息的一种格式,这种格式被众多开源程序所用,是最广泛的一种配置文件类型;
- 详细格式见下图:
库公约
- 针对c/c++开发的项目,我们针对各种平台一般最终需要提供动态链接库和静态链接库;
- 对于静态库文件,我们常见的Windows平台中一般是.lib为扩展名,类Unix平台中以.a为扩展名,里面相同的都是由一些C或者其他语言生成的object(.o为扩展名)文件打包而成;
- 对于动态链接库文件,一般在Windows平台中是以.dll作为扩展名,类Unix平台中以.so作为扩展名,里面都是一些符号连接和函数的声明、构造信息等等,一般可以使用工具nm等查看到相关信息,ldd来查看符号连接、依赖等信息;
- 静态库文件一般比动态连接库大得多,静态库可以解出多个.o结尾的object文件,通过这个方法,我们可以合并很多小的静态库,并合并相应的头文件。静态库的信息相对比较全,主要用来作开发等;
- 动态库相对来说只有一些符号连接等信息,往往用来支配程序(可执行文件)的运行,而且比静态库会获取到更小的内存空间,从而节省了程序的运行空间;
- 类Unix动态链接库标准命名规则(soname):
lib + 链接库名字 + .so + .版本号
每当链接库接口改变时都递增版本号。soname 文件其实只是一个符号链接而已,指向他的real name 文件,更为详细的命令方式如下(real name):
lib + 链接库名字 + .so + .版本号.次版本号.发行号
- 实际上,我们连接库时,使用的是如下动态链接库(linker name):
lib + 链接库名字 + .so
编译器以这个名字来请求指定的链接库。
- 当程序在内部列出所需要的链接库时,仅仅使用链接库名字。当你创建一个链接库时,使用 real
name。安装一个新的链接库时,把它复制到一个DLL文件夹里,然后运行程序 ldconfig。ldconfig 检查存在的 real name
文件,并且创建指向它的符号链接 soname 文件。ldconfig 并重新建立 cache 文件 /etc/ld.so.cache。
- ldconfig 不会创建 linker name 文件,但是一般性 linker name
文件在安装链接库的时候创建。linker name 文件也只是一个符号链接,指向最新的 soname 文件或 real name
文件。建议指向 soname 文件,因为当你更新库以后,在编译器链接的时候,一般总是想使用新的库。
- 一般而言,链接库必须放置在文件系统的指定位置。
- 多数开源软件遵守 GNU 标准:当分发源代码的时候,库默认安装在 /usr/local/lib,命令安装在 /usr/local/bin。该标准还定义了如何重写这些默认标准以及如何调用安装程序。
- Filesystem Hierarchy Standard(FHS) 规定:多数库应安装在 /usr/lib,启动时需要的库安装在 /lib,非系统库应安装在 /usr/local/lib
- 多数开源软件遵守 GNU 标准:当分发源代码的时候,库默认安装在 /usr/local/lib,命令安装在 /usr/local/bin。该标准还定义了如何重写这些默认标准以及如何调用安装程序。
- GNU 标准是针对开发人员的,FHS 是针对发行者的。
- 在基于 GNU glibc 的系统上,包括所有 linux 系统,ELF
可执行二进制文件的运行自动导致程序加载器被加载并且运行。在 linux 下,加载器是
/lib/ld-linux.so.X(X是版本号)。然后加载器搜索、加载程序所要使用的动态链接库,被搜索的文件夹列表保存在文件
/etc/ld.so.conf 里。
- 使用环境变量LD_LIBRARY_PATH, 该变量所指定的文件夹将会首先被搜索,然后才会搜索默认的链接库文件夹。该变量对开发和测试比较有用,但不应该为了给普通用户使用而设置。
- 在Linux下你可以直接调用程序加载器,比如,你可以传递PATH参数给加载器代替该变量来运行程序:
/lib/ld-linux.so.2 --library-path PATH EXECUTABLE
|
不带参数执行加载器,可以得到更多帮助。但是,不要这样执行程序,仅供调试时使用。
- 另外环境变量LD_DEBUG供调试使用的。该变量是dl*函数的开关,用来显示正在做的事情的详细信息。可以取值为:
参数 | 解释 |
---|---|
files |
显示so文件的加载顺序 |
bindings |
显示关于符号帮定的信息 |
libs |
显示库搜索路径的信息 |
versions |
显示版本依赖的信息 |
help |
使用该值运行程序将会显示可用的选项 |
- 在GNU的编译器中(gcc),很多的编译选项能够很好的辅助我们来创建动态连接库;
- 用 -fpic 或 -fPIC 选项创建要放入动态链接库中的目标文件。使用该选项生成的代码是位置无关的代码(动态链接库的必要条件)。使用 gcc 的 -Wl 选项传递 soname 参数给链接器。-Wl 选项里不能有未转义的 whitespace。
- -g 选项使代码包含调试信息,-Wall 选项用来产生警告,两者并不是创建动态链接库必须的,但是建议加上。
- 不要 strip 所生成的动态链接库,或使用编译器参数 -fomit-frame-pointer,这样做将会无法使用调试器。
- -fPIC 选项总是可以使用,但生成的代码比使用 -fpic 的要大。-fpic 选项生成的代码比较小、快,但是有平台相关的限制,当创建 DLL 时,链接器将会告诉你是否符合限制。
- 链接器还有一个有用的选项 -rpath,可以用来指定程序在运行时搜索DLL时的路径,使用 gcc 时可以这样传递参数给链接器:
- 用 -fpic 或 -fPIC 选项创建要放入动态链接库中的目标文件。使用该选项生成的代码是位置无关的代码(动态链接库的必要条件)。使用 gcc 的 -Wl 选项传递 soname 参数给链接器。-Wl 选项里不能有未转义的 whitespace。
-Wl,-rpath,$(DEFAULT_LIB_INSTALL_PATH)
若使用了这个选项,就可以考虑不用LD_LIBRARY_PATH这个环境变量了。
样例
- 这里用了一个工程uc作为用例来说明该框架的强大以及灵活多变的可扩展性(目前版本是0.0.2-2版本):
http://github.com/cnangel/UC/tree/master