.NET Core 2.0 应用程序高级调试:完全掌握Linux、macOS和Windows跨平台调试技术
上QQ阅读APP看书,第一时间看更新

2.1 .NET Core源代码在Linux操作系统上的编译

.NET Core可以支持Debian/Ubuntu、Red Hat/CentOS、SUSE/OpenSUSE等各种发行版本的Linux操作系统。下面就取几款典型的操作系统来说明编译.NET Core代码的步骤。

2.1.1 获取.NET Core源代码

.NET Core的源代码保存在Github网站上,因此获取.NET Core代码需要在Linux操作系统上安装Git客户端,如命令2.1所示。

命令2.1 Debian上安装Git客户端

在CentOS上,需要使用yum来进行安装,如命令2.2所示。

命令2.2 CentOS上安装Git客户端

然后在磁盘上用mkdir创建一个名为dotnet的文件夹,如命令2.3所示。

命令2.3 创建dotnet文件夹

最后通过git clone获取coreclr和corefx两个代码仓库的代码,如命令2.4所示。

命令2.4 复制coreclr和corefx代码到本地

至此,.NET Core重要的运行时(coreclr)和基础类库(corefx)两部分的源代码已经获取到本地。

2.1.2 安装编译源代码必要的工具

.NET Core源代码的底层与操作系统交互的部分由C/C++写成,并且依赖一些第三方的函数库。同时,用于编译整个项目的makefile文件是使用CMake来生成的。这主要是为了方便让.NET Core的源代码可以跨平台编译。通过CMake(最低版本要求2.8.12)可以生成针对macOS、Linux和Windows平台的makefile文件。因此,为了编译.NET Core,需要在Linux操作系统上安装编译所需的C/C++编译器、第三方依赖库和CMake工具。.NET Core的C/C++编译器使用的不是gcc/g++,而是Clang,并且需要Clang 3.9版本。

其实,.NET Core最早是依赖Clang 3.6环境的。但是由于Clang整体发展迅速,再继续使用3.6版本已经显得非常不合时宜了,尤其是用于调试的调试器LLDB 3.6功能比较弱。于是,产品组在.NET Core 2.1这个版本上将编译环境改为了Clang 3.9。

主要依赖的第三方库有CMake、llvm-3.9、Clang-3.9、lldb-3.9、liblldb-3.9-dev、libunwind8、libunwind8-dev、gettext、libicu-dev、liblttng-ust-dev、libcurl4-openssl-dev、libssl-dev、uuid-dev、libkrb5-dev、libnuma-dev等。

对于Debian和Ubuntu来说,LLVM组织提供了对应的安装包,只要把.NET Core编译所需的LLVM 3.9加入到apt源中即可安装。但是对于Red Hat和CentOS来说,默认可安装的版本是LLVM 3.4,因此需要手动编译LLVM 3.9并进行安装。

首先,安装CMake工具,在Debian/Ubuntu上默认的CMake版本都已经是大于3.4的版本了,因此直接安装即可。在安装结束后通过cmake--version确认一下安装的版本。

在Debian/Ubuntu上安装完CMake之后,还需要安装gcc和g++编译器,用来编译.NET Core源代码。好在Debian/Ubuntu源上提供的gcc和g++版本足够新,不需要通过编译源代码的方式进行安装,如命令2.5所示。

命令2.5 Debian安装CMake和gcc

CentOS的情况比较复杂,默认源上的CMake版本很老,还是2.8版本,因此需要从cmake.org上面下载CMake 3.8版本的源代码进行编译和安装,如命令2.6所示。

命令2.6 CentOS编译安装CMake和gcc

在完成CMake的安装之后,就需要安装.NET Core编译依赖的第三方库了,如命令2.7所示。

命令2.7 Debian安装第三方依赖库

CentOS与Debian略有不同,如命令2.8所示。

命令2.8 CentOS安装第三方类库

在完成以上步骤之后,安装编译.NET Core所需的LLVM环境。对于Debian/Ubuntu来说,只要把位于llvm.org/apt/的源位置加入到apt配置文件中,并安装llvm的apt公钥即可,如命令2.9所示。

命令2.9 Debian安装LLVM3.9、Clang3. 9、LLDB3.9

debian-gnu-linux-8:~$ wget - O - http://llvm.org/apt/llvm- snapshot.gpg.key | sudo apt-key add - debian-gnu-l inux-8:~$ cd/usr/l ib/llvm-3 .9/l ib

对于Red Hat和CentOS操作系统,LLVM和LLDB的安装稍微复杂一些,需要手工下载LLVM和LLDB的源代码在CentOS操作系统上直接编译。具体步骤请参考2.1.3节。

2.1.3 在CentOS上手工编译LLVM、Clang和LLDB

由于.NET Core在编译、调试时对LLVM、Clang和LLDB的版本有要求,Red Hat和CentOS默认源中的版本不能满足,因此,需要手工在Red Hat和CentOS用指定版本的源代码进行编译。

CentOS上的软件以及相关源上的软件包都比较老,如果在CentOS上使用CMake 2.8.12版本,在编译LLVM、Clang和LLDB时报告编译错误,那么请升级CMake到最新的版本3.8.2,步骤如命令2.10所示。

命令2.10 CentOS编译安装CMake

编译LLVM对编译机器的内存有一定的要求,请保证计算机内存在6GB以上,否则会在构建过程中,尤其是链接的时候,出现很多莫名其妙的错误。LLVM体积庞大,构建后,源代码文件夹有几十吉字节,因此最好空闲的磁盘空间有100GB以上。

LLVM 3.9版本编译的步骤如下:

(1)下载LLVM 3.9版本的源代码,解压缩并改名放入llvm文件夹。然后编译和安装LLVM,如命令2.11所示。

命令2.11 CentOS下载LLVM安装构建LLVM的依赖库

(2)下载Clang,并放入llvm/tools文件夹内,再解压缩,如命令2.12所示。

命令2.12 CentOS下载解压缩Clang

(3)下载LLDB,并放入llvm/tools文件夹内,再解压缩,如命令2.13所示。

命令2.13 CentOS下载解压缩LLDB

(4)编译、安装LLVM、Clang和LLDB,如命令2.14所示。

命令2.14 CentOS下构建LLVM系列组件

(5)在安装LLVM 3.9的过程中,安装脚本还需要使用Python 2.7来帮助运行安装脚本,因此,可能会在安装LLVM 3.9的过程中遇到找不到Python的问题。因此,还需要在LLVM构建目录下再编译一份Python 2.7。所以需要下载和安装Python 2.7,然后再通过Cmake执行安装脚本安装LLVM 3.9。以下是Python 2.7的编译相关步骤,如命令2.15所示。

命令2.15 CentOS下安装Python 2.7到LLVM目录

(6)在编译和安装结束之后,通过下面的命令确认Clang和LLDB的版本,如命令2.16所示。

命令2.16 CentOS下验证LLDB安装

在以上步骤执行完成后,才算是在Red Hat或者CentOS上部署了可以支持.NETCore编译调试的环境。

在构建和安装LLVM 3.9之后,及时删除llvm文件夹,以便节省磁盘空间。

2.1.4 在Linux上编译.NET Core源代码

经过以上的准备,就可以正式开始编译.NET Core的源代码了。coreclr项目和corefx项目中各自带有build.sh Bash脚本文件用来编译coreclr项目和corefx项目,编译.NET Core只需要跳转到对应目录执行build.sh脚本文件即可,如命令2.17所示。

命令2.17 构建coreclr和corefx

由于在编译过程中build.sh Bash脚本还需要从GitHub上下载dotnet CLI项目,并且需要编译的文件非常多,通常编译时间会持续十几分钟到几十分钟不等。具体编译速度严重依赖于编译计算机自身的CPU性能和磁盘I/O性能。

coreclr项目的编译结果保存在dotnet/coreclr/bin/Product/Linux.x64.Debug目录下,主要是与调试相关的SOS组件和与.NET Core运行时相关的部分。这些编译输出构成了.NET Core运行时和核心程序。在该目录下还有一个PDB子目录,内含有相关符号表文件(∗.pdb),这些文件将在未来用于帮助调试者分析内存转储(core dump),如图2.1所示。

图2.1 coreclr项目在Debian 8上的编译输出

CoreFx项目编译的结果保存在dotnet/corefx/bin/runtime/netcoreapp-Linux-Debug-x64目录内,如图2.2所示。这个目录中含有.NET Core的全部基础类库(BCL)程序集以及对应的PDB符号表文件。在调试时,符号表文件用来查找代码、变量地址与中间语言IL之间的对应关系。因此,一旦某个版本的.NET Core用在了生产环境,那么最好保存一份该版本的PDB符号表文件。

图2.2 CoreFx项目在Debian 8上的编译输出

针对不太熟悉Linux系统的用户,在这里补充一个小知识:Linux通常使用颜色来区分文件的类型,而文件的扩展名并不是那么重要。默认状态下Linux文件类型和颜色的对应关系如表2.1所示。

表2.1 Linux下文件颜色与文件类型对应表

当然,这些颜色和文件类型的对应关系可以通过修改/etc/DIR_COLORS file文件进行自定义配置。因此在一些特定的Linux发行版本上,表示特定文件类型的颜色可能略有不同。