create-test-plan.py 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931
  1. #!/usr/bin/env python
  2. import argparse
  3. import dataclasses
  4. import fnmatch
  5. from enum import Enum
  6. import json
  7. import logging
  8. import os
  9. import re
  10. from typing import Optional
  11. logger = logging.getLogger(__name__)
  12. class AppleArch(Enum):
  13. Aarch64 = "aarch64"
  14. X86_64 = "x86_64"
  15. class MsvcArch(Enum):
  16. X86 = "x86"
  17. X64 = "x64"
  18. Arm64 = "arm64"
  19. class JobOs(Enum):
  20. WindowsLatest = "windows-latest"
  21. UbuntuLatest = "ubuntu-latest"
  22. MacosLatest = "macos-latest"
  23. Ubuntu22_04 = "ubuntu-22.04"
  24. Ubuntu24_04 = "ubuntu-24.04"
  25. Ubuntu24_04_arm = "ubuntu-24.04-arm"
  26. Macos14 = "macos-14" # macOS Sonoma (2023)
  27. Macos15 = "macos-15" # macOS Sequoia (2024)
  28. Macos26 = "macos-26" # macOS Tahoe (2025)
  29. class SdlPlatform(Enum):
  30. Android = "android"
  31. Emscripten = "emscripten"
  32. Haiku = "haiku"
  33. LoongArch64 = "loongarch64"
  34. Msys2 = "msys2"
  35. Linux = "linux"
  36. MacOS = "macos"
  37. Ios = "ios"
  38. Tvos = "tvos"
  39. Msvc = "msvc"
  40. N3ds = "n3ds"
  41. PowerPC = "powerpc"
  42. PowerPC64 = "powerpc64"
  43. Ps2 = "ps2"
  44. Psp = "psp"
  45. Vita = "vita"
  46. Riscos = "riscos"
  47. FreeBSD = "freebsd"
  48. NetBSD = "netbsd"
  49. OpenBSD = "openbsd"
  50. NGage = "ngage"
  51. class Msys2Platform(Enum):
  52. Mingw32 = "mingw32"
  53. Mingw64 = "mingw64"
  54. Clang64 = "clang64"
  55. Ucrt64 = "ucrt64"
  56. class IntelCompiler(Enum):
  57. Icc = "icc"
  58. Icx = "icx"
  59. class VitaGLES(Enum):
  60. Pib = "pib"
  61. Pvr = "pvr"
  62. @dataclasses.dataclass(slots=True)
  63. class JobSpec:
  64. name: str
  65. os: JobOs
  66. platform: SdlPlatform
  67. artifact: Optional[str]
  68. container: Optional[str] = None
  69. no_cmake: bool = False
  70. xcode: bool = False
  71. android_mk: bool = False
  72. android_gradle: bool = False
  73. lean: bool = False
  74. android_arch: Optional[str] = None
  75. android_abi: Optional[str] = None
  76. android_platform: Optional[int] = None
  77. msys2_platform: Optional[Msys2Platform] = None
  78. intel: Optional[IntelCompiler] = None
  79. apple_framework: Optional[bool] = None
  80. apple_archs: Optional[set[AppleArch]] = None
  81. msvc_project: Optional[str] = None
  82. msvc_arch: Optional[MsvcArch] = None
  83. clang_cl: bool = False
  84. gdk: bool = False
  85. vita_gles: Optional[VitaGLES] = None
  86. more_hard_deps: bool = False
  87. JOB_SPECS = {
  88. "msys2-mingw32": JobSpec(name="Windows (msys2, mingw32)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msys2, artifact="SDL-mingw32", msys2_platform=Msys2Platform.Mingw32, ),
  89. "msys2-mingw64": JobSpec(name="Windows (msys2, mingw64)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msys2, artifact="SDL-mingw64", msys2_platform=Msys2Platform.Mingw64, ),
  90. "msys2-clang64": JobSpec(name="Windows (msys2, clang64)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msys2, artifact="SDL-mingw64-clang", msys2_platform=Msys2Platform.Clang64, ),
  91. "msys2-ucrt64": JobSpec(name="Windows (msys2, ucrt64)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msys2, artifact="SDL-mingw64-ucrt", msys2_platform=Msys2Platform.Ucrt64, ),
  92. "msvc-x64": JobSpec(name="Windows (MSVC, x64)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msvc, artifact="SDL-VC-x64", msvc_arch=MsvcArch.X64, msvc_project="VisualC/SDL.sln", ),
  93. "msvc-x86": JobSpec(name="Windows (MSVC, x86)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msvc, artifact="SDL-VC-x86", msvc_arch=MsvcArch.X86, msvc_project="VisualC/SDL.sln", ),
  94. "msvc-clang-x64": JobSpec(name="Windows (MSVC, clang-cl x64)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msvc, artifact="SDL-clang-cl-x64", msvc_arch=MsvcArch.X64, clang_cl=True, ),
  95. "msvc-clang-x86": JobSpec(name="Windows (MSVC, clang-cl x86)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msvc, artifact="SDL-clang-cl-x86", msvc_arch=MsvcArch.X86, clang_cl=True, ),
  96. "msvc-arm64": JobSpec(name="Windows (MSVC, ARM64)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msvc, artifact="SDL-VC-arm64", msvc_arch=MsvcArch.Arm64, ),
  97. "msvc-gdk-x64": JobSpec(name="GDK (MSVC, x64)", os=JobOs.WindowsLatest, platform=SdlPlatform.Msvc, artifact="SDL-VC-GDK", msvc_arch=MsvcArch.X64, msvc_project="VisualC-GDK/SDL.sln", gdk=True, no_cmake=True, ),
  98. "ubuntu-22.04": JobSpec(name="Ubuntu 22.04", os=JobOs.Ubuntu22_04, platform=SdlPlatform.Linux, artifact="SDL-ubuntu22.04", ),
  99. "ubuntu-latest": JobSpec(name="Ubuntu (latest)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Linux, artifact="SDL-ubuntu-latest", ),
  100. "ubuntu-24.04-arm64": JobSpec(name="Ubuntu 24.04 (ARM64)", os=JobOs.Ubuntu24_04_arm, platform=SdlPlatform.Linux, artifact="SDL-ubuntu24.04-arm64", ),
  101. "steamrt3": JobSpec(name="Steam Linux Runtime 3.0 (x86_64)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Linux, artifact="SDL-steamrt3", container="registry.gitlab.steamos.cloud/steamrt/sniper/sdk:latest" ),
  102. "steamrt3-arm64": JobSpec(name="Steam Linux Runtime 3.0 (arm64)", os=JobOs.Ubuntu24_04_arm, platform=SdlPlatform.Linux, artifact="SDL-steamrt3-arm64", container="registry.gitlab.steamos.cloud/steamrt/sniper/sdk/arm64:latest" ),
  103. "steamrt4": JobSpec(name="Steam Linux Runtime 4.0 (x86_64)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Linux, artifact="SDL-steamrt4", container="registry.gitlab.steamos.cloud/steamrt/steamrt4/sdk:latest", more_hard_deps = True, ),
  104. "steamrt4-arm64": JobSpec(name="Steam Linux Runtime 4.0 (arm64)", os=JobOs.Ubuntu24_04_arm, platform=SdlPlatform.Linux, artifact="SDL-steamrt4-arm64", container="registry.gitlab.steamos.cloud/steamrt/steamrt4/sdk/arm64:latest", more_hard_deps = True, ),
  105. "ubuntu-intel-icx": JobSpec(name="Ubuntu 22.04 (Intel oneAPI)", os=JobOs.Ubuntu22_04, platform=SdlPlatform.Linux, artifact="SDL-ubuntu22.04-oneapi", intel=IntelCompiler.Icx, ),
  106. "ubuntu-intel-icc": JobSpec(name="Ubuntu 22.04 (Intel Compiler)", os=JobOs.Ubuntu22_04, platform=SdlPlatform.Linux, artifact="SDL-ubuntu22.04-icc", intel=IntelCompiler.Icc, ),
  107. "macos-framework-x64": JobSpec(name="MacOS (Framework) (x64)", os=JobOs.Macos14, platform=SdlPlatform.MacOS, artifact="SDL-macos-framework", apple_framework=True, apple_archs={AppleArch.Aarch64, AppleArch.X86_64, }, xcode=True, ),
  108. "macos-framework-arm64": JobSpec(name="MacOS (Framework) (arm64)", os=JobOs.MacosLatest, platform=SdlPlatform.MacOS, artifact=None, apple_framework=True, apple_archs={AppleArch.Aarch64, AppleArch.X86_64, }, ),
  109. "macos-26-framework-arm64": JobSpec(name="MacOS 26 (Framework) (arm64)",os=JobOs.Macos26, platform=SdlPlatform.MacOS, artifact=None, apple_framework=True, apple_archs={AppleArch.Aarch64, AppleArch.X86_64, }, ),
  110. "macos-gnu-arm64": JobSpec(name="MacOS (GNU prefix)", os=JobOs.MacosLatest, platform=SdlPlatform.MacOS, artifact="SDL-macos-arm64-gnu", apple_framework=False, apple_archs={AppleArch.Aarch64, }, ),
  111. "ios": JobSpec(name="iOS (CMake & xcode)", os=JobOs.MacosLatest, platform=SdlPlatform.Ios, artifact="SDL-ios-arm64", xcode=True, ),
  112. "tvos": JobSpec(name="tvOS (CMake & xcode)", os=JobOs.MacosLatest, platform=SdlPlatform.Tvos, artifact="SDL-tvos-arm64", xcode=True, ),
  113. "android-cmake": JobSpec(name="Android (CMake)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Android, artifact="SDL-android-arm64", android_abi="arm64-v8a", android_arch="aarch64", android_platform=23, ),
  114. "android-cmake-lean": JobSpec(name="Android (CMake, lean)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Android, artifact="SDL-lean-android-arm64", android_abi="arm64-v8a", android_arch="aarch64", android_platform=23, lean=True, ),
  115. "android-mk": JobSpec(name="Android (Android.mk)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Android, artifact=None, no_cmake=True, android_mk=True, ),
  116. "android-gradle": JobSpec(name="Android (Gradle)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Android, artifact=None, no_cmake=True, android_gradle=True, ),
  117. "emscripten": JobSpec(name="Emscripten", os=JobOs.UbuntuLatest, platform=SdlPlatform.Emscripten, artifact="SDL-emscripten", ),
  118. "haiku": JobSpec(name="Haiku", os=JobOs.UbuntuLatest, platform=SdlPlatform.Haiku, artifact="SDL-haiku-x64", container="ghcr.io/haiku/cross-compiler:x86_64-r1beta5", ),
  119. "loongarch64": JobSpec(name="LoongArch64", os=JobOs.UbuntuLatest, platform=SdlPlatform.LoongArch64, artifact="SDL-loongarch64", ),
  120. "n3ds": JobSpec(name="Nintendo 3DS", os=JobOs.UbuntuLatest, platform=SdlPlatform.N3ds, artifact="SDL-n3ds", container="devkitpro/devkitarm:latest", ),
  121. "ppc": JobSpec(name="PowerPC", os=JobOs.UbuntuLatest, platform=SdlPlatform.PowerPC, artifact="SDL-ppc", container="dockcross/linux-ppc:latest", ),
  122. "ppc64": JobSpec(name="PowerPC64", os=JobOs.UbuntuLatest, platform=SdlPlatform.PowerPC64, artifact="SDL-ppc64le", container="dockcross/linux-ppc64le:latest", ),
  123. "ps2": JobSpec(name="Sony PlayStation 2", os=JobOs.UbuntuLatest, platform=SdlPlatform.Ps2, artifact="SDL-ps2", container="ps2dev/ps2dev:latest", ),
  124. "psp": JobSpec(name="Sony PlayStation Portable", os=JobOs.UbuntuLatest, platform=SdlPlatform.Psp, artifact="SDL-psp", container="pspdev/pspdev:latest", ),
  125. "vita-pib": JobSpec(name="Sony PlayStation Vita (GLES w/ pib)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Vita, artifact="SDL-vita-pib", container="vitasdk/vitasdk:latest", vita_gles=VitaGLES.Pib, ),
  126. "vita-pvr": JobSpec(name="Sony PlayStation Vita (GLES w/ PVR_PSP2)", os=JobOs.UbuntuLatest, platform=SdlPlatform.Vita, artifact="SDL-vita-pvr", container="vitasdk/vitasdk:latest", vita_gles=VitaGLES.Pvr, ),
  127. "riscos": JobSpec(name="RISC OS", os=JobOs.UbuntuLatest, platform=SdlPlatform.Riscos, artifact="SDL-riscos", container="riscosdotinfo/riscos-gccsdk-4.7:latest", ),
  128. "netbsd": JobSpec(name="NetBSD", os=JobOs.UbuntuLatest, platform=SdlPlatform.NetBSD, artifact="SDL-netbsd-x64", ),
  129. "openbsd": JobSpec(name="OpenBSD", os=JobOs.UbuntuLatest, platform=SdlPlatform.OpenBSD, artifact="SDL-openbsd-x64", ),
  130. "freebsd": JobSpec(name="FreeBSD", os=JobOs.UbuntuLatest, platform=SdlPlatform.FreeBSD, artifact="SDL-freebsd-x64", ),
  131. "ngage": JobSpec(name="N-Gage", os=JobOs.WindowsLatest, platform=SdlPlatform.NGage, artifact="SDL-ngage", ),
  132. }
  133. class StaticLibType(Enum):
  134. STATIC_LIB = "SDL3-static.lib"
  135. A = "libSDL3.a"
  136. class SharedLibType(Enum):
  137. WIN32 = "SDL3.dll"
  138. SO_0 = "libSDL3.so.0"
  139. SO = "libSDL3.so"
  140. DYLIB = "libSDL3.0.dylib"
  141. FRAMEWORK = "SDL3.framework/Versions/A/SDL3"
  142. @dataclasses.dataclass(slots=True)
  143. class JobDetails:
  144. name: str
  145. key: str
  146. os: str
  147. platform: str
  148. artifact: str
  149. no_cmake: bool
  150. ccache: bool = False
  151. build_tests: bool = True
  152. container: str = ""
  153. cmake_build_type: str = "RelWithDebInfo"
  154. shell: str = "sh"
  155. sudo: str = "sudo"
  156. cmake_config_emulator: str = ""
  157. apk_packages: list[str] = dataclasses.field(default_factory=list)
  158. apt_packages: list[str] = dataclasses.field(default_factory=list)
  159. brew_packages: list[str] = dataclasses.field(default_factory=list)
  160. cmake_toolchain_file: str = ""
  161. cmake_arguments: list[str] = dataclasses.field(default_factory=list)
  162. cmake_generator: str = "Ninja"
  163. cmake_build_arguments: list[str] = dataclasses.field(default_factory=list)
  164. clang_tidy: bool = True
  165. cppflags: list[str] = dataclasses.field(default_factory=list)
  166. cc: str = ""
  167. cxx: str = ""
  168. cflags: list[str] = dataclasses.field(default_factory=list)
  169. cxxflags: list[str] = dataclasses.field(default_factory=list)
  170. ldflags: list[str] = dataclasses.field(default_factory=list)
  171. pollute_directories: list[str] = dataclasses.field(default_factory=list)
  172. use_cmake: bool = True
  173. shared: bool = True
  174. static: bool = True
  175. shared_lib: Optional[SharedLibType] = None
  176. static_lib: Optional[StaticLibType] = None
  177. run_tests: bool = True
  178. test_pkg_config: bool = True
  179. cc_from_cmake: bool = False
  180. source_cmd: str = ""
  181. pretest_cmd: str = ""
  182. java: bool = False
  183. android_apks: list[str] = dataclasses.field(default_factory=list)
  184. android_ndk: bool = False
  185. android_mk: bool = False
  186. android_gradle: bool = False
  187. minidump: bool = False
  188. intel: bool = False
  189. msys2_msystem: str = ""
  190. msys2_env: str = ""
  191. msys2_no_perl: bool = False
  192. werror: bool = True
  193. msvc_vcvars_arch: str = ""
  194. msvc_vcvars_sdk: str = ""
  195. msvc_project: str = ""
  196. msvc_project_flags: list[str] = dataclasses.field(default_factory=list)
  197. setup_ninja: bool = False
  198. setup_libusb_arch: str = ""
  199. xcode_sdk: str = ""
  200. cpactions: bool = False
  201. setup_gdk_folder: str = ""
  202. cpactions_os: str = ""
  203. cpactions_version: str = ""
  204. cpactions_arch: str = ""
  205. cpactions_setup_cmd: str = ""
  206. cpactions_install_cmd: str = ""
  207. setup_vita_gles_type: str = ""
  208. check_sources: bool = False
  209. setup_python: bool = False
  210. pypi_packages: list[str] = dataclasses.field(default_factory=list)
  211. setup_gage_sdk_path: str = ""
  212. binutils_strings: str = "strings"
  213. def to_workflow(self, enable_artifacts: bool) -> dict[str, str|bool]:
  214. data = {
  215. "name": self.name,
  216. "key": self.key,
  217. "os": self.os,
  218. "ccache": self.ccache,
  219. "container": self.container if self.container else "",
  220. "platform": self.platform,
  221. "artifact": self.artifact,
  222. "enable-artifacts": enable_artifacts,
  223. "shell": self.shell,
  224. "msys2-msystem": self.msys2_msystem,
  225. "msys2-env": self.msys2_env,
  226. "msys2-no-perl": self.msys2_no_perl,
  227. "android-ndk": self.android_ndk,
  228. "java": self.java,
  229. "intel": self.intel,
  230. "apk-packages": my_shlex_join(self.apk_packages),
  231. "apt-packages": my_shlex_join(self.apt_packages),
  232. "test-pkg-config": self.test_pkg_config,
  233. "brew-packages": my_shlex_join(self.brew_packages),
  234. "pollute-directories": my_shlex_join(self.pollute_directories),
  235. "no-cmake": self.no_cmake,
  236. "build-tests": self.build_tests,
  237. "source-cmd": self.source_cmd,
  238. "pretest-cmd": self.pretest_cmd,
  239. "cmake-config-emulator": self.cmake_config_emulator,
  240. "cc": self.cc,
  241. "cxx": self.cxx,
  242. "cflags": my_shlex_join(self.cppflags + self.cflags),
  243. "cxxflags": my_shlex_join(self.cppflags + self.cxxflags),
  244. "ldflags": my_shlex_join(self.ldflags),
  245. "cmake-generator": self.cmake_generator,
  246. "cmake-toolchain-file": self.cmake_toolchain_file,
  247. "clang-tidy": self.clang_tidy,
  248. "cmake-arguments": my_shlex_join(self.cmake_arguments),
  249. "cmake-build-arguments": my_shlex_join(self.cmake_build_arguments),
  250. "shared": self.shared,
  251. "static": self.static,
  252. "shared-lib": self.shared_lib.value if self.shared_lib else None,
  253. "static-lib": self.static_lib.value if self.static_lib else None,
  254. "cmake-build-type": self.cmake_build_type,
  255. "run-tests": self.run_tests,
  256. "android-apks": my_shlex_join(self.android_apks),
  257. "android-gradle": self.android_gradle,
  258. "android-mk": self.android_mk,
  259. "werror": self.werror,
  260. "sudo": self.sudo,
  261. "msvc-vcvars-arch": self.msvc_vcvars_arch,
  262. "msvc-vcvars-sdk": self.msvc_vcvars_sdk,
  263. "msvc-project": self.msvc_project,
  264. "msvc-project-flags": my_shlex_join(self.msvc_project_flags),
  265. "setup-ninja": self.setup_ninja,
  266. "setup-libusb-arch": self.setup_libusb_arch,
  267. "cc-from-cmake": self.cc_from_cmake,
  268. "xcode-sdk": self.xcode_sdk,
  269. "cpactions": self.cpactions,
  270. "cpactions-os": self.cpactions_os,
  271. "cpactions-version": self.cpactions_version,
  272. "cpactions-arch": self.cpactions_arch,
  273. "cpactions-setup-cmd": self.cpactions_setup_cmd,
  274. "cpactions-install-cmd": self.cpactions_install_cmd,
  275. "setup-vita-gles-type": self.setup_vita_gles_type,
  276. "setup-gdk-folder": self.setup_gdk_folder,
  277. "check-sources": self.check_sources,
  278. "setup-python": self.setup_python,
  279. "pypi-packages": my_shlex_join(self.pypi_packages),
  280. "setup-ngage-sdk-path": self.setup_gage_sdk_path,
  281. "binutils-strings": self.binutils_strings,
  282. }
  283. return {k: v for k, v in data.items() if v != ""}
  284. def my_shlex_join(s):
  285. def escape(s):
  286. if s[:1] == "'" and s[-1:] == "'":
  287. return s
  288. if set(s).intersection(set("; \t")):
  289. return f'"{s}"'
  290. return s
  291. return " ".join(escape(s))
  292. def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool) -> JobDetails:
  293. job = JobDetails(
  294. name=spec.name,
  295. key=key,
  296. os=spec.os.value,
  297. artifact=spec.artifact or "",
  298. container=spec.container or "",
  299. platform=spec.platform.value,
  300. sudo="sudo",
  301. no_cmake=spec.no_cmake,
  302. )
  303. if job.os.startswith("ubuntu"):
  304. job.apt_packages.extend([
  305. "ninja-build",
  306. "pkg-config",
  307. ])
  308. pretest_cmd = []
  309. if trackmem_symbol_names:
  310. pretest_cmd.append("export SDL_TRACKMEM_SYMBOL_NAMES=1")
  311. else:
  312. pretest_cmd.append("export SDL_TRACKMEM_SYMBOL_NAMES=0")
  313. win32 = spec.platform in (SdlPlatform.Msys2, SdlPlatform.Msvc)
  314. fpic = None
  315. build_parallel = True
  316. if spec.lean:
  317. job.cppflags.append("-DSDL_LEAN_AND_MEAN=1")
  318. if win32:
  319. job.cmake_arguments.append("-DSDLTEST_PROCDUMP=ON")
  320. job.minidump = True
  321. if spec.intel is not None:
  322. match spec.intel:
  323. case IntelCompiler.Icx:
  324. job.cc = "icx"
  325. job.cxx = "icpx"
  326. case IntelCompiler.Icc:
  327. job.cc = "icc"
  328. job.cxx = "icpc"
  329. # Disable deprecation warning
  330. job.cppflags.append("-diag-disable=10441")
  331. # Avoid 'Catastrophic error: cannot open precompiled header file'
  332. job.cmake_arguments.append("-DCMAKE_DISABLE_PRECOMPILE_HEADERS:BOOL=ON")
  333. job.clang_tidy = False
  334. case _:
  335. raise ValueError(f"Invalid intel={spec.intel}")
  336. job.source_cmd = f"source /opt/intel/oneapi/setvars.sh;"
  337. job.intel = True
  338. job.shell = "bash"
  339. job.cmake_arguments.extend((
  340. f"-DCMAKE_C_COMPILER={job.cc}",
  341. f"-DCMAKE_CXX_COMPILER={job.cxx}",
  342. "-DCMAKE_SYSTEM_NAME=Linux",
  343. ))
  344. match spec.platform:
  345. case SdlPlatform.Msvc:
  346. job.setup_ninja = not spec.gdk
  347. job.clang_tidy = False # complains about \threadsafety: "unknown command tag name [clang-diagnostic-documentation-unknown-command]"
  348. job.msvc_project = spec.msvc_project if spec.msvc_project else ""
  349. job.msvc_project_flags.append("-p:TreatWarningsAsError=true")
  350. job.test_pkg_config = False
  351. job.shared_lib = SharedLibType.WIN32
  352. job.static_lib = StaticLibType.STATIC_LIB
  353. job.cmake_arguments.extend((
  354. "-DCMAKE_MSVC_DEBUG_INFORMATION_FORMAT=ProgramDatabase",
  355. "-DCMAKE_EXE_LINKER_FLAGS=-DEBUG",
  356. "-DCMAKE_SHARED_LINKER_FLAGS=-DEBUG",
  357. ))
  358. job.cmake_arguments.append("'-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded$<$<CONFIG:Debug>:Debug>'")
  359. if spec.clang_cl:
  360. job.cmake_arguments.extend((
  361. "-DCMAKE_C_COMPILER=clang-cl",
  362. "-DCMAKE_CXX_COMPILER=clang-cl",
  363. ))
  364. match spec.msvc_arch:
  365. case MsvcArch.X86:
  366. job.cflags.append("/clang:-m32")
  367. job.cxxflags.append("/clang:-m32")
  368. job.ldflags.append("/MACHINE:X86")
  369. case MsvcArch.X64:
  370. job.cflags.append("/clang:-m64")
  371. job.cxxflags.append("/clang:-m64")
  372. job.ldflags.append("/MACHINE:X64")
  373. case _:
  374. raise ValueError(f"Unsupported clang-cl architecture (arch={spec.msvc_arch})")
  375. if spec.msvc_project:
  376. match spec.msvc_arch:
  377. case MsvcArch.X86:
  378. msvc_platform = "Win32"
  379. case MsvcArch.X64:
  380. msvc_platform = "x64"
  381. case _:
  382. raise ValueError(f"Unsupported vcxproj architecture (arch={spec.msvc_arch})")
  383. if spec.gdk:
  384. msvc_platform = f"Gaming.Desktop.{msvc_platform}"
  385. job.msvc_project_flags.append(f"-p:Platform={msvc_platform}")
  386. match spec.msvc_arch:
  387. case MsvcArch.X86:
  388. job.msvc_vcvars_arch = "x64_x86"
  389. case MsvcArch.X64:
  390. job.msvc_vcvars_arch = "x64"
  391. case MsvcArch.Arm64:
  392. job.msvc_vcvars_arch = "x64_arm64"
  393. job.run_tests = False
  394. if spec.gdk:
  395. job.setup_gdk_folder = "VisualC-GDK"
  396. else:
  397. match spec.msvc_arch:
  398. case MsvcArch.X86:
  399. job.setup_libusb_arch = "x86"
  400. case MsvcArch.X64:
  401. job.setup_libusb_arch = "x64"
  402. case SdlPlatform.Linux:
  403. if spec.name.startswith("Ubuntu"):
  404. assert spec.os.value.startswith("ubuntu-")
  405. job.apt_packages.extend((
  406. "ccache",
  407. "gnome-desktop-testing",
  408. "libasound2-dev",
  409. "libpulse-dev",
  410. "libaudio-dev",
  411. "libjack-dev",
  412. "libsndio-dev",
  413. "libusb-1.0-0-dev",
  414. "libx11-dev",
  415. "libxext-dev",
  416. "libxrandr-dev",
  417. "libxcursor-dev",
  418. "libxfixes-dev",
  419. "libxi-dev",
  420. "libxss-dev",
  421. "libxtst-dev",
  422. "libwayland-dev",
  423. "libxkbcommon-dev",
  424. "libdrm-dev",
  425. "libgbm-dev",
  426. "libgl1-mesa-dev",
  427. "libgles2-mesa-dev",
  428. "libegl1-mesa-dev",
  429. "libdbus-1-dev",
  430. "libibus-1.0-dev",
  431. "libudev-dev",
  432. "fcitx-libs-dev",
  433. "libfribidi-dev",
  434. # testffmpeg
  435. "libavcodec-dev",
  436. "libavfilter-dev",
  437. "libavutil-dev",
  438. "libswresample-dev",
  439. "libswscale-dev",
  440. ))
  441. match = re.match(r"ubuntu-(?P<year>[0-9]+)\.(?P<month>[0-9]+|latest).*", spec.os.value)
  442. ubuntu_ge_22 = True
  443. if match and match["month"] != "latest":
  444. ubuntu_year, ubuntu_month = [int(match["year"]), int(match["month"])]
  445. ubuntu_ge_22 = ubuntu_year >= 22
  446. job.apt_packages.extend(("libpipewire-0.3-dev", "libdecor-0-dev"))
  447. job.apt_packages.extend((
  448. "libunwind-dev", # For SDL_test memory tracking
  449. ))
  450. job.ccache = True
  451. if trackmem_symbol_names:
  452. # older libunwind is slow
  453. job.cmake_arguments.append("-DSDLTEST_TIMEOUT_MULTIPLIER=2")
  454. job.shared_lib = SharedLibType.SO_0
  455. job.static_lib = StaticLibType.A
  456. fpic = True
  457. if spec.more_hard_deps:
  458. # Some distros prefer to make important dependencies
  459. # mandatory, so that SDL won't start up but lack expected
  460. # functionality if they're missing
  461. job.cmake_arguments.extend([
  462. "-DSDL_ALSA_SHARED=OFF",
  463. "-DSDL_FRIBIDI_SHARED=OFF",
  464. "-DSDL_HIDAPI_LIBUSB_SHARED=OFF",
  465. "-DSDL_PULSEAUDIO_SHARED=OFF",
  466. "-DSDL_X11_SHARED=OFF",
  467. "-DSDL_WAYLAND_LIBDECOR_SHARED=OFF",
  468. "-DSDL_WAYLAND_SHARED=OFF",
  469. ])
  470. case SdlPlatform.Ios | SdlPlatform.Tvos:
  471. job.brew_packages.extend([
  472. "ccache",
  473. "ninja",
  474. ])
  475. job.ccache = True
  476. job.clang_tidy = False
  477. job.run_tests = False
  478. job.test_pkg_config = False
  479. job.shared_lib = SharedLibType.DYLIB
  480. job.static_lib = StaticLibType.A
  481. match spec.platform:
  482. case SdlPlatform.Ios:
  483. if spec.xcode:
  484. job.xcode_sdk = 'iphoneos'
  485. job.cmake_arguments.extend([
  486. "-DCMAKE_SYSTEM_NAME=iOS",
  487. "-DCMAKE_OSX_ARCHITECTURES=\"arm64\"",
  488. "-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0",
  489. ])
  490. case SdlPlatform.Tvos:
  491. if spec.xcode:
  492. job.xcode_sdk = 'appletvos'
  493. job.cmake_arguments.extend([
  494. "-DCMAKE_SYSTEM_NAME=tvOS",
  495. "-DCMAKE_OSX_ARCHITECTURES=\"arm64\"",
  496. "-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0",
  497. ])
  498. case SdlPlatform.MacOS:
  499. if spec.apple_framework:
  500. job.static = False
  501. job.clang_tidy = False
  502. job.test_pkg_config = False
  503. job.cmake_arguments.extend((
  504. "'-DCMAKE_OSX_ARCHITECTURES=x86_64;arm64'",
  505. "-DCMAKE_OSX_DEPLOYMENT_TARGET=10.13",
  506. "-DSDL_FRAMEWORK=ON",
  507. ))
  508. job.shared_lib = SharedLibType.FRAMEWORK
  509. else:
  510. job.clang_tidy = True
  511. job.cmake_arguments.extend((
  512. "-DCMAKE_OSX_ARCHITECTURES=arm64",
  513. "-DCMAKE_OSX_DEPLOYMENT_TARGET=10.13",
  514. "-DCLANG_TIDY_BINARY=$(brew --prefix llvm)/bin/clang-tidy",
  515. ))
  516. job.brew_packages.extend((
  517. # Brew provides a single architecture (aarch64), so it's not usable for fat libraries
  518. "ffmpeg", # testffmpeg
  519. ))
  520. job.shared_lib = SharedLibType.DYLIB
  521. job.static_lib = StaticLibType.A
  522. job.ccache = True
  523. job.apt_packages = []
  524. job.brew_packages.extend((
  525. "ninja",
  526. ))
  527. if job.ccache:
  528. job.brew_packages.append("ccache")
  529. if job.clang_tidy:
  530. job.brew_packages.append("llvm")
  531. if spec.xcode:
  532. job.xcode_sdk = "macosx"
  533. case SdlPlatform.Android:
  534. job.android_gradle = spec.android_gradle
  535. job.android_mk = spec.android_mk
  536. job.apt_packages.append("ccache")
  537. job.run_tests = False
  538. job.shared_lib = SharedLibType.SO
  539. job.static_lib = StaticLibType.A
  540. if spec.android_mk or not spec.no_cmake:
  541. job.android_ndk = True
  542. if spec.android_gradle or not spec.no_cmake:
  543. job.java = True
  544. if spec.android_mk or spec.android_gradle:
  545. job.apt_packages = []
  546. if not spec.no_cmake:
  547. job.ccache = True
  548. job.cmake_arguments.extend((
  549. f"-DANDROID_PLATFORM={spec.android_platform}",
  550. f"-DANDROID_ABI={spec.android_abi}",
  551. ))
  552. job.cmake_toolchain_file = "${ANDROID_NDK_HOME}/build/cmake/android.toolchain.cmake"
  553. job.cc = f"${{ANDROID_NDK_HOME}}/toolchains/llvm/prebuilt/linux-x86_64/bin/clang --target={spec.android_arch}-none-linux-androideabi{spec.android_platform}"
  554. job.android_apks = [
  555. "testaudiorecording-apk",
  556. "testautomation-apk",
  557. "testcontroller-apk",
  558. "testmultiaudio-apk",
  559. "testsprite-apk",
  560. ]
  561. # -fPIC is required after updating NDK from 21 to 28
  562. job.cflags.append("-fPIC")
  563. job.cxxflags.append("-fPIC")
  564. case SdlPlatform.Emscripten:
  565. job.clang_tidy = False # clang-tidy does not understand -gsource-map
  566. job.shared = False
  567. job.ccache = True
  568. job.apt_packages.append("ccache")
  569. job.cmake_config_emulator = "emcmake"
  570. job.cmake_build_type = "Debug"
  571. job.test_pkg_config = False
  572. job.cmake_arguments.extend((
  573. "-DSDLTEST_BROWSER=chrome",
  574. "-DSDLTEST_TIMEOUT_MULTIPLIER=4",
  575. "-DSDLTEST_CHROME_BINARY=${CHROME_BINARY}",
  576. ))
  577. job.cflags.extend((
  578. "-gsource-map",
  579. "-ffile-prefix-map=${PWD}=/SDL",
  580. ))
  581. job.ldflags.extend((
  582. "--source-map-base", "/",
  583. ))
  584. pretest_cmd.extend((
  585. "# Start local HTTP server",
  586. "cmake --build build --target serve-sdl-tests --verbose &",
  587. "chrome --version",
  588. "chromedriver --version",
  589. ))
  590. job.static_lib = StaticLibType.A
  591. job.setup_python = True
  592. job.pypi_packages.append("selenium")
  593. case SdlPlatform.Ps2:
  594. job.ccache = False # actions/ccache does not work in psp container (incompatible tar of busybox)
  595. build_parallel = False
  596. job.shared = False
  597. job.sudo = ""
  598. job.apt_packages = []
  599. job.apk_packages = ["ccache", "cmake", "gmp", "mpc1", "mpfr4", "ninja", "pkgconf", "git", ]
  600. job.cmake_toolchain_file = "${PS2DEV}/ps2sdk/ps2dev.cmake"
  601. job.clang_tidy = False
  602. job.run_tests = False
  603. job.shared = False
  604. job.cc = "mips64r5900el-ps2-elf-gcc"
  605. job.ldflags = ["-L${PS2DEV}/ps2sdk/ee/lib", "-L${PS2DEV}/gsKit/lib", "-L${PS2DEV}/ps2sdk/ports/lib", ]
  606. job.static_lib = StaticLibType.A
  607. case SdlPlatform.Psp:
  608. job.ccache = False # actions/ccache does not work in psp container (incompatible tar of busybox)
  609. build_parallel = False
  610. job.sudo = ""
  611. job.apt_packages = []
  612. job.apk_packages = ["ccache", "cmake", "gmp", "mpc1", "mpfr4", "ninja", "pkgconf", ]
  613. job.cmake_toolchain_file = "${PSPDEV}/psp/share/pspdev.cmake"
  614. job.clang_tidy = False
  615. job.run_tests = False
  616. job.shared = False
  617. job.cc = "psp-gcc"
  618. job.ldflags = ["-L${PSPDEV}/lib", "-L${PSPDEV}/psp/lib", "-L${PSPDEV}/psp/sdk/lib", ]
  619. job.pollute_directories = ["${PSPDEV}/include", "${PSPDEV}/psp/include", "${PSPDEV}/psp/sdk/include", ]
  620. job.static_lib = StaticLibType.A
  621. case SdlPlatform.Vita:
  622. job.ccache = True
  623. job.sudo = ""
  624. job.apt_packages = []
  625. job.apk_packages = ["ccache", "cmake", "ninja", "pkgconf", "bash", "tar"]
  626. job.cmake_toolchain_file = "${VITASDK}/share/vita.toolchain.cmake"
  627. assert spec.vita_gles is not None
  628. job.setup_vita_gles_type = {
  629. VitaGLES.Pib: "pib",
  630. VitaGLES.Pvr: "pvr",
  631. }[spec.vita_gles]
  632. job.cmake_arguments.extend((
  633. f"-DVIDEO_VITA_PIB={ 'true' if spec.vita_gles == VitaGLES.Pib else 'false' }",
  634. f"-DVIDEO_VITA_PVR={ 'true' if spec.vita_gles == VitaGLES.Pvr else 'false' }",
  635. "-DSDL_ARMNEON=ON",
  636. "-DSDL_ARMSIMD=ON",
  637. ))
  638. # Fix vita.toolchain.cmake (https://github.com/vitasdk/vita-toolchain/pull/253)
  639. job.source_cmd = r"""sed -i -E "s#set\\( PKG_CONFIG_EXECUTABLE \"\\$\\{VITASDK}/bin/arm-vita-eabi-pkg-config\" \\)#set\\( PKG_CONFIG_EXECUTABLE \"${VITASDK}/bin/arm-vita-eabi-pkg-config\" CACHE PATH \"Path of pkg-config executable\" \\)#" ${VITASDK}/share/vita.toolchain.cmake"""
  640. job.clang_tidy = False
  641. job.run_tests = False
  642. job.shared = False
  643. job.cc = "arm-vita-eabi-gcc"
  644. job.static_lib = StaticLibType.A
  645. case SdlPlatform.Haiku:
  646. job.ccache = True
  647. fpic = False
  648. job.run_tests = False
  649. job.apt_packages.append("ccache")
  650. job.cc = "x86_64-unknown-haiku-gcc"
  651. job.cxx = "x86_64-unknown-haiku-g++"
  652. job.sudo = ""
  653. job.cmake_arguments.extend((
  654. f"-DCMAKE_C_COMPILER={job.cc}",
  655. f"-DCMAKE_CXX_COMPILER={job.cxx}",
  656. "-DCMAKE_SYSTEM_NAME=Haiku",
  657. ))
  658. job.shared_lib = SharedLibType.SO_0
  659. job.static_lib = StaticLibType.A
  660. case SdlPlatform.PowerPC64 | SdlPlatform.PowerPC:
  661. job.ccache = True
  662. # FIXME: Enable SDL_WERROR
  663. job.werror = False
  664. job.clang_tidy = False
  665. job.run_tests = False
  666. job.sudo = ""
  667. job.apt_packages = ["ccache"]
  668. job.shared_lib = SharedLibType.SO_0
  669. job.static_lib = StaticLibType.A
  670. job.cmake_arguments.extend((
  671. "-DSDL_UNIX_CONSOLE_BUILD=ON",
  672. ))
  673. case SdlPlatform.LoongArch64:
  674. job.ccache = True
  675. fpic = True
  676. job.run_tests = False
  677. job.apt_packages.append("ccache")
  678. job.cc = "${LOONGARCH64_CC}"
  679. job.cxx = "${LOONGARCH64_CXX}"
  680. job.cmake_arguments.extend((
  681. f"-DCMAKE_C_COMPILER={job.cc}",
  682. f"-DCMAKE_CXX_COMPILER={job.cxx}",
  683. "-DSDL_UNIX_CONSOLE_BUILD=ON",
  684. "-DCMAKE_SYSTEM_NAME=Linux",
  685. ))
  686. job.shared_lib = SharedLibType.SO_0
  687. job.static_lib = StaticLibType.A
  688. case SdlPlatform.N3ds:
  689. job.cmake_generator = "Unix Makefiles"
  690. job.cmake_build_arguments.append("-j$(nproc)")
  691. job.ccache = False
  692. job.shared = False
  693. job.apt_packages = []
  694. job.clang_tidy = False
  695. job.run_tests = False
  696. job.cc_from_cmake = True
  697. job.cmake_toolchain_file = "${DEVKITPRO}/cmake/3DS.cmake"
  698. job.binutils_strings = "/opt/devkitpro/devkitARM/bin/arm-none-eabi-strings"
  699. job.static_lib = StaticLibType.A
  700. case SdlPlatform.Msys2:
  701. job.ccache = True
  702. job.shell = "msys2 {0}"
  703. assert spec.msys2_platform
  704. job.msys2_msystem = spec.msys2_platform.value
  705. job.msys2_env = {
  706. "mingw32": "mingw-w64-i686",
  707. "mingw64": "mingw-w64-x86_64",
  708. "clang64": "mingw-w64-clang-x86_64",
  709. "ucrt64": "mingw-w64-ucrt-x86_64",
  710. }[spec.msys2_platform.value]
  711. job.msys2_no_perl = spec.msys2_platform in (Msys2Platform.Mingw32, )
  712. job.shared_lib = SharedLibType.WIN32
  713. job.static_lib = StaticLibType.A
  714. case SdlPlatform.Riscos:
  715. job.ccache = False # FIXME: enable when container gets upgrade
  716. # FIXME: Enable SDL_WERROR
  717. job.werror = False
  718. job.apt_packages = ["ccache", "cmake", "ninja-build"]
  719. job.test_pkg_config = False
  720. job.shared = False
  721. job.run_tests = False
  722. job.sudo = ""
  723. job.cmake_arguments.extend((
  724. "-DRISCOS:BOOL=ON",
  725. "-DCMAKE_DISABLE_PRECOMPILE_HEADERS:BOOL=ON",
  726. "-DSDL_GCC_ATOMICS:BOOL=OFF",
  727. ))
  728. job.cmake_toolchain_file = "/home/riscos/env/toolchain-riscos.cmake"
  729. job.static_lib = StaticLibType.A
  730. case SdlPlatform.FreeBSD | SdlPlatform.NetBSD | SdlPlatform.OpenBSD:
  731. job.cpactions = True
  732. job.no_cmake = True
  733. job.run_tests = False
  734. job.apt_packages = []
  735. job.shared_lib = SharedLibType.SO_0
  736. job.static_lib = StaticLibType.A
  737. match spec.platform:
  738. case SdlPlatform.FreeBSD:
  739. job.cpactions_os = "freebsd"
  740. job.cpactions_version = "14.3"
  741. job.cpactions_arch = "x86-64"
  742. job.cpactions_setup_cmd = "sudo pkg update"
  743. job.cpactions_install_cmd = "sudo pkg install -y cmake ninja pkgconf libXcursor libXext libXinerama libXi libXfixes libXrandr libXScrnSaver libXxf86vm wayland wayland-protocols libxkbcommon mesa-libs libglvnd evdev-proto libinotify alsa-lib jackit pipewire pulseaudio sndio dbus zh-fcitx ibus libudev-devd"
  744. job.cmake_arguments.extend((
  745. "-DSDL_CHECK_REQUIRED_INCLUDES=/usr/local/include",
  746. "-DSDL_CHECK_REQUIRED_LINK_OPTIONS=-L/usr/local/lib",
  747. ))
  748. case SdlPlatform.NetBSD:
  749. job.cpactions_os = "netbsd"
  750. job.cpactions_version = "10.1"
  751. job.cpactions_arch = "x86-64"
  752. job.cpactions_setup_cmd = "export PATH=\"/usr/pkg/sbin:/usr/pkg/bin:/sbin:$PATH\"; export PKG_CONFIG_PATH=\"/usr/pkg/lib/pkgconfig\";export PKG_PATH=\"https://cdn.netBSD.org/pub/pkgsrc/packages/NetBSD/$(uname -p)/$(uname -r|cut -f \"1 2\" -d.)/All/\";echo \"PKG_PATH=$PKG_PATH\";echo \"uname -a -> \"$(uname -a)\"\";sudo -E sysctl -w security.pax.aslr.enabled=0;sudo -E sysctl -w security.pax.aslr.global=0;sudo -E pkgin clean;sudo -E pkgin update"
  753. job.cpactions_install_cmd = "sudo -E pkgin -y install cmake dbus pkgconf ninja-build pulseaudio libxkbcommon wayland wayland-protocols libinotify libusb1"
  754. case SdlPlatform.OpenBSD:
  755. job.cpactions_os = "openbsd"
  756. job.cpactions_version = "7.7"
  757. job.cpactions_arch = "x86-64"
  758. job.cpactions_setup_cmd = "sudo pkg_add -u"
  759. job.cpactions_install_cmd = "sudo pkg_add cmake ninja pkgconf wayland wayland-protocols libxkbcommon libinotify pulseaudio dbus ibus"
  760. case SdlPlatform.NGage:
  761. build_parallel = False
  762. job.cmake_build_type = "Release"
  763. job.setup_ninja = True
  764. job.static_lib = StaticLibType.STATIC_LIB
  765. job.shared_lib = None
  766. job.clang_tidy = False
  767. job.werror = False # FIXME: enable SDL_WERROR
  768. job.shared = False
  769. job.run_tests = False
  770. job.setup_gage_sdk_path = "C:/ngagesdk"
  771. job.cmake_toolchain_file = "C:/ngagesdk/cmake/ngage-toolchain.cmake"
  772. job.test_pkg_config = False
  773. case _:
  774. raise ValueError(f"Unsupported platform={spec.platform}")
  775. if "ubuntu" in spec.name.lower():
  776. job.check_sources = True
  777. job.setup_python = True
  778. if job.ccache:
  779. job.cmake_arguments.extend((
  780. "-DCMAKE_C_COMPILER_LAUNCHER=ccache",
  781. "-DCMAKE_CXX_COMPILER_LAUNCHER=ccache",
  782. ))
  783. if not build_parallel:
  784. job.cmake_build_arguments.append("-j1")
  785. if job.cflags or job.cppflags:
  786. job.cmake_arguments.append(f"-DCMAKE_C_FLAGS=\"{my_shlex_join(job.cflags + job.cppflags)}\"")
  787. if job.cxxflags or job.cppflags:
  788. job.cmake_arguments.append(f"-DCMAKE_CXX_FLAGS=\"{my_shlex_join(job.cxxflags + job.cppflags)}\"")
  789. if job.ldflags:
  790. job.cmake_arguments.append(f"-DCMAKE_SHARED_LINKER_FLAGS=\"{my_shlex_join(job.ldflags)}\"")
  791. job.cmake_arguments.append(f"-DCMAKE_EXE_LINKER_FLAGS=\"{my_shlex_join(job.ldflags)}\"")
  792. job.pretest_cmd = "\n".join(pretest_cmd)
  793. def tf(b):
  794. return "ON" if b else "OFF"
  795. if fpic is not None:
  796. job.cmake_arguments.append(f"-DCMAKE_POSITION_INDEPENDENT_CODE={tf(fpic)}")
  797. if job.no_cmake:
  798. job.cmake_arguments = []
  799. return job
  800. def spec_to_platform(spec: JobSpec, key: str, enable_artifacts: bool, trackmem_symbol_names: bool) -> dict[str, str|bool]:
  801. logger.info("spec=%r", spec)
  802. job = spec_to_job(spec, key=key, trackmem_symbol_names=trackmem_symbol_names)
  803. logger.info("job=%r", job)
  804. platform = job.to_workflow(enable_artifacts=enable_artifacts)
  805. logger.info("platform=%r", platform)
  806. return platform
  807. def main():
  808. parser = argparse.ArgumentParser(allow_abbrev=False)
  809. parser.add_argument("--github-variable-prefix", default="platforms")
  810. parser.add_argument("--github-ci", action="store_true")
  811. parser.add_argument("--verbose", action="store_true")
  812. parser.add_argument("--commit-message-file")
  813. parser.add_argument("--no-artifact", dest="enable_artifacts", action="store_false")
  814. parser.add_argument("--trackmem-symbol-names", dest="trackmem_symbol_names", action="store_true")
  815. args = parser.parse_args()
  816. logging.basicConfig(level=logging.INFO if args.verbose else logging.WARNING)
  817. remaining_keys = set(JOB_SPECS.keys())
  818. all_level_keys = (
  819. # Level 1
  820. (
  821. "haiku",
  822. ),
  823. )
  824. filters = []
  825. if args.commit_message_file:
  826. with open(args.commit_message_file, "r") as f:
  827. commit_message = f.read()
  828. for m in re.finditer(r"\[sdl-ci-filter (.*)]", commit_message, flags=re.M):
  829. filters.append(m.group(1).strip(" \t\n\r\t'\""))
  830. if re.search(r"\[sdl-ci-artifacts?]", commit_message, flags=re.M):
  831. args.enable_artifacts = True
  832. if re.search(r"\[sdl-ci-(full-)?trackmem(-symbol-names)?]", commit_message, flags=re.M):
  833. args.trackmem_symbol_names = True
  834. if not filters:
  835. filters.append("*")
  836. logger.info("filters: %r", filters)
  837. all_level_platforms = {}
  838. all_platforms = {key: spec_to_platform(spec, key=key, enable_artifacts=args.enable_artifacts, trackmem_symbol_names=args.trackmem_symbol_names) for key, spec in JOB_SPECS.items()}
  839. for level_i, level_keys in enumerate(all_level_keys, 1):
  840. level_key = f"level{level_i}"
  841. logger.info("Level %d: keys=%r", level_i, level_keys)
  842. assert all(k in remaining_keys for k in level_keys)
  843. level_platforms = tuple(all_platforms[key] for key in level_keys)
  844. remaining_keys.difference_update(level_keys)
  845. all_level_platforms[level_key] = level_platforms
  846. logger.info("=" * 80)
  847. logger.info("Keys before filter: %r", remaining_keys)
  848. filtered_remaining_keys = set()
  849. for filter in filters:
  850. filtered_remaining_keys.update(fnmatch.filter(remaining_keys, filter))
  851. logger.info("Keys after filter: %r", filtered_remaining_keys)
  852. remaining_keys = filtered_remaining_keys
  853. logger.info("Remaining: %r", remaining_keys)
  854. all_level_platforms["others"] = tuple(all_platforms[key] for key in remaining_keys)
  855. if args.github_ci:
  856. for level, platforms in all_level_platforms.items():
  857. platforms_json = json.dumps(platforms)
  858. txt = f"{args.github_variable_prefix}-{level}={platforms_json}"
  859. logger.info("%s", txt)
  860. if "GITHUB_OUTPUT" in os.environ:
  861. with open(os.environ["GITHUB_OUTPUT"], "a") as f:
  862. f.write(txt)
  863. f.write("\n")
  864. else:
  865. logger.warning("GITHUB_OUTPUT not defined")
  866. return 0
  867. if __name__ == "__main__":
  868. raise SystemExit(main())