FFI Navigtor在Windows环境下的"No Such File or Directory"Bug解决过程
一年未更,沉淀积累。
今日立春,万象更新!
这两天花了大概10个小时尝试在Windows环境下使用TVM工程的FFI Navigator插件,最终成功,在此记录。
传送门:只想看方法不想看过程的直接跳至分支B处阅读。
背景:
1. FFI 是多语言交互接口,在TVM工程中大量使用它来实现后端C++与前端Python之类的语言交互。
2. FFI的使用导致Python程序调用C++函数的相关代码无法跟踪函数定义。
3. 于是TVM大佬陈天奇自己写了一个FFI Navigator(https://github.com/tqchen/ffi-navigator)用来实现Python与C++之间的代码跟踪。
解决过程:
1. 我的传统开发方式是本地Windows PC准备一套代码,通过WinSCP与Linux服务器端同步,编译与debug过程都通过SSH使用命令行实现,本地代码仅用于通过VSCode检视与编写。由于FFI Navigator现在仅支持VSCode与emacs,所以选择使用VSCode版本。
2. 在VSCode上安装了FFI Navigator的Extension,发现还需要pip安装FFI Navigator,pip安装报错Retrying after connection broken by,参考文章https://blog.csdn.net/weixin_40995629/article/details/80180609解决。解决方法:pip install -i https://pypi.mirrors.ustc.edu.cn/simple gensim。
3. pip安装FFI Navigator之后还提示未安装,阅读Github的Readme,发现还需要Build from Source步骤 ( https://github.com/tqchen/ffi-navigator/tree/main/vscode-extension )。
4. 尝试步骤Run npm install && npm run compile
on the vscode-extension folder,报错cb() never called,未能成功。搜索到有两种解决方法,一是使用cnpm,二是删除代理(忘了是哪篇文章),使用指定代理(https://www.cnblogs.com/wenbinjiang/p/11062959.html)。
5. 方法二不管用,使用方法一成功。成功执行cnpm install与npm run compile,但仍然提示未安装FFI Navigator。
6. 在VSCode的Extension界面Disable,Enable,Uninstall,Install,然后重启VSCode ( 后来发现VSCode不加载某插件,可能是卡在某其他插件的下载更新步骤上,比如C/C++ Extension,国内网络状况大家都明白,这时候可以把这个卡住的插件disable来解决尴尬 ) 。
7. VSCode下方出现了FFI Navigator的打印信息,也不报未安装FFI Navigator的错误了,感觉离成功很近了。但是每当在FFI函数接口使用Ctrl+鼠标点击跟踪定义时,会出现一段报错:
8. 思考了半天,发现这个路径是按照Linux系统的路径在找文件,所以找不到。
时间线在这里分叉,我当时的探索,与我现在的探索,是两个思路,记为分支A与分支B:
分支A:
1. 在服务器端安装使用VSCode,由于我的TVM是在Docker中的。还要研究SSH -X在Docker镜像中的转发问题,作罢。
2. 在服务器端直接安装使用VSCode,这台服务器yum出问题,会直接卡住,提示yum lock。使用另一终端kill掉进程后可退出,但yum还是无法使用。
3. 搜索发现yum clean all,不管用,yum makecache方法,卡住,可能需要替换yum源头,其他方法参考:https://www.cnblogs.com/wpjamer/articles/10317821.html,怕弄得更糟没敢用。
4. 使用VSCode Remote SSH插件,查阅方法:https://code.visualstudio.com/docs/remote/ssh#_getting-started。
-
Install an OpenSSH compatible SSH client if one is not already present.
-
Install Visual Studio Code or Visual Studio Code Insiders.
-
Install the Remote Development extension pack
-
5. 在Docker镜像里面安装OpenSSH,但同样还要解决SSH直接链接Docker镜像的问题,参考文档:https://www.cnblogs.com/jesse131/p/13543308.html。觉得麻烦没弄。
6. 本地Remote WSL方式,WSL太难装没弄。
分支B:
1. 修改报错路径输出脚本langserver.py第62行的内容。
2. 直接修改后并不会立即生效,要重启VSCode,应该是本模块仅在启动时import一次。
3. 用Print函数并不会打印输出,仿照报错中的其他打印信息使用本地方法:self.logger.info。其实self.logger是logging,有些没有self的域直接用logging就可以打印。
4. 打印发现langserver.py中第62行的路径确实是错误的,Windows路径中的“d:”变成了“d%3A”。网上搜到有人提到URL路径中的%的问题,受到文章:https://www.cnblogs.com/zhangcheng1/p/11174736.html与https://bbs.csdn.net/topics/200020651的启发,发现是URL特殊字符处理的问题。参考方法:https://www.runoob.com/python/att-string-replace.html。扩展阅读:http://www.360doc.com/content/11/1223/16/2150778_174499703.shtml。思路在这里又一次分叉:
分支B1:
直接修改langserver.py第62行m_text_document__definition(self, **kwargs)报错处之前的path内容,path = path..replace("%3A",":")。虽然不报错,但是m_text_document__definition函数返回空路径,应该有其他问题。
分支B2:
1. 修改langserver.py第16行uri2path()函数中的语句,将str(pathlib.Path(raw_path[1:]))修改为str(pathlib.Path(raw_path[1:])).replace("%3A",":")。发现还是会报错,报错提示FFI Navigator启动时遍历某个.cc文件时打不开。(其实我首先尝试的是分支B2,到这一步我觉得我可能弄错了,又回去尝试分支B1,B1失败后我在食堂吃中午饭的时候觉得有可能B2是对的,但是正确的路径反而暴露了文件打开的另一个问题,于是进行下一步B2.2)
2. 文件打开报错定位至workspace.py的第79行,报错UnicodeDecodeError: 'gbk' codec can't decode byte 0x9d。查阅文章:https://blog.csdn.net/u012369535/article/details/97927853。
3. 将workspace.py69-79行所有的open方法加上编码限定,即由open(path)改为open(path, encoding='UTF-8')。
4. 问题基本解决,FFI Navigator成功跨语言由Python至C++跟踪函数。
5. 由C++至Python跨语言Reference跟踪报错,修改langserver.py第63行与第87行的open函数,修改方法同步骤B2.3。
6. 问题完全解决。
VSCode插件调试心得:
1. VSCode插件本身不复杂。
2. 可能由于PC配置差或者网络差,VSCode插件启动有问题,有时候我想用的这个插件启动不起来,这样也就没法打印调试。解决方法是将这个插件Uninstall再Install然后再关闭并打开VSCode,猜测是首先启动新加载的插件。
3. 重启VSCode,插件python源码的修改才能生效,应该是插件仅在启动时import一次。
总结:
1. 基本解决思路是靠搜索引擎搜索技术博客(这也是我为啥要写这篇,当然也是为了总结解决问题的思路)+积累的技术基础知识+现有问题的分析。
2. 很多时候改源码可能并不是最难的解决方案,Github上很多代码都需要先调试再用。
3. 尽早采用最简单直接的解决方案。
4. 使用Github的时候先仔细阅读ReadMe。
5. 不用对技术细节问题过于执着,不能解决马上找替代方案。人的精力有限,Debug过程就像游戏中血槽不断减少的Player一样,一定要把高精力时刻用在最直接最可行的方案上,不要过于执着!