From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM12-BN8-obe.outbound.protection.outlook.com (NAM12-BN8-obe.outbound.protection.outlook.com [40.92.21.18]) by mx.groups.io with SMTP id smtpd.web08.5823.1638924372394031562 for ; Tue, 07 Dec 2021 16:46:14 -0800 Authentication-Results: mx.groups.io; dkim=fail reason="body hash did not verify" header.i=@outlook.com header.s=selector1 header.b=pp7McNcC; spf=pass (domain: outlook.com, ip: 40.92.21.18, mailfrom: michael.kubacki@outlook.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=UHv+MEpSq50OUNVrINUS2edr6zC5vzv6tLUWht//Fb5QkJtKD4vB3GnspMy94f0fycHK0hS/BcxzhXHw/1olAnMbGWf0igqkhkXyZ+eqKOHI3XmsFZm5wN1L0SmsjbyeBLGSKEn4GhfcYoDAZWxGVKBuRbKGwKncj22duBlSpQeCpgj2+FcTSJZdOaB2EeX0/BRJG66eKYikBdirbXtVDYmP7lpumZjMProJffm4SE5tax8v1jSnAGzBuXT4VTgJh4OWkjFXW16UIPaX8//VUPShyPbriMBUj05pwsMTaDI6sdWMVVsDKxC0VhhrtYNV64dsL4OERM5vERvLPQmLjw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=b7G0rasF2/qkHNfr1L86V4YFk8lF32MGTlZHqkenBgk=; b=kGuJq2ohH2GE+BtdEPtO2Uhl1X23nIuEfqk2lok7JX6ffGC8s7Q0jyTFYHFv77TnG4lx6nQlctkNpjLXVU1+yoD60l1zdRBhqYHHD5vv7PDK6S/YvTrkfUULLd9yQKDLD9tLf4q+Lz3O9/aUa9FCIPr8I+g4Xd3czKjhIqQz6l2o372VqtewrGHDjG+4XdOOApyorWJHafs1A2Be/a2tTnpMl/7KC2shD0/PKJH6D89sC8sjG8prZkEuu+JZinVTyo5hrfZdbLTJ2hHlYlrGZ9PA8/yYwFiLE/Mwmv6ZnipLmxwiXNSiOUzJIfdOB2ezPB4/JqXjHyxUeHXqcD0XyQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=outlook.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=b7G0rasF2/qkHNfr1L86V4YFk8lF32MGTlZHqkenBgk=; b=pp7McNcC/UUtYlWEosOEtyz6qD5LEbZ7z2e9ip0UcjFI4tBsHls1aNhCuw0xiuxR6WYsPLC5X2xuO4qOk36hSYR6g5UDC7EXZdlU4jS8IP4C+Q5mSvodMpy7bg/BR7Mz4fdEQ2zOhYJIeIkcbQtAEYHn0mZmngCQWxZcq4aTc5JqJohEEpczsTVIaKav+w8ePZqPYsFXlPB7VAxsS7D1rmqEycVmAlXRXul9mJmEN3j9sJ0cmMsF0d+chPuiCf5LitOKnyqiwVY+OZ1ulRX2xkznJcDwxchO6bUY6G0o1DvwwBaooUQ62dEPEKCIHrJ1+26NRXFw2mj83i++dwD9gQ== Received: from MWHPR07MB3440.namprd07.prod.outlook.com (2603:10b6:301:69::28) by MW2PR07MB3930.namprd07.prod.outlook.com (2603:10b6:907:2::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4755.20; Wed, 8 Dec 2021 00:46:10 +0000 Received: from MWHPR07MB3440.namprd07.prod.outlook.com ([fe80::75d8:b961:c6c3:e97e]) by MWHPR07MB3440.namprd07.prod.outlook.com ([fe80::75d8:b961:c6c3:e97e%6]) with mapi id 15.20.4755.022; Wed, 8 Dec 2021 00:46:10 +0000 From: "Michael Kubacki" To: devel@edk2.groups.io CC: Andrew Fish , Leif Lindholm , Michael D Kinney , Liming Gao Subject: [edk2-wiki][PATCH v1 1/1] Add Uncrustify formatting overview Date: Tue, 7 Dec 2021 19:45:22 -0500 Message-ID: X-Mailer: git-send-email 2.28.0.windows.1 X-TMN: [/qeBRsaCVzJwPFe/ieg8rQh+JjET4P02h00dOb/Yvf4Z7NGWatsxhSonw87AwYcH] X-ClientProxiedBy: BN9PR03CA0125.namprd03.prod.outlook.com (2603:10b6:408:fe::10) To MWHPR07MB3440.namprd07.prod.outlook.com (2603:10b6:301:69::28) Return-Path: michael.kubacki@outlook.com X-Microsoft-Original-Message-ID: <20211208004522.2864-1-michael.kubacki@outlook.com> MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from localhost.localdomain (2601:703:0:bb0:f152:2f78:df20:9a57) by BN9PR03CA0125.namprd03.prod.outlook.com (2603:10b6:408:fe::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4755.21 via Frontend Transport; Wed, 8 Dec 2021 00:46:08 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: a314062f-e93f-470b-b657-08d9b9e42029 X-MS-TrafficTypeDiagnostic: MW2PR07MB3930:EE_ X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: NRBsohH+aq4dPjdOscQzRM1EwFrB3/h1z6zb1RZF+qkewrKQsU6AMR6ZIxBXLedhZgY/vEVD4eJavYJN0pK4gtroeb5ZY7EDzd46A+vlWKgkJlwwg8op6Knkp2PwDFksNEGBPwp612uQw0KxCsY+U2GWbAsX3FH+8e1mGoUN3JT9p+oAaocZ3he0zrfOHzOzXRWC54H1Lus8a28fZg8ZU2zzBitwqErZV61njZLySA4gBWgcRMgsd6iJ3D87Gu/3Kog7D2x0LOD4CoRfUiK39m7oin+1Wkgz0QWE3iMHXV+N/akbfVpcqH4ZoB36gNpZdzx6oAVnlU5nyxnpjabSCgs3C/dBAWdquHvexSCEeKdEu3wa0XraqODpK2VnvTaxO2oGwIef9c4XCCoDNaYQMN49tCYYuXpYHXBJjuHWdxNaeKCzqoIMZKG/K4E2dYLIqCz73T0Elri9VymQckry+RufINgBv+kQpDSKi0MiMbZKFkHmZDG+tZV5FJV4VD7E+qNY/CfXuJbR7OE7ajOZXuwyix3LWztI5QXnUkpnro3CqgoupFpG5H6uMtMYKKO/u7bMNvl5VGDWSzUeM0ILUoCkyUBm5RwdXi81U74iMRjRve0WGzeNpaO3Kc8AaoGI5rbIErmi0bOzrjJct/MVR8LPKHe8GEpW8SKZ3NmuQ7w= X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?8dzPAjHaYx4f9CZ4pv36WlpQPXQ0W8R+/JlRjWH4THlCCZn/PmRULsgJ3Rl+?= =?us-ascii?Q?QwWdTjCR0+9nMYflW8eTgks9j2s7fYw56vdD7lURb4qfY3XCVzO/ChgjE5Hu?= =?us-ascii?Q?J6Uh37nGKANa4wBB5gLv+YmJixXpYm3WE3Gd4l51lKljfCOEtp7p/aBvm1SG?= =?us-ascii?Q?Qqk53FzeQPLNuKKDXYenElHoOLsXTTETYhKNp0dc2RK2X+0CtySTRYFtFOFu?= =?us-ascii?Q?P+fKVG/Jo0MlIRDOptc0UoGhUNQQzji6gxTmXkNSN9upQ78uo4B2lC0Rv76E?= =?us-ascii?Q?iEXqNI22TkQfe8G7YkxLprp8COiLDX5Ew2s8veoScS0II8WYTUB1YnUNkDz1?= =?us-ascii?Q?FYFbAXBc9TAnxakiK+fQx2pEdnpbba4xet6FT4Whr0CPO1aTqT7WckwA7nyd?= =?us-ascii?Q?wcJuhM0QgXgX1zgIRtGcgUhSqKK6iHZ/I0c35EF0QOdGi4mnjVw+gNQxD4Gw?= =?us-ascii?Q?Y9v0PeYrqIBhUeppM3hDu3nsAR7sI7w+fMq3er4nm6CIpwUMZoiPBSnj8ZkH?= =?us-ascii?Q?AhMLpOz0YpHy5EjEGOeot0+gM660WqKrAomxyR8JhBCMhiuQ1xV1bJDj+CEJ?= =?us-ascii?Q?ND5QVv/u5VQop6b9xatEHr9p900V8cy/WblUVSBAJxPh1iJ6tBtwrU/ctUit?= =?us-ascii?Q?fvhs2NOc80LNX01ji5a/uEW67Vxq0NEeqR3jvXQzjXn26B6L48/VBB+E7Nmn?= =?us-ascii?Q?shdNALbtpGDgsYH040WWDT3h3xQD+KZU5C/pN/BNoZJT2lkPYM+ThqsIDm6d?= =?us-ascii?Q?y3a3QhzlnRlTtJn0bZXrOKta3PzVndu8Y6OIyzOkyiSyzQ7adJXCI5RZ2heo?= =?us-ascii?Q?lmzXz7M6Hllk/+hIE6iuPqGuzrxcltlJc3xs8AxA6264EqEpz8Z9PxC9GBTk?= =?us-ascii?Q?DTSp2KJn3mud0n4oaEDIt2cxxKfbJJQ/8YKQNewm5k9gPUEmluMHrlqonbWB?= =?us-ascii?Q?lxmpi3lyVvkQPZkbSxoUPD0DdBiTtKp1Tfu5AWLAuBfOxpFtEA+u7UOnWoON?= =?us-ascii?Q?+ege101ALK8UwQkhgvCXR6GQ3g=3D=3D?= X-OriginatorOrg: outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: a314062f-e93f-470b-b657-08d9b9e42029 X-MS-Exchange-CrossTenant-AuthSource: MWHPR07MB3440.namprd07.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 08 Dec 2021 00:46:10.1203 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: MW2PR07MB3930 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain From: Michael Kubacki This wiki page describes how Uncrustify is used in EDK II and how to install and use Uncrustify during the EDK II code development process. Cc: Andrew Fish Cc: Leif Lindholm Cc: Michael D Kinney Cc: Liming Gao Signed-off-by: Michael Kubacki --- EDK-II-Code-Formatting.md | 247 ++++++++++++++++++++ 1 file changed, 247 insertions(+) diff --git a/EDK-II-Code-Formatting.md b/EDK-II-Code-Formatting.md new file mode 100644 index 000000000000..e671663e5dcd --- /dev/null +++ b/EDK-II-Code-Formatting.md @@ -0,0 +1,247 @@ +# EDK II Code Formatting + +To better achieve the goals of the [EDK II C Coding Standards Specificatio= n](https://edk2-docs.gitbook.io/edk-ii-c-coding-standards-specification/), +EDK II code formatting is automated using a source code beautifier called = Uncrustify. Uncrustify is compatible with +C/C++ in addition to other languages. In EDK II, it is used to format C la= nguage source code. + +## Uncrustify in the edk2 Repository + +The Uncrustify collateral in the edk2 repository contains all of the resou= rces needed to get the Uncrustify application +and run it with the same settings as other developers. + +> Uncrustify is automatically run against code submitted in edk2 as a cont= inuous integration (CI) plugin called +"UncrustifyCheck". The plugin is available in the following directory: +[.pytool/Plugin/UncrustifyCheck](https://github.com/tianocore/edk2/tree/ma= ster/.pytool/Plugin/UncrustifyCheck) + +The UncrustifyCheck plugin in edk2 contains the following files used to ch= eck code for compliance to the coding +standard: + +* **default_file_header.txt** - A text file containing a template that is = placed at the top of files missing a file + header. +* **default_function_header.txt** - A text file containing a template that= is placed above functions that are missing + a function header. +* **Readme.md** - A file that contains details about how the plugin works = and how to use it. +* **uncrustify_ext_dep.yml** - An "external dependency" file that is used = to get the current version of the Uncrustify + application used by the plugin. This file contains the NuGet feed URL an= d the version currently used. +* **uncrustify_plug_in.yaml** - A file that contains information to descri= be the plugin to the build environment. +* **uncrustify.cfg** - A file used by the Uncrustify application to contro= l how it formats code. If you want to tweak + particular formatting details, this is the place to start. +* **UncrustifyCheck.py** - The actual Python file that is the CI plugin. L= ike all CI plugins, this plugin can be run + in local CI and server CI. + +## EDK II Uncrustify Fork + +Due to nuances in the way EDK II formats code, some changes were made to t= he upstream Uncrustify application. These +were changes that could not be made purely through the Uncrustify configur= ation file. For more details about the fork, +please visit that project overview in the link below. + +* Uncrustify upstream repository: https://github.com/uncrustify/uncrustify +* Uncrustify EDK II fork repository (in Project Mu): https://dev.azure.com= /projectmu/Uncrustify + +## Developer Workflow + +Developers must install Uncrustify and run the application against their c= ode before sending patch review emails or +submitting pull requests. Pull requests run against EDK II CI which includ= es the UncrustifyCheck CI plugin. + +Fortunately, Uncrustify can be installed quickly, you can format your code= quickly locally, and you can verify the +code against the UncrustifyCheck CI plugin before sending it to others. + +The recommended flow is: + +1. Clone the edk2 source code repository +2. Use the `stuart*` commands to pull the Uncrustify application into the = edk2 workspace +3. Set up the ability to run Uncrustify locally (for example, using the Vi= sual Studio Code Uncrustify plugin) +4. Make and test code changes +5. Run EDK II CI locally to verify UncrustifyCheck passes +6. Send the code patch to the EDK II mailing list + +## Installing Uncrustify + +Uncrustify is a portable executable that is built in the [EDK II Uncrustif= y fork repository](https://dev.azure.com/projectmu/Uncrustify) +and ultimately published into a NuGet feed in that fork project. + +### Recommended Installation: In edk2 repository + +It is strongly recommended to follow this flow. It sets up the workspace t= o work with local CI and automatically gets +the current supported version of the application. + +The Uncrustify tool is installed automatically when the Pytools environmen= t is used and the `stuart*` commands are run +to complete environment setup. Review the edk2 [.pytool/Readme.md](https:/= /github.com/tianocore/edk2/tree/master/.pytool#running-ci-locally) +file for details on `stuart` and this overall flow. + +After running the `stuart_update` command, the Uncrustify application cont= ent should be brought down into +`.pytool\Plugin\UncrustifyCheck\mu-uncrustify-release_extdep` in your edk2= workspace. The contents of this directory +now represent the contents of the NuGet package and it should contain a Li= nux and Windows executable of the +application. + +### Manual Installation: Download from the fork project + +The release pipeline in the EDK II Uncrustify fork project contains the bu= ild information for each release. Each build +in this pipeline represents a release. By going to a specific build, the d= etails mapping the build to source code +(such as the branch and commit) are present. + +The build content is published as a NuGet package to a NuGet feed. This is= the same feed, the recommended installation +instructions automatically pull from. The NuGet feed is available in the [= "Artifacts"](https://dev.azure.com/projectmu/Uncrustify/_packaging?_a=3Dfee= d&feed=3Dmu_uncrustify) +section of the fork project. If you hover/click on a specific package entr= y (e.g. "mu-uncrustify-release"), a set of +three ellipsis will appear. Click the ellipsis and a context menu will app= ear. The NuGet package can be downloaded +by clicking "Download \". + +Once downloaded, the `.nupkg` file can be treated as a zip file. If the fi= le is opened as a zip file, the executable +can be found in the `mu-uncrustify-` directory. + +## How to Run Uncrustify + +Once Uncrustify is installed, you can run the application in a number of w= ays. In all cases, you should be using the +Uncrustify application built from the [Uncrustify EDK II fork](https://dev= .azure.com/projectmu/Uncrustify) and the +[Uncrustify configuration file](https://github.com/tianocore/edk2/blob/mas= ter/.pytool/Plugin/UncrustifyCheck/uncrustify.cfg) +currently checked into edk2. + +### Recommended Usage: Visual Studio (VS) Code Plugin + +The Visual Studio Code plugin provides a way to seamlessly run Uncrustify = against code at anytime in the editor and +the configuration details are set once in the editor configuration file. + +1. Install the Uncrustify VS Code extension: + > Name: Uncrustify + Id: zachflower.uncrustify + Description: Code format using uncrustify + Publisher: Zachary Flower + VS Marketplace Link: + +2. Configure the Uncrustify plugin for your local setup by adding the foll= owing to your VS Code settings.json file: + (Windows example) + + ```json + "uncrustify.configPath.windows": "path_to_your_config_file", + "uncrustify.executablePath.windows": "path_to_your_uncrustify_executabl= e" + ``` + + > Windows Example: + > + >```json + >"uncrustify.configPath.windows": "D:/src/edk2/.pytool/Plugin/Uncrustif= yCheck/uncrustify.cfg", + >"uncrustify.executablePath.windows": "D:/src/edk2/.pytool/Plugin/Uncru= stifyCheck/mu-uncrustify-release_extdep/Windows-x86/uncrustify.exe" + >``` + +3. Open a C source code file, _`Ctrl+Shift+P` -> Format Document With... -= > Configure Default Formatter -> Uncrustify_ + +4. Then, _`Ctrl+Shift+P` -> Format Document_ any time you would like to fo= rmat your source code file with Uncrustify + +### Manual Usage: Run in a Terminal + +These instructions are written for Windows 10. These activities could be f= urther automated into a high-level script +but that has not been done yet. + +1. Generate a list of the files to run against. This example generates a r= ecursive list of all .c and .h files. + + * It is recommended to run this in cleanly cloned edk2 repo without sub= modules to prevent submodule files + (such as Brotli files in MdeModulePkg) from getting included in the f= ile list (if you are running against all + files). Including all files will significantly increase the amount of= time Uncrustify takes to run. + + * Sample Powershell command to recursively write all .c and .h files in= a given package to a text file: + + ```powershell + Get-ChildItem -Path .\MdePkg\* -Include *.c, *.h -Recurse -Force | %{= $_.fullname} | Out-File + -FilePath .\MdePkgFiles.txt -Encoding utf8 + ``` + + > **WARNING** Powershell will put the UTF-8 BOM at the beginning of the= output file. Uncrustify does not recognize the BOM + and it should be removed before passing the file as input to Uncrustify= . If it is not removed, Uncrustify will + not read the first file path in the text file properly which will cause= the file to not be formatted. + +2. Run Uncrustify using the generated text file as input + + The following assume you move the EDK II Uncrustify configuration file = to the directory .uncrustify in your edk2 + workspace. + + ```shell + uncrustify.exe -c .\.pytool\Plugin\UncrustifyCheck\uncrustify.cfg -F Md= ePkgFiles.txt --replace --no-backup --if-changed + ``` + + > *Note:* When testing a configuration change, it is sometimes useful t= o run Uncrustify against a particular file + and check the debug output to understand what rule was applied and wh= y it was applied. The command shows an + example of how to run the configuration file `uncrustify.cfg` against= the source file `VariableSmm.c` where the + file is forced to be treated as C, the debug output is written to `un= crustify_debug.txt` and the log severity level + is set to "all". + + ```shell + uncrustify.exe -c .\.pytool\Plugin\UncrustifyCheck\uncrustify.cfg -f .\= MdeModulePkg\Universal\Variable\RuntimeDxe\VariableSmm.c -o output.c -l C -= p uncrustify_debug.txt -L A 2>verbose_debug.txt + ``` + +Uncrustify will update the source files in-place (with the commands given)= . This allows you to diff the results with +git. From here, you can iteratively tweak the configuration file and check= the results until your satisfied with the +outcome. + +## Uncrustify in CI + +The UncrustifyCheck CI plugin that will verify formatting on the server ca= n be run locally. It is recommended to run +local CI to verify the patch submission will pass CI on the server. + +This can be done using the `stuart_ci_build` command. + +> Tip: To quickly only run UncrustifyCheck, remove the other plugin direct= ories from your local `.pytool` directory + and, of course, add them back when you're done. + +Here's an example of running UncrustifyCheck against MdeModulePkg from the= root of an edk2 workspace: + +`stuart_ci_build -c .pytool/CISettings.py -p MdeModulePkg` + +If a file has a formatting error, it will be noted in the output from `stu= art_ci_build`. This is visible in the +terminal output in local CI and the build output log in server CI. + +Read the [UncrustifyCheck Readme.md](https://github.com/tianocore/edk2/blo= b/master/.pytool/Plugin/UncrustifyCheck/Readme.md) +to understand more about how the plugin can be configured for CI. + +## Extra Reading: Tracing History Across the Uncrustify Changes + +It might be helpful to view the entire history rewritten with Uncrustify f= ormatting on every commit. For example, an +alternate version of the edk2 repository that serves as "documentation" wi= th the entire history re-written. + +A tool called git-filter-repo can be used to perform this transformation a= nd runs in a reasonable period of time +(a few hours): + +* +* + +The following steps can be used to perform this transformation. This is th= e Windows process. A Linux process will be +added in the future. + + > **WARNING** This operation modifies (rewrites) all the commits in the= local copy of the repo. Do not perform + these steps on a local repo you are using for active deve= lopment. + +1. Clone edk2 into a new directory (see **WARNING**) + + ```shell + git clone https://github.com/tianocore/edk2.git edk2-uncrustified + cd edk2-uncrustified + ``` + +2. Setup python virtual env, install pytools, and run stuart commands to s= etup build environment which includes + installing uncrustify tools. See [Running CI Locally](https://github.co= m/tianocore/edk2/tree/master/.pytool#running-ci-locally). + +3. Make a backup copy of the plugin UncrustifyCheck outside WORKSPACE. (e.= g. C:\Temp\UncrustifyCheck) so the + Uncrustify executable and EDK II specific Uncrustify configuration file= are available when working with a branch + that does not have those tools in its scope. + + ```shell + xcopy .pytool\Plugin\UncrustifyCheck C:\Temp\UncrustifyCheck + ``` + +4. Use lint-history.py from git-filter-repo examples + + * [git-filter-repo](https://github.com/newren/git-filter-repo) + * [lint-history](https://github.com/newren/git-filter-repo/blob/main/co= ntrib/filter-repo-demos/lint-history) + +Line #127 - Add try except around subprocess.check_call() with except bein= g pass. This is required because there are a +few commits of C files in the edk2 repo that have incorrect C syntax and d= o not build with a C compiler and break the +Uncrustify parser. Skip reformat of C files that can not be parsed by uncr= ustify. These rare instances are addressed in +the commit that fixes the C syntax error. + +Run this slightly modified version of lint-history. Include only .c/.h fil= es and exclude directories that start with +`Tools` or `BaseTools`. This step took about 2.2 hours on a laptop. + +```shell +lint-history.py + --relevant "return (not filename.startswith(b'Tools') and not filename= .startswith(b'BaseTools') and (filename.endswith(b'.c') or filename.endswit= h(b'.h')))" + c:\\work\\GitHub\\tianocore\\foo\\UncrustifyCheck\\mu-uncrustify-relea= se_extdep\\Windows-x86\\uncrustify.exe -c c:\\work\\GitHub\\tianocore\\foo\= \UncrustifyCheck\\uncrustify.cfg --replace --no-backup --if-changed +``` --=20 2.28.0.windows.1