All Stories

可以用bjam做点事了

  今天把一个用了wxWidgets、Xerces-C++、luabind的工程用bjam写了个构建脚本,可以用MinGW来编译,也可以用VC来编译,这就是bjam的好处,很少需要关心不同编译器的命令行参数。  经过这次实践,还发现alternative的选择原来是要跟它的属性完全对应上才行。比如一个目标,写了toolset和variant以及threading,则在命令行中要把这三个全都设置上,不然它就说找不到匹配的目标。这让我有点头痛,假如我只想在命令行上选择toolset,而让其他两个属性固定死,那怎么办。  不过还算可以了,目前基本能满足实际需求了。

继续bjam

  bjam编译Windows下的rc文件不用特别指定,就像其他C/C++代码文件一样,直接放个文件名就行了,它能自动认出来,并调用相应的资源编译器来,只不过生成的二进制文件后缀还是跟代码文件编译出来的一样,不过并不影响最后的链接过程。  对于debug或release下使用不同配置的情况,需要至少每一种情况写一遍目标,同样如果是不同的toolset也这么处理。  今天把一个使用WTL写的工程用bjam系统编译了一把,果然也不是很麻烦,不过需要写不少特定的参数,bjam的默认配置不够用了,所以这样的情况还是不适合用bjam的。简单地说来,适合用bjam的场合,至少是没有一个好用的IDE的情况下。  想起直接在bjam里用wx-config来生成的编译选项,居然会出错,因为wx-config的输出后面多了个回车,用make就没影响,而链接选项在bjam中也没影响。没办法,去网上找到wx-config的源代码,只有一个文件,不过有几千行,稍微找了一下输出的代码,把末尾的回车换行去掉,再试了下,果然可以了。

bjam使用点滴

  要在工程的根目录下放一个Jamroot文件,可以没有扩展名,也可以加.jam为扩展名,这样其他子目录下的可以命名为Jamfile了。  基本上是个大小写敏感的系统。  还没找到怎么让它来自己编译Windows的资源文件。  用path.glob-tree可以指定目录来进行glob-tree,如果光用glob-tree,是只能从当前Jamfile所在目录开始全部搜索的。

bjam有点意思

  在编译Luabind成独立的库时,顺便学了一下bjam。bjam在某些场合下挺有用的,如果之前用的是make,再来用bjam,感觉就是用过汇编之后来用高级脚本语言。  折腾了一阵子后,我的感觉就是bjam几乎是完全给boost设计的。其中最突出的特点是,编译器无关。它在这方面做不了少工作,只要指定一个toolset,它就能自动查找编译器所在的路径,而且不用关心编译命令行,因为大部分常用的选项它都提供自己的抽象方式来表达。还有就是它似乎有良好的可扩展性,在boost的源代码目录下有几bjam的工作目录,下面有几个子目录,里面分别存放着一些jam文件,在写jamfile时,可以import模块进来用。  我捣鼓了一阵,把自己一个工程,里面有几十个C++源文件,从GNU make转成了bjam工程。感觉有点新鲜,但总的说来,它应该是适用于这样的场合:工程是可移植的,即要跨操作系统,跨编译器。

Luabind还是有必要的

  写着写着,发现Luabind不是先前想的那样有了SWIG就可以抛弃了的,还是有用武之地的。  主要体现在两个地方。  一、从C++调用Lua函数。Luabind提供了两个方法,在Boost的协助下极其出色地分别实现了调用全局函数和其他可被作为函数调用的对象的调用。这两个方法都以C++模板实现了可变参数类型和可变参数个数的调用,而不是C库中printf使用的那种方法。这得益于强大的Booster::mpl。  二、提供C++中自定义类型的高度灵活的部分封装。用SWIG通过分析C++声明一股脑儿全都封装了,当然可以通过预定义宏SWIG可标识不想被封装的部分,但这需要修改C++源代码,以致于破坏C++源代码的整体风格,而且灵活性明显不行。用Luabind可以随心所欲地把任意一个类的其中几个方法封装了,这个优点是我在看了Luabind中自带的几个example才想到的,比如它演示封装了boost::regex,boost::filesystem,如果想用SWIG,几乎不可能达到目的。

