Evaluate the CppDepend metrics tool on Uefi firmware - shijunjing/edk2 GitHub Wiki
Evaluate the CppDepend metrics tool: https://www.cppdepend.com/
Collect build commands and generate report
Get your 14-day free CppDepend trial Today!
https://www.cppdepend.com/protected/CppDepend2020.1.zip
Use Build Monitor to collect MSVC toolchain's build commands with multi-thread enabled by default
- Follow the doc steps: https://www.cppdepend.com/BuildMonitor to generate the "build file specification"
C:\steven\edk2>C:\steven\Metrics\CppDepend\CppDepend2020.1\BuildMonitor64.exe -o OvmfPkgIa32X64.dsc.UsbKbDxe.VS2015x86.IA32.X64.build build -p OvmfPkg\OvmfPkgIa32X64.dsc -t VS2015x86 -a IA32 -a X64 -m MdeModulePkg\Bus\Usb\UsbKbDxe\UsbKbDxe.inf
- Create new CppDepend project:
- Set the CppDepend output dir:
- Add build spec as OvmfPkgIa32X64.dsc.UsbKbDxe.VS2015x86.IA32.X64.build
- Click "Run Full Analysis and Build Report"
Build Monitor Problem on MSVC toolchain with default multi-thread
- Missing libs and files:
It looks that CppDepend collect all found files in outputdir\SourceFiles.zip. E.g. C:\steven\Metrics\CppDepend\Project\OvmfPkgIa32X64.dsc.UsbKbDxe.VS2015x86.IA32.X64\SourceFiles.zip
Below is the real libs used in the module UsbKbDxe, see it in C:\steven\edk2\Build\Ovmf3264\DEBUG_VS2015x86\X64\MdeModulePkg\Bus\Usb\UsbKbDxe\UsbKbDxe\OUTPUT\static_library_files.lst:
c:/steven/edk2/Build/Ovmf3264/DEBUG_VS2015x86/X64/MdePkg/Library/BaseLib/BaseLib/OUTPUT/BaseLib.lib
c:/steven/edk2/Build/Ovmf3264/DEBUG_VS2015x86/X64/MdePkg/Library/DxePcdLib/DxePcdLib/OUTPUT/DxePcdLib.lib
c:/steven/edk2/Build/Ovmf3264/DEBUG_VS2015x86/X64/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr/OUTPUT/BaseMemoryLibRepStr.lib
c:/steven/edk2/Build/Ovmf3264/DEBUG_VS2015x86/X64/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib/OUTPUT/BaseDebugPrintErrorLevelLib.lib
c:/steven/edk2/Build/Ovmf3264/DEBUG_VS2015x86/X64/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev/OUTPUT/BaseIoLibIntrinsicSev.lib
c:/steven/edk2/Build/Ovmf3264/DEBUG_VS2015x86/X64/MdePkg/Library/BasePrintLib/BasePrintLib/OUTPUT/BasePrintLib.lib
c:/steven/edk2/Build/Ovmf3264/DEBUG_VS2015x86/X64/OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort/OUTPUT/PlatformDebugLibIoPort.lib
c:/steven/edk2/Build/Ovmf3264/DEBUG_VS2015x86/X64/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib/OUTPUT/UefiBootServicesTableLib.lib
c:/steven/edk2/Build/Ovmf3264/DEBUG_VS2015x86/X64/MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib/OUTPUT/UefiMemoryAllocationLib.lib
c:/steven/edk2/Build/Ovmf3264/DEBUG_VS2015x86/X64/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol/OUTPUT/UefiDevicePathLibDevicePathProtocol.lib
c:/steven/edk2/Build/Ovmf3264/DEBUG_VS2015x86/X64/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib/OUTPUT/UefiRuntimeServicesTableLib.lib
c:/steven/edk2/Build/Ovmf3264/DEBUG_VS2015x86/X64/MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib/OUTPUT/UefiHiiServicesLib.lib
c:/steven/edk2/Build/Ovmf3264/DEBUG_VS2015x86/X64/MdePkg/Library/UefiLib/UefiLib/OUTPUT/UefiLib.lib
c:/steven/edk2/Build/Ovmf3264/DEBUG_VS2015x86/X64/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint/OUTPUT/UefiDriverEntryPoint.lib
c:/steven/edk2/Build/Ovmf3264/DEBUG_VS2015x86/X64/MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib/OUTPUT/DxeReportStatusCodeLib.lib
c:/steven/edk2/Build/Ovmf3264/DEBUG_VS2015x86/X64/MdePkg/Library/UefiUsbLib/UefiUsbLib/OUTPUT/UefiUsbLib.lib
c:/steven/edk2/Build/Ovmf3264/DEBUG_VS2015x86/X64/MdeModulePkg/Library/UefiHiiLib/UefiHiiLib/OUTPUT/UefiHiiLib.lib
c:/steven/edk2/Build/Ovmf3264/DEBUG_VS2015x86/X64/MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe/OUTPUT/UsbKbDxe.lib
Unzip SourceFiles.zip and show all CppDepend found lib folders:
C:\steven\Metrics\CppDepend\Project\OvmfPkgIa32X64.dsc.UsbKbDxe.VS2015x86.IA32.X64\SourceFiles>tree steven
Folder PATH listing for volume XPx64
Volume serial number is 280A-7EC6
C:\STEVEN\METRICS\CPPDEPEND\PROJECT\OVMFPKGIA32X64.DSC.USBKBDXE.VS2015X86.IA32.X64\SOURCEFILES\STEVEN
└───edk2
├───build
│ └───ovmf3264
│ └───debug_vs2015x86
│ └───x64
│ └───mdemodulepkg
│ └───bus
│ └───usb
│ └───usbkbdxe
│ └───usbkbdxe
│ └───debug
├───mdemodulepkg
│ ├───bus
│ │ └───usb
│ │ └───usbkbdxe
│ ├───include
│ │ └───library
│ └───library
│ ├───uefihiilib
│ └───uefihiiserviceslib
└───mdepkg
├───include
│ └───library
└───library
├───basedebugprinterrorlevellib
├───baseiolibintrinsic
├───baselib
│ └───x64
├───basememorylibrepstr
├───baseprintlib
├───dxepcdlib
├───uefilib
├───uefimemoryallocationlib
└───uefiusblib
After compare above library directories, we can see below 6 libraries are missing in CppDepend, total 6/18= 33% missing rate.
OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort/OUTPUT/PlatformDebugLibIoPort.lib
MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib/OUTPUT/UefiBootServicesTableLib.lib
MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol/OUTPUT/UefiDevicePathLibDevicePathProtocol.lib
MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib/OUTPUT/UefiRuntimeServicesTableLib.lib
MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint/OUTPUT/UefiDriverEntryPoint.lib
MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib/OUTPUT/DxeReportStatusCodeLib.lib
Use Build Monitor to collect MSVC toolchain's build commands with multi-thread disabled (single thread: -n 1)
- Clean build the UsbKbDxe again with -n 1 option
C:\steven\edk2>C:\steven\Metrics\CppDepend\CppDepend2020.1\BuildMonitor64.exe build -p OvmfPkg\OvmfPkgIa32X64.dsc -t VS2015x86 -a IA32 -a X64 -m MdeModulePkg\Bus\Usb\UsbKbDxe\UsbKbDxe.inf -o OvmfPkgIa32X64.dsc.UsbKbDxe.VS2015x86.IA32.X64.p1.build -n 1
- Create new CppDepend project: OvmfPkgIa32X64.dsc.UsbKbDxe.VS2015x86.IA32.X64.p1.
- Set Project Name as OvmfPkgIa32X64.dsc.UsbKbDxe.VS2015x86.IA32.X64.p1
- Set ProjectFile as C:\steven\Metrics\CppDepend\Project\OvmfPkgIa32X64.dsc.UsbKbDxe.VS2015x86.IA32.X64.p1.cdproj
- Set Output Directories as C:\steven\Metrics\CppDepend\Project\OvmfPkgIa32X64.dsc.UsbKbDxe.VS2015x86.IA32.X64.p1
- Unzip SourceFiles.zip and check all CppDepend found lib folders again:
C:\steven\Metrics\CppDepend\Project\OvmfPkgIa32X64.dsc.UsbKbDxe.VS2015x86.IA32.X64.p1\SourceFiles>tree steven
Folder PATH listing for volume XPx64
Volume serial number is 280A-7EC6
C:\STEVEN\METRICS\CPPDEPEND\PROJECT\OVMFPKGIA32X64.DSC.USBKBDXE.VS2015X86.IA32.X64.P1\SOURCEFILES\STEVEN
└───edk2
├───build
│ └───ovmf3264
│ └───debug_vs2015x86
│ └───x64
│ └───mdemodulepkg
│ └───bus
│ └───usb
│ └───usbkbdxe
│ └───usbkbdxe
│ └───debug
├───mdemodulepkg
│ ├───bus
│ │ └───usb
│ │ └───usbkbdxe
│ ├───include
│ │ └───library
│ └───library
│ ├───dxereportstatuscodelib
│ ├───uefihiilib
│ └───uefihiiserviceslib
├───mdepkg
│ ├───include
│ │ └───library
│ └───library
│ ├───basedebugprinterrorlevellib
│ ├───baseiolibintrinsic
│ ├───baselib
│ │ └───x64
│ ├───basememorylibrepstr
│ ├───baseprintlib
│ ├───dxepcdlib
│ ├───uefibootservicestablelib
│ ├───uefidevicepathlibdevicepathprotocol
│ ├───uefidriverentrypoint
│ ├───uefilib
│ ├───uefimemoryallocationlib
│ ├───uefiruntimeservicestablelib
│ └───uefiusblib
└───ovmfpkg
└───library
└───platformdebuglibioport
OK, this time all the libraries are found by CppDepend!
-
See the usbkbdxe driver all libraries dependency graph here. More details usage: Dependency Graph
-
But CppDepend looks cannot completely convert the MSVC command to clang parser command. There are +3400 Clang Parsing Errors in the final result:
Use Build Monitor to collect file build commands with CLANGPDB toolchain (single thread: -n 1)
Use the BuildMonitor64.exe to clean build the UsbKbDxe module and OvmfPkgIa32X64 platform with CLANGPDB toolchain:
C:\steven\edk2>set CLANG_HOST_BIN=n
C:\steven\edk2>set CLANG_BIN=C:\Program Files\LLVM\bin\
C:\steven\edk2>C:\steven\Metrics\CppDepend\CppDepend2020.1\BuildMonitor64.exe build -p OvmfPkg\OvmfPkgIa32X64.dsc -t CLANGPDB -a IA32 -a X64 -m MdeModulePkg\Bus\Usb\UsbKbDxe\UsbKbDxe.inf -o OvmfPkgIa32X64.dsc.UsbKbDxe.CLANGPDB.IA32.X64.p1.build -n 1
C:\steven\edk2>rmdir Build /s /q
C:\steven\edk2>C:\steven\Metrics\CppDepend\CppDepend2020.1\BuildMonitor64.exe build -p OvmfPkg\OvmfPkgIa32X64.dsc -t CLANGPDB -a IA32 -a X64 -o OvmfPkgIa32X64.dsc.CLANGPDB.IA32.X64.p1.build -n 1
- Create new CppDepend projects for the UsbKbDxe module and OvmfPkgIa32X64 platform. There are almost no Clang Parsing Error (+3400 --> only 7 in whole OVMF platform), the CLANGPDB clang build&link commands perfectly match the CppDepend, great!!
Comment Problems:
The tool report the comment percentage is 57%, which looks very high.
Dependency (reference) Query Example:
Method reference: Select methods that are using me directly:
from m in Methods where m.IsUsing ("edk2/UefiCpuPkg/CpuDxe/CpuMp.c/__Globals/GetGdtr(void*)")
select new { m, m.NbLinesOfCode }
Method reference: Select methods that are using me (directly or indirectly):
from m in Methods
let depth0 = m.DepthOfIsUsing("edk2/UefiCpuPkg/CpuDxe/CpuMp.c/__Globals/GetGdtr(void*)")
where depth0 >= 0 orderby depth0
select new { m, depth0 }
Global Variable reference: Select Types that are using me directly:
from t in Types where t.IsUsing ("edk2/UefiCpuPkg/CpuDxe/CpuMp.c/__Globals/mMpServiceHandle")
select new { t, t.NbLinesOfCode }
Global Variable reference: Select methods that is assigning me (directly or indirectly):
from m in Methods
let depth0 = m.DepthOfAssignField("edk2/UefiCpuPkg/CpuDxe/CpuMp.c/__Globals/mMpServiceHandle")
where depth0 >= 0 orderby depth0
select new { m, depth0 }
File reference: Select files that are using me directly:
from f in Files where f.IsUsing ("edk2/UefiCpuPkg/CpuDxe/CpuMp.c") select new { f, f.NbLinesOfCode }
File reference: Select methods that are using me (directly or indirectly):
from m in Methods where m.IsUsing ("edk2/UefiCpuPkg/CpuDxe/CpuMp.c")
select new { m, m.NbLinesOfCode }
See more reference query pictures here: https://github.com/shijunjing/WikiDoc/tree/master/CppDepend