必须要记录一下今天给导师打工的经历。
前情提要:
经过好几个星期(每星期打一天工)的努力,某个不知道哪来的保密性C++项目编译完成,并顺利通过了基本案例测试,大概是基于Qt+OSG的项目。案例就是启动一个demo,使用几个不同的运行引擎跑通,然后最后在基于osg的三维地图中进行结果展示。
编译过程不复杂,原本在其他地方已经编译通,并且完整的vs工程和所有cache都拷贝过来的。经历的过程大概就是重新设置一系列的环境变量和库的路径,暴力修改cache中的绝对路径,补充不完整的库等等。当然,这里有收获一个重要知识,就是OSG和OSGEarth库是相匹配的,两个库版本必须兼容。本质含义是因为OSGEarth库是依赖OSG库编译的,所以使用OSGEarth库时,需要包含编译OSGEarth库时用的OSG库。
另外跑通案例之余要让其他人分析代码。所以第一要先编译出官方的documentation。仔细查看cmake编译出来包含多个子项目的vs解决方案才发现,里面某个target就是documentation,这个之前没印象还真没发现。项目本身是通过sphinx去编译写好的rst文件组织成html。安装sphinx受了不少苦,主要是离线环境安装加项目依赖特定老版本的库编译。最终方案是,参考项目文件的时间,找了这个时间点附近的环境和库。大概是python 3.6,然后安装低版本sphinx,但是安装低版本sphinx可能会依赖比较高版本的其他库,比如jinja库,这个时候就只能报错哪个再重新安装低版本的依赖了。离线安装方式就是在一个纯净环境(创建一个虚拟环境),安装特定版本库,然后导出所有依赖到requirements,再打包所有库到新环境安装就行。
另外源代码辅助阅读方面,使用doxygen编译源代码,绘制类图、调用图,生成一个API手册,同时添加源码进去方便阅读和跳转。doxygen生成注意的规范:规模较大的项目,如果整个大路径(特别是包含编译目录)都包含的话,大概率不可能能扫描完,所以要注意排除掉一些明显的大目录,只要源码的目录,不用使用exclude(不知道为什么不生效),而是用exclude_pattern.
好了,这是前面的工作,进入正题:
今天的工作很简单,只是要将全部弄好的东西,迁移到另一台电脑上。理论上全部环境一样,包括依赖库如qt等的目录,以及项目存放路径。所以只需要把所有东西拷贝过去即可,只需要一点点漫长的时间(这么麻烦就是为了省点事和少点坑,结果还是这么多坑!!!)
已经拷贝完毕,打开一跑好像还行,准备收工前严谨一点把流程跑完,结果最后一步结果分析软件崩了(error opengl version test failed. requires valid graphics context)!寄,要爬坑!分析过程:
- 重新cmake configure、generate(中间历史小问题解决了一下),单独重新编译结果分析软件,没用。
- 再回到原本那台电脑,软件是可以正常使用的。只是引入一个新的小bug,就是在vs直接编译打开软件,是没办法直接启动结果分析软件,但是双击exe打开就可以。不过这是小问题,分清楚主要矛盾。
- 那接下来就是找不同了,两台电脑到底有啥不一样。
- 大概搜索一下这个报错,显示的全是osg使用相关的错误(获得灵感一)。问gpt,提示是硬件驱动方面的问题(获得灵感二)。
- 大概看了一下osg相关的解决方案,都是源码编写的问题。按道理我一个电脑可以不应该是这方面的问题。还得从环境方面入手,项目的环境配置文档总共就几行。库的依赖主要就是vs和qt。vs基本就是自动安装的,那看看qt。qt是5.12.7,看了一下学弟安装的,发现不是同一个安装包安装的,虽然安装完都是5.12.7. 遂卸载换成我的安装包。(学弟用的安装包还特别坑,卸载巨慢)这个时候认为是osg::QGraphicsWindow相关的错,应该是qt的问题,觉得胜券在握。
- 然后终于重装qt完成,结果,一样!
- 这个时候做了个重要的测验,完整拷贝过来的文件,在移动硬盘中的目录中,在这台新电脑中直接运行,同样报错,而直接把移动硬盘放到原本硬盘运行,可以!说明不是程序和项目的问题,是环境问题。
- 依着这个思路,那往下更加极致地做,把项目打包生成,使用cmake的target的install。然后拷贝所有相关的依赖库,主要包括osg和qt相关的,qt相关的用windeployqt即可,osg的直接拷贝环境变量相应文件夹所有dll。反复试了多次都不行。直到已经取消新电脑中所有的环境变量,用walk dependency检查了可以运行那边的依赖,基本全部依赖都拷贝了,还是一样!按道理新电脑全部环境变量都没有了,旧电脑所有库依赖也删除了,所有依赖都打包了,那应该没有别的影响因素了,到这里基本放弃。
- 放弃吃饭的路上。将这个场景联想了一下。问题已经转化成,打包发布一个软件,同时已经把所有依赖带上(包括系统的vcruntime.dll等),但还是在编译电脑能用,发布的电脑不能用的问题。两个电脑基本都是纯净系统,都是只装了编译需要的库,现在这些库也没影响了,还有什么不同呢。依靠灵感二,大概率不是软件层面的区别了,而是系统和硬件层面。这个时候的建议是重装系统试试吧。但是硬件可能也有所不同,姑且尝试把两台主机的硬件设备交换了一下(主要是显示器)交换了一下,结果还是不行!基本放弃。
- 然后过了一会想起新电脑虽然把库依赖的环境变量删了,但没有像旧电脑一样把全部依赖删除。再这样试试。这个时候,接到了一个oc电话。。
- 结束后,随便运行一下新电脑的程序,发现不行了!!非常开心。出现问题不可怕,有时候有问题有时候没问题才可怕!之前可以,而现在不行,所以就是这段时间发生的变化导致的问题。仔细想了一下,忽然发现前面交换显示器后,原电脑的显示器是hdmi口,随手查到了主机主板的接口(原本在独显接口上,但是这个接口在靠下面,不是很好插,最后生气懒了就随手插在上面顺手那个口)。而且,原本那台显示器是VAG口,它只能插在主机主板口上!而且,前面第一次交换,就是因为懒,把交换的hdmi线就是插在上面的主板口了。稍微还原旧电脑原本的插线,果然就可以了!
- 到这里基本就解决问题了。剩下就是恢复测试现场,做好文档记录,做到最开始要交付给别人的样子。
反思:
- 工程化问题很大程度上就是一种找茬、找不同的过程。因为工程化很多时候就是把原本一个设计号的标准流程,形成一种可重复的标准不断推广开来。这个时候环境的差异就会导致各种工程化问题。
- 这个解密过程不亚于一种推理游戏,虽然模型可以简化成一种找不同。比如代码层面,就可以对代码进行二分删除进行“找茬”.
- 但更主要的是,要使用专业知识和经验,获取到通往胜利道路的灵感和思路。然后通过反馈不断完善自己的思路。这种积累和分析能力,是工程师非常重要的。总不能什么问题都这样用通用的蛮力去”推理“。
- 很多时候我的不足就是太谨慎、太保守。一定要在极限程度完美证明一件事情。其实上述很多过程都没必要、没意义。软件层面的差异很容易就能被认为不是主要因素(不是确认,而是一种直觉)。但为了确认,花了太大的力气。反而是反复告诉自己这件事就是做不成、消磨时间精力。
- 早一点从战略层面分析,发散思维,找可能性,找到通往成功的道路,这是最重要的。
- 而这,就是天才和普通人思维的差距?
- 当然,努力的方向就是做一个成熟的工程师,现在能做的,就是抓住、积攒经验吧。
- 作者:Olimi
- 链接:https://olimi.icu/article/edfe596f-a442-4746-87eb-7d8cbbbe7de8
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。