generic.yml 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. name: 'Build'
  2. run-name: 'Configure, Build and Test SDL'
  3. on:
  4. workflow_call:
  5. inputs:
  6. platforms:
  7. description: 'JSON-encoded test properties'
  8. type: string
  9. required: true
  10. jobs:
  11. build:
  12. name: ${{ matrix.platform.name }}
  13. runs-on: ${{ matrix.platform.os }}
  14. container: ${{ matrix.platform.container }}
  15. defaults:
  16. run:
  17. shell: ${{ matrix.platform.shell }}
  18. strategy:
  19. fail-fast: false
  20. matrix:
  21. platform: ${{ fromJSON(inputs.platforms) }}
  22. steps:
  23. - name: 'Set up MSYS2'
  24. if: ${{ matrix.platform.platform == 'msys2' }}
  25. uses: msys2/setup-msys2@v2
  26. with:
  27. msystem: ${{ matrix.platform.msys2-msystem }}
  28. install: >-
  29. ${{ matrix.platform.msys2-env }}-cc
  30. ${{ matrix.platform.msys2-env }}-cmake
  31. ${{ matrix.platform.msys2-env }}-ninja
  32. ${{ (!matrix.platform.msys2-no-perl && format('{0}-perl', matrix.platform.msys2-env)) || '' }}
  33. ${{ matrix.platform.msys2-env }}-pkg-config
  34. ${{ matrix.platform.msys2-env }}-clang-tools-extra
  35. ${{ (matrix.platform.ccache && format('{0}-ccache', matrix.platform.msys2-env)) || '' }}
  36. - name: 'About this job'
  37. run: |
  38. echo "key=${{ matrix.platform.key }}"
  39. echo "name=${{ matrix.platform.name }}"
  40. echo "os=${{ matrix.platform.os }}"
  41. echo ""
  42. echo "Add [sdl-ci-filter ${{ matrix.platform.key }}] to your commit message to reduce the number of jobs."
  43. - uses: actions/checkout@v4
  44. - name: 'Set up ninja'
  45. if: ${{ matrix.platform.setup-ninja }}
  46. uses: ./.github/actions/setup-ninja
  47. - name: 'Set up libusb for MSVC'
  48. if: ${{ matrix.platform.setup-libusb-arch != '' }}
  49. uses: ./.github/actions/setup-msvc-libusb
  50. with:
  51. arch: ${{ matrix.platform.setup-libusb-arch }}
  52. - uses: mymindstorm/setup-emsdk@v14
  53. if: ${{ matrix.platform.platform == 'emscripten' }}
  54. with:
  55. version: 3.1.35
  56. - uses: browser-actions/setup-chrome@v1
  57. id: setup-chrome
  58. if: ${{ matrix.platform.platform == 'emscripten' }}
  59. with:
  60. install-chromedriver: true
  61. - name: 'Add chrome to PATH'
  62. if: ${{ matrix.platform.platform == 'emscripten' }}
  63. run: |
  64. chrome_dir="$(dirname "${{ steps.setup-chrome.outputs.chrome-path }}")"
  65. chromedriver_dir="$(dirname "${{ steps.setup-chrome.outputs.chromedriver-path }}")"
  66. echo "CHROME_BINARY=${{ steps.setup-chrome.outputs.chrome-path }}" >>$GITHUB_ENV
  67. echo "CHROMEDRIVER_BINARY=${{ steps.setup-chrome.outputs.chromedriver-path }}" >>$GITHUB_ENV
  68. echo "chrome_dir=${chrome_dir}"
  69. echo "chromedriver_dir=${chromedriver_dir}"
  70. echo "${chrome_dir}" >>${GITHUB_PATH}
  71. echo "${chromedriver_dir}" >>${GITHUB_PATH}
  72. - uses: nttld/setup-ndk@v1
  73. if: ${{ matrix.platform.android-ndk }}
  74. id: setup-ndk
  75. with:
  76. local-cache: true
  77. ndk-version: r21e
  78. - name: 'Configure Android NDK variables'
  79. if: ${{ matrix.platform.android-ndk }}
  80. shell: sh
  81. run: |
  82. # We cannot use GitHub expressions in the controller job
  83. echo "ANDROID_NDK_HOME=${{ steps.setup-ndk.outputs.ndk-path }}" >>$GITHUB_ENV
  84. - uses: actions/setup-java@v4
  85. if: ${{ matrix.platform.java }}
  86. with:
  87. distribution: 'temurin'
  88. java-version: '17'
  89. - uses: ilammy/msvc-dev-cmd@v1
  90. if: ${{ matrix.platform.platform == 'msvc' }}
  91. with:
  92. arch: ${{ matrix.platform.msvc-vcvars-arch }}
  93. sdk: ${{ matrix.platform.msvc-vcvars-sdk }}
  94. - name: 'Set up Windows GDK Desktop'
  95. uses: ./.github/actions/setup-gdk-desktop
  96. if: ${{ matrix.platform.setup-gdk-folder != '' }}
  97. with:
  98. folder: '${{ matrix.platform.setup-gdk-folder }}'
  99. - name: 'Set up LoongArch64 toolchain'
  100. uses: ./.github/actions/setup-loongarch64-toolchain
  101. id: setup-loongarch64-toolchain
  102. if: ${{ matrix.platform.platform == 'loongarch64' }}
  103. - name: 'Setup Intel oneAPI toolchain'
  104. id: intel
  105. if: ${{ matrix.platform.intel }}
  106. run: |
  107. # Download the key to system keyring
  108. wget -O- https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB \
  109. | gpg --dearmor | sudo tee /usr/share/keyrings/oneapi-archive-keyring.gpg > /dev/null
  110. # Add signed entry to apt sources and configure the APT client to use Intel repository:
  111. echo "deb [signed-by=/usr/share/keyrings/oneapi-archive-keyring.gpg] https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list
  112. # Update package list
  113. sudo apt-get update -y
  114. # Install oneAPI
  115. sudo apt-get install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic
  116. - name: 'Install apk packages'
  117. if: ${{ matrix.platform.apk-packages != '' }}
  118. run: |
  119. ${{ matrix.platform.sudo }} apk update
  120. ${{ matrix.platform.sudo }} apk add ${{ matrix.platform.apk-packages }}
  121. - name: 'Install apt packages'
  122. if: ${{ matrix.platform.apt-packages != '' }}
  123. run: |
  124. ${{ matrix.platform.sudo }} apt-get update
  125. ${{ matrix.platform.sudo }} apt-get install -y ${{ matrix.platform.apt-packages }}
  126. - name: 'Install brew packages'
  127. if: ${{ matrix.platform.brew-packages != '' }}
  128. run: |
  129. export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1
  130. brew update
  131. brew install ${{ matrix.platform.brew-packages }}
  132. - name: 'Setup Python'
  133. uses: 'actions/setup-python@main'
  134. if: ${{ matrix.platform.setup-python }}
  135. with:
  136. python-version: '3.x'
  137. - name: 'Install PyPI packages'
  138. if: ${{ matrix.platform.pypi-packages != '' }}
  139. run: |
  140. python -m pip install --user ${{ matrix.platform.pypi-packages }}
  141. - name: 'Set up GLES for VITA' # Must be after apk
  142. if: ${{ matrix.platform.setup-vita-gles-type != '' }}
  143. uses: ./.github/actions/setup-vita-gles
  144. with:
  145. type: ${{ matrix.platform.setup-vita-gles-type }}
  146. - name: 'Pollute toolchain with "bad" SDL headers'
  147. if: ${{ matrix.platform.pollute-directories != '' }}
  148. #shell: ${{ matrix.platform.shell }}
  149. run: |
  150. # Create "bad" SDL headers in the toolchain.
  151. # SDL sources should not use these.
  152. for include in ${{ matrix.platform.pollute-directories }}; do
  153. toolchain_directory="${include}/SDL3"
  154. echo "Creating directory ${toolchain_directory}"
  155. mkdir -p "${toolchain_directory}/SDL3"
  156. for header in include/SDL3/*.h; do
  157. dest="${toolchain_directory}/SDL3/$(basename "${header}")"
  158. echo "Creating ${dest}"
  159. echo '#error "System SDL headers must not be used by build system"' >"$dest"
  160. done
  161. done
  162. - name: 'Calculate ccache key'
  163. if: ${{ matrix.platform.ccache }}
  164. id: prepare-restore-ccache
  165. run: |
  166. echo "timestamp=$(date -u "+%Y%m%d%H%M_%S")" >> "$GITHUB_OUTPUT"
  167. - name: 'Restore ccache'
  168. if: ${{ matrix.platform.ccache }}
  169. uses: actions/cache/restore@v4
  170. id: restore-ccache
  171. with:
  172. path: ${{ runner.temp }}/ccache
  173. key: ccache-${{ matrix.platform.key }}-${{ steps.prepare-restore-ccache.outputs.timestamp }}
  174. restore-keys: |
  175. ccache-${{matrix.platform.key}}
  176. - name: 'Configure ccache'
  177. if: ${{ matrix.platform.ccache }}
  178. run: |
  179. echo 'CCACHE_DIR=${{ runner.temp }}/ccache' >>${GITHUB_ENV}
  180. - name: 'Prepare ccache'
  181. if: ${{ matrix.platform.ccache && steps.restore-ccache.outputs.cache-hit }}
  182. run: |
  183. if [ "x${{ runner.os }}" = "xmacOS" ]; then
  184. touch_date="2025-02-01T12:00:00Z"
  185. else
  186. touch_date="2025-02-01"
  187. fi
  188. find "${CCACHE_DIR}" -type f -exec touch -a -m -d "$touch_date" {} +
  189. ccache -s
  190. ccache -z
  191. - name: 'Configure (CMake)'
  192. if: ${{ !matrix.platform.no-cmake }}
  193. #shell: ${{ matrix.platform.shell }}
  194. run: |
  195. ${{ matrix.platform.source-cmd }}
  196. ${{ matrix.platform.cmake-config-emulator }} cmake -S . -B build -GNinja \
  197. -Wdeprecated -Wdev -Werror \
  198. ${{ matrix.platform.cmake-toolchain-file != '' && format('-DCMAKE_TOOLCHAIN_FILE={0}', matrix.platform.cmake-toolchain-file) || '' }} \
  199. -DSDL_WERROR=${{ matrix.platform.werror }} \
  200. -DSDL_EXAMPLES=${{ matrix.platform.build-tests }} \
  201. -DSDL_TESTS=${{ matrix.platform.build-tests }} \
  202. -DSDLTEST_TRACKMEM=ON \
  203. -DSDL_INSTALL_TESTS=${{ matrix.platform.build-tests }} \
  204. -DSDL_CLANG_TIDY=${{ matrix.platform.clang-tidy }} \
  205. -DSDL_INSTALL_DOCS=ON \
  206. -DSDL_INSTALL_CPACK=ON \
  207. -DSDL_INSTALL_DOCS=ON \
  208. ${{ matrix.platform.cmake-arguments }} \
  209. -DSDL_SHARED=${{ matrix.platform.shared }} \
  210. -DSDL_STATIC=${{ matrix.platform.static }} \
  211. -DSDL_VENDOR_INFO="Github Workflow" \
  212. -DCMAKE_INSTALL_PREFIX=prefix \
  213. -DCMAKE_INSTALL_LIBDIR=lib \
  214. -DCMAKE_BUILD_TYPE=${{ matrix.platform.cmake-build-type }}
  215. - name: 'Build (CMake)'
  216. id: build
  217. if: ${{ !matrix.platform.no-cmake }}
  218. # shell: ${{ matrix.platform.shell }}
  219. run: |
  220. ${{ matrix.platform.source-cmd }}
  221. cmake --build build --config ${{ matrix.platform.cmake-build-type }} --verbose -- ${{ matrix.platform.cmake-build-arguments }}
  222. - name: 'Verify SDL_REVISION'
  223. if: ${{ !matrix.platform.no-cmake }}
  224. run: |
  225. echo "This should show us the SDL_REVISION"
  226. echo "Shared library:"
  227. ${{ (matrix.platform.shared-lib && format('strings build/{0} | grep "Github Workflow"', matrix.platform.shared-lib)) || 'echo "<Shared library not supported by platform>"' }}
  228. echo "Static library:"
  229. ${{ (matrix.platform.static-lib && format('strings build/{0} | grep "Github Workflow"', matrix.platform.static-lib)) || 'echo "<Static library not supported by platform>"' }}
  230. - name: 'Run build-time tests (CMake)'
  231. id: tests
  232. if: ${{ !matrix.platform.no-cmake && matrix.platform.run-tests }}
  233. # shell: ${{ matrix.platform.shell }}
  234. run: |
  235. ${{ matrix.platform.source-cmd }}
  236. ${{ matrix.platform.pretest-cmd }}
  237. set -eu
  238. export SDL_TESTS_QUICK=1
  239. ctest -VV --test-dir build/ -j2
  240. - name: "Build test apk's (CMake)"
  241. id: apks
  242. if: ${{ always() && steps.build.outcome == 'success' && matrix.platform.android-apks != '' }}
  243. # shell: ${{ matrix.platform.shell }}
  244. run: |
  245. ${{ matrix.platform.source-cmd }}
  246. cmake --build build --config ${{ matrix.platform.cmake-build-type }} \
  247. --target \
  248. ${{ matrix.platform.android-apks }} \
  249. --verbose \
  250. -- ${{ matrix.platform.cmake-build-arguments }}
  251. - name: 'Install (CMake)'
  252. id: install
  253. if: ${{ always() && steps.build.outcome == 'success' }}
  254. # shell: ${{ matrix.platform.shell }}
  255. run: |
  256. ${{ matrix.platform.source-cmd }}
  257. cmake --install build --config ${{ matrix.platform.cmake-build-type }}
  258. echo "prefix=$(pwd)/prefix" >> $GITHUB_OUTPUT
  259. ( cd prefix; find . ) | LC_ALL=C sort -u
  260. - name: 'Package (CPack)'
  261. id: package
  262. if: ${{ always() && steps.build.outcome == 'success' }}
  263. # shell: ${{ matrix.platform.shell }}
  264. run: |
  265. # DMG creation on macOS occasionally fails, so try multiple times
  266. # https://gitlab.kitware.com/cmake/cmake/-/issues/25671
  267. success=0
  268. max_tries=10
  269. for i in $(seq $max_tries); do
  270. cmake --build build/ --config ${{ matrix.platform.cmake-build-type }} --target package -- ${{ matrix.platform.cmake-build-arguments }} && success=1
  271. if test $success = 1; then
  272. break
  273. fi
  274. echo "Package creation failed. Sleep 1 second and try again."
  275. sleep 1
  276. done
  277. if test $success = 0; then
  278. echo "Package creation failed after $max_tries attempts."
  279. exit 1
  280. fi
  281. - name: 'Verify CMake configuration files'
  282. if: ${{ steps.install.outcome == 'success' }}
  283. # shell: ${{ matrix.platform.shell }}
  284. run: |
  285. ${{ matrix.platform.source-cmd }}
  286. ${{ matrix.platform.cmake-config-emulator }} cmake -S cmake/test -B cmake_test_build -GNinja \
  287. ${{ matrix.platform.cmake-toolchain-file != '' && format('-DCMAKE_TOOLCHAIN_FILE={0}', matrix.platform.cmake-toolchain-file) || '' }} \
  288. -DTEST_SHARED=${{ matrix.platform.shared }} \
  289. -DTEST_STATIC=${{ matrix.platform.static }} \
  290. ${{ matrix.platform.cmake-arguments }} \
  291. -DCMAKE_BUILD_TYPE=${{ matrix.platform.cmake-build-type }} \
  292. -DCMAKE_PREFIX_PATH="${{ steps.install.outputs.prefix }}"
  293. cmake --build cmake_test_build --verbose --config ${{ matrix.platform.cmake-build-type }} -- ${{ matrix.platform.cmake-build-arguments }}
  294. - name: 'Extract CC/CXX/CFLAGS/CXXFLAGS from CMake toolchain'
  295. if: ${{ steps.install.outcome == 'success' && matrix.platform.cc-from-cmake }}
  296. # shell: ${{ matrix.platform.shell }}
  297. run: |
  298. cmake -S .github/cmake -B /tmp/cmake_extract \
  299. ${{ matrix.platform.cmake-toolchain-file != '' && format('-DCMAKE_TOOLCHAIN_FILE={0}', matrix.platform.cmake-toolchain-file) || '' }} \
  300. -DCMAKE_BUILD_TYPE=${{ matrix.platform.cmake-build-type }} \
  301. -DVAR_PATH=/tmp/env.txt
  302. cat /tmp/env.txt >> $GITHUB_ENV
  303. - name: 'Verify sdl3.pc'
  304. # shell: ${{ matrix.platform.shell }}
  305. if: ${{ steps.install.outcome == 'success' && matrix.platform.test-pkg-config }}
  306. run: |
  307. ${{ matrix.platform.source-cmd }}
  308. ${{ matrix.platform.cc && format('export CC="{0}"', matrix.platform.cc) || '' }}
  309. ${{ matrix.platform.cflags && format('export CFLAGS="{0}"', matrix.platform.cflags) || '' }}
  310. ${{ matrix.platform.ldflags && format('export LDFLAGS="{0}"', matrix.platform.ldflags) || '' }}
  311. export PKG_CONFIG_PATH=${{ steps.install.outputs.prefix }}/lib/pkgconfig
  312. cmake/test/test_pkgconfig.sh
  313. - name: 'Build (cross-platform-actions, BSD)'
  314. id: cpactions
  315. if: ${{ matrix.platform.cpactions }}
  316. uses: cross-platform-actions/action@v0.27.0
  317. with:
  318. operating_system: '${{ matrix.platform.cpactions-os }}'
  319. architecture: '${{ matrix.platform.cpactions-arch }}'
  320. version: '${{ matrix.platform.cpactions-version }}'
  321. run: |
  322. ${{ matrix.platform.cpactions-setup-cmd }}
  323. ${{ matrix.platform.cpactions-install-cmd }}
  324. cmake -S . -B build -GNinja \
  325. ${{ matrix.platform.cmake-toolchain-file != '' && format('-DCMAKE_TOOLCHAIN_FILE={0}', matrix.platform.cmake-toolchain-file) || '' }} \
  326. -Wdeprecated -Wdev -Werror \
  327. -DSDL_WERROR=${{ matrix.platform.werror }} \
  328. -DSDL_INSTALL_DOCS=ON \
  329. ${{ matrix.platform.cmake-arguments }} \
  330. -DSDL_SHARED=${{ matrix.platform.shared }} \
  331. -DSDL_STATIC=${{ matrix.platform.static }} \
  332. -DSDL_VENDOR_INFO="Github Workflow" \
  333. -DCMAKE_INSTALL_PREFIX=prefix \
  334. -DCMAKE_INSTALL_LIBDIR=lib \
  335. -DCMAKE_BUILD_TYPE=${{ matrix.platform.cmake-build-type }}
  336. cmake --build build/ --config ${{ matrix.platform.cmake-build-type }} --verbose
  337. cmake --build build/ --config ${{ matrix.platform.cmake-build-type }} --target package
  338. cmake --build build/ --config ${{ matrix.platform.cmake-build-type }} --target clean
  339. rm -rf build/dist/_CPack_Packages
  340. rm -rf build/CMakeFiles
  341. rm -rf build/docs
  342. - name: Add msbuild to PATH
  343. id: setup-msbuild
  344. if: ${{ matrix.platform.msvc-project != '' }}
  345. uses: microsoft/setup-msbuild@v2
  346. - name: Build msbuild
  347. if: ${{ matrix.platform.msvc-project != '' }}
  348. run: |
  349. "$(cygpath -u '${{ steps.setup-msbuild.outputs.msbuildPath }}\msbuild.exe')" ${{ matrix.platform.msvc-project }} -m -p:BuildInParallel=true -p:Configuration=Release ${{ matrix.platform.msvc-project-flags }}
  350. - name: 'Build (Android.mk)'
  351. if: ${{ matrix.platform.android-mk }}
  352. run: |
  353. ./build-scripts/androidbuildlibs.sh
  354. - name: 'Create Gradle project (Android)'
  355. if: ${{ matrix.platform.android-gradle }}
  356. run: |
  357. for folder in build-ndk-build build-cmake; do
  358. python build-scripts/create-android-project.py \
  359. --output "${folder}" \
  360. --variant copy \
  361. org.libsdl.testspriteminimal \
  362. test/testspriteminimal.c test/icon.h
  363. done
  364. echo ""
  365. echo "Project contents:"
  366. echo ""
  367. find "build-ndk-build/org.libsdl.testspriteminimal"
  368. - name: 'Build Android app (Gradle & ndk-build)'
  369. if: ${{ matrix.platform.android-gradle }}
  370. run: |
  371. cd build-ndk-build/org.libsdl.testspriteminimal
  372. ./gradlew -i assembleRelease
  373. - name: 'Build Android app (Gradle & CMake)'
  374. if: ${{ matrix.platform.android-gradle }}
  375. run: |
  376. cd build-cmake/org.libsdl.testspriteminimal
  377. ./gradlew -i assembleRelease -PBUILD_WITH_CMAKE=1
  378. - name: 'Build (xcode)'
  379. if: ${{ matrix.platform.xcode-sdk != '' }}
  380. run: |
  381. xcodebuild -project Xcode/SDL/SDL.xcodeproj -target SDL3 -configuration Release -sdk ${{ matrix.platform.xcode-sdk }} clean build
  382. - name: 'Prune old ccache files'
  383. if: ${{ matrix.platform.ccache }}
  384. run: |
  385. ccache --evict-older-than=1d
  386. ccache -s
  387. - name: 'Save ccache'
  388. if: ${{ matrix.platform.ccache }}
  389. uses: actions/cache/save@v4
  390. with:
  391. path: ${{ runner.temp }}/ccache
  392. key: ${{ steps.restore-ccache.outputs.cache-primary-key }}
  393. - name: 'Check Sources'
  394. if: ${{ matrix.platform.check-sources }}
  395. run: |
  396. set -e
  397. build-scripts/test-versioning.sh
  398. python build-scripts/check_android_jni.py
  399. python build-scripts/check_stdlib_usage.py
  400. - name: 'Upload binary package'
  401. uses: actions/upload-artifact@v4
  402. if: ${{ always() && matrix.platform.artifact != '' && (steps.package.outcome == 'success' || steps.cpactions.outcome == 'success') && (matrix.platform.enable-artifacts || steps.tests.outcome == 'failure') }}
  403. with:
  404. if-no-files-found: error
  405. name: '${{ matrix.platform.artifact }}'
  406. path: |
  407. build/dist/SDL3*
  408. build/include*
  409. - name: 'Upload minidumps'
  410. uses: actions/upload-artifact@v4
  411. if: ${{ always() && steps.tests.outcome == 'failure' && (matrix.platform.platform == 'msvc' || matrix.platform.platform == 'msys2') }}
  412. with:
  413. if-no-files-found: ignore
  414. name: '${{ matrix.platform.artifact }}-minidumps'
  415. path: build/**/*.dmp
  416. - name: "Upload Android test apk's"
  417. uses: actions/upload-artifact@v4
  418. if: ${{ matrix.platform.enable-artifacts && always() && matrix.platform.artifact != '' && steps.apks.outcome == 'success' }}
  419. with:
  420. if-no-files-found: error
  421. name: '${{ matrix.platform.artifact }}-apks'
  422. path: build/test/*.apk