CISettings.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  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. from edk2toolext.environment import shell_environment
  11. from edk2toolext.invocables.edk2_ci_build import CiBuildSettingsManager
  12. from edk2toolext.invocables.edk2_setup import SetupSettingsManager, RequiredSubmodule
  13. from edk2toolext.invocables.edk2_update import UpdateSettingsManager
  14. from edk2toolext.invocables.edk2_pr_eval import PrEvalSettingsManager
  15. from edk2toollib.utility_functions import GetHostInfo
  16. class Settings(CiBuildSettingsManager, UpdateSettingsManager, SetupSettingsManager, PrEvalSettingsManager):
  17. def __init__(self):
  18. self.ActualPackages = []
  19. self.ActualTargets = []
  20. self.ActualArchitectures = []
  21. self.ActualToolChainTag = ""
  22. self.UseBuiltInBaseTools = None
  23. self.ActualScopes = None
  24. # ####################################################################################### #
  25. # Extra CmdLine configuration #
  26. # ####################################################################################### #
  27. def AddCommandLineOptions(self, parserObj):
  28. group = parserObj.add_mutually_exclusive_group()
  29. group.add_argument("-force_piptools", "--fpt", dest="force_piptools", action="store_true", default=False, help="Force the system to use pip tools")
  30. group.add_argument("-no_piptools", "--npt", dest="no_piptools", action="store_true", default=False, help="Force the system to not use pip tools")
  31. def RetrieveCommandLineOptions(self, args):
  32. super().RetrieveCommandLineOptions(args)
  33. if args.force_piptools:
  34. self.UseBuiltInBaseTools = True
  35. if args.no_piptools:
  36. self.UseBuiltInBaseTools = False
  37. # ####################################################################################### #
  38. # Default Support for this Ci Build #
  39. # ####################################################################################### #
  40. def GetPackagesSupported(self):
  41. ''' return iterable of edk2 packages supported by this build.
  42. These should be edk2 workspace relative paths '''
  43. return ("ArmPkg",
  44. "ArmPlatformPkg",
  45. "ArmVirtPkg",
  46. "DynamicTablesPkg",
  47. "EmbeddedPkg",
  48. "EmulatorPkg",
  49. "IntelFsp2Pkg",
  50. "IntelFsp2WrapperPkg",
  51. "MdePkg",
  52. "MdeModulePkg",
  53. "NetworkPkg",
  54. "PcAtChipsetPkg",
  55. "SecurityPkg",
  56. "UefiCpuPkg",
  57. "FmpDevicePkg",
  58. "ShellPkg",
  59. "SignedCapsulePkg",
  60. "StandaloneMmPkg",
  61. "FatPkg",
  62. "CryptoPkg",
  63. "PrmPkg",
  64. "UnitTestFrameworkPkg",
  65. "OvmfPkg",
  66. "RedfishPkg",
  67. "UefiPayloadPkg"
  68. )
  69. def GetArchitecturesSupported(self):
  70. ''' return iterable of edk2 architectures supported by this build '''
  71. return (
  72. "IA32",
  73. "X64",
  74. "ARM",
  75. "AARCH64",
  76. "RISCV64")
  77. def GetTargetsSupported(self):
  78. ''' return iterable of edk2 target tags supported by this build '''
  79. return ("DEBUG", "RELEASE", "NO-TARGET", "NOOPT")
  80. # ####################################################################################### #
  81. # Verify and Save requested Ci Build Config #
  82. # ####################################################################################### #
  83. def SetPackages(self, list_of_requested_packages):
  84. ''' Confirm the requested package list is valid and configure SettingsManager
  85. to build the requested packages.
  86. Raise UnsupportedException if a requested_package is not supported
  87. '''
  88. unsupported = set(list_of_requested_packages) - \
  89. set(self.GetPackagesSupported())
  90. if(len(unsupported) > 0):
  91. logging.critical(
  92. "Unsupported Package Requested: " + " ".join(unsupported))
  93. raise Exception("Unsupported Package Requested: " +
  94. " ".join(unsupported))
  95. self.ActualPackages = list_of_requested_packages
  96. def SetArchitectures(self, list_of_requested_architectures):
  97. ''' Confirm the requests architecture list is valid and configure SettingsManager
  98. to run only the requested architectures.
  99. Raise Exception if a list_of_requested_architectures is not supported
  100. '''
  101. unsupported = set(list_of_requested_architectures) - \
  102. set(self.GetArchitecturesSupported())
  103. if(len(unsupported) > 0):
  104. logging.critical(
  105. "Unsupported Architecture Requested: " + " ".join(unsupported))
  106. raise Exception(
  107. "Unsupported Architecture Requested: " + " ".join(unsupported))
  108. self.ActualArchitectures = list_of_requested_architectures
  109. def SetTargets(self, list_of_requested_target):
  110. ''' Confirm the request target list is valid and configure SettingsManager
  111. to run only the requested targets.
  112. Raise UnsupportedException if a requested_target is not supported
  113. '''
  114. unsupported = set(list_of_requested_target) - \
  115. set(self.GetTargetsSupported())
  116. if(len(unsupported) > 0):
  117. logging.critical(
  118. "Unsupported Targets Requested: " + " ".join(unsupported))
  119. raise Exception("Unsupported Targets Requested: " +
  120. " ".join(unsupported))
  121. self.ActualTargets = list_of_requested_target
  122. # ####################################################################################### #
  123. # Actual Configuration for Ci Build #
  124. # ####################################################################################### #
  125. def GetActiveScopes(self):
  126. ''' return tuple containing scopes that should be active for this process '''
  127. if self.ActualScopes is None:
  128. scopes = ("cibuild", "edk2-build", "host-based-test")
  129. self.ActualToolChainTag = shell_environment.GetBuildVars().GetValue("TOOL_CHAIN_TAG", "")
  130. is_linux = GetHostInfo().os.upper() == "LINUX"
  131. if self.UseBuiltInBaseTools is None:
  132. is_linux = GetHostInfo().os.upper() == "LINUX"
  133. # try and import the pip module for basetools
  134. try:
  135. import edk2basetools
  136. self.UseBuiltInBaseTools = True
  137. except ImportError:
  138. self.UseBuiltInBaseTools = False
  139. pass
  140. if self.UseBuiltInBaseTools == True:
  141. scopes += ('pipbuild-unix',) if is_linux else ('pipbuild-win',)
  142. logging.warning("Using Pip Tools based BaseTools")
  143. else:
  144. logging.warning("Falling back to using in-tree BaseTools")
  145. if is_linux and self.ActualToolChainTag.upper().startswith("GCC"):
  146. if "AARCH64" in self.ActualArchitectures:
  147. scopes += ("gcc_aarch64_linux",)
  148. if "ARM" in self.ActualArchitectures:
  149. scopes += ("gcc_arm_linux",)
  150. if "RISCV64" in self.ActualArchitectures:
  151. scopes += ("gcc_riscv64_unknown",)
  152. self.ActualScopes = scopes
  153. return self.ActualScopes
  154. def GetRequiredSubmodules(self):
  155. ''' return iterable containing RequiredSubmodule objects.
  156. If no RequiredSubmodules return an empty iterable
  157. '''
  158. rs = []
  159. rs.append(RequiredSubmodule(
  160. "ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3", False))
  161. rs.append(RequiredSubmodule(
  162. "CryptoPkg/Library/OpensslLib/openssl", False))
  163. rs.append(RequiredSubmodule(
  164. "UnitTestFrameworkPkg/Library/CmockaLib/cmocka", False))
  165. rs.append(RequiredSubmodule(
  166. "MdeModulePkg/Universal/RegularExpressionDxe/oniguruma", False))
  167. rs.append(RequiredSubmodule(
  168. "MdeModulePkg/Library/BrotliCustomDecompressLib/brotli", False))
  169. rs.append(RequiredSubmodule(
  170. "BaseTools/Source/C/BrotliCompress/brotli", False))
  171. rs.append(RequiredSubmodule(
  172. "RedfishPkg/Library/JsonLib/jansson", False))
  173. return rs
  174. def GetName(self):
  175. return "Edk2"
  176. def GetDependencies(self):
  177. return [
  178. ]
  179. def GetPackagesPath(self):
  180. return ()
  181. def GetWorkspaceRoot(self):
  182. ''' get WorkspacePath '''
  183. return os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
  184. def FilterPackagesToTest(self, changedFilesList: list, potentialPackagesList: list) -> list:
  185. ''' Filter potential packages to test based on changed files. '''
  186. build_these_packages = []
  187. possible_packages = potentialPackagesList.copy()
  188. for f in changedFilesList:
  189. # split each part of path for comparison later
  190. nodes = f.split("/")
  191. # python file change in .pytool folder causes building all
  192. if f.endswith(".py") and ".pytool" in nodes:
  193. build_these_packages = possible_packages
  194. break
  195. # BaseTools files that might change the build
  196. if "BaseTools" in nodes:
  197. if os.path.splitext(f) not in [".txt", ".md"]:
  198. build_these_packages = possible_packages
  199. break
  200. return build_these_packages