由于最近都在写c#,对其底层实现产生了很大兴趣,所以计划把源码拉下来学习一番。 首先备忘一下环境搭建:

源代码

仓库:https://github.com/mono/mono.git
其中submodule一堆,最好开挂拉,否则一天都拉不完。

文档:https://www.mono-project.com/docs/

.net assembly,也就是dll文件,或叫cil模块的格式定义:
https://docs.microsoft.com/en-us/dotnet/standard/assembly/file-format
https://www.ecma-international.org/publications/standards/Ecma-335.htm

编译:传统的三件套configuremakemake install
也可以按文档中所说,由于是从git source编译,第一步换成autogen.sh,其实差别不大,autogen.sh的结果就是生成configure并运行,但后者已经提交到仓库了直接使用也可。

关于autogen.shautoconfautomake:
https://stackoverflow.com/questions/50044091/what-is-the-job-of-autogen-sh-when-building-a-c-package-on-linux

不过有一点注意:为了编译调试版(方便单步跟踪,否则行号会因为优化而不匹配),应该使用以下参数:
./configure CFLAGS="-g -O0"

还有一点就是--prefix选项,它会影响安装的位置,默认是在/usr/local/[bin|lib],在linux上这也是预编译包的安装位置,所以如果自己编译测试用的最好重载该选项装到其它地方去
但是在mac上预编译安装都在/Library/Framework下面,所以也不怕冲突,就没有改了,因为改过之后运行程序还得设置LD_LIBRARY_PATH变量,有点麻烦。

编译完之后的mono可执行程序在mono/mini/mono,如果不make install,直接运行它,会因为找不到各种运行时库而报错,至于怎么配置使它可以源码树中找,一时还没有发现好办法。因为光看Makefile中的安装过程,就有大量的建目录、复制文件等操作,这些应该都是约定好的结构甚至可能硬编码在代码里,只能以后慢慢学习了。

IDE

有了代码就要开始读,而且最好是边运行边读,通过不断修改测试一些小例子来观察运行流程。
首先vscode是可以调试走起的,但是基于语义的智能提示和跳转我还不知道怎么弄,众所周知,c/c++的工程是最灵活也是最麻烦的,因为根本就没有标准的工程文件,从make,qmake,cmake,scon到msbuild,xcodeproject之流,五花八门,基本上是个IDE就会搞一个自己的格式,但又不通用。而最通用的make又过于松散难以嵌入IDE中搭配GUI工作流。
mono的源码是通过make编译的,要让IDE通过理解makefile来实现智能提示是不太可能。但是要把这个makefile改成其它工程文件也是不会的 😰
一顿搜索后发现Clion这个好东西,跟之前用过的AndroidStudioRider是一家,顺便提下我心中的好IDE标准:

  • 各种面板切换、任务执行都有快捷键,且能自定义配置
  • 编辑器支持vim模式,可以切分
  • 集成终端
  • 有目录树或项目、工作区概念
  • 快速定位文件、查找符号

以上是不论具体语言和开发目标,仅做为一个通用编辑器该有的功能,各语言相关的智能提示当然也是必须的。jetbrain系列IDE和vscode恰好都在这几方面做得够好,论细致体贴j家的更胜一筹,但vscode好在插件多可以同时兼顾好几种不同语言的混合项目开发。

说回Clion。。。在使用中一些小技巧:

配置cmake项目,获得语义智能提示

可以直接在gui上操作:File->New CMake Project from Sources,选择源码根目录,会生成一个巨大的CMakeLists.txt文件,其内只有一个executable类型的project,名字就是目录名,并将几乎所有子目录都做为include目录,所有c文件都做为源文件加进来。有了这个文件,Clion就大概知道要怎么构建项目,从中得到语义信息来做智能提示了。

配置custom build target,启用调试

上一步的副作用是自动添加一个CMake Application的Run/Debug Configuration,然而cmake除了提供一个近似的工程信息给Clion做语义分析外,并没有别的用处,这个自动生成的Configuration也不能build和run。为此,手动添加一个custom build target,其中Target需要再去专门的界面配置一番,Executable就选择外面make编译好的mono可执行文件,再把Before launch里的Build去掉,也就是IDE里只管读写源文件和调试,build去终端自己敲make。如此,就得到了一个可看可调的IDE,设断点、单步、检查变量,都可以像在vs里一样方便使用了~

debugger里的小技巧

尚未解决的问题

  1. 能否写类似vs里的autoexp?对于复杂的容器数据类型自定义在watch窗口中的展开视图
  2. 能否支持类似vs里的mixed调试,即native和managed代码都可以下断点、单步跟踪
  3. 能否将mono的编译机制改为cmake,实现modify-build-debug一体化?