CISettings.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  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. "SourceLevelDebugPkg",
  68. "UefiPayloadPkg"
  69. )
  70. def GetArchitecturesSupported(self):
  71. ''' return iterable of edk2 architectures supported by this build '''
  72. return (
  73. "IA32",
  74. "X64",
  75. "ARM",
  76. "AARCH64",
  77. "RISCV64")
  78. def GetTargetsSupported(self):
  79. ''' return iterable of edk2 target tags supported by this build '''
  80. return ("DEBUG", "RELEASE", "NO-TARGET", "NOOPT")
  81. # ####################################################################################### #
  82. # Verify and Save requested Ci Build Config #
  83. # ####################################################################################### #
  84. def SetPackages(self, list_of_requested_packages):
  85. ''' Confirm the requested package list is valid and configure SettingsManager
  86. to build the requested packages.
  87. Raise UnsupportedException if a requested_package is not supported
  88. '''
  89. unsupported = set(list_of_requested_packages) - \
  90. set(self.GetPackagesSupported())
  91. if(len(unsupported) > 0):
  92. logging.critical(
  93. "Unsupported Package Requested: " + " ".join(unsupported))
  94. raise Exception("Unsupported Package Requested: " +
  95. " ".join(unsupported))
  96. self.ActualPackages = list_of_requested_packages
  97. def SetArchitectures(self, list_of_requested_architectures):
  98. ''' Confirm the requests architecture list is valid and configure SettingsManager
  99. to run only the requested architectures.
  100. Raise Exception if a list_of_requested_architectures is not supported
  101. '''
  102. unsupported = set(list_of_requested_architectures) - \
  103. set(self.GetArchitecturesSupported())
  104. if(len(unsupported) > 0):
  105. logging.critical(
  106. "Unsupported Architecture Requested: " + " ".join(unsupported))
  107. raise Exception(
  108. "Unsupported Architecture Requested: " + " ".join(unsupported))
  109. self.ActualArchitectures = list_of_requested_architectures
  110. def SetTargets(self, list_of_requested_target):
  111. ''' Confirm the request target list is valid and configure SettingsManager
  112. to run only the requested targets.
  113. Raise UnsupportedException if a requested_target is not supported
  114. '''
  115. unsupported = set(list_of_requested_target) - \
  116. set(self.GetTargetsSupported())
  117. if(len(unsupported) > 0):
  118. logging.critical(
  119. "Unsupported Targets Requested: " + " ".join(unsupported))
  120. raise Exception("Unsupported Targets Requested: " +
  121. " ".join(unsupported))
  122. self.ActualTargets = list_of_requested_target
  123. # ####################################################################################### #
  124. # Actual Configuration for Ci Build #
  125. # ####################################################################################### #
  126. def GetActiveScopes(self):
  127. ''' return tuple containing scopes that should be active for this process '''
  128. if self.ActualScopes is None:
  129. scopes = ("cibuild", "edk2-build", "host-based-test")
  130. self.ActualToolChainTag = shell_environment.GetBuildVars().GetValue("TOOL_CHAIN_TAG", "")
  131. is_linux = GetHostInfo().os.upper() == "LINUX"
  132. if self.UseBuiltInBaseTools is None:
  133. is_linux = GetHostInfo().os.upper() == "LINUX"
  134. # try and import the pip module for basetools
  135. try:
  136. import edk2basetools
  137. self.UseBuiltInBaseTools = True
  138. except ImportError:
  139. self.UseBuiltInBaseTools = False
  140. pass
  141. if self.UseBuiltInBaseTools == True:
  142. scopes += ('pipbuild-unix',) if is_linux else ('pipbuild-win',)
  143. logging.warning("Using Pip Tools based BaseTools")
  144. else:
  145. logging.warning("Falling back to using in-tree BaseTools")
  146. if is_linux and self.ActualToolChainTag.upper().startswith("GCC"):
  147. if "AARCH64" in self.ActualArchitectures:
  148. scopes += ("gcc_aarch64_linux",)
  149. if "ARM" in self.ActualArchitectures:
  150. scopes += ("gcc_arm_linux",)
  151. if "RISCV64" in self.ActualArchitectures:
  152. scopes += ("gcc_riscv64_unknown",)
  153. self.ActualScopes = scopes
  154. return self.ActualScopes
  155. def GetRequiredSubmodules(self):
  156. ''' return iterable containing RequiredSubmodule objects.
  157. If no RequiredSubmodules return an empty iterable
  158. '''
  159. rs = []
  160. rs.append(RequiredSubmodule(
  161. "ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3", False))
  162. rs.append(RequiredSubmodule(
  163. "CryptoPkg/Library/OpensslLib/openssl", False))
  164. rs.append(RequiredSubmodule(
  165. "UnitTestFrameworkPkg/Library/CmockaLib/cmocka", False))
  166. rs.append(RequiredSubmodule(
  167. "MdeModulePkg/Universal/RegularExpressionDxe/oniguruma", False))
  168. rs.append(RequiredSubmodule(
  169. "MdeModulePkg/Library/BrotliCustomDecompressLib/brotli", False))
  170. rs.append(RequiredSubmodule(
  171. "BaseTools/Source/C/BrotliCompress/brotli", False))
  172. rs.append(RequiredSubmodule(
  173. "RedfishPkg/Library/JsonLib/jansson", False))
  174. return rs
  175. def GetName(self):
  176. return "Edk2"
  177. def GetDependencies(self):
  178. return [
  179. ]
  180. def GetPackagesPath(self):
  181. return ()
  182. def GetWorkspaceRoot(self):
  183. ''' get WorkspacePath '''
  184. return os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
  185. def FilterPackagesToTest(self, changedFilesList: list, potentialPackagesList: list) -> list:
  186. ''' Filter potential packages to test based on changed files. '''
  187. build_these_packages = []
  188. possible_packages = potentialPackagesList.copy()
  189. for f in changedFilesList:
  190. # split each part of path for comparison later
  191. nodes = f.split("/")
  192. # python file change in .pytool folder causes building all
  193. if f.endswith(".py") and ".pytool" in nodes:
  194. build_these_packages = possible_packages
  195. break
  196. # BaseTools files that might change the build
  197. if "BaseTools" in nodes:
  198. if os.path.splitext(f) not in [".txt", ".md"]:
  199. build_these_packages = possible_packages
  200. break
  201. return build_these_packages