里程碑,全静态开发环境配置完成:Qt+Qwt+VTK+Boost

来源:互联网 发布:android 文件存储数据 编辑:程序博客网 时间:2024/06/11 04:51
 

为什么要用静态开发环境?

这要从我本人的倾向性来说了,我个人不太喜欢类似微软.net的那种要使用必须装某个环境的程序,既麻烦又不人性化。那么静态连接比动态连接好吗?也并不是这样,动态连接的一个好处就是可以形成一个程序调用链,当操作系统中具备某个环境的时候,使用动态连接的程序往往需要很少的代码量,而且生成的可执行文件也往往不大,我个人曾经写过一个超过2000行代码的.NET界面程序,最后生成的可执行文件居然500K都不到,但是代价就是牺牲了程序的可移植性,别说是跨操作系统,就是不同的软件环境也往往会导致软件不可用。那么静态链接生成的文件就一定大于动态连接?非也。静态连接由于是根据调用关系来执行编译,因此在code generation的过程中,往往只生成有用的代码,因此静态编虽然所产生的可执行文件往往很大,但是他的size,却小于动态生成的文件+各种动态链接的总和,因此动态连接和静态连接只能说各有所长,并不是谁一定好于谁。另外一点要说明的是,动态链接是微软独有的东西,因此使用动态链接的软件一定没法跨平台(正常环境下,不包括类似wine模拟的情况),而静态连接虽然也不一定完全能跨平台(有些操作系统二进制解析方式不一样),但是具有了跨平台的可能性。

好,下面开始说我配置静态环境的过程。

首先是Qt,选Qt做界面原因有如下几点:1. 跨平台 2. 开源 3. 文档丰富。在几个图形SDK的选择中,我放弃了MFC和.net,MFC倒是有静态版本,但是非开源,并且是非OO编写的库。我对.NET的印象蛮好的,虽然接触时间不长,但是非常人性化的开发方法,非常高效的开发环境很适合企业使用,但是缺点同上,非跨平台、非开源。

上面也说了,Qt是开源的开发环境,因此你可以自己编译,怎么编,需要什么环境,完全自己定制。但是这个编译过程实在太长了,4,5个小时,等待的时间很痛苦。我在下载QT源码后,由于经验缺乏,直接就编译了,最后编译出个动态版本的QT库,后来读了下QT的configuration文档,发现有static参数,便重新配置,重新编译,过了一夜,发现虽然声称的是LIB,但是仍然存在调用系统DLL的情况,后来上网搜,发现得直接改configure文件,把MD编译方式变成MT,然后再配置,再编译,又是一宿,试一下,终于变成静态库了。

编译Qwt的过程就简单的多了,直接下载源码,qmake,nmake,好家伙,一大堆error,全是error link 2001类型的错误,查了下Qt库文件,发现好好的,怎么能存在2001错误呢?进Qwt的Qwtconfig文件里看了下,发现他把QT库的位置设置成了系统环境变量里的那个动态QT库的位置了,为了避免将来还有类似错误,赶紧把环境变量改了,qmake,nmake,一切正常。但是发现Qwt控件用不了了,为什么?因为qdesigner只能加载动态DLL,于是用动态版本的QT再次生成一遍,这次把生成的DLL拷贝到Qdesigner的plugin文件夹下,OK,可以正常加载。

配置Boost开始没遇到多少问题,但是使用的时候问题来了,各种redefination,心想,boost应该不至于吧,这可是有名的跨平台STL强化库啊,最后仔细看了下编译参数,发现bjam有个build-type变量,这个变量默认值是minimal,而minimal只安装最小的库,于是我重新编译,把build-type设置成complete,这次时间蛮长的,1个多小时,好了,没错了。

配置和QT兼容的静态VTK,这绝对是个技术活,涉及到了二次开发。这也是我喜欢用开源开发库的原因之一,你觉得哪不好,或者哪不符合你需求,你可以自己改,有bug也可以自己搞定。第一次编译VTK的时候,特意把cmake里的shared-library设置成off,但是生成的库仍然是含有动态线程库的LIB,网上查了下,发现cmake里有个选项,是c_release_flag,这个选项设置成MT才能生成静态线程库的LIB,再次编译,试一试,好了。过了阶段,尝试把VTK往QT里集成,又出问题了,而且是redifination的问题,网上查了下,发现在vtk论坛上,使用static-Qt-VTK的人几乎全有和我相同的问题,VTK的一位开发人员也说,虽然他已经极力避免这类错误了,但还是存在,因此他建议的解决方法是放弃静态连接,全部使用动态,我看到这个帖子心里一沉,想,自己付出的努力就这么白费了?难道没有其他解决方法吗?于是我给自己一天的时间,这一天内,如果能找到解决方法,就继续静态环境开发,如果找不到,全部转成动态环境,不要让环境耽误了毕设。自己看了下错误的LOG,找到了redefination的变量所在,尝试替换,但失败,其实可以预料到的,类似VTK这种大型图形开发库,重命名一个变量或者函数远远不是replace keyword这么简单,这里面有很多的函数调用链,牵一发而动全身,说不定哪就出岔子了,既然没法重命名,那就尝试换编译方式,仔细看了下存在命名冲突的文件,发现全部是libtiff的文件,而在查QT的时候,发现QT居然也有libtiff文件,OK,那么我是不是可以用QT的libtiff来编译VTK呢?尝试一下,各种错误,发现不少can not open头文件错误,于是一个一个拷贝,把所有需要的头文件拷贝进来,又出错了,这次是template错误,出现在qglobal里的错误,仔细查了下,发现是c standard和c++ standard冲突导致的,去libtiff文件夹下发现libtiff是C文件,因此所有文件里全有extern "C",于是我仔细的把含有Qglobal.h的文件里,把qglobal用extern "C++"罩起来,再次编译,通过,运行example,命名冲突消失。但是又有问题了,而且是error link 2001,刚把命名冲突解决,就出现unresolved,真是秀逗,仔细查了下,发现是QVtkWidget无实现,网上查了下,发现这个类是在QVtkplugin.lib里实现的,去lib文件夹看了下,发现并没少这个文件,那怎么还有2001错误?打开QVtkWidget工程看了下,发现居然是个生成Dll的工程,这才知道,VTK默认生成QVTKplugin是动态的,因为只有动态的才能加载,而cmake里设置C_Flage_Release并不包括这个子工程的设置,于是手动设置成MT和LIB,再次编译,成功,加载,成功,集成,成功。

 

OK,到这里,环境配置全部完成,编程这么多年,第一次在配置环境上遇到如此多的问题,好在都解决了,这个经历同时也让自己更加确认一个事实:遇到问题多思考,总能想到解决方案。

原创粉丝点击