![.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=1739244033-yklnuYfUMc9n4yLl4xWv9MtxYoAKLn0G-0-2a23157624e15fe05450d62d2f6f675e)
命令2.1 Debian上安装Git客户端
在CentOS上,需要使用yum来进行安装,如命令2.2所示。
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-P27_2.jpg?sign=1739244033-3x9FEpYWhbq4J85A3Q6yUc299eOxnV1d-0-f59447be0923b70f74781d02eaa2287e)
命令2.2 CentOS上安装Git客户端
然后在磁盘上用mkdir创建一个名为dotnet的文件夹,如命令2.3所示。
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-P28_1.jpg?sign=1739244033-VM17z2I7vkfEWNJkqhdx2cDaKQ2nOuxS-0-a3bc1ec721cbcb3452bbc3b136146da7)
命令2.3 创建dotnet文件夹
最后通过git clone获取coreclr和corefx两个代码仓库的代码,如命令2.4所示。
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-P28_2.jpg?sign=1739244033-yOAhh7Akc590DwLhILUd1LQgG1EJOx3x-0-15f9099dceea78333ea41cb9cd6128c8)
命令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=1739244033-JCZ09DNNyL6PWCXAVReJzy4FlIvFt6N5-0-a49ad24a22d15b0336897ffa050eb6a2)
命令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=1739244033-e0nin0AC6AA41NIUBPShVzrhwseUS50r-0-0e456a5f9b8c94a6e4033d6af25e1f83)
命令2.6 CentOS编译安装CMake和gcc
在完成CMake的安装之后,就需要安装.NET Core编译依赖的第三方库了,如命令2.7所示。
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-P29_3.jpg?sign=1739244033-dIE7QmHEdQhW33fpCWoNUfBkzEMEtWfX-0-cf14aa6b6075d96d3feffc8f3628d99b)
命令2.7 Debian安装第三方依赖库
CentOS与Debian略有不同,如命令2.8所示。
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-P29_4.jpg?sign=1739244033-07xY9JaNvwtsWfadWoMqgwTKaIhQI4wX-0-94772d859c9bab89ed91756d9dcf9823)
命令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=1739244033-cop3M1Ck10Rek5wawPqNBLNK4iK66UPI-0-9bf7253e255ebf4fea4282a02db335f9)
命令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=1739244033-N4UaCzBtccQdAvnsUZE8mffXYOWd3kPR-0-bc9b36ee57e99b07694a222b0b172a7f)
命令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=1739244033-jeCwHfR2sVXxfdYIfWODApec9O7Zg1Sl-0-668661f6c1a2ca1c7488d4031181d935)
命令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=1739244033-8dW6iRWirvrFEU0O9Zi9Itu30qRwKQ7D-0-f414b70cb793436b174a67473d106c2b)
命令2.12 CentOS下载解压缩Clang
(3)下载LLDB,并放入llvm/tools文件夹内,再解压缩,如命令2.13所示。
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-P31_4.jpg?sign=1739244033-lRGJ1n4HcITxcOufTStRVHTLgx8XLf2W-0-f74f1017ca7fab824e2aea5f937c9d28)
命令2.13 CentOS下载解压缩LLDB
(4)编译、安装LLVM、Clang和LLDB,如命令2.14所示。
![](https://epubservercos.yuewen.com/43E55D/15253386304111506/epubprivate/OEBPS/Images/Figure-P32_1.jpg?sign=1739244033-iNGJkgs5zFp9MMBewbFtkUNRiu8OS7sn-0-f9c02fb8b93a2512730cf75a95a2a885)
命令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=1739244033-Hz7JbIfDrZk3naZ4Sdw0hnKWHC2PFGcC-0-27a4d45ae0b5e16dc19f662172e74d1c)
命令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=1739244033-sGJwdR87Db3WofPVPB6d8ADqp5WFCXmE-0-c47cc210a2367f776dae0928eee87f3f)
命令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=1739244033-oOlh2i8IpFpYbpUF5eht8TyMBL6lN8g2-0-e6dd4ccb88042b15b3275f4d00613331)
命令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=1739244033-LBFWRuZ0IrSp35363Fl8Hjqn0aSKgff1-0-4295d70a7a27fa2e04df30854183aa02)
图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=1739244033-ypgE2hr6BQZ11suEBOzLqeKEns5fESXd-0-a7eff2e8a20d2cc7ee9c9e7891ae82ef)
图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=1739244033-6ZA10KHSl0u4oXPHfhC3fZpa2Ohk3FHz-0-2add1aa458cf3275f1746414d42bd368)
当然,这些颜色和文件类型的对应关系可以通过修改/etc/DIR_COLORS file文件进行自定义配置。因此在一些特定的Linux发行版本上,表示特定文件类型的颜色可能略有不同。