1 | # @file
|
---|
2 | #
|
---|
3 | # Copyright (c) Microsoft Corporation.
|
---|
4 | # Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
|
---|
5 | # Copyright (c) 2020 - 2021, ARM Limited. All rights reserved.<BR>
|
---|
6 | # SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
7 | ##
|
---|
8 | import os
|
---|
9 | import logging
|
---|
10 | import sys
|
---|
11 | from edk2toolext.environment import shell_environment
|
---|
12 | from edk2toolext.invocables.edk2_ci_build import CiBuildSettingsManager
|
---|
13 | from edk2toolext.invocables.edk2_setup import SetupSettingsManager, RequiredSubmodule
|
---|
14 | from edk2toolext.invocables.edk2_update import UpdateSettingsManager
|
---|
15 | from edk2toolext.invocables.edk2_pr_eval import PrEvalSettingsManager
|
---|
16 | from edk2toollib.utility_functions import GetHostInfo
|
---|
17 | from pathlib import Path
|
---|
18 |
|
---|
19 |
|
---|
20 | try:
|
---|
21 | # Temporarily needed until edk2 can update to the latest edk2-pytools
|
---|
22 | # that has the CodeQL helpers.
|
---|
23 | #
|
---|
24 | # May not be present until submodules are populated.
|
---|
25 | #
|
---|
26 | root = Path(__file__).parent.parent.resolve()
|
---|
27 | sys.path.append(str(root/'BaseTools'/'Plugin'/'CodeQL'/'integration'))
|
---|
28 | import stuart_codeql as codeql_helpers
|
---|
29 | except ImportError:
|
---|
30 | pass
|
---|
31 |
|
---|
32 |
|
---|
33 | class Settings(CiBuildSettingsManager, UpdateSettingsManager, SetupSettingsManager, PrEvalSettingsManager):
|
---|
34 |
|
---|
35 | def __init__(self):
|
---|
36 | self.ActualPackages = []
|
---|
37 | self.ActualTargets = []
|
---|
38 | self.ActualArchitectures = []
|
---|
39 | self.ActualToolChainTag = ""
|
---|
40 | self.UseBuiltInBaseTools = None
|
---|
41 | self.ActualScopes = None
|
---|
42 |
|
---|
43 | # ####################################################################################### #
|
---|
44 | # Extra CmdLine configuration #
|
---|
45 | # ####################################################################################### #
|
---|
46 |
|
---|
47 | def AddCommandLineOptions(self, parserObj):
|
---|
48 | group = parserObj.add_mutually_exclusive_group()
|
---|
49 | group.add_argument("-force_piptools", "--fpt", dest="force_piptools", action="store_true", default=False, help="Force the system to use pip tools")
|
---|
50 | group.add_argument("-no_piptools", "--npt", dest="no_piptools", action="store_true", default=False, help="Force the system to not use pip tools")
|
---|
51 |
|
---|
52 | try:
|
---|
53 | codeql_helpers.add_command_line_option(parserObj)
|
---|
54 | except NameError:
|
---|
55 | pass
|
---|
56 |
|
---|
57 | def RetrieveCommandLineOptions(self, args):
|
---|
58 | super().RetrieveCommandLineOptions(args)
|
---|
59 | if args.force_piptools:
|
---|
60 | self.UseBuiltInBaseTools = True
|
---|
61 | if args.no_piptools:
|
---|
62 | self.UseBuiltInBaseTools = False
|
---|
63 |
|
---|
64 | try:
|
---|
65 | self.codeql = codeql_helpers.is_codeql_enabled_on_command_line(args)
|
---|
66 | except NameError:
|
---|
67 | pass
|
---|
68 |
|
---|
69 | # ####################################################################################### #
|
---|
70 | # Default Support for this Ci Build #
|
---|
71 | # ####################################################################################### #
|
---|
72 |
|
---|
73 | def GetPackagesSupported(self):
|
---|
74 | ''' return iterable of edk2 packages supported by this build.
|
---|
75 | These should be edk2 workspace relative paths '''
|
---|
76 |
|
---|
77 | return ("ArmPkg",
|
---|
78 | "ArmPlatformPkg",
|
---|
79 | "ArmVirtPkg",
|
---|
80 | "DynamicTablesPkg",
|
---|
81 | "EmbeddedPkg",
|
---|
82 | "EmulatorPkg",
|
---|
83 | "IntelFsp2Pkg",
|
---|
84 | "IntelFsp2WrapperPkg",
|
---|
85 | "MdePkg",
|
---|
86 | "MdeModulePkg",
|
---|
87 | "NetworkPkg",
|
---|
88 | "PcAtChipsetPkg",
|
---|
89 | "SecurityPkg",
|
---|
90 | "UefiCpuPkg",
|
---|
91 | "FmpDevicePkg",
|
---|
92 | "ShellPkg",
|
---|
93 | "SignedCapsulePkg",
|
---|
94 | "StandaloneMmPkg",
|
---|
95 | "FatPkg",
|
---|
96 | "CryptoPkg",
|
---|
97 | "PrmPkg",
|
---|
98 | "UnitTestFrameworkPkg",
|
---|
99 | "OvmfPkg",
|
---|
100 | "RedfishPkg",
|
---|
101 | "SourceLevelDebugPkg",
|
---|
102 | "UefiPayloadPkg"
|
---|
103 | )
|
---|
104 |
|
---|
105 | def GetArchitecturesSupported(self):
|
---|
106 | ''' return iterable of edk2 architectures supported by this build '''
|
---|
107 | return (
|
---|
108 | "IA32",
|
---|
109 | "X64",
|
---|
110 | "ARM",
|
---|
111 | "AARCH64",
|
---|
112 | "RISCV64",
|
---|
113 | "LOONGARCH64")
|
---|
114 |
|
---|
115 | def GetTargetsSupported(self):
|
---|
116 | ''' return iterable of edk2 target tags supported by this build '''
|
---|
117 | return ("DEBUG", "RELEASE", "NO-TARGET", "NOOPT")
|
---|
118 |
|
---|
119 | # ####################################################################################### #
|
---|
120 | # Verify and Save requested Ci Build Config #
|
---|
121 | # ####################################################################################### #
|
---|
122 |
|
---|
123 | def SetPackages(self, list_of_requested_packages):
|
---|
124 | ''' Confirm the requested package list is valid and configure SettingsManager
|
---|
125 | to build the requested packages.
|
---|
126 |
|
---|
127 | Raise UnsupportedException if a requested_package is not supported
|
---|
128 | '''
|
---|
129 | unsupported = set(list_of_requested_packages) - \
|
---|
130 | set(self.GetPackagesSupported())
|
---|
131 | if(len(unsupported) > 0):
|
---|
132 | logging.critical(
|
---|
133 | "Unsupported Package Requested: " + " ".join(unsupported))
|
---|
134 | raise Exception("Unsupported Package Requested: " +
|
---|
135 | " ".join(unsupported))
|
---|
136 | self.ActualPackages = list_of_requested_packages
|
---|
137 |
|
---|
138 | def SetArchitectures(self, list_of_requested_architectures):
|
---|
139 | ''' Confirm the requests architecture list is valid and configure SettingsManager
|
---|
140 | to run only the requested architectures.
|
---|
141 |
|
---|
142 | Raise Exception if a list_of_requested_architectures is not supported
|
---|
143 | '''
|
---|
144 | unsupported = set(list_of_requested_architectures) - \
|
---|
145 | set(self.GetArchitecturesSupported())
|
---|
146 | if(len(unsupported) > 0):
|
---|
147 | logging.critical(
|
---|
148 | "Unsupported Architecture Requested: " + " ".join(unsupported))
|
---|
149 | raise Exception(
|
---|
150 | "Unsupported Architecture Requested: " + " ".join(unsupported))
|
---|
151 | self.ActualArchitectures = list_of_requested_architectures
|
---|
152 |
|
---|
153 | def SetTargets(self, list_of_requested_target):
|
---|
154 | ''' Confirm the request target list is valid and configure SettingsManager
|
---|
155 | to run only the requested targets.
|
---|
156 |
|
---|
157 | Raise UnsupportedException if a requested_target is not supported
|
---|
158 | '''
|
---|
159 | unsupported = set(list_of_requested_target) - \
|
---|
160 | set(self.GetTargetsSupported())
|
---|
161 | if(len(unsupported) > 0):
|
---|
162 | logging.critical(
|
---|
163 | "Unsupported Targets Requested: " + " ".join(unsupported))
|
---|
164 | raise Exception("Unsupported Targets Requested: " +
|
---|
165 | " ".join(unsupported))
|
---|
166 | self.ActualTargets = list_of_requested_target
|
---|
167 |
|
---|
168 | # ####################################################################################### #
|
---|
169 | # Actual Configuration for Ci Build #
|
---|
170 | # ####################################################################################### #
|
---|
171 |
|
---|
172 | def GetActiveScopes(self):
|
---|
173 | ''' return tuple containing scopes that should be active for this process '''
|
---|
174 | if self.ActualScopes is None:
|
---|
175 | scopes = ("cibuild", "edk2-build", "host-based-test")
|
---|
176 |
|
---|
177 | self.ActualToolChainTag = shell_environment.GetBuildVars().GetValue("TOOL_CHAIN_TAG", "")
|
---|
178 |
|
---|
179 | is_linux = GetHostInfo().os.upper() == "LINUX"
|
---|
180 |
|
---|
181 | if self.UseBuiltInBaseTools is None:
|
---|
182 | is_linux = GetHostInfo().os.upper() == "LINUX"
|
---|
183 | # try and import the pip module for basetools
|
---|
184 | try:
|
---|
185 | import edk2basetools
|
---|
186 | self.UseBuiltInBaseTools = True
|
---|
187 | except ImportError:
|
---|
188 | self.UseBuiltInBaseTools = False
|
---|
189 | pass
|
---|
190 |
|
---|
191 | if self.UseBuiltInBaseTools == True:
|
---|
192 | scopes += ('pipbuild-unix',) if is_linux else ('pipbuild-win',)
|
---|
193 | logging.warning("Using Pip Tools based BaseTools")
|
---|
194 | else:
|
---|
195 | logging.warning("Falling back to using in-tree BaseTools")
|
---|
196 |
|
---|
197 | try:
|
---|
198 | scopes += codeql_helpers.get_scopes(self.codeql)
|
---|
199 |
|
---|
200 | if self.codeql:
|
---|
201 | shell_environment.GetBuildVars().SetValue(
|
---|
202 | "STUART_CODEQL_AUDIT_ONLY",
|
---|
203 | "TRUE",
|
---|
204 | "Set in CISettings.py")
|
---|
205 | except NameError:
|
---|
206 | pass
|
---|
207 |
|
---|
208 | self.ActualScopes = scopes
|
---|
209 | return self.ActualScopes
|
---|
210 |
|
---|
211 | def GetRequiredSubmodules(self):
|
---|
212 | ''' return iterable containing RequiredSubmodule objects.
|
---|
213 | If no RequiredSubmodules return an empty iterable
|
---|
214 | '''
|
---|
215 | rs = []
|
---|
216 | rs.append(RequiredSubmodule(
|
---|
217 | "ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3", False))
|
---|
218 | rs.append(RequiredSubmodule(
|
---|
219 | "CryptoPkg/Library/OpensslLib/openssl", False))
|
---|
220 | rs.append(RequiredSubmodule(
|
---|
221 | "UnitTestFrameworkPkg/Library/CmockaLib/cmocka", False))
|
---|
222 | rs.append(RequiredSubmodule(
|
---|
223 | "UnitTestFrameworkPkg/Library/GoogleTestLib/googletest", False))
|
---|
224 | rs.append(RequiredSubmodule(
|
---|
225 | "MdeModulePkg/Universal/RegularExpressionDxe/oniguruma", False))
|
---|
226 | rs.append(RequiredSubmodule(
|
---|
227 | "MdeModulePkg/Library/BrotliCustomDecompressLib/brotli", False))
|
---|
228 | rs.append(RequiredSubmodule(
|
---|
229 | "BaseTools/Source/C/BrotliCompress/brotli", False))
|
---|
230 | rs.append(RequiredSubmodule(
|
---|
231 | "RedfishPkg/Library/JsonLib/jansson", False))
|
---|
232 | rs.append(RequiredSubmodule(
|
---|
233 | "UnitTestFrameworkPkg/Library/SubhookLib/subhook", False))
|
---|
234 | rs.append(RequiredSubmodule(
|
---|
235 | "MdePkg/Library/BaseFdtLib/libfdt", False))
|
---|
236 | rs.append(RequiredSubmodule(
|
---|
237 | "MdePkg/Library/MipiSysTLib/mipisyst", False))
|
---|
238 | rs.append(RequiredSubmodule(
|
---|
239 | "CryptoPkg/Library/MbedTlsLib/mbedtls", False))
|
---|
240 | rs.append(RequiredSubmodule(
|
---|
241 | "SecurityPkg/DeviceSecurity/SpdmLib/libspdm", False))
|
---|
242 | return rs
|
---|
243 |
|
---|
244 | def GetName(self):
|
---|
245 | return "Edk2"
|
---|
246 |
|
---|
247 | def GetDependencies(self):
|
---|
248 | return [
|
---|
249 | ]
|
---|
250 |
|
---|
251 | def GetPackagesPath(self):
|
---|
252 | return ()
|
---|
253 |
|
---|
254 | def GetWorkspaceRoot(self):
|
---|
255 | ''' get WorkspacePath '''
|
---|
256 | return os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
---|
257 |
|
---|
258 | def FilterPackagesToTest(self, changedFilesList: list, potentialPackagesList: list) -> list:
|
---|
259 | ''' Filter potential packages to test based on changed files. '''
|
---|
260 | build_these_packages = []
|
---|
261 | possible_packages = potentialPackagesList.copy()
|
---|
262 | for f in changedFilesList:
|
---|
263 | # split each part of path for comparison later
|
---|
264 | nodes = f.split("/")
|
---|
265 |
|
---|
266 | # python file change in .pytool folder causes building all
|
---|
267 | if f.endswith(".py") and ".pytool" in nodes:
|
---|
268 | build_these_packages = possible_packages
|
---|
269 | break
|
---|
270 |
|
---|
271 | # BaseTools files that might change the build
|
---|
272 | if "BaseTools" in nodes:
|
---|
273 | if os.path.splitext(f) not in [".txt", ".md"]:
|
---|
274 | build_these_packages = possible_packages
|
---|
275 | break
|
---|
276 | return build_these_packages
|
---|