研究了半天SMTP发送HTML

  主要的内容生成功能基本完成90%了,于是就研究一下怎么把这html内容通过SMTP发送出去。原来有一个从CodeProject上找的SMTP类,直接用WinSock写的,倒是也可以正常工作,接口也很简单,而且当时沾沾自喜经过自己修改,是可以支持中文的,其实是自己土了。现在只是想把这个类再修改一下,可以直接发送html内容,不过看起来似乎有点儿复杂。  用Outlook Express发了几个邮件,用Wireshark抓来看了看,看得云里雾里。后来找到另外一个示例程序,有源代码,也可以发送html,用Wireshark看了看,发现差别还真大。最后看到一个说明里提到,RFC2110里就是讲这个的,于是马上找来瞄了几眼,终于有点儿理解了。原来Outlook Express在一封邮件里包含了2封邮件的内容,分别是html和plain text的,这样无论对方的客户端能不能支持html阅读,都可以方便地看到真正的邮件内容,当然html中的链接嵌入对象除外。

这个进展还真是慢

  回来整了几个小时,没搞出什么花样,只是把tab页对象换了个地方。本来是没想到要换的,只是今天突然想起,要截获tab页关闭的消息,于是折腾了那么久,发现在原来的那个类里搞不定,不知道是什么原因。开始我只是想试试直接用wxFlatNotebook对象的Connect方法,可是根本不知道那些参数要怎么写。后来我把那类从wxEvtHandler继承了啊,消息映射也加了,但就是不行。后来看到wxFlatNotebook官方的sample里是把这消息映射放在一个wxFrame里处理的,于是我也照样学样把它放到MainFrame里去了,果然能截获了,而且从设计角度讲,这也比之前那样好,因为这个wxFlatNotebook应该是全局使用的。只是没弄懂原因,有点不爽。

MySQL还不错

  老雷要一个自动发汇报邮件的程序,这个任务落到我的头上,于是我这周开始整这玩意儿。所有的数据几乎都是存放在MySQL里的,一个是RedMine的内容,另一个是组里自己开发应用程序使用情况统计工具,服务器端也使用的MySQL。今天我发感叹地跟开发那应用程序使用情况统计工具的同事说,幸亏你们当时选用了MySQL,不然还要更麻烦一点,比如万一选了个Access或者Sqlite3,还不能方面地远程访问。如果是SQL Server,还得使用一套不同的数据库访问方法。  通过这两天使用mysql++来访问MySQL的经历,我感觉无论是MySQL引擎,还是暴露的API,都挺不错的。大概是因为ADO访问SQL Server用得有点反胃了。那段经历让我觉得最为不爽的是,如果SQL写得有点问题,就会抛异常,而且这异常就是catch不了,因此很难排错。这次用mysql++在这方面就做得不错,异常可能catch到,而且给出的出错信息很准确,定位很方便。另外有点值得一提的是,mysql++里有一个重载了很多类型转换符的String类,呵呵,这也是一种办法啊,不过使用operator+时却遇到了点小麻烦。  开发这个程序最大的收获大概就是这个了,大部分情况下,可以用MySQL来代替MS SQL Server了。再扯远点,Access也有点不好的,打开的时候特别慢,用Sqlite就挺快的,而且Sqlite3还是是弱类型的,呵呵。

不要盲目追求最新版本

  无论是软件,还是程序库,应该选定一个并不太旧的稳定版本,一段时间内,比如半年,一直使用该版本。  一个明显的例子是之前用4.3.2版的gcc编译好的wxMSW,后来年到4.3.3版的gcc了,就下载下来试用了一下,发现原来的工程死活链接有问题,报什么虚函数找不到云云,再换回4.3.2就又可以了。由此看来,4.3.2和4.3.3编译出来的.o文件可能在内存等方面有变化。我也不想再花时间去用4.3.3编译一遍wxMSW了,太浪费时间了,而且如果要换,就要把其他相关的库都换一遍,至少包括boost,Xerces-C++,wxLua,青春啊,不能就这么耗费掉啊!