From nobody Thu Apr 25 01:43:31 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+94109+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+94109+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1663830551; cv=none; d=zohomail.com; s=zohoarc; b=KcFHqPIURIg2KBiGwYgWsIVTnHVJEt4bttCD7baUhSIfg0zMTP013lZJXDqbXFdE5h2JY3P2pBpuRTq/4Oe0+tvJiY20YHrlmy8O8TAG+TpoCXxYgaHk3Sf7q5SPb1pEJFv4j4jYBBKSXnhfzgAa3SOH3x/JZoFGgmNgHShgqQg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1663830551; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=1807msc/o8Mj2PD4Kdf02jM7+eaP5ZNIeu16qoaiJ+o=; b=MDufTrvzTxiunr9QIbQaw/IbjoKA/LR6p7vvTGddRRt5I5UnGsXxW8Dqp+yV+UxTQ5t83KNvmuveP1rIybdTANw1vKM7Dj2BlGM9CekRNJCAq0TCl9bYBHALIPJdgKJTIwQ4vL4h7aese1rmwemSXxbNh0v7ueFS4bzOakB1rSA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+94109+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1663830551344147.17695686624404; Thu, 22 Sep 2022 00:09:11 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id yTvGYY1788612xstPDWJewqu; Thu, 22 Sep 2022 00:09:11 -0700 X-Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by mx.groups.io with SMTP id smtpd.web11.4494.1663830549554291597 for ; Thu, 22 Sep 2022 00:09:10 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10477"; a="364198666" X-IronPort-AV: E=Sophos;i="5.93,335,1654585200"; d="scan'208";a="364198666" X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Sep 2022 00:09:08 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.93,335,1654585200"; d="scan'208";a="621986200" X-Received: from gguo-desk.gar.corp.intel.com ([10.5.215.23]) by fmsmga007.fm.intel.com with ESMTP; 22 Sep 2022 00:09:08 -0700 From: "Guo, Gua" To: devel@edk2.groups.io Cc: Gua Guo , Michael D Kinney , Sean Brogan , Bret Barkelew , Michael Kubacki Subject: [edk2-devel] [PATCH v3 1/2] UnitTestFrameworkPkg: Add code coverage support for GCC Date: Thu, 22 Sep 2022 15:09:04 +0800 Message-Id: <3a060305c0eaf9a996043795744c4ada4f83914b.1663830230.git.gua.guo@intel.com> In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,gua.guo@intel.com X-Gm-Message-State: kt9Ja6JaPdEE7Z9l1LKDbNd5x1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1663830551; bh=xlXeEvp3ATVfh9fC6ryfasOm16dUEBHa1Z0KSIF7/sw=; h=Cc:Date:From:Reply-To:Subject:To; b=uZpbQxczOiNvoRQSG2ZSouQTlE8/56q5FUPJypYNwCUPKd0fGHswEGsZyJtHpXidUOC oNAApG1ZyupVU2VxgOl6keoED4HPkGr5zB/Zj0nn+tNPoHY2Ddb0Jd1gmHmWI+pwzV0Rp 0XjM0Pp/KeBMBthK4qig+zw/paToC/GaE04= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1663830553197100002 Content-Type: text/plain; charset="utf-8" From: Gua Guo In order to collect code coverage after running executable file, generate *.gcda and *.gcno file that require by lcov tool to generate code coverage report. Cc: Michael D Kinney Cc: Sean Brogan Cc: Bret Barkelew Cc: Michael Kubacki Signed-off-by: Gua Guo --- UnitTestFrameworkPkg/ReadMe.md | 42 +++++++++++++++++-- .../UnitTestFrameworkPkg.ci.yaml | 2 + .../UnitTestFrameworkPkgHost.dsc.inc | 3 +- 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/UnitTestFrameworkPkg/ReadMe.md b/UnitTestFrameworkPkg/ReadMe.md index e696412cb3..3c69cfdd97 100644 --- a/UnitTestFrameworkPkg/ReadMe.md +++ b/UnitTestFrameworkPkg/ReadMe.md @@ -60,7 +60,7 @@ you should be good to go. =20 See this example in 'SampleUnitTestUefiShell.inf'... =20 -``` +```inf [Packages] MdePkg/MdePkg.dec =20 @@ -75,7 +75,7 @@ See this example in 'SampleUnitTestUefiShell.inf'... Also, if you want you test to automatically be picked up by the Test Runne= r plugin, you will need to make sure that the module `BASE_NAME` contains the word `Test`... =20 -``` +```inf [Defines] BASE_NAME =3D SampleUnitTestUefiShell ``` @@ -361,7 +361,7 @@ RUNNING TEST SUITE: Int Safe Conversions Test Suite ``` =20 You can also, if you are so inclined, read the output from the exact insta= nce of the test that was run during -`stuart_ci_build`. The ouput file can be found on a path that looks like: +`stuart_ci_build`. The output file can be found on a path that looks like: =20 `Build//HostTest//...result.= xml` =20 @@ -399,6 +399,42 @@ CMOCKA_XML_FILE=3D =20 This mode is used by the test running plugin to aggregate the results for = CI test status reporting in the web view. =20 +### Code Coverage + +Host based Unit Tests will automatically i enable coverage data. +This is primarily leveraged for pipeline builds, but this can be leveraged= locally using the +lcov linux tool, and parsed using the lcov_cobertura python tool. pycobert= ura is used to +covert this coverage data to a human readable HTML file. These tools must = be installed +to parse code coverage. + +- Windows Prerequisite + ```bash + Download and install https://github.com/OpenCppCoverage/OpenCppCoverage/= tags + pip install pycobertura + ``` + +- Linux Prerequisite + ```bash + sudo apt-get install -y lcov + pip install lcov_cobertura + pip install pycobertura + ``` + +During CI builds, use the ```CODE_COVERAGE=3DTRUE``` flag to generate the= code coverage XML files, +and additionally use the ```CC_HTML=3DTRUE``` flag to generate the HTML fi= le. This will be generated +in Build/coverage.html. + +There is currently no official guidance or support for code coverage when = compiling +in Visual Studio at this time. +During CI builds, use the ```CODE_COVERAGE=3DTRUE``` flag to generate the= code coverage XML files, +and additionally use the ```CC_HTML=3DTRUE``` flag to generate the HTML fi= le. This will be generated +in Build/coverage.html. + +Example +```bash + stuart_ci_build -c .pytool/CISettings.py -t NOOPT TOOL_CHAIN_TAG=3DVS20= 19 -p MdeModulePkg CC_HTML=3DTRUE CODE_COVERAGE=3DTRUE + ``` + ### Important Note =20 This works on both Windows and Linux, but is currently limited to x64 arch= itectures. Working on getting others, but we diff --git a/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml b/UnitTestFr= ameworkPkg/UnitTestFrameworkPkg.ci.yaml index 77d51e1348..f68882e1cf 100644 --- a/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml +++ b/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml @@ -90,6 +90,8 @@ "pytools", "NOFAILURE", "cmockery", + "cobertura", + "pycobertura", "DHAVE", # build flag for cmocka in the INF "corthon", # Contact GitHub account in Readme "mdkinney", # Contact GitHub account in Readme diff --git a/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc b/UnitTe= stFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc index 4dd8d4ac67..ca46b8513a 100644 --- a/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc +++ b/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc @@ -25,7 +25,8 @@ GCC:*_*_*_CC_FLAGS =3D -D UNIT_TESTING_DEBUG=3D1 XCODE:*_*_*_CC_FLAGS =3D -D UNIT_TESTING_DEBUG=3D1 !endif - + GCC:*_GCC5_*_CC_FLAGS =3D --coverage + GCC:*_GCC5_*_DLINK_FLAGS =3D --coverage [BuildOptions.common.EDKII.HOST_APPLICATION] # # MSFT --=20 2.31.1.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#94109): https://edk2.groups.io/g/devel/message/94109 Mute This Topic: https://groups.io/mt/93843729/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu Apr 25 01:43:31 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+94110+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+94110+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1663830552; cv=none; d=zohomail.com; s=zohoarc; b=YoTPOCDd+AEQ1m9kU+cYqzHo9qJ/dVSS1W1MgWneTvvfIa5UEsCUFk2YvzDOYKsE/IJ2pTAodtT6pOsXFnmBSRUhWCz3ace8x23/sDCbgGxCMpri9puEBqbU50HxT3YeRdTj41tXKUPvitVIOMVoXoKMZfh8p8PHJTryvBFzxmU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1663830552; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=p2whg2F/qdZ+2nPIP9LcXOdJjv7egDLnKlhrQfwzbVc=; b=V86260uFf+eKpfNFwLtjMXutZXkNeJWeMqmCr+jMQhCKc6eChRKWU+OLoxZKXr2nQ0wlNWm22MUSh6X8gOIxh22bNZV+go73lTHPXlFSZf1UTUtwdNR5ohaABgN7lY6v1qFM+ZlsjEkoIFDrVKFQPhoJk0Z1RDGrMYBdJHb6ycY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+94110+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1663830552968822.546128196396; Thu, 22 Sep 2022 00:09:12 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id kHKVYY1788612xu2rwJfHZba; Thu, 22 Sep 2022 00:09:12 -0700 X-Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by mx.groups.io with SMTP id smtpd.web11.4494.1663830549554291597 for ; Thu, 22 Sep 2022 00:09:12 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10477"; a="364198680" X-IronPort-AV: E=Sophos;i="5.93,335,1654585200"; d="scan'208";a="364198680" X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Sep 2022 00:09:10 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.93,335,1654585200"; d="scan'208";a="621986204" X-Received: from gguo-desk.gar.corp.intel.com ([10.5.215.23]) by fmsmga007.fm.intel.com with ESMTP; 22 Sep 2022 00:09:10 -0700 From: "Guo, Gua" To: devel@edk2.groups.io Cc: Gua Guo , Bob Feng , Liming Gao , Bret Barkelew , Michael D Kinney , Sean Brogan Subject: [edk2-devel] [PATCH v3 2/2] BaseTools/Plugin: Add coverage support for Unit Test Date: Thu, 22 Sep 2022 15:09:05 +0800 Message-Id: <9bd869e8a7384e1e60680d18a3e2713cd2891f2f.1663830230.git.gua.guo@intel.com> In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,gua.guo@intel.com X-Gm-Message-State: IWP3p3bt05f20qWaxitb8ygSx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1663830552; bh=1l87ABUBF0EbP1o5nHaKTlfxhBNX33FiAFbITDir2aY=; h=Cc:Date:From:Reply-To:Subject:To; b=UWy+vTLlYgJgs3o8KYmWKa02yLmBdcixCq99vA9gy8w3q7CtcWZTwv1Ug3q5MVEAu8U D12dYIhMTWb7O0TBXowlHTyC4Wkjb+SzkJAlDSjFR87fbxYNWA8qnUWEWZv9dSCZoVEnv jRj5ihXfj7bvM71/OBq0h51tj8N5tvg0yQg= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1663830555221100010 Content-Type: text/plain; charset="utf-8" From: Gua Guo For GCC, use lcov to generate Unit Test code coverage report For VS2019, use OpenCppCoverage to generate code coverage report Cc: Bob Feng Cc: Liming Gao Cc: Bret Barkelew Cc: Michael D Kinney Cc: Sean Brogan Signed-off-by: Gua Guo --- .../HostBasedUnitTestRunner.py | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/BaseTools/Plugin/HostBasedUnitTestRunner/HostBasedUnitTestRunn= er.py b/BaseTools/Plugin/HostBasedUnitTestRunner/HostBasedUnitTestRunner.py index c1eeaf2625..0b77576f3c 100644 --- a/BaseTools/Plugin/HostBasedUnitTestRunner/HostBasedUnitTestRunner.py +++ b/BaseTools/Plugin/HostBasedUnitTestRunner/HostBasedUnitTestRunner.py @@ -112,4 +112,128 @@ class HostBasedUnitTestRunner(IUefiBuildPlugin): " %s - %s" % (case.attrib['na= me'], result.text)) failure_count +=3D 1 =20 + if thebuilder.env.GetValue("CODE_COVERAGE") =3D=3D "TRUE": + if thebuilder.env.GetValue("TOOL_CHAIN_TAG") =3D=3D "GCC5": + self.gen_code_coverage_gcc(thebuilder) + elif thebuilder.env.GetValue("TOOL_CHAIN_TAG") =3D=3D "VS2= 019": + self.gen_code_coverage_msvc(thebuilder) + else: + logging.info("Skipping code coverage. Only supported o= n GCC.") + return failure_count + + def gen_code_coverage_gcc(self, thebuilder): + logging.info("Generating UnitTest code coverage") + + buildOutputBase =3D thebuilder.env.GetValue("BUILD_OUTPUT_BASE") + workspace =3D thebuilder.env.GetValue("WORKSPACE") + + # Generate base code coverage for all source files + ret =3D RunCmd("lcov", f"--no-external --capture --initial --direc= tory {buildOutputBase} --output-file {buildOutputBase}/cov-base.info --rc l= cov_branch_coverage=3D1") + if(ret !=3D 0): + logging.error("UnitTest Coverage: Failed to build initial cove= rage data.") + return 1 + + # Coverage data for tested files only + ret =3D RunCmd("lcov", f"--capture --directory {buildOutputBase}/ = --output-file {buildOutputBase}/coverage-test.info --rc lcov_branch_coverag= e=3D1") + if(ret !=3D 0): + logging.error("UnitTest Coverage: Failed to build coverage dat= a for tested files.") + return 1 + + # Aggregate all coverage data + ret =3D RunCmd("lcov", f"--add-tracefile {buildOutputBase}/cov-bas= e.info --add-tracefile {buildOutputBase}/coverage-test.info --output-file {= buildOutputBase}/total-coverage.info --rc lcov_branch_coverage=3D1") + if(ret !=3D 0): + logging.error("UnitTest Coverage: Failed to aggregate coverage= data.") + return 1 + + # Generate coverage XML + ret =3D RunCmd("lcov_cobertura",f"{buildOutputBase}/total-coverage= .info -o {buildOutputBase}/compare.xml") + if(ret !=3D 0): + logging.error("UnitTest Coverage: Failed to generate coverage = XML.") + return 1 + + # Filter out auto-generated and test code + ret =3D RunCmd("lcov_cobertura",f"{buildOutputBase}/total-coverage= .info --excludes ^.*UnitTest\|^.*MU\|^.*Mock\|^.*DEBUG -o {buildOutputBase}= /coverage.xml") + if(ret !=3D 0): + logging.error("UnitTest Coverage: Failed generate filtered cov= erage XML.") + return 1 + + # Generate all coverage file + testCoverageList =3D glob.glob (f"{workspace}/Build/**/total-cover= age.info", recursive=3DTrue) + + coverageFile =3D "" + for testCoverage in testCoverageList: + coverageFile +=3D " --add-tracefile " + testCoverage + ret =3D RunCmd("lcov", f"{coverageFile} --output-file {workspace}/= Build/all-coverage.info --rc lcov_branch_coverage=3D1") + if(ret !=3D 0): + logging.error("UnitTest Coverage: Failed generate all coverage= file.") + return 1 + + # Generate and HTML file if requested.by each package + if thebuilder.env.GetValue("CC_HTML") =3D=3D "TRUE": + ret =3D RunCmd("pycobertura", f"show --format html --output {b= uildOutputBase}/coverage.html {buildOutputBase}/coverage.xml --source {work= space}") + if(ret !=3D 0): + logging.error("UnitTest Coverage: Failed to generate HTML = in single package..") + + # Generate and HTML file if requested.for all package + if os.path.isfile(f"{workspace}/Build/coverage.xml"): + os.remove(f"{workspace}/Build/coverage.xml") + ret =3D RunCmd("lcov_cobertura",f"{workspace}/Build/all-coverage.i= nfo --excludes ^.*UnitTest\|^.*MU\|^.*Mock\|^.*DEBUG -o {workspace}/Build/c= overage.xml") + + if thebuilder.env.GetValue("CC_HTML") =3D=3D "TRUE": + if os.path.isfile(f"{workspace}/Build/coverage.html"): + os.remove(f"{workspace}/Build/coverage.html") + ret =3D RunCmd("pycobertura", f"show --format html --output {w= orkspace}/Build/coverage.html {workspace}/Build/coverage.xml --source {work= space}") + if(ret !=3D 0): + logging.error("UnitTest Coverage: Failed to generate HTML.= ") + + return 0 + + + def gen_code_coverage_msvc(self, thebuilder): + logging.info("Generating UnitTest code coverage") + + + buildOutputBase =3D thebuilder.env.GetValue("BUILD_OUTPUT_BASE") + testList =3D glob.glob(os.path.join(buildOutputBase, "**","*Test*.= exe"), recursive=3DTrue) + workspace =3D thebuilder.env.GetValue("WORKSPACE") + + # Generate coverage file + coverageFile =3D "" + for testFile in testList: + ret =3D RunCmd("OpenCppCoverage", f"--source {workspace} --exp= ort_type binary:{testFile}.cov -- {testFile}") + coverageFile +=3D " --input_coverage=3D" + testFile + ".cov" + if(ret !=3D 0): + logging.error("UnitTest Coverage: Failed to collect covera= ge data.") + return 1 + + # Generate and HTML file if requested.by each package + if thebuilder.env.GetValue("CC_HTML") =3D=3D "TRUE": + ret =3D RunCmd("OpenCppCoverage", f"--export_type cobertura:{b= uildOutputBase}/coverage.xml --working_dir=3D{workspace}/Build {coverageFil= e}") + if(ret !=3D 0): + logging.error("UnitTest Coverage: Failed to generate cober= tura format xml in single package.") + return 1 + + ret =3D RunCmd("pycobertura", f"show --format html --output {b= uildOutputBase}/cverage.html {buildOutputBase}/coverage.xml --source {works= pace}") + if(ret !=3D 0): + logging.error("UnitTest Coverage: Failed to generate HTML = in single package.") + return 1 + + # Generate total report HTML file for all package + testCoverageList =3D glob.glob(os.path.join(workspace, "Build", "*= *","*Test*.exe.cov"), recursive=3DTrue) + coverageFile =3D "" + for testCoverage in testCoverageList: + coverageFile +=3D " --input_coverage=3D" + testCoverage + + if thebuilder.env.GetValue("CC_HTML") =3D=3D "TRUE": + ret =3D RunCmd("OpenCppCoverage", f"--export_type cobertura:{w= orkspace}/Build/coverage.xml --working_dir=3D{workspace}/Build {coverageFil= e}") + if(ret !=3D 0): + logging.error("UnitTest Coverage: Failed to generate cober= tura format xml.") + return 1 + + ret =3D RunCmd("pycobertura", f"show --format html --output {w= orkspace}/Build/coverage.html {workspace}/Build/coverage.xml --source {work= space}") + if(ret !=3D 0): + logging.error("UnitTest Coverage: Failed to generate HTML.= ") + return 1 + + return 0 --=20 2.31.1.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#94110): https://edk2.groups.io/g/devel/message/94110 Mute This Topic: https://groups.io/mt/93843730/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-