标签 Ubuntu 下的文章

Hello,autoconf和automake

部门绝大多数的产品都运行在Sun的小型机上,底层的操作系统是Solaris。这两年公司开始主推刀片机(物美价廉^_^),不过刀片机上运行的也是Solaris 10 for x86版本。基于同种OS的前提下在Sparc和x86两种体系之间做移植比较简单,主要考虑字节序问题就可以了。不过对于可移植性的考虑不足还是让我们付出了较大的工作量。 在即将进行的新版本产品开发中,可移植性依旧没有被列入到必须要考虑实现的特性列表中,不过从未来产品演化和发展的角度考虑,现在就应该未雨绸缪,在可移植性方面多下工夫!

对于用C语言实现的服务器后端程序而言,GNU(/'gnu:/)的autoconfautomake(GNU autotools工具包的主要组成部分)显然已经成为这方面的事实标准!诸多知名开源应用和工具都采用autoconf和automake来生成相关的Build环境,"configure -> make -> make install"是采用这两个工具的应用软件的标准编译安装流程。不过autoconf和automake的学习门槛却不低,记得几年前曾尝试学习过这两个工具,结果被其纷繁芜杂的依赖关系搞得晕头转向,加之当时缺少些许耐心,也就放弃了(估计很多人都有与我类似的经历^_^)。

autoconf,顾名思义是用来做“自动配置”的,配置什么呢?配置软件代码包,目的是用来使软件包适应种类繁多的“Posix-like system"。automake,则是用来生成Makefile的原型-Makefile.in的。在大工程里,各种依赖关系纠结,如果采用纯手工编写Makefile方式,复杂度很高,而且Makefile的学习门槛也不低,想写出一份扩展性良好的通用Makefile也非易事。automake则试图将程序员从那些"扯不断理还乱"的依赖关系中解脱出来,你只需告诉automake你的工程里有哪些源文件、哪些目标文件、要连接什么库及各个文件的位置即可,automake帮你自动生成一份Makefile.in,Makefile.in则是configure脚本自动生成Makefile过程的输入。

重新学习使用autoconf和automake,最重要的就是迅速获得一个正反馈!这就好比学习一门新的计算机编程语言,如果能在3分钟之内迅速写出一个"Hello World"程序,编译运行成功,并在屏幕上看到有"Hello World"输出,那么有了这个正反馈后你八成才会有继续学习的动力,否则很多耐性不足的人就会止步于此(例如很多Java语言初学者就止步于配置JDK环境变量上)。

我将这个“正反馈”寄托在使用autoconf和automake来migrate一个几年前写的小工具库上了。这个工具库没比"hello world"复杂多少^_^,其大致组织结构是这样的:

lcut/
    – src/
        – apr_ring.h
        – lcut.h
        – lcut.c
        – example/
            – runtests.c

autoconf和automake虽然名字中都有一个"auto",但这并不意味着不需要任何“手工”操作。你起码需要手工完成两个文件:configure.in和Makefile.am。configure.in全工程只有一个,放置在工程最顶层目录下。这个文件包含一系列autoconf测试宏,用于告知autoconf生成的configure脚本需要在目标主机上做哪些check工作;至于Makefile.am,看文件后缀也可以知道这个文件是给automake使用的。Makefile.am可以有多个,简单来说只要你想在哪个目录下放置一个Makefile就需要在这个目录下编写一个对应的Makefile.am。Makefile.am的功用前面提到过,它要比Makefile简单许多,层次也更高,有些类似一种"声明式(declarative)语言”的脚本,你无须告知它怎么做,只需告知它要做的事情是什么样子的即可。

增加configure.in和Makefile.am后的源码包组织形式如下(新增文件用'+'标识):

lcut/
    + configure.in
    + Makefile.am
    – src/
        – apr_ring.h
        – lcut.h
        – lcut.c
        + Makefile.am
        – example/
            + Makefile.am
            – runtests.c

configure.in的生成是“半自动”的。GNU提供了一个名为autoscan的工具以帮助生成一个configure.in的模板。在lcut的目录下运行autoscan –verbose,我们得到一个名为configure.scan的文件,并得到autoscan的运行日志如下:
tonybai@tonybai-ubuntu-laptop:~/lcut$ autoscan –verbose
autoscan: srcdir = .
cfiles: src/apr_ring.h src/lcut.h src/lcut.c src/example/runtests.c
makefiles:
shfiles:

function:
malloc: src/lcut.c:132 src/lcut.c:203 src/lcut.c:241
memset: src/lcut.c:139 src/lcut.c:209 src/lcut.c:247

header:
stddef.h: src/apr_ring.h:40
stdlib.h: src/lcut.h:45
string.h: src/lcut.c:17

identifier:
size_t: src/lcut.h:214 src/lcut.c:78

program:
cc: src/apr_ring.h src/lcut.h src/lcut.c src/example/runtests.c

makevar:
librarie:

可以看出autoscan将lcut下的各类文件做了个全面扫描,根据其内部规则找出带有移植性问题的函数、头文件以及标识符等,并在configure.scan中放置了对应的autoconf测试宏,configure.scan的初始版本内容如下:
AC_PREREQ([2.65])
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
AC_CONFIG_SRCDIR([src/apr_ring.h])
AC_CONFIG_HEADERS([config.h])

# Checks for programs.
AC_PROG_CC

# Checks for libraries.

# Checks for header files.
AC_CHECK_HEADERS([stddef.h stdlib.h string.h])

# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_SIZE_T

# Checks for library functions.
AC_FUNC_MALLOC
AC_CHECK_FUNCS([memset])

AC_OUTPUT

将configure.scan直接改名为configure.in(或configure.ac),我们就得到了configure.in的模板,剩下的工作就是根据需要修改该模板了。configure.in文件包含一组autoconf测试宏,关于这些测试宏的具体含义可参考GNU autoconf手册。这里仅针对某些宏做简要说明:
-> AC_PREREQ 这个宏是一个指示符,用于告知autoconf该configure.in需要的最低autoconf版本号是多少,上面例子中版本号是2.65,如果你用低于2.65版本的autoconf来处理configure.in,就会提示版本太低。
-> AC_INIT和AC_OUTPUT这两个宏标识着configure.in主体(body)内容的开始和结束,两个宏都可以接收一些options(参见manual)。
-> AC_CONFIG_SRCDIR 则是放置在configure脚本中的一个safety检测,用于检查特定文件的存在性,以确保软件包本身结构的正确性。
-> AC_CONFIG_HEADERS 指示需要输出config.h,config.h是configure过程输出的结果之一,其内容为一组#define directive,你的源件包代码可以包含config.h(在所有其他header files的前面)并使用这些directive来编写一些具有良好移植性的代码。

上述configure.in模板不完全能满足我们的要求,所以我们需要对configure.in内容进行修改,修改后的configure.in如下:

AC_PREREQ([2.65])
AC_INIT([lcut], [0.1], [bigwhite.cn@gmail.com])
AM_INIT_AUTOMAKE([foreign -Wall -Werror])
AC_CONFIG_SRCDIR([src/apr_ring.h])
AC_CONFIG_HEADERS([src/config.h])
AC_CONFIG_FILES([Makefile src/Makefile src/example/Makefile])

# Checks for programs.
AC_PROG_CC

# Checks for libraries.
AC_PROG_RANLIB

# Checks for header files.
AC_CHECK_HEADERS([stddef.h stdlib.h string.h])

# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_SIZE_T

# Checks for library functions.
AC_FUNC_MALLOC
AC_CHECK_FUNCS([memset])

AC_OUTPUT

以下对修改的地方做一些简要说明:
-> AM_INIT_AUTOMAKE 初始化automake并告知automake打开所有警告,另外将警告视为错误,注意:这里的-Wall -Werror虽和GCC的某些options名字相同,但这只是巧合,这里的-Wall -Werror并不是给gcc传递-Wall和-Werror选项,这两个选项是针对automake本身的。foreign选项则是告知automake此软件包非GNU软件包,不必严格遵循GNU软件包的标准,比如软件包必须包含ChangeLog、AUTHORS等文件。
-> AC_CONFIG_FILES 则是告知需要生成并输出相关文件,上面的AC_CONFIG_FILES([Makefile src/Makefile src/example/Makefile])与 AC_OUTPUT([Makefile src/Makefile src/example/Makefile])是等价的。
-> AC_PROG_RANLIB 在需要生成.a静态链接库的软件包中都要加上这个宏。

configure.in告一段落,下一个需要手工编辑的是Makefile.am。在这个lcut的例子里,我们需要三个Makefile.am(如上面的规划所描述)。 顶层Makefile.am内容如下:
SUBDIRS = src src/example

src/Makefile.am内容如下:
lib_LIBRARIES = liblcut.a
liblcut_a_SOURCES = lcut.c
include_HEADERS = apr_ring.h lcut.h

src/example/Makefile.am内容如下:
noinst_PROGRAMS = runtests
runtests_SOURCES = runtests.c
runtests_LDADD = $(top_srcdir)/src/liblcut.a

这里的Makefile.am相对比较简单,其语法格式在automake manual里有详尽说明,这里不重述。值得一提的是noinst_XX,对于不需要安装(install)的可执行程序、静态库等,都使用noinst_XX作为前缀描述。另外top_srcdir是内置的全局变量,可直接使用。

configure.in和Makefile.am都已经具备,只欠“东风”了,下面的Makefile生成操作都是“auto”的了。

首先在源码包顶层目录下使用autoheader生成config.h.in,在例子里我们的config.h.in放置在src下了;
然后同样在源码包顶层目录下运行aclocal,aclocal将根据configure.in生成aclocal.m4;
最后运行autoconf,configure脚本被自动生成; 运行automake,我们得到所有Makefile.in。

Build环境就此初步搭建完毕。运行"configure -> make -> make install",我们顺利的得到了安装后的库,example下的runtests程序运行也OK。以上脚本在Ubuntu 10.04和Solaris 10 for x86下均测试通过。另外Ubuntu linux默认自带了全部autotools工具,这让我的学习过程变得更加轻便顺畅了!

我们再按照顺序回顾一下使用autoconf和automake的步骤:
-> 策划你的项目目录结构,将编写好的第一版源码文件放到各个位置上;
-> 在顶层目录下运行autoscan获得configure.in模板 (configure.scan->configure.in)
-> 手工编辑configure.in,满足个性化需要
-> 手工建立并编辑各个层次的Makefile.am
-> 在顶层目录下运行autoheader,生成相应config.h.in
-> 在顶层目录下运行aclocal,生成aclocal.m4
-> 在顶层目录下运行autoconf,生成configure
-> 在顶层目录下运行automake,生成各级Makefile.in

autoconf和automake很是强大,以上也仅仅算是学到了这两个工具的一些皮毛。面对更加复杂的软件包,学习和实践还在继续!

使用Ubuntu文档模板

每次安装Ubuntu后,主文件夹(你的$HOME目录)下都会默认建立起一些目录,诸如:下载、音乐、图片等,这些目录的用途通过其名字都可以猜个八九不离十,只有一个叫作“模板”的目录一直让我摸不到头脑。直到这次彻底迁移到Ubuntu,我才发现这个“模板”目录的妙用!

平时工作中常常需要新建一些文档,以前用Windows时都会使用右键菜单,点击“新建”,然后选择不同的文档类型。但在Ubuntu上却发现右键快捷菜单中“创建文档”的二级菜单项中默认只有"空文件”这一种文档类型,这显然不能满足我的需求!

在网上Google如何将更多文档类型添加到右键快捷菜单中。首先得到的答复是:Ubuntu Tweak可以做到。

启动Ubuntu Tweak,选择“个人设定”-> "管理模板“。这里有一堆"未启用的模板",诸如.odt、.ods、Html文档等模板类型,你可以把你需要的模板拖到左侧”已启用模板“列表中。选择完后,你在右键菜单“创建文档”中就可以看到这些类型的文档模板了。

不过如何添加Ubuntu Tweak里没有包含的文档模板类型呢?继续Google!在Ubuntu中文论坛上我找到了最终答案:将你期望的文档模板放入“模板”文件夹即可。恍然大悟,原来“模板”目录的用途是这样的啊。

打开$HOME目录下的模板文件夹,发现刚刚使用Ubuntu Tweak拖拽过来的文档模板都存放在这里。把一个word_template.doc的Ms Word文件作为文档模板放入此文件夹,打开右键菜单,果然看到了"word_template.doc"的菜单项。点击该菜单项,一个新doc文件就创建成功了,其实Ubuntu就是将“模板”目录下的word_template.doc文档模板复制了一份供你使用。

这种灵活性让人大呼过瘾!因为你完全可以将自己定制的文档模板放入右键菜单中!比如:公司一般都有很多办公或设计的模板文件,需要时要么在本机找到这些模板文件Copy一份,要么到公司办公网络上下载一份新的。这样一来很多人(包括我^_^)常因无法找到存储模板文件的位置或记不住下载地址而浪费了很多时间!使用Ubuntu文档模板后你只需要将文档模板放入“模板”目录,下次你就可以通过右键菜单创建新文档了!如果你是C程序员,你也可以将一份定制好的.h或.c或Makefile文件放到右键菜单中。如果你的公司模板文件太多,都放在“模板”目录下会导致右键菜单显示过长,你可以通过在“模板”目录下建立分类子目录来解决这个问题。这些子目录也将出现在右键菜单中,并可级联打开下一级菜单,显示子目录下的文档模板列表。如此灵活的功能是Windows所无法提供的(起码我目前还不知道Windows中有类似功能^_^)。

这里顺便将近期使用Ubuntu时学到的一些技巧叨咕叨咕:
* 关于Ubuntu剪切板
与Windows上全局一个剪切板不同的是,Ubuntu上提供两个剪切板:一个叫Primary clipboard,通过标准的Ctrl+v(终端用Ctrl+Shift+c)/Ctrl+v复制和粘贴。而另外一个是Selection Clipboard,顾名思义,选择即复制,鼠标中键粘贴。遗憾的是这两个剪切板居然不能混合使用。Primary Clipboard的内容无法通过敲击鼠标中键粘贴,反之亦然。安装Parcellite(GTK+剪切板管理器)可以在一定程度上解决这个问题。安装后,在其"首选项"配置中将以下三项均选上:
    -> Use Copy (Ctrl-C)
    -> Use Primary (Selection)
    -> Sync clipboards
这样两个剪切板的内容就可以共享了,即通过选择复制的内容,可以使用Ctrl+v粘贴了。

* apt-get代理设置
在单位通过公司代理上网,使用Ubuntu 9.04的时候,只需在.bashrc中配置http_proxy环境变量即可,apt-get可以顺利连接到Internet。但是换了Ubuntu 10.04后,http_proxy即使设置了,apt-get也无法连接到Internet。这个问题曾经一度无解,直到近期才找到答案:通过配置/etc/apt/apt.conf(若无此文件,则新建)达到为apt-get设置代理的目的。在apt.conf中添加如下一行:
Acquire::http::Proxy "http://user:pass@server:port";

* Gconf-editor
Ubuntu下也有一个类似注册表编辑器的工具:gconf-editor,用来对Gnome桌面环境和相关应用配置。其设置项目甚多,目前了解不多,这里就不深叨咕了^_^。

后记:短短两周的时间,部门内部已经相继有三位同事在各自的电脑中安装了Ubuntu 10.04,看来Ubuntu的魅力还是"不可小觑"的^_^。

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats