![.NET Core 2.0 应用程序高级调试:完全掌握Linux、macOS和Windows跨平台调试技术](https://wfqqreader-1252317822.image.myqcloud.com/cover/625/26793625/b_26793625.jpg)
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所示。
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-P27_1.jpg?sign=1738846819-NbSAoozFZInPdOs1nrEej5DVJyQExVe9-0-4467b810b6842257dd19f408e14c2727)
命令2.1 Debian上安装Git客户端
在CentOS上,需要使用yum来进行安装,如命令2.2所示。
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-P27_2.jpg?sign=1738846819-tInT7QU4TRgQCxImEW1vPDdtjNjOKPoN-0-063e00331fe6c4fe48f77bfcc2286e2b)
命令2.2 CentOS上安装Git客户端
然后在磁盘上用mkdir创建一个名为dotnet的文件夹,如命令2.3所示。
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-P28_1.jpg?sign=1738846819-EneJJhYPptaGeklMgGvKaFxFTTDetmEl-0-77de96567fe9efa455e7b337f19da8de)
命令2.3 创建dotnet文件夹
最后通过git clone获取coreclr和corefx两个代码仓库的代码,如命令2.4所示。
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-P28_2.jpg?sign=1738846819-kYktNb42vWiDngXJMvlKUYqNCCC3vPyO-0-fecbbd553c73b42afaeb2f426290e3d1)
命令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所示。
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-P29_1.jpg?sign=1738846819-mqRfV26rEYIkNtN4XVrlqceQ9KewtWVI-0-d14999693e05dfd2f46ac91945474603)
命令2.5 Debian安装CMake和gcc
CentOS的情况比较复杂,默认源上的CMake版本很老,还是2.8版本,因此需要从cmake.org上面下载CMake 3.8版本的源代码进行编译和安装,如命令2.6所示。
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-P29_2.jpg?sign=1738846819-qdR5ND5uDkyv173NkQuhz9EwxI0TTmso-0-9bfbbe1973cdaa9d33a6900efbdc69c6)
命令2.6 CentOS编译安装CMake和gcc
在完成CMake的安装之后,就需要安装.NET Core编译依赖的第三方库了,如命令2.7所示。
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-P29_3.jpg?sign=1738846819-F1t2QRcs3zCb8AZRkTVnLxbEfk4mKt8i-0-2c9b8385d07a1fbe68c4b44df4caa752)
命令2.7 Debian安装第三方依赖库
CentOS与Debian略有不同,如命令2.8所示。
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-P29_4.jpg?sign=1738846819-FtKjt1ytlG1gCJiVCCVrx5OdccEt1J00-0-d479d74dba3088cc4ede9dfd98130ece)
命令2.8 CentOS安装第三方类库
在完成以上步骤之后,安装编译.NET Core所需的LLVM环境。对于Debian/Ubuntu来说,只要把位于llvm.org/apt/的源位置加入到apt配置文件中,并安装llvm的apt公钥即可,如命令2.9所示。
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-P30_2.jpg?sign=1738846819-FD12wrJ6oyFzjpfUxfc87hGqwHaz02aB-0-072ca9ddcb65790a29950a04285be750)
命令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所示。
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-P30_3.jpg?sign=1738846819-akBMSHbZBZ7e4PZ8gW7fsto1qxTRXqUM-0-fa72e704a3211e746ebf923e624ea326)
命令2.10 CentOS编译安装CMake
编译LLVM对编译机器的内存有一定的要求,请保证计算机内存在6GB以上,否则会在构建过程中,尤其是链接的时候,出现很多莫名其妙的错误。LLVM体积庞大,构建后,源代码文件夹有几十吉字节,因此最好空闲的磁盘空间有100GB以上。
LLVM 3.9版本编译的步骤如下:
(1)下载LLVM 3.9版本的源代码,解压缩并改名放入llvm文件夹。然后编译和安装LLVM,如命令2.11所示。
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-P31_2.jpg?sign=1738846819-0kOujBOnXsOgaB7dx4ZcNtD7GFQmAC0m-0-76af68af5331a08a808d1816e31e149b)
命令2.11 CentOS下载LLVM安装构建LLVM的依赖库
(2)下载Clang,并放入llvm/tools文件夹内,再解压缩,如命令2.12所示。
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-P31_3.jpg?sign=1738846819-Yv7YDIXzskbCxKG6cJ0Z0UM1XZVLAUkD-0-9494099cebcb341fce7e0123f4cb04a3)
命令2.12 CentOS下载解压缩Clang
(3)下载LLDB,并放入llvm/tools文件夹内,再解压缩,如命令2.13所示。
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-P31_4.jpg?sign=1738846819-hcF5SbcGRfMy0v4xwe3dHV02LBl1WJBM-0-b7cfb2b281fc72e9c3d51fdf2f1098d5)
命令2.13 CentOS下载解压缩LLDB
(4)编译、安装LLVM、Clang和LLDB,如命令2.14所示。
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-P32_1.jpg?sign=1738846819-hBgSTjWlZ5FRcEe8zHoadc0a2kHq2wic-0-58def7988c866196913a19f73f24b935)
命令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所示。
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-P32_2.jpg?sign=1738846819-VQyk4IYUWoh6nMUWMJiZqSMTQFJ6sb9h-0-c36dff03916992a8bab5b289cbc087eb)
命令2.15 CentOS下安装Python 2.7到LLVM目录
(6)在编译和安装结束之后,通过下面的命令确认Clang和LLDB的版本,如命令2.16所示。
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-P32_3.jpg?sign=1738846819-4tCvWWULB3Opwel7JxNLWPGoa19Q5i7c-0-3104cb7db16b52372ecd11c4ae272648)
命令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所示。
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-P33_1.jpg?sign=1738846819-LHvOfiZ4DkrQTI09vtEWuZNlFOPdLU3V-0-aef263457b847e1c9b9ec1cd5c8cf818)
命令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所示。
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-P33_2.jpg?sign=1738846819-lWzKKXoY7rfU44TuoR2xhMieylxlzRE8-0-4d307ae14e1dbbb2a46a7a68c8439739)
图2.1 coreclr项目在Debian 8上的编译输出
CoreFx项目编译的结果保存在dotnet/corefx/bin/runtime/netcoreapp-Linux-Debug-x64目录内,如图2.2所示。这个目录中含有.NET Core的全部基础类库(BCL)程序集以及对应的PDB符号表文件。在调试时,符号表文件用来查找代码、变量地址与中间语言IL之间的对应关系。因此,一旦某个版本的.NET Core用在了生产环境,那么最好保存一份该版本的PDB符号表文件。
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-P34_1.jpg?sign=1738846819-iWJ13JNygMD4rSRCREuhir5BkSYw9Hkh-0-baee704a8d0c26c03d508340e34f1d25)
图2.2 CoreFx项目在Debian 8上的编译输出
针对不太熟悉Linux系统的用户,在这里补充一个小知识:Linux通常使用颜色来区分文件的类型,而文件的扩展名并不是那么重要。默认状态下Linux文件类型和颜色的对应关系如表2.1所示。
表2.1 Linux下文件颜色与文件类型对应表
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-T34_2.jpg?sign=1738846819-LAz7HodaTRZDxiiNmTjiPjwpQzcS5VOF-0-230d1c582dd2009bb867f7bb91065e35)
当然,这些颜色和文件类型的对应关系可以通过修改/etc/DIR_COLORS file文件进行自定义配置。因此在一些特定的Linux发行版本上,表示特定文件类型的颜色可能略有不同。