create-test-plan.py 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933
  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, msvc_project="VisualC/SDL.sln", ),
  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 MsvcArch.Arm64:
  382. msvc_platform = "ARM64"
  383. case _:
  384. raise ValueError(f"Unsupported vcxproj architecture (arch={spec.msvc_arch})")
  385. if spec.gdk:
  386. msvc_platform = f"Gaming.Desktop.{msvc_platform}"
  387. job.msvc_project_flags.append(f"-p:Platform={msvc_platform}")
  388. match spec.msvc_arch:
  389. case MsvcArch.X86:
  390. job.msvc_vcvars_arch = "x64_x86"
  391. case MsvcArch.X64:
  392. job.msvc_vcvars_arch = "x64"
  393. case MsvcArch.Arm64:
  394. job.msvc_vcvars_arch = "x64_arm64"
  395. job.run_tests = False
  396. if spec.gdk:
  397. job.setup_gdk_folder = "VisualC-GDK"
  398. else:
  399. match spec.msvc_arch:
  400. case MsvcArch.X86:
  401. job.setup_libusb_arch = "x86"
  402. case MsvcArch.X64:
  403. job.setup_libusb_arch = "x64"
  404. case SdlPlatform.Linux:
  405. if spec.name.startswith("Ubuntu"):
  406. assert spec.os.value.startswith("ubuntu-")
  407. job.apt_packages.extend((
  408. "ccache",
  409. "gnome-desktop-testing",
  410. "libasound2-dev",
  411. "libpulse-dev",
  412. "libaudio-dev",
  413. "libjack-dev",
  414. "libsndio-dev",
  415. "libusb-1.0-0-dev",
  416. "libx11-dev",
  417. "libxext-dev",
  418. "libxrandr-dev",
  419. "libxcursor-dev",
  420. "libxfixes-dev",
  421. "libxi-dev",
  422. "libxss-dev",
  423. "libxtst-dev",
  424. "libwayland-dev",
  425. "libxkbcommon-dev",
  426. "libdrm-dev",
  427. "libgbm-dev",
  428. "libgl1-mesa-dev",
  429. "libgles2-mesa-dev",
  430. "libegl1-mesa-dev",
  431. "libdbus-1-dev",
  432. "libibus-1.0-dev",
  433. "libudev-dev",
  434. "fcitx-libs-dev",
  435. "libfribidi-dev",
  436. # testffmpeg
  437. "libavcodec-dev",
  438. "libavfilter-dev",
  439. "libavutil-dev",
  440. "libswresample-dev",
  441. "libswscale-dev",
  442. ))
  443. match = re.match(r"ubuntu-(?P<year>[0-9]+)\.(?P<month>[0-9]+|latest).*", spec.os.value)
  444. ubuntu_ge_22 = True
  445. if match and match["month"] != "latest":
  446. ubuntu_year, ubuntu_month = [int(match["year"]), int(match["month"])]
  447. ubuntu_ge_22 = ubuntu_year >= 22
  448. job.apt_packages.extend(("libpipewire-0.3-dev", "libdecor-0-dev"))
  449. job.apt_packages.extend((
  450. "libunwind-dev", # For SDL_test memory tracking
  451. ))
  452. job.ccache = True
  453. if trackmem_symbol_names:
  454. # older libunwind is slow
  455. job.cmake_arguments.append("-DSDLTEST_TIMEOUT_MULTIPLIER=2")
  456. job.shared_lib = SharedLibType.SO_0
  457. job.static_lib = StaticLibType.A
  458. fpic = True
  459. if spec.more_hard_deps:
  460. # Some distros prefer to make important dependencies
  461. # mandatory, so that SDL won't start up but lack expected
  462. # functionality if they're missing
  463. job.cmake_arguments.extend([
  464. "-DSDL_ALSA_SHARED=OFF",
  465. "-DSDL_FRIBIDI_SHARED=OFF",
  466. "-DSDL_HIDAPI_LIBUSB_SHARED=OFF",
  467. "-DSDL_PULSEAUDIO_SHARED=OFF",
  468. "-DSDL_X11_SHARED=OFF",
  469. "-DSDL_WAYLAND_LIBDECOR_SHARED=OFF",
  470. "-DSDL_WAYLAND_SHARED=OFF",
  471. ])
  472. case SdlPlatform.Ios | SdlPlatform.Tvos:
  473. job.brew_packages.extend([
  474. "ccache",
  475. "ninja",
  476. ])
  477. job.ccache = True
  478. job.clang_tidy = False
  479. job.run_tests = False
  480. job.test_pkg_config = False
  481. job.shared_lib = SharedLibType.DYLIB
  482. job.static_lib = StaticLibType.A
  483. match spec.platform:
  484. case SdlPlatform.Ios:
  485. if spec.xcode:
  486. job.xcode_sdk = 'iphoneos'
  487. job.cmake_arguments.extend([
  488. "-DCMAKE_SYSTEM_NAME=iOS",
  489. "-DCMAKE_OSX_ARCHITECTURES=\"arm64\"",
  490. "-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0",
  491. ])
  492. case SdlPlatform.Tvos:
  493. if spec.xcode:
  494. job.xcode_sdk = 'appletvos'
  495. job.cmake_arguments.extend([
  496. "-DCMAKE_SYSTEM_NAME=tvOS",
  497. "-DCMAKE_OSX_ARCHITECTURES=\"arm64\"",
  498. "-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0",
  499. ])
  500. case SdlPlatform.MacOS:
  501. if spec.apple_framework:
  502. job.static = False
  503. job.clang_tidy = False
  504. job.test_pkg_config = False
  505. job.cmake_arguments.extend((
  506. "'-DCMAKE_OSX_ARCHITECTURES=x86_64;arm64'",
  507. "-DCMAKE_OSX_DEPLOYMENT_TARGET=10.13",
  508. "-DSDL_FRAMEWORK=ON",
  509. ))
  510. job.shared_lib = SharedLibType.FRAMEWORK
  511. else:
  512. job.clang_tidy = True
  513. job.cmake_arguments.extend((
  514. "-DCMAKE_OSX_ARCHITECTURES=arm64",
  515. "-DCMAKE_OSX_DEPLOYMENT_TARGET=10.13",
  516. "-DCLANG_TIDY_BINARY=$(brew --prefix llvm)/bin/clang-tidy",
  517. ))
  518. job.brew_packages.extend((
  519. # Brew provides a single architecture (aarch64), so it's not usable for fat libraries
  520. "ffmpeg", # testffmpeg
  521. ))
  522. job.shared_lib = SharedLibType.DYLIB
  523. job.static_lib = StaticLibType.A
  524. job.ccache = True
  525. job.apt_packages = []
  526. job.brew_packages.extend((
  527. "ninja",
  528. ))
  529. if job.ccache:
  530. job.brew_packages.append("ccache")
  531. if job.clang_tidy:
  532. job.brew_packages.append("llvm")
  533. if spec.xcode:
  534. job.xcode_sdk = "macosx"
  535. case SdlPlatform.Android:
  536. job.android_gradle = spec.android_gradle
  537. job.android_mk = spec.android_mk
  538. job.apt_packages.append("ccache")
  539. job.run_tests = False
  540. job.shared_lib = SharedLibType.SO
  541. job.static_lib = StaticLibType.A
  542. if spec.android_mk or not spec.no_cmake:
  543. job.android_ndk = True
  544. if spec.android_gradle or not spec.no_cmake:
  545. job.java = True
  546. if spec.android_mk or spec.android_gradle:
  547. job.apt_packages = []
  548. if not spec.no_cmake:
  549. job.ccache = True
  550. job.cmake_arguments.extend((
  551. f"-DANDROID_PLATFORM={spec.android_platform}",
  552. f"-DANDROID_ABI={spec.android_abi}",
  553. ))
  554. job.cmake_toolchain_file = "${ANDROID_NDK_HOME}/build/cmake/android.toolchain.cmake"
  555. job.cc = f"${{ANDROID_NDK_HOME}}/toolchains/llvm/prebuilt/linux-x86_64/bin/clang --target={spec.android_arch}-none-linux-androideabi{spec.android_platform}"
  556. job.android_apks = [
  557. "testaudiorecording-apk",
  558. "testautomation-apk",
  559. "testcontroller-apk",
  560. "testmultiaudio-apk",
  561. "testsprite-apk",
  562. ]
  563. # -fPIC is required after updating NDK from 21 to 28
  564. job.cflags.append("-fPIC")
  565. job.cxxflags.append("-fPIC")
  566. case SdlPlatform.Emscripten:
  567. job.clang_tidy = False # clang-tidy does not understand -gsource-map
  568. job.shared = False
  569. job.ccache = True
  570. job.apt_packages.append("ccache")
  571. job.cmake_config_emulator = "emcmake"
  572. job.cmake_build_type = "Debug"
  573. job.test_pkg_config = False
  574. job.cmake_arguments.extend((
  575. "-DSDLTEST_BROWSER=chrome",
  576. "-DSDLTEST_TIMEOUT_MULTIPLIER=4",
  577. "-DSDLTEST_CHROME_BINARY=${CHROME_BINARY}",
  578. ))
  579. job.cflags.extend((
  580. "-gsource-map",
  581. "-ffile-prefix-map=${PWD}=/SDL",
  582. ))
  583. job.ldflags.extend((
  584. "--source-map-base", "/",
  585. ))
  586. pretest_cmd.extend((
  587. "# Start local HTTP server",
  588. "cmake --build build --target serve-sdl-tests --verbose &",
  589. "chrome --version",
  590. "chromedriver --version",
  591. ))
  592. job.static_lib = StaticLibType.A
  593. job.setup_python = True
  594. job.pypi_packages.append("selenium")
  595. case SdlPlatform.Ps2:
  596. job.ccache = False # actions/ccache does not work in psp container (incompatible tar of busybox)
  597. build_parallel = False
  598. job.shared = False
  599. job.sudo = ""
  600. job.apt_packages = []
  601. job.apk_packages = ["ccache", "cmake", "gmp", "mpc1", "mpfr4", "ninja", "pkgconf", "git", ]
  602. job.cmake_toolchain_file = "${PS2DEV}/ps2sdk/ps2dev.cmake"
  603. job.clang_tidy = False
  604. job.run_tests = False
  605. job.shared = False
  606. job.cc = "mips64r5900el-ps2-elf-gcc"
  607. job.ldflags = ["-L${PS2DEV}/ps2sdk/ee/lib", "-L${PS2DEV}/gsKit/lib", "-L${PS2DEV}/ps2sdk/ports/lib", ]
  608. job.static_lib = StaticLibType.A
  609. case SdlPlatform.Psp:
  610. job.ccache = False # actions/ccache does not work in psp container (incompatible tar of busybox)
  611. build_parallel = False
  612. job.sudo = ""
  613. job.apt_packages = []
  614. job.apk_packages = ["ccache", "cmake", "gmp", "mpc1", "mpfr4", "ninja", "pkgconf", ]
  615. job.cmake_toolchain_file = "${PSPDEV}/psp/share/pspdev.cmake"
  616. job.clang_tidy = False
  617. job.run_tests = False
  618. job.shared = False
  619. job.cc = "psp-gcc"
  620. job.ldflags = ["-L${PSPDEV}/lib", "-L${PSPDEV}/psp/lib", "-L${PSPDEV}/psp/sdk/lib", ]
  621. job.pollute_directories = ["${PSPDEV}/include", "${PSPDEV}/psp/include", "${PSPDEV}/psp/sdk/include", ]
  622. job.static_lib = StaticLibType.A
  623. case SdlPlatform.Vita:
  624. job.ccache = True
  625. job.sudo = ""
  626. job.apt_packages = []
  627. job.apk_packages = ["ccache", "cmake", "ninja", "pkgconf", "bash", "tar"]
  628. job.cmake_toolchain_file = "${VITASDK}/share/vita.toolchain.cmake"
  629. assert spec.vita_gles is not None
  630. job.setup_vita_gles_type = {
  631. VitaGLES.Pib: "pib",
  632. VitaGLES.Pvr: "pvr",
  633. }[spec.vita_gles]
  634. job.cmake_arguments.extend((
  635. f"-DVIDEO_VITA_PIB={ 'true' if spec.vita_gles == VitaGLES.Pib else 'false' }",
  636. f"-DVIDEO_VITA_PVR={ 'true' if spec.vita_gles == VitaGLES.Pvr else 'false' }",
  637. "-DSDL_ARMNEON=ON",
  638. "-DSDL_ARMSIMD=ON",
  639. ))
  640. # Fix vita.toolchain.cmake (https://github.com/vitasdk/vita-toolchain/pull/253)
  641. 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"""
  642. job.clang_tidy = False
  643. job.run_tests = False
  644. job.shared = False
  645. job.cc = "arm-vita-eabi-gcc"
  646. job.static_lib = StaticLibType.A
  647. case SdlPlatform.Haiku:
  648. job.ccache = True
  649. fpic = False
  650. job.run_tests = False
  651. job.apt_packages.append("ccache")
  652. job.cc = "x86_64-unknown-haiku-gcc"
  653. job.cxx = "x86_64-unknown-haiku-g++"
  654. job.sudo = ""
  655. job.cmake_arguments.extend((
  656. f"-DCMAKE_C_COMPILER={job.cc}",
  657. f"-DCMAKE_CXX_COMPILER={job.cxx}",
  658. "-DCMAKE_SYSTEM_NAME=Haiku",
  659. ))
  660. job.shared_lib = SharedLibType.SO_0
  661. job.static_lib = StaticLibType.A
  662. case SdlPlatform.PowerPC64 | SdlPlatform.PowerPC:
  663. job.ccache = True
  664. # FIXME: Enable SDL_WERROR
  665. job.werror = False
  666. job.clang_tidy = False
  667. job.run_tests = False
  668. job.sudo = ""
  669. job.apt_packages = ["ccache"]
  670. job.shared_lib = SharedLibType.SO_0
  671. job.static_lib = StaticLibType.A
  672. job.cmake_arguments.extend((
  673. "-DSDL_UNIX_CONSOLE_BUILD=ON",
  674. ))
  675. case SdlPlatform.LoongArch64:
  676. job.ccache = True
  677. fpic = True
  678. job.run_tests = False
  679. job.apt_packages.append("ccache")
  680. job.cc = "${LOONGARCH64_CC}"
  681. job.cxx = "${LOONGARCH64_CXX}"
  682. job.cmake_arguments.extend((
  683. f"-DCMAKE_C_COMPILER={job.cc}",
  684. f"-DCMAKE_CXX_COMPILER={job.cxx}",
  685. "-DSDL_UNIX_CONSOLE_BUILD=ON",
  686. "-DCMAKE_SYSTEM_NAME=Linux",
  687. ))
  688. job.shared_lib = SharedLibType.SO_0
  689. job.static_lib = StaticLibType.A
  690. case SdlPlatform.N3ds:
  691. job.cmake_generator = "Unix Makefiles"
  692. job.cmake_build_arguments.append("-j$(nproc)")
  693. job.ccache = False
  694. job.shared = False
  695. job.apt_packages = []
  696. job.clang_tidy = False
  697. job.run_tests = False
  698. job.cc_from_cmake = True
  699. job.cmake_toolchain_file = "${DEVKITPRO}/cmake/3DS.cmake"
  700. job.binutils_strings = "/opt/devkitpro/devkitARM/bin/arm-none-eabi-strings"
  701. job.static_lib = StaticLibType.A
  702. case SdlPlatform.Msys2:
  703. job.ccache = True
  704. job.shell = "msys2 {0}"
  705. assert spec.msys2_platform
  706. job.msys2_msystem = spec.msys2_platform.value
  707. job.msys2_env = {
  708. "mingw32": "mingw-w64-i686",
  709. "mingw64": "mingw-w64-x86_64",
  710. "clang64": "mingw-w64-clang-x86_64",
  711. "ucrt64": "mingw-w64-ucrt-x86_64",
  712. }[spec.msys2_platform.value]
  713. job.msys2_no_perl = spec.msys2_platform in (Msys2Platform.Mingw32, )
  714. job.shared_lib = SharedLibType.WIN32
  715. job.static_lib = StaticLibType.A
  716. case SdlPlatform.Riscos:
  717. job.ccache = False # FIXME: enable when container gets upgrade
  718. # FIXME: Enable SDL_WERROR
  719. job.werror = False
  720. job.apt_packages = ["ccache", "cmake", "ninja-build"]
  721. job.test_pkg_config = False
  722. job.shared = False
  723. job.run_tests = False
  724. job.sudo = ""
  725. job.cmake_arguments.extend((
  726. "-DRISCOS:BOOL=ON",
  727. "-DCMAKE_DISABLE_PRECOMPILE_HEADERS:BOOL=ON",
  728. "-DSDL_GCC_ATOMICS:BOOL=OFF",
  729. ))
  730. job.cmake_toolchain_file = "/home/riscos/env/toolchain-riscos.cmake"
  731. job.static_lib = StaticLibType.A
  732. case SdlPlatform.FreeBSD | SdlPlatform.NetBSD | SdlPlatform.OpenBSD:
  733. job.cpactions = True
  734. job.no_cmake = True
  735. job.run_tests = False
  736. job.apt_packages = []
  737. job.shared_lib = SharedLibType.SO_0
  738. job.static_lib = StaticLibType.A
  739. match spec.platform:
  740. case SdlPlatform.FreeBSD:
  741. job.cpactions_os = "freebsd"
  742. job.cpactions_version = "14.3"
  743. job.cpactions_arch = "x86-64"
  744. job.cpactions_setup_cmd = "sudo pkg update"
  745. 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"
  746. job.cmake_arguments.extend((
  747. "-DSDL_CHECK_REQUIRED_INCLUDES=/usr/local/include",
  748. "-DSDL_CHECK_REQUIRED_LINK_OPTIONS=-L/usr/local/lib",
  749. ))
  750. case SdlPlatform.NetBSD:
  751. job.cpactions_os = "netbsd"
  752. job.cpactions_version = "10.1"
  753. job.cpactions_arch = "x86-64"
  754. 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"
  755. job.cpactions_install_cmd = "sudo -E pkgin -y install cmake dbus pkgconf ninja-build pulseaudio libxkbcommon wayland wayland-protocols libinotify libusb1"
  756. case SdlPlatform.OpenBSD:
  757. job.cpactions_os = "openbsd"
  758. job.cpactions_version = "7.7"
  759. job.cpactions_arch = "x86-64"
  760. job.cpactions_setup_cmd = "sudo pkg_add -u"
  761. job.cpactions_install_cmd = "sudo pkg_add cmake ninja pkgconf wayland wayland-protocols libxkbcommon libinotify pulseaudio dbus ibus"
  762. case SdlPlatform.NGage:
  763. build_parallel = False
  764. job.cmake_build_type = "Release"
  765. job.setup_ninja = True
  766. job.static_lib = StaticLibType.STATIC_LIB
  767. job.shared_lib = None
  768. job.clang_tidy = False
  769. job.werror = False # FIXME: enable SDL_WERROR
  770. job.shared = False
  771. job.run_tests = False
  772. job.setup_gage_sdk_path = "C:/ngagesdk"
  773. job.cmake_toolchain_file = "C:/ngagesdk/cmake/ngage-toolchain.cmake"
  774. job.test_pkg_config = False
  775. case _:
  776. raise ValueError(f"Unsupported platform={spec.platform}")
  777. if "ubuntu" in spec.name.lower():
  778. job.check_sources = True
  779. job.setup_python = True
  780. if job.ccache:
  781. job.cmake_arguments.extend((
  782. "-DCMAKE_C_COMPILER_LAUNCHER=ccache",
  783. "-DCMAKE_CXX_COMPILER_LAUNCHER=ccache",
  784. ))
  785. if not build_parallel:
  786. job.cmake_build_arguments.append("-j1")
  787. if job.cflags or job.cppflags:
  788. job.cmake_arguments.append(f"-DCMAKE_C_FLAGS=\"{my_shlex_join(job.cflags + job.cppflags)}\"")
  789. if job.cxxflags or job.cppflags:
  790. job.cmake_arguments.append(f"-DCMAKE_CXX_FLAGS=\"{my_shlex_join(job.cxxflags + job.cppflags)}\"")
  791. if job.ldflags:
  792. job.cmake_arguments.append(f"-DCMAKE_SHARED_LINKER_FLAGS=\"{my_shlex_join(job.ldflags)}\"")
  793. job.cmake_arguments.append(f"-DCMAKE_EXE_LINKER_FLAGS=\"{my_shlex_join(job.ldflags)}\"")
  794. job.pretest_cmd = "\n".join(pretest_cmd)
  795. def tf(b):
  796. return "ON" if b else "OFF"
  797. if fpic is not None:
  798. job.cmake_arguments.append(f"-DCMAKE_POSITION_INDEPENDENT_CODE={tf(fpic)}")
  799. if job.no_cmake:
  800. job.cmake_arguments = []
  801. return job
  802. def spec_to_platform(spec: JobSpec, key: str, enable_artifacts: bool, trackmem_symbol_names: bool) -> dict[str, str|bool]:
  803. logger.info("spec=%r", spec)
  804. job = spec_to_job(spec, key=key, trackmem_symbol_names=trackmem_symbol_names)
  805. logger.info("job=%r", job)
  806. platform = job.to_workflow(enable_artifacts=enable_artifacts)
  807. logger.info("platform=%r", platform)
  808. return platform
  809. def main():
  810. parser = argparse.ArgumentParser(allow_abbrev=False)
  811. parser.add_argument("--github-variable-prefix", default="platforms")
  812. parser.add_argument("--github-ci", action="store_true")
  813. parser.add_argument("--verbose", action="store_true")
  814. parser.add_argument("--commit-message-file")
  815. parser.add_argument("--no-artifact", dest="enable_artifacts", action="store_false")
  816. parser.add_argument("--trackmem-symbol-names", dest="trackmem_symbol_names", action="store_true")
  817. args = parser.parse_args()
  818. logging.basicConfig(level=logging.INFO if args.verbose else logging.WARNING)
  819. remaining_keys = set(JOB_SPECS.keys())
  820. all_level_keys = (
  821. # Level 1
  822. (
  823. "haiku",
  824. ),
  825. )
  826. filters = []
  827. if args.commit_message_file:
  828. with open(args.commit_message_file, "r") as f:
  829. commit_message = f.read()
  830. for m in re.finditer(r"\[sdl-ci-filter (.*)]", commit_message, flags=re.M):
  831. filters.append(m.group(1).strip(" \t\n\r\t'\""))
  832. if re.search(r"\[sdl-ci-artifacts?]", commit_message, flags=re.M):
  833. args.enable_artifacts = True
  834. if re.search(r"\[sdl-ci-(full-)?trackmem(-symbol-names)?]", commit_message, flags=re.M):
  835. args.trackmem_symbol_names = True
  836. if not filters:
  837. filters.append("*")
  838. logger.info("filters: %r", filters)
  839. all_level_platforms = {}
  840. 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()}
  841. for level_i, level_keys in enumerate(all_level_keys, 1):
  842. level_key = f"level{level_i}"
  843. logger.info("Level %d: keys=%r", level_i, level_keys)
  844. assert all(k in remaining_keys for k in level_keys)
  845. level_platforms = tuple(all_platforms[key] for key in level_keys)
  846. remaining_keys.difference_update(level_keys)
  847. all_level_platforms[level_key] = level_platforms
  848. logger.info("=" * 80)
  849. logger.info("Keys before filter: %r", remaining_keys)
  850. filtered_remaining_keys = set()
  851. for filter in filters:
  852. filtered_remaining_keys.update(fnmatch.filter(remaining_keys, filter))
  853. logger.info("Keys after filter: %r", filtered_remaining_keys)
  854. remaining_keys = filtered_remaining_keys
  855. logger.info("Remaining: %r", remaining_keys)
  856. all_level_platforms["others"] = tuple(all_platforms[key] for key in remaining_keys)
  857. if args.github_ci:
  858. for level, platforms in all_level_platforms.items():
  859. platforms_json = json.dumps(platforms)
  860. txt = f"{args.github_variable_prefix}-{level}={platforms_json}"
  861. logger.info("%s", txt)
  862. if "GITHUB_OUTPUT" in os.environ:
  863. with open(os.environ["GITHUB_OUTPUT"], "a") as f:
  864. f.write(txt)
  865. f.write("\n")
  866. else:
  867. logger.warning("GITHUB_OUTPUT not defined")
  868. return 0
  869. if __name__ == "__main__":
  870. raise SystemExit(main())