From 8b77e53ffb5db9519086ab6c0c23f591c4109d81 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Mon, 7 Oct 2024 04:29:08 +0200 Subject: [PATCH] Add parametrized build script [ci skip] --- .github/actions/setup-ninja/action.yml | 62 + .github/fetch_sdl_vc.ps1 | 40 - .github/workflows/release.yml | 735 +++++++++ .gitignore | 1 + CMakeLists.txt | 18 +- VisualC/SDL_image.vcxproj | 226 ++- VisualC/SDL_image.vcxproj.filters | 44 +- .../cmake/sdl3_image-config-version.cmake | 54 - .../pkg-support/cmake/sdl3_image-config.cmake | 73 - Xcode/SDL_image.xcodeproj/project.pbxproj | 2 +- Xcode/pkg-support/build.xcconfig | 21 + .../resources/CMake/SDL3_imageConfig.cmake | 95 ++ ...on.cmake => SDL3_imageConfigVersion.cmake} | 0 .../resources/CMake/sdl3_image-config.cmake | 61 - .../cmake/SDL3_image/SDL3_imageConfig.cmake | 174 ++ .../SDL3_image/SDL3_imageConfigVersion.cmake | 76 + build-scripts/android-prefab.sh | 353 ---- build-scripts/build-release.py | 1429 +++++++++++++++++ .../cmake-toolchain-mingw64-i686.cmake | 18 + .../cmake-toolchain-mingw64-x86_64.cmake | 18 + build-scripts/create-release.py | 42 + .../pkg-support/android/INSTALL.md.in | 61 + .../pkg-support/android/__main__.py.in | 104 ++ .../android/cmake/SDL3_imageConfig.cmake | 128 ++ .../cmake/SDL3_imageConfigVersion.cmake.in | 33 + .../pkg-support/android/description.json.in | 5 + build-scripts/pkg-support/mingw/Makefile | 39 + .../mingw/cmake/SDL3_imageConfig.cmake | 0 .../mingw/cmake/SDL3_imageConfigVersion.cmake | 4 +- .../msvc/cmake/SDL3_imageConfig.cmake.in | 115 ++ .../cmake/SDL3_imageConfigVersion.cmake.in | 33 + build-scripts/release-info.json | 286 ++++ build-scripts/test-versioning.sh | 8 - cmake/SDL3_imageConfig.cmake.in | 15 +- cmake/sdlcpu.cmake | 156 ++ cmake/test/CMakeLists.txt | 9 + external/dav1d | 2 +- external/download.sh | 4 +- 38 files changed, 3783 insertions(+), 761 deletions(-) create mode 100644 .github/actions/setup-ninja/action.yml delete mode 100644 .github/fetch_sdl_vc.ps1 create mode 100644 .github/workflows/release.yml delete mode 100644 VisualC/pkg-support/cmake/sdl3_image-config-version.cmake delete mode 100644 VisualC/pkg-support/cmake/sdl3_image-config.cmake create mode 100644 Xcode/pkg-support/build.xcconfig create mode 100644 Xcode/pkg-support/resources/CMake/SDL3_imageConfig.cmake rename Xcode/pkg-support/resources/CMake/{sdl3_image-config-version.cmake => SDL3_imageConfigVersion.cmake} (100%) delete mode 100644 Xcode/pkg-support/resources/CMake/sdl3_image-config.cmake create mode 100644 Xcode/pkg-support/resources/share/cmake/SDL3_image/SDL3_imageConfig.cmake create mode 100644 Xcode/pkg-support/resources/share/cmake/SDL3_image/SDL3_imageConfigVersion.cmake delete mode 100755 build-scripts/android-prefab.sh create mode 100755 build-scripts/build-release.py create mode 100644 build-scripts/cmake-toolchain-mingw64-i686.cmake create mode 100644 build-scripts/cmake-toolchain-mingw64-x86_64.cmake create mode 100755 build-scripts/create-release.py create mode 100644 build-scripts/pkg-support/android/INSTALL.md.in create mode 100755 build-scripts/pkg-support/android/__main__.py.in create mode 100644 build-scripts/pkg-support/android/cmake/SDL3_imageConfig.cmake create mode 100644 build-scripts/pkg-support/android/cmake/SDL3_imageConfigVersion.cmake.in create mode 100644 build-scripts/pkg-support/android/description.json.in create mode 100644 build-scripts/pkg-support/mingw/Makefile rename mingw/pkg-support/cmake/sdl3_image-config.cmake => build-scripts/pkg-support/mingw/cmake/SDL3_imageConfig.cmake (100%) rename mingw/pkg-support/cmake/sdl3_image-config-version.cmake => build-scripts/pkg-support/mingw/cmake/SDL3_imageConfigVersion.cmake (83%) create mode 100644 build-scripts/pkg-support/msvc/cmake/SDL3_imageConfig.cmake.in create mode 100644 build-scripts/pkg-support/msvc/cmake/SDL3_imageConfigVersion.cmake.in create mode 100644 build-scripts/release-info.json create mode 100644 cmake/sdlcpu.cmake diff --git a/.github/actions/setup-ninja/action.yml b/.github/actions/setup-ninja/action.yml new file mode 100644 index 00000000..b5d5fad0 --- /dev/null +++ b/.github/actions/setup-ninja/action.yml @@ -0,0 +1,62 @@ +name: 'Setup ninja' +description: 'Download ninja and add it to the PATH environment variable' +inputs: + version: + description: 'Ninja version' + default: '1.12.1' +runs: + using: 'composite' + steps: + - name: 'Calculate variables' + id: calc + shell: sh + run: | + case "${{ runner.os }}-${{ runner.arch }}" in + "Linux-X86" | "Linux-X64") + archive="ninja-linux.zip" + ;; + "Linux-ARM64") + archive="ninja-linux-aarch64.zip" + ;; + "macOS-X86" | "macOS-X64" | "macOS-ARM64") + archive="ninja-mac.zip" + ;; + "Windows-X86" | "Windows-X64") + archive="ninja-win.zip" + ;; + "Windows-ARM64") + archive="ninja-winarm64.zip" + ;; + *) + echo "Unsupported ${{ runner.os }}-${{ runner.arch }}" + exit 1; + ;; + esac + echo "archive=${archive}" >> ${GITHUB_OUTPUT} + echo "cache-key=${archive}-${{ inputs.version }}-${{ runner.os }}-${{ runner.arch }}" >> ${GITHUB_OUTPUT} + - name: 'Restore cached ${{ steps.calc.outputs.archive }}' + id: cache-restore + uses: actions/cache/restore@v4 + with: + path: '${{ runner.temp }}/${{ steps.calc.outputs.archive }}' + key: ${{ steps.calc.outputs.cache-key }} + - name: 'Download ninja ${{ inputs.version }} for ${{ runner.os }} (${{ runner.arch }})' + if: ${{ (!steps.cache-restore.outputs.cache-hit || steps.cache-restore.outputs.cache-hit == 'false') }} + shell: pwsh + run: | + Invoke-WebRequest "https://github.com/ninja-build/ninja/releases/download/v${{ inputs.version }}/${{ steps.calc.outputs.archive }}" -OutFile "${{ runner.temp }}/${{ steps.calc.outputs.archive }}" + - name: 'Cache ${{ steps.calc.outputs.archive }}' + if: ${{ (!steps.cache-restore.outputs.cache-hit || steps.cache-restore.outputs.cache-hit == 'false') }} + uses: actions/cache/save@v4 + with: + path: '${{ runner.temp }}/${{ steps.calc.outputs.archive }}' + key: ${{ steps.calc.outputs.cache-key }} + - name: 'Extract ninja' + shell: pwsh + run: | + 7z "-o${{ runner.temp }}/ninja-${{ inputs.version }}-${{ runner.arch }}" x "${{ runner.temp }}/${{ steps.calc.outputs.archive }}" + - name: 'Set output variables' + id: final + shell: pwsh + run: | + echo "${{ runner.temp }}/ninja-${{ inputs.version }}-${{ runner.arch }}" >> $env:GITHUB_PATH diff --git a/.github/fetch_sdl_vc.ps1 b/.github/fetch_sdl_vc.ps1 deleted file mode 100644 index 83d4db70..00000000 --- a/.github/fetch_sdl_vc.ps1 +++ /dev/null @@ -1,40 +0,0 @@ -$ErrorActionPreference = "Stop" - -$project_root = "$psScriptRoot\.." -Write-Output "project_root: $project_root" - -$sdl3_version = "3.0.0" -$sdl3_zip = "SDL3-devel-$($sdl3_version)-VC.zip" - -$sdl3_url = "https://github.com/libsdl-org/SDL/releases/download/release-$($sdl3_version)/SDL3-devel-$($sdl3_version)-VC.zip" -$sdl3_dlpath = "$($Env:TEMP)\$sdl3_zip" - -$sdl3_bindir = "$($project_root)" -$sdl3_extractdir = "$($sdl3_bindir)\SDL3-$($sdl3_version)" -$sdl3_root_name = "SDL3-devel-VC" - -echo "sdl3_bindir: $sdl3_bindir" -echo "sdl3_extractdir: $sdl3_extractdir" -echo "sdl3_root_name: $sdl3_root_name" - -echo "Cleaning previous artifacts" -if (Test-Path $sdl3_extractdir) { - Remove-Item $sdl3_extractdir -Recurse -Force -} -if (Test-Path "$($sdl3_bindir)/$sdl3_root_name") { - Remove-Item "$($sdl3_bindir)/$sdl3_root_name" -Recurse -Force -} -if (Test-Path $sdl3_dlpath) { - Remove-Item $sdl3_dlpath -Force -} - -Write-Output "Downloading $sdl3_url" -Invoke-WebRequest -Uri $sdl3_url -OutFile $sdl3_dlpath - -Write-Output "Extracting archive" -Expand-Archive $sdl3_dlpath -DestinationPath $sdl3_bindir - -Write-Output "Setting up SDL3 folder" -Rename-Item $sdl3_extractdir $sdl3_root_name - -Write-Output "Done" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..b94a5523 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,735 @@ +name: 'release' +run-name: 'Create SDL_image release artifacts for ${{ inputs.commit }}' + +on: + workflow_dispatch: + inputs: + commit: + description: 'Commit of SDL_image' + required: true + +jobs: + + src: + runs-on: ubuntu-latest + outputs: + project: ${{ steps.releaser.outputs.project }} + version: ${{ steps.releaser.outputs.version }} + src-tar-gz: ${{ steps.releaser.outputs.src-tar-gz }} + src-tar-xz: ${{ steps.releaser.outputs.src-tar-xz }} + src-zip: ${{ steps.releaser.outputs.src-zip }} + steps: + - name: 'Set up Python' + uses: actions/setup-python@v5 + with: + python-version: '3.11' + - name: 'Fetch build-release.py' + uses: actions/checkout@v4 + with: + ref: ${{ inputs.commit }} + sparse-checkout: 'build-scripts/build-release.py' + - name: 'Set up SDL sources' + uses: actions/checkout@v4 + with: + ref: ${{ inputs.commit }} + path: 'SDL' + fetch-depth: 0 + - name: 'Build Source archive' + id: releaser + shell: bash + env: + GH_TOKEN: ${{ github.token }} + run: | + python build-scripts/build-release.py \ + --actions source \ + --commit ${{ inputs.commit }} \ + --root "${{ github.workspace }}/SDL" \ + --github \ + --debug + - name: 'Store source archives' + uses: actions/upload-artifact@v4 + with: + name: sources + path: '${{ github.workspace}}/dist' + + linux-verify: + needs: [src] + runs-on: ubuntu-latest + steps: + - name: 'Set up Python' + uses: actions/setup-python@v5 + with: + python-version: '3.11' + - name: 'Download source archives' + uses: actions/download-artifact@v4 + with: + name: sources + path: '/tmp' + - name: 'Unzip ${{ needs.src.outputs.src-zip }}' + id: zip + run: | + set -e + mkdir /tmp/zipdir + cd /tmp/zipdir + unzip "/tmp/${{ needs.src.outputs.src-zip }}" + echo "path=/tmp/zipdir/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$GITHUB_OUTPUT + - name: 'Untar ${{ needs.src.outputs.src-tar-gz }}' + id: tar + run: | + set -e + mkdir -p /tmp/tardir + tar -C /tmp/tardir -v -x -f "/tmp/${{ needs.src.outputs.src-tar-gz }}" + echo "path=/tmp/tardir/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$GITHUB_OUTPUT + - name: 'Compare contents of ${{ needs.src.outputs.src-zip }} and ${{ needs.src.outputs.src-tar-gz }}' + run: | + set -e + diff "${{ steps.zip.outputs.path }}" "${{ steps.tar.outputs.path }}" + - name: 'Test versioning' + shell: bash + run: | + ${{ steps.tar.outputs.path }}/build-scripts/test-versioning.sh + - name: 'Fetch build-release.py' + uses: actions/checkout@v4 + with: + ref: ${{ inputs.commit }} + sparse-checkout: 'build-scripts/build-release.py' + - name: 'Download dependencies' + id: deps + env: + GH_TOKEN: ${{ github.token }} + run: | + python build-scripts/build-release.py \ + --actions download \ + --commit ${{ inputs.commit }} \ + --root "${{ steps.tar.outputs.path }}" \ + --github \ + --debug + - name: 'Extract dependencies, build and install them' + id: deps-build + run: | + tar -C /tmp -v -x -f "${{ steps.deps.outputs.dep-path }}/SDL3-${{ steps.deps.outputs.dep-sdl-version }}.tar.xz" + cmake -S /tmp/SDL3-${{ steps.deps.outputs.dep-sdl-version }} -B /tmp/SDL-build -DCMAKE_INSTALL_PREFIX=/tmp/deps-prefix + cmake --build /tmp/SDL-build + cmake --install /tmp/SDL-build + echo "path=/tmp/deps-prefix" >>$GITHUB_OUTPUT + - name: 'CMake (configure + build)' + run: | + cmake \ + -S ${{ steps.tar.outputs.path }} \ + -B /tmp/build \ + -DSDL3IMAGE_SAMPLES=ON \ + -DSDL3IMAGE_TESTS=ON \ + -DCMAKE_PREFIX_PATH="${{ steps.deps-build.outputs.path }}" + cmake --build /tmp/build --verbose + # ctest --test-dir /tmp/build --no-tests=error --output-on-failure + + dmg: + needs: [src] + runs-on: macos-latest + outputs: + dmg: ${{ steps.releaser.outputs.dmg }} + steps: + - name: 'Set up Python' + uses: actions/setup-python@v5 + with: + python-version: '3.11' + - name: 'Fetch build-release.py' + uses: actions/checkout@v4 + with: + ref: ${{ inputs.commit }} + sparse-checkout: 'build-scripts/build-release.py' + - name: 'Install nasm' + run: | + brew install nasm + - name: 'Download source archives' + uses: actions/download-artifact@v4 + with: + name: sources + path: '${{ github.workspace }}' + - name: 'Untar ${{ needs.src.outputs.src-tar-gz }}' + id: tar + run: | + mkdir -p "${{ github.workspace }}/tardir" + tar -C "${{ github.workspace }}/tardir" -v -x -f "${{ github.workspace }}/${{ needs.src.outputs.src-tar-gz }}" + echo "path=${{ github.workspace }}/tardir/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$GITHUB_OUTPUT + - name: 'Download external dependencies' + run: | + sh "${{ steps.tar.outputs.path }}/external/download.sh" --depth 1 + - name: 'Build SDL3_image.dmg' + id: releaser + shell: bash + env: + GH_TOKEN: ${{ github.token }} + run: | + python build-scripts/build-release.py \ + --actions dmg \ + --commit ${{ inputs.commit }} \ + --root "${{ steps.tar.outputs.path }}" \ + --github \ + --debug + - name: 'Store DMG image file' + uses: actions/upload-artifact@v4 + with: + name: dmg + path: '${{ github.workspace }}/dist' + + dmg-verify: + needs: [dmg, src] + runs-on: macos-latest + steps: + - name: 'Set up Python' + uses: actions/setup-python@v5 + with: + python-version: '3.11' + - name: 'Fetch build-release.py' + uses: actions/checkout@v4 + with: + ref: ${{ inputs.commit }} + sparse-checkout: 'build-scripts/build-release.py' + - name: 'Download source archives' + uses: actions/download-artifact@v4 + with: + name: sources + path: '${{ github.workspace }}' + - name: 'Untar ${{ needs.src.outputs.src-tar-gz }}' + id: src + run: | + mkdir -p /tmp/tardir + tar -C /tmp/tardir -v -x -f "${{ github.workspace }}/${{ needs.src.outputs.src-tar-gz }}" + echo "path=/tmp/tardir/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$GITHUB_OUTPUT + - name: 'Download dependencies' + id: deps + env: + GH_TOKEN: ${{ github.token }} + run: | + python build-scripts/build-release.py \ + --actions download \ + --commit ${{ inputs.commit }} \ + --root "${{ steps.src.outputs.path }}" \ + --github \ + --debug + - name: 'Mount dependencies' + id: deps-mount + run: | + hdiutil attach "${{ steps.deps.outputs.dep-path }}/SDL3-${{ steps.deps.outputs.dep-sdl-version }}.dmg" + sdl_mount_pount="/Volumes/SDL3" + if [ ! -d "$sdl_mount_pount/SDL3.xcframework" ]; then + echo "Cannot find SDL3.xcframework!" + exit 1 + fi + echo "path=${sdl_mount_pount}" >>$GITHUB_OUTPUT + - name: 'Download ${{ needs.dmg.outputs.dmg }}' + uses: actions/download-artifact@v4 + with: + name: dmg + path: '${{ github.workspace }}' + - name: 'Mount ${{ needs.dmg.outputs.dmg }}' + id: mount + run: | + hdiutil attach '${{ github.workspace }}/${{ needs.dmg.outputs.dmg }}' + mount_point="/Volumes/${{ needs.src.outputs.project }}" + if [ ! -d "$mount_point/${{ needs.src.outputs.project }}.xcframework" ]; then + echo "Cannot find ${{ needs.src.outputs.project }}.xcframework!" + exit 1 + fi + echo "mount-point=${mount_point}">>$GITHUB_OUTPUT + - name: 'Verify presence of optional frameworks' + run: | + OPTIONAL_FRAMEWORKS="avif jxl webp" + rc=0 + for opt in $OPTIONAL_FRAMEWORKS; do + fw_path="${{ steps.mount.outputs.mount-point }}/optional/${opt}.xcframework" + if [ -d "${fw_path}" ]; then + echo "$fw_path OK" + else + echo "$fw_path MISSING" + rc=1 + fi + done + exit $rc + - name: 'CMake (configure + build) Darwin' + run: | + set -e + cmake -S "${{ steps.src.outputs.path }}/cmake/test" \ + -DTEST_SHARED=TRUE \ + -DTEST_SHARED=TRUE \ + -DTEST_STATIC=FALSE \ + -DCMAKE_PREFIX_PATH="${{ steps.mount.outputs.mount-point }};${{ steps.deps-mount.outputs.path }}" \ + -DCMAKE_SYSTEM_NAME=Darwin \ + -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \ + -Werror=dev \ + -B build_darwin + cmake --build build_darwin --config Release --verbose + + - name: 'CMake (configure + build) iOS' + run: | + cmake -S "${{ steps.src.outputs.path }}/cmake/test" \ + -DTEST_SHARED=TRUE \ + -DTEST_STATIC=FALSE \ + -DCMAKE_PREFIX_PATH="${{ steps.mount.outputs.mount-point }};${{ steps.deps-mount.outputs.path }}" \ + -DCMAKE_SYSTEM_NAME=iOS \ + -DCMAKE_OSX_ARCHITECTURES="arm64" \ + -Werror=dev \ + -B build_ios + cmake --build build_ios --config Release --verbose + - name: 'CMake (configure + build) tvOS' + run: | + cmake -S "${{ steps.src.outputs.path }}/cmake/test" \ + -DTEST_SHARED=TRUE \ + -DTEST_STATIC=FALSE \ + -DCMAKE_PREFIX_PATH="${{ steps.mount.outputs.mount-point }};${{ steps.deps-mount.outputs.path }}" \ + -DCMAKE_SYSTEM_NAME=tvOS \ + -DCMAKE_OSX_ARCHITECTURES="arm64" \ + -Werror=dev \ + -B build_tvos + cmake --build build_tvos --config Release --verbose + - name: 'CMake (configure + build) iOS simulator' + run: | + sysroot=$(xcodebuild -version -sdk iphonesimulator Path) + echo "sysroot=$sysroot" + cmake -S "${{ steps.src.outputs.path }}/cmake/test" \ + -DTEST_SHARED=TRUE \ + -DTEST_STATIC=FALSE \ + -DCMAKE_PREFIX_PATH="${{ steps.mount.outputs.mount-point }};${{ steps.deps-mount.outputs.path }}" \ + -DCMAKE_SYSTEM_NAME=iOS \ + -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \ + -DCMAKE_OSX_SYSROOT="${sysroot}" \ + -Werror=dev \ + -B build_ios_simulator + cmake --build build_ios_simulator --config Release --verbose + - name: 'CMake (configure + build) tvOS simulator' + run: | + sysroot=$(xcodebuild -version -sdk appletvsimulator Path) + echo "sysroot=$sysroot" + cmake -S "${{ steps.src.outputs.path }}/cmake/test" \ + -DTEST_SHARED=TRUE \ + -DTEST_STATIC=FALSE \ + -DCMAKE_PREFIX_PATH="${{ steps.mount.outputs.mount-point }};${{ steps.deps-mount.outputs.path }}" \ + -DCMAKE_SYSTEM_NAME=tvOS \ + -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \ + -DCMAKE_OSX_SYSROOT="${sysroot}" \ + -Werror=dev \ + -B build_tvos_simulator + cmake --build build_tvos_simulator --config Release --verbose + msvc: + needs: [src] + runs-on: windows-2019 + outputs: + VC-x86: ${{ steps.releaser.outputs.VC-x86 }} + VC-x64: ${{ steps.releaser.outputs.VC-x64 }} + VC-devel: ${{ steps.releaser.outputs.VC-devel }} + steps: + - name: 'Set up Python' + uses: actions/setup-python@v5 + with: + python-version: '3.11' + - name: 'Fetch build-release.py' + uses: actions/checkout@v4 + with: + ref: ${{ inputs.commit }} + sparse-checkout: 'build-scripts/build-release.py' + - name: 'Download source archives' + uses: actions/download-artifact@v4 + with: + name: sources + path: '${{ github.workspace }}' + - name: 'Unzip ${{ needs.src.outputs.src-zip }}' + id: zip + run: | + New-Item C:\temp -ItemType Directory -ErrorAction SilentlyContinue + cd C:\temp + unzip "${{ github.workspace }}/${{ needs.src.outputs.src-zip }}" + echo "path=C:\temp\${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$Env:GITHUB_OUTPUT + - name: 'Download external dependencies' + run: | + ${{ steps.zip.outputs.path }}/external/Get-GitModules.ps1 + - name: 'Build MSVC binary archives' + id: releaser + env: + GH_TOKEN: ${{ github.token }} + run: | + python build-scripts/build-release.py ` + --actions download msvc ` + --commit ${{ inputs.commit }} ` + --root "${{ steps.zip.outputs.path }}" ` + --github ` + --debug + - name: 'Store MSVC archives' + uses: actions/upload-artifact@v4 + with: + name: msvc + path: '${{ github.workspace }}/dist' + + msvc-verify: + needs: [msvc, src] + runs-on: windows-latest + steps: + - name: 'Fetch .github/actions/setup-ninja/action.yml' + uses: actions/checkout@v4 + with: + ref: ${{ inputs.commit }} + sparse-checkout: | + .github/actions/setup-ninja/action.yml + build-scripts/build-release.py + - name: 'Set up Python' + uses: actions/setup-python@v5 + with: + python-version: '3.11' + - name: Set up ninja + uses: ./.github/actions/setup-ninja + - name: 'Download source archives' + uses: actions/download-artifact@v4 + with: + name: sources + path: '${{ github.workspace }}' + - name: 'Unzip ${{ needs.src.outputs.src-zip }}' + id: src + run: | + mkdir '${{ github.workspace }}/sources' + cd '${{ github.workspace }}/sources' + unzip "${{ github.workspace }}/${{ needs.src.outputs.src-zip }}" + echo "path=${{ github.workspace }}/sources/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$env:GITHUB_OUTPUT + - name: 'Download dependencies' + id: deps + env: + GH_TOKEN: ${{ github.token }} + run: | + python build-scripts/build-release.py ` + --actions download ` + --commit ${{ inputs.commit }} ` + --root "${{ steps.src.outputs.path }}" ` + --github ` + --debug + - name: 'Extract dependencies' + id: deps-extract + run: | + mkdir '${{ github.workspace }}/deps-vc' + cd '${{ github.workspace }}/deps-vc' + unzip "${{ steps.deps.outputs.dep-path }}/SDL3-devel-${{ steps.deps.outputs.dep-sdl-version }}-VC.zip" + echo "path=${{ github.workspace }}/deps-vc" >>$env:GITHUB_OUTPUT + - name: 'Download MSVC binaries' + uses: actions/download-artifact@v4 + with: + name: msvc + path: '${{ github.workspace }}' + - name: 'Unzip ${{ needs.msvc.outputs.VC-devel }}' + id: bin + run: | + mkdir '${{ github.workspace }}/vc' + cd '${{ github.workspace }}/vc' + unzip "${{ github.workspace }}/${{ needs.msvc.outputs.VC-devel }}" + echo "path=${{ github.workspace }}/vc/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$env:GITHUB_OUTPUT + - name: 'Configure vcvars x86' + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x64_x86 + - name: 'CMake (configure + build + tests) x86' + run: | + cmake -S "${{ steps.src.outputs.path }}/cmake/test" ` + -B build_x86 ` + -GNinja ` + -DCMAKE_BUILD_TYPE=Debug ` + -Werror=dev ` + -DTEST_SHARED=TRUE ` + -DTEST_STATIC=FALSE ` + -DCMAKE_SUPPRESS_REGENERATION=TRUE ` + -DCMAKE_PREFIX_PATH="${{ steps.bin.outputs.path }};${{ steps.deps-extract.outputs.path }}" + Start-Sleep -Seconds 2 + cmake --build build_x86 --config Release --verbose + - name: 'Configure vcvars x64' + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x64 + - name: 'CMake (configure + build + tests) x64' + run: | + cmake -S "${{ steps.src.outputs.path }}/cmake/test" ` + -B build_x64 ` + -GNinja ` + -DCMAKE_BUILD_TYPE=Debug ` + -Werror=dev ` + -DTEST_SHARED=TRUE ` + -DTEST_STATIC=FALSE ` + -DCMAKE_SUPPRESS_REGENERATION=TRUE ` + -DCMAKE_PREFIX_PATH="${{ steps.bin.outputs.path }};${{ steps.deps-extract.outputs.path }}" + Start-Sleep -Seconds 2 + cmake --build build_x64 --config Release --verbose + - name: 'Configure vcvars arm64' + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x64_arm64 + - name: 'CMake (configure + build + tests) arm64' + run: | + cmake -S "${{ steps.src.outputs.path }}/cmake/test" ` + -B build_arm64 ` + -GNinja ` + -DCMAKE_BUILD_TYPE=Debug ` + -Werror=dev ` + -DTEST_SHARED=TRUE ` + -DTEST_STATIC=FALSE ` + -DCMAKE_SUPPRESS_REGENERATION=TRUE ` + -DCMAKE_PREFIX_PATH="${{ steps.bin.outputs.path }};${{ steps.deps-extract.outputs.path }}" + Start-Sleep -Seconds 2 + cmake --build build_arm64 --config Release --verbose + + mingw: + needs: [src] + runs-on: ubuntu-24.04 # FIXME: current ubuntu-latest ships an outdated mingw, replace with ubuntu-latest once 24.04 becomes the new default + outputs: + mingw-devel-tar-gz: ${{ steps.releaser.outputs.mingw-devel-tar-gz }} + mingw-devel-tar-xz: ${{ steps.releaser.outputs.mingw-devel-tar-xz }} + steps: + - name: 'Set up Python' + uses: actions/setup-python@v5 + with: + python-version: '3.11' + - name: 'Fetch build-release.py' + uses: actions/checkout@v4 + with: + ref: ${{ inputs.commit }} + sparse-checkout: 'build-scripts/build-release.py' + - name: 'Install Mingw toolchain' + run: | + sudo apt-get update -y + sudo apt-get install -y gcc-mingw-w64 g++-mingw-w64 ninja-build + - name: 'Download source archives' + uses: actions/download-artifact@v4 + with: + name: sources + path: '${{ github.workspace }}' + - name: 'Untar ${{ needs.src.outputs.src-tar-gz }}' + id: tar + run: | + mkdir -p /tmp/tardir + tar -C /tmp/tardir -v -x -f "${{ github.workspace }}/${{ needs.src.outputs.src-tar-gz }}" + echo "path=/tmp/tardir/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$GITHUB_OUTPUT + - name: 'Build MinGW binary archives' + id: releaser + env: + GH_TOKEN: ${{ github.token }} + run: | + python build-scripts/build-release.py \ + --actions download mingw \ + --commit ${{ inputs.commit }} \ + --root "${{ steps.tar.outputs.path }}" \ + --github \ + --debug + - name: 'Store MinGW archives' + uses: actions/upload-artifact@v4 + with: + name: mingw + path: '${{ github.workspace }}/dist' + + mingw-verify: + needs: [mingw, src] + runs-on: ubuntu-latest + steps: + - name: 'Set up Python' + uses: actions/setup-python@v5 + with: + python-version: '3.11' + - name: 'Fetch build-release.py' + uses: actions/checkout@v4 + with: + ref: ${{ inputs.commit }} + sparse-checkout: 'build-scripts/build-release.py' + - name: 'Install Mingw toolchain' + run: | + sudo apt-get update -y + sudo apt-get install -y gcc-mingw-w64 g++-mingw-w64 ninja-build + - name: 'Download source archives' + uses: actions/download-artifact@v4 + with: + name: sources + path: '${{ github.workspace }}' + - name: 'Untar ${{ needs.src.outputs.src-tar-gz }}' + id: src + run: | + mkdir -p /tmp/tardir + tar -C /tmp/tardir -v -x -f "${{ github.workspace }}/${{ needs.src.outputs.src-tar-gz }}" + echo "path=/tmp/tardir/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$GITHUB_OUTPUT + - name: 'Download dependencies' + id: deps + env: + GH_TOKEN: ${{ github.token }} + run: | + python build-scripts/build-release.py \ + --actions download \ + --commit ${{ inputs.commit }} \ + --root "${{ steps.src.outputs.path }}" \ + --github \ + --debug + - name: 'Untar and install dependencies' + id: deps-extract + run: | + mkdir -p /tmp/deps-mingw/cmake + mkdir -p /tmp/deps-mingw/i686-w64-mingw32 + mkdir -p /tmp/deps-mingw/x86_64-w64-mingw32 + + mkdir -p /tmp/deps-mingw-extract/sdl3 + tar -C /tmp/deps-mingw-extract/sdl3 -v -x -f "${{ steps.deps.outputs.dep-path }}/SDL3-devel-${{ steps.deps.outputs.dep-sdl-version }}-mingw.tar.xz" + make -C /tmp/deps-mingw-extract/sdl3/SDL3-${{ steps.deps.outputs.dep-sdl-version }} install-all DESTDIR=/tmp/deps-mingw + + # FIXME: this should be fixed in SDL3 releases after 3.1.3 + mkdir -p /tmp/deps-mingw/cmake + cp -rv /tmp/deps-mingw-extract/sdl3/SDL3-${{ steps.deps.outputs.dep-sdl-version }}/cmake/* /tmp/deps-mingw/cmake + - name: 'Download MinGW binaries' + uses: actions/download-artifact@v4 + with: + name: mingw + path: '${{ github.workspace }}' + - name: 'Untar and install ${{ needs.mingw.outputs.mingw-devel-tar-gz }}' + id: bin + run: | + mkdir -p /tmp/mingw-tardir + tar -C /tmp/mingw-tardir -v -x -f "${{ github.workspace }}/${{ needs.mingw.outputs.mingw-devel-tar-gz }}" + make -C /tmp/mingw-tardir/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }} install-all DESTDIR=/tmp/deps-mingw + - name: 'CMake (configure + build) i686' + run: | + set -e + cmake -S "${{ steps.src.outputs.path }}/cmake/test" \ + -DCMAKE_BUILD_TYPE="Release" \ + -DTEST_SHARED=TRUE \ + -DTEST_STATIC=TRUE \ + -DCMAKE_PREFIX_PATH="/tmp/deps-mingw" \ + -DCMAKE_TOOLCHAIN_FILE="${{ steps.src.outputs.path }}/build-scripts/cmake-toolchain-mingw64-i686.cmake" \ + -Werror=dev \ + -B build_x86 + cmake --build build_x86 --config Release --verbose + - name: 'CMake (configure + build) x86_64' + run: | + set -e + cmake -S "${{ steps.src.outputs.path }}/cmake/test" \ + -DCMAKE_BUILD_TYPE="Release" \ + -DTEST_SHARED=TRUE \ + -DTEST_STATIC=TRUE \ + -DCMAKE_PREFIX_PATH="/tmp/deps-mingw" \ + -DCMAKE_TOOLCHAIN_FILE="${{ steps.src.outputs.path }}/build-scripts/cmake-toolchain-mingw64-x86_64.cmake" \ + -Werror=dev \ + -B build_x64 + cmake --build build_x64 --config Release --verbose + + android: + needs: [src] + runs-on: ubuntu-latest + outputs: + android-aar: ${{ steps.releaser.outputs.android-aar }} + steps: + - name: 'Set up Python' + uses: actions/setup-python@v5 + with: + python-version: '3.11' + - name: 'Fetch build-release.py' + uses: actions/checkout@v4 + with: + sparse-checkout: 'build-scripts/build-release.py' + - name: 'Setup Android NDK' + uses: nttld/setup-ndk@v1 + with: + local-cache: true + ndk-version: r21e + - name: 'Setup Java JDK' + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '11' + - name: 'Install ninja' + run: | + sudo apt-get update -y + sudo apt-get install -y ninja-build + - name: 'Download source archives' + uses: actions/download-artifact@v4 + with: + name: sources + path: '${{ github.workspace }}' + - name: 'Untar ${{ needs.src.outputs.src-tar-gz }}' + id: tar + run: | + mkdir -p /tmp/tardir + tar -C /tmp/tardir -v -x -f "${{ github.workspace }}/${{ needs.src.outputs.src-tar-gz }}" + echo "path=/tmp/tardir/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$GITHUB_OUTPUT + - name: 'Build Android prefab binary archive(s)' + id: releaser + env: + GH_TOKEN: ${{ github.token }} + run: | + python build-scripts/build-release.py \ + --actions download android \ + --commit ${{ inputs.commit }} \ + --root "${{ steps.tar.outputs.path }}" \ + --github \ + --debug + - name: 'Store Android archive(s)' + uses: actions/upload-artifact@v4 + with: + name: android + path: '${{ github.workspace }}/dist' + + android-verify: + needs: [android, src] + runs-on: ubuntu-latest + steps: + - name: 'Set up Python' + uses: actions/setup-python@v5 + with: + python-version: '3.11' + - uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '17' + - name: 'Download source archives' + uses: actions/download-artifact@v4 + with: + name: sources + path: '${{ github.workspace }}' + - name: 'Download Android .aar archive' + uses: actions/download-artifact@v4 + with: + name: android + path: '${{ github.workspace }}' + - name: 'Untar ${{ needs.src.outputs.src-tar-gz }}' + id: src + run: | + mkdir -p /tmp/tardir + tar -C /tmp/tardir -v -x -f "${{ github.workspace }}/${{ needs.src.outputs.src-tar-gz }}" + echo "path=/tmp/tardir/${{ needs.src.outputs.project }}-${{ needs.src.outputs.version }}" >>$GITHUB_OUTPUT + - name: 'Extract Android SDK from AAR' + id: sdk + run: | + python "${{ github.workspace }}/${{ needs.android.outputs.android-aar }}" -o /tmp/deps-android + - name: 'Download dependencies' + id: deps + env: + GH_TOKEN: ${{ github.token }} + run: | + python "${{ steps.src.outputs.path }}/build-scripts/build-release.py" \ + --actions download \ + --commit ${{ inputs.commit }} \ + --root "${{ steps.src.outputs.path }}" \ + --github \ + --debug + - name: 'Extract dependencies' + id: deps-extract + run: | + python "${{ steps.deps.outputs.dep-path }}/SDL3-${{ steps.deps.outputs.dep-sdl-version }}.aar" -o /tmp/deps-android + - name: 'Install ninja' + run: | + sudo apt-get update -y + sudo apt-get install -y ninja-build + - name: 'CMake (configure + build) x86, x64, arm32, arm64' + run: | + android_abis="x86 x86_64 armeabi-v7a arm64-v8a" + for android_abi in ${android_abis}; do + echo "Configuring ${android_abi}..." + cmake -S "${{ steps.src.outputs.path }}/cmake/test" \ + -GNinja \ + -DTEST_FULL=TRUE \ + -DTEST_STATIC=FALSE \ + -DCMAKE_PREFIX_PATH="/tmp/deps-android" \ + -DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK_HOME}/build/cmake/android.toolchain.cmake \ + -DANDROID_ABI=${android_abi} \ + -Werror=dev \ + -DCMAKE_BUILD_TYPE=Release \ + -B "${android_abi}" + echo "Building ${android_abi}..." + cmake --build "${android_abi}" --config Release --verbose + done diff --git a/.gitignore b/.gitignore index 461b42f8..f4eb9a94 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,4 @@ Release *.ncb *.suo *.sdf +Xcode/build.xcconfig diff --git a/CMakeLists.txt b/CMakeLists.txt index 5611f006..e43eb833 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") set(MAJOR_VERSION 3) set(MINOR_VERSION 0) set(MICRO_VERSION 0) -set(SDL_REQUIRED_VERSION 3.0.0) +set(SDL_REQUIRED_VERSION 3.1.3) if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) message(FATAL_ERROR "Prevented in-tree built. Please create a build directory outside of the SDL_image source code and call cmake from there") @@ -289,21 +289,6 @@ set_target_properties(${sdl3_image_target_name} PROPERTIES C_VISIBILITY_PRESET "hidden" ) -if (MSVC AND CMAKE_BUILD_TYPE MATCHES "Release") - target_compile_options(${sdl3_image_target_name} PRIVATE /Zi) - - # Tell linker to include symbol data - set_target_properties(${sdl3_image_target_name} PROPERTIES - LINK_FLAGS "/INCREMENTAL:NO /DEBUG /OPT:REF /OPT:ICF" - ) - - # Set file name & location - set_target_properties(${sdl3_image_target_name} PROPERTIES - COMPILE_PDB_NAME ${sdl3_image_target_name} - COMPILE_PDB_OUTPUT_DIR ${CMAKE_BINARY_DIR} - ) -endif() - sdl_target_link_option_version_file(${sdl3_image_target_name} "${CMAKE_CURRENT_SOURCE_DIR}/src/SDL_image.sym") if(NOT ANDROID) @@ -1038,6 +1023,7 @@ if(SDLIMAGE_INSTALL) endif() configure_package_config_file(cmake/SDL3_imageConfig.cmake.in SDL3_imageConfig.cmake + NO_SET_AND_CHECK_MACRO INSTALL_DESTINATION "${SDLIMAGE_INSTALL_CMAKEDIR}" ) write_basic_package_version_file("${PROJECT_BINARY_DIR}/SDL3_imageConfigVersion.cmake" diff --git a/VisualC/SDL_image.vcxproj b/VisualC/SDL_image.vcxproj index 98b04cd5..041bc2ab 100644 --- a/VisualC/SDL_image.vcxproj +++ b/VisualC/SDL_image.vcxproj @@ -1,5 +1,8 @@  + + $(ProjectDir) + Debug @@ -44,32 +47,16 @@ - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.40219.1 - $(SolutionDir)\$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ - $(SolutionDir)\$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ - $(SolutionDir)\$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ - $(SolutionDir)\$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ AllRules.ruleset @@ -85,20 +72,20 @@ - $(ProjectDir)..\include;$(SolutionDir)..\external\SDL\include;$(IncludePath) - $(SolutionDir)$(PlatformName)\$(Configuration);$(LibraryPath) + $(ProjectDir)..\include;$(ProjectDir)..\..\SDL\include;$(IncludePath) + $(SolutionDir)$(PlatformName)\$(Configuration);$(ProjectDir)..\..\SDL\VisualC\$(PlatformName)\$(Configuration);$(LibraryPath) - $(ProjectDir)..\include;$(SolutionDir)..\external\SDL\include;$(IncludePath) - $(SolutionDir)$(PlatformName)\$(Configuration);$(LibraryPath) + $(ProjectDir)..\include;$(ProjectDir)..\..\SDL\include;$(IncludePath) + $(SolutionDir)$(PlatformName)\$(Configuration);$(ProjectDir)..\..\SDL\VisualC\$(PlatformName)\$(Configuration);$(LibraryPath) - $(ProjectDir)..\include;$(SolutionDir)..\external\SDL\include;$(IncludePath) - $(SolutionDir)$(PlatformName)\$(Configuration);$(LibraryPath) + $(ProjectDir)..\include;$(ProjectDir)..\..\SDL\include;$(IncludePath) + $(SolutionDir)$(PlatformName)\$(Configuration);$(ProjectDir)..\..\SDL\VisualC\$(PlatformName)\$(Configuration);$(LibraryPath) - $(ProjectDir)..\include;$(SolutionDir)..\external\SDL\include;$(IncludePath) - $(SolutionDir)$(PlatformName)\$(Configuration);$(LibraryPath) + $(ProjectDir)..\include;$(ProjectDir)..\..\SDL\include;$(IncludePath) + $(SolutionDir)$(PlatformName)\$(Configuration);$(ProjectDir)..\..\SDL\VisualC\$(PlatformName)\$(Configuration);$(LibraryPath) @@ -106,7 +93,7 @@ true true Win32 - .\Debug/SDL3_image.tlb + ./$(Configuration)/$(Platform)/SDL3_image.tlb @@ -127,7 +114,6 @@ true Windows - @@ -135,7 +121,7 @@ true true X64 - .\Debug/SDL3_image.tlb + ./$(Configuration)/$(Platform)/SDL3_image.tlb @@ -156,7 +142,6 @@ true Windows - @@ -164,7 +149,7 @@ true true Win32 - .\Release/SDL3_image.tlb + ./$(Configuration)/$(Platform)/SDL3_image.tlb @@ -182,7 +167,6 @@ SDL3.lib;%(AdditionalDependencies) Windows - @@ -190,7 +174,7 @@ true true X64 - .\Release/SDL3_image.tlb + ./$(Configuration)/$(Platform)/SDL3_image.tlb @@ -208,7 +192,6 @@ Windows SDL3.lib;%(AdditionalDependencies) - @@ -233,154 +216,149 @@ - + - - - {81ce8daf-ebb2-4761-8e45-b71abcca8c68} - - Document - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) Document - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) Document - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) Document - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ + Copying %(Filename)%(Extension) + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ + Copying %(Filename)%(Extension) + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) + + + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ + Copying %(Filename)%(Extension) + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ + Copying %(Filename)%(Extension) + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) + + + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ + Copying %(Filename)%(Extension) + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ + Copying %(Filename)%(Extension) + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) + + + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ + Copying %(Filename)%(Extension) + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ + Copying %(Filename)%(Extension) + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) + + + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) + + Document - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) Document - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) Document - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) Document - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) - - - - - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ - Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ - Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) - - - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ - Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ - Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) - - - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ - Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ - Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) - - - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ - Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ - Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) - copy %(FullPath) $(SolutionDir)\$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) + copy %(FullPath) $(SolutionDir)$(Platform)\$(Configuration)\ Copying %(Filename)%(Extension) - $(SolutionDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension) + $(SolutionDir)$(Platform)\$(Configuration)\%(Filename)%(Extension) diff --git a/VisualC/SDL_image.vcxproj.filters b/VisualC/SDL_image.vcxproj.filters index 36156e59..be762419 100644 --- a/VisualC/SDL_image.vcxproj.filters +++ b/VisualC/SDL_image.vcxproj.filters @@ -86,29 +86,6 @@ Sources - - - x64 - - - x64 - - - x64 - - - x64 - - - x64 - - - x64 - - - x64 - - x64 @@ -116,24 +93,45 @@ x86 + + x64 + x86 + + x64 + x86 + + x64 + x86 + + x64 + x86 + + x64 + x86 + + x64 + x86 + + x64 + x86 diff --git a/VisualC/pkg-support/cmake/sdl3_image-config-version.cmake b/VisualC/pkg-support/cmake/sdl3_image-config-version.cmake deleted file mode 100644 index 7c01743e..00000000 --- a/VisualC/pkg-support/cmake/sdl3_image-config-version.cmake +++ /dev/null @@ -1,54 +0,0 @@ -# based on the files generated by CMake's write_basic_package_version_file - -# SDL3_image CMake version configuration file: -# This file is meant to be placed in a cmake subfolder of SDL3_image-devel-3.x.y-VC - -if(NOT EXISTS "${CMAKE_CURRENT_LIST_DIR}/../include/SDL3_image/SDL_image.h") - message(AUTHOR_WARNING "Could not find SDL3_image/SDL_image.h. This script is meant to be placed in a CMake subfolder of SDL3_image-devel-3.x.y-VC") - return() -endif() - -file(READ "${CMAKE_CURRENT_LIST_DIR}/../include/SDL3_image/SDL_image.h" _sdl_image_h) -string(REGEX MATCH "#define[ \t]+SDL_IMAGE_MAJOR_VERSION[ \t]+([0-9]+)" _sdl_major_re "${_sdl_image_h}") -set(_sdl_major "${CMAKE_MATCH_1}") -string(REGEX MATCH "#define[ \t]+SDL_IMAGE_MINOR_VERSION[ \t]+([0-9]+)" _sdl_minor_re "${_sdl_image_h}") -set(_sdl_minor "${CMAKE_MATCH_1}") -string(REGEX MATCH "#define[ \t]+SDL_IMAGE_MICRO_VERSION[ \t]+([0-9]+)" _sdl_micro_re "${_sdl_image_h}") -set(_sdl_micro "${CMAKE_MATCH_1}") -if(_sdl_major_re AND _sdl_minor_re AND _sdl_micro_re) - set(PACKAGE_VERSION "${_sdl_major}.${_sdl_minor}.${_sdl_micro}") -else() - message(AUTHOR_WARNING "Could not extract version from SDL_image.h.") - return() -endif() - -if(PACKAGE_FIND_VERSION_RANGE) - # Package version must be in the requested version range - if ((PACKAGE_FIND_VERSION_RANGE_MIN STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_MIN) - OR ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_GREATER PACKAGE_FIND_VERSION_MAX) - OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND PACKAGE_VERSION VERSION_GREATER_EQUAL PACKAGE_FIND_VERSION_MAX))) - set(PACKAGE_VERSION_COMPATIBLE FALSE) - else() - set(PACKAGE_VERSION_COMPATIBLE TRUE) - endif() -else() - if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) - set(PACKAGE_VERSION_COMPATIBLE FALSE) - else() - set(PACKAGE_VERSION_COMPATIBLE TRUE) - if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) - set(PACKAGE_VERSION_EXACT TRUE) - endif() - endif() -endif() - -# if the using project doesn't have CMAKE_SIZEOF_VOID_P set, fail. -if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "") - set(PACKAGE_VERSION_UNSUITABLE TRUE) -endif() - -# check that the installed version has the same 32/64bit-ness as the one which is currently searching: -if(NOT (CMAKE_SIZEOF_VOID_P STREQUAL "8" OR CMAKE_SIZEOF_VOID_P STREQUAL "4")) - set(PACKAGE_VERSION "${PACKAGE_VERSION} (32+64bit)") - set(PACKAGE_VERSION_UNSUITABLE TRUE) -endif() diff --git a/VisualC/pkg-support/cmake/sdl3_image-config.cmake b/VisualC/pkg-support/cmake/sdl3_image-config.cmake deleted file mode 100644 index e26a5f8c..00000000 --- a/VisualC/pkg-support/cmake/sdl3_image-config.cmake +++ /dev/null @@ -1,73 +0,0 @@ -# SDL3_image CMake configuration file: -# This file is meant to be placed in a cmake subfolder of SDL3_image-devel-3.x.y-VC - -include(FeatureSummary) -set_package_properties(SDL3_image PROPERTIES - URL "https://www.libsdl.org/projects/SDL_image/" - DESCRIPTION "SDL_image is an image file loading library" -) - -cmake_minimum_required(VERSION 3.0) - -set(SDL3_image_FOUND TRUE) - -set(SDLIMAGE_AVIF FALSE) -set(SDLIMAGE_BMP TRUE) -set(SDLIMAGE_GIF TRUE) -set(SDLIMAGE_JPG TRUE) -set(SDLIMAGE_JXL FALSE) -set(SDLIMAGE_LBM TRUE) -set(SDLIMAGE_PCX TRUE) -set(SDLIMAGE_PNG TRUE) -set(SDLIMAGE_PNM TRUE) -set(SDLIMAGE_QOI TRUE) -set(SDLIMAGE_SVG TRUE) -set(SDLIMAGE_TGA TRUE) -set(SDLIMAGE_TIF FALSE) -set(SDLIMAGE_XCF FALSE) -set(SDLIMAGE_XPM TRUE) -set(SDLIMAGE_XV TRUE) -set(SDLIMAGE_WEBP FALSE) - -set(SDLIMAGE_JPG_SAVE FALSE) -set(SDLIMAGE_PNG_SAVE FALSE) - -set(SDLIMAGE_VENDORED FALSE) - -set(SDLIMAGE_BACKEND_IMAGEIO FALSE) -set(SDLIMAGE_BACKEND_STB TRUE) -set(SDLIMAGE_BACKEND_WIC FALSE) - -if(CMAKE_SIZEOF_VOID_P STREQUAL "4") - set(_sdl_arch_subdir "x86") -elseif(CMAKE_SIZEOF_VOID_P STREQUAL "8") - set(_sdl_arch_subdir "x64") -else() - unset(_sdl_arch_subdir) - set(SDL3_image_FOUND FALSE) - return() -endif() - -set(_sdl3image_incdir "${CMAKE_CURRENT_LIST_DIR}/../include") -set(_sdl3image_library "${CMAKE_CURRENT_LIST_DIR}/../lib/${_sdl_arch_subdir}/SDL3_image.lib") -set(_sdl3image_dll "${CMAKE_CURRENT_LIST_DIR}/../lib/${_sdl_arch_subdir}/SDL3_image.dll") - -# All targets are created, even when some might not be requested though COMPONENTS. -# This is done for compatibility with CMake generated SDL3_image-target.cmake files. - -if(NOT TARGET SDL3_image::SDL3_image) - add_library(SDL3_image::SDL3_image SHARED IMPORTED) - set_target_properties(SDL3_image::SDL3_image - PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${_sdl3image_incdir}" - IMPORTED_IMPLIB "${_sdl3image_library}" - IMPORTED_LOCATION "${_sdl3image_dll}" - COMPATIBLE_INTERFACE_BOOL "SDL3_SHARED" - INTERFACE_SDL3_SHARED "ON" - ) -endif() - -unset(_sdl_arch_subdir) -unset(_sdl3image_incdir) -unset(_sdl3image_library) -unset(_sdl3image_dll) diff --git a/Xcode/SDL_image.xcodeproj/project.pbxproj b/Xcode/SDL_image.xcodeproj/project.pbxproj index 3fcef8a6..61388c1b 100644 --- a/Xcode/SDL_image.xcodeproj/project.pbxproj +++ b/Xcode/SDL_image.xcodeproj/project.pbxproj @@ -566,7 +566,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "PRODUCT_NAME=SDL3_image\nOPTIONAL_FRAMEWORKS=\"avif jxl webp\"\n\nmkdir -p build/dmg-tmp\ncp -a build/$PRODUCT_NAME.xcframework build/dmg-tmp/\ncp pkg-support/resources/ReadMe.txt build/dmg-tmp\nfor i in $OPTIONAL_FRAMEWORKS; do\n if [ -d build/$i.xcframework ]; then\n mkdir -p build/dmg-tmp/optional\n cp -a build/$i.xcframework build/dmg-tmp/optional/\n fi\ndone\n\n# remove the .DS_Store files if any (we may want to provide one in the future for fancy .dmgs)\nrm -rf build/dmg-tmp/.DS_Store\n\n# create the dmg\nhdiutil create -ov -fs HFS+ -volname $PRODUCT_NAME -srcfolder build/dmg-tmp build/$PRODUCT_NAME.dmg\n\n# clean up\nrm -rf build/dmg-tmp\n"; + shellScript = "set -ex\n\nPRODUCT_NAME=SDL3_image\nOPTIONAL_FRAMEWORKS=\"avif jxl webp\"\n\nmkdir -p build/dmg-tmp/share/cmake/$PRODUCT_NAME\ncp -a build/$PRODUCT_NAME.xcframework build/dmg-tmp/\ncp pkg-support/resources/ReadMe.txt build/dmg-tmp\ncp pkg-support/resources/share/cmake/${PRODUCT_NAME}/${PRODUCT_NAME}Config.cmake build/dmg-tmp/share/cmake/${PRODUCT_NAME}\ncp pkg-support/resources/share/cmake/${PRODUCT_NAME}/${PRODUCT_NAME}ConfigVersion.cmake build/dmg-tmp/share/cmake/${PRODUCT_NAME}\nfor i in $OPTIONAL_FRAMEWORKS; do\n if [ -d build/$i.xcframework ]; then\n mkdir -p build/dmg-tmp/optional\n cp -a build/$i.xcframework build/dmg-tmp/optional/\n fi\ndone\n\n# remove the .DS_Store files if any (we may want to provide one in the future for fancy .dmgs)\nrm -rf build/dmg-tmp/.DS_Store\n\n# create the dmg\nhdiutil create -ov -fs HFS+ -volname $PRODUCT_NAME -srcfolder build/dmg-tmp build/$PRODUCT_NAME.dmg\n\n# clean up\nrm -rf build/dmg-tmp\n"; }; /* End PBXShellScriptBuildPhase section */ diff --git a/Xcode/pkg-support/build.xcconfig b/Xcode/pkg-support/build.xcconfig new file mode 100644 index 00000000..28fc1578 --- /dev/null +++ b/Xcode/pkg-support/build.xcconfig @@ -0,0 +1,21 @@ +// +// build.xcconfig +// + +// Configuration settings file format documentation can be found at: +// https://help.apple.com/xcode/#/dev745c5c974 + +// Uncomment these lines to enable AVIF support +// If you do this, you should run external/download.sh to download the decode libraries and add avif.framework to your application bundle. +AVIF_PREPROCESSOR_DEFINITIONS = LOAD_AVIF +AVIF_FRAMEWORK_LDFLAGS = -weak_framework avif + +// Uncomment these lines to enable JPEG-XL support +// If you do this, you should run external/download.sh to download the decode libraries and add jxl.framework to your application bundle. +JXL_PREPROCESSOR_DEFINITIONS = LOAD_JXL +JXL_FRAMEWORK_LDFLAGS = -weak_framework jxl + +// Uncomment these lines to enable WebP support +// If you do this, you should run external/download.sh to download the decode libraries and add webp.framework to your application bundle. +WEBP_PREPROCESSOR_DEFINITIONS = LOAD_WEBP +WEBP_FRAMEWORK_LDFLAGS = -weak_framework webp diff --git a/Xcode/pkg-support/resources/CMake/SDL3_imageConfig.cmake b/Xcode/pkg-support/resources/CMake/SDL3_imageConfig.cmake new file mode 100644 index 00000000..16601673 --- /dev/null +++ b/Xcode/pkg-support/resources/CMake/SDL3_imageConfig.cmake @@ -0,0 +1,95 @@ +# SDL3_image CMake configuration file: +# This file is meant to be placed in Resources/CMake of a SDL3_image framework + +# INTERFACE_LINK_OPTIONS needs CMake 3.12 +cmake_minimum_required(VERSION 3.12) + +include(FeatureSummary) +set_package_properties(SDL3_image PROPERTIES + URL "https://www.libsdl.org/projects/SDL_image/" + DESCRIPTION "SDL_image is an image file loading library" +) + +set(SDL3_image_FOUND TRUE) + +set(SDLIMAGE_AVIF TRUE) +set(SDLIMAGE_BMP TRUE) +set(SDLIMAGE_GIF TRUE) +set(SDLIMAGE_JPG TRUE) +set(SDLIMAGE_JXL TRUE) +set(SDLIMAGE_LBM TRUE) +set(SDLIMAGE_PCX TRUE) +set(SDLIMAGE_PNG TRUE) +set(SDLIMAGE_PNM TRUE) +set(SDLIMAGE_QOI TRUE) +set(SDLIMAGE_SVG TRUE) +set(SDLIMAGE_TGA TRUE) +set(SDLIMAGE_TIF TRUE) +set(SDLIMAGE_XCF TRUE) +set(SDLIMAGE_XPM TRUE) +set(SDLIMAGE_XV TRUE) +set(SDLIMAGE_WEBP TRUE) + +set(SDLIMAGE_JPG_SAVE TRUE) +set(SDLIMAGE_PNG_SAVE TRUE) + +set(SDLIMAGE_VENDORED FALSE) + +set(SDLIMAGE_BACKEND_IMAGEIO TRUE) +set(SDLIMAGE_BACKEND_STB FALSE) +set(SDLIMAGE_BACKEND_WIC FALSE) + +# Compute the installation prefix relative to this file. +set(_sdl3_image_framework_path "${CMAKE_CURRENT_LIST_DIR}") # > /SDL3_image.framework/Resources/CMake/ +get_filename_component(_sdl3_image_framework_path "${_sdl3_image_framework_path}" REALPATH) # > /SDL3_image.framework/Versions/Current/Resources/CMake +get_filename_component(_sdl3_image_framework_path "${_sdl3_image_framework_path}" REALPATH) # > /SDL3_image.framework/Versions/A/Resources/CMake/ +get_filename_component(_sdl3_image_framework_path "${_sdl3_image_framework_path}" PATH) # > /SDL3_image.framework/Versions/A/Resources/ +get_filename_component(_sdl3_image_framework_path "${_sdl3_image_framework_path}" PATH) # > /SDL3_image.framework/Versions/A/ +get_filename_component(_sdl3_image_framework_path "${_sdl3_image_framework_path}" PATH) # > /SDL3_image.framework/Versions/ +get_filename_component(_sdl3_image_framework_path "${_sdl3_image_framework_path}" PATH) # > /SDL3_image.framework/ +get_filename_component(_sdl3_image_framework_parent_path "${_sdl3_image_framework_path}" PATH) # > / + +# All targets are created, even when some might not be requested though COMPONENTS. +# This is done for compatibility with CMake generated SDL3_image-target.cmake files. + +if(NOT TARGET SDL3_image::SDL3_image-shared) + add_library(SDL3_image::SDL3_image-shared SHARED IMPORTED) + set_target_properties(SDL3_image::SDL3_image-shared + PROPERTIES + FRAMEWORK "TRUE" + IMPORTED_LOCATION "${_sdl3_image_framework_path}/SDL3_image" + COMPATIBLE_INTERFACE_BOOL "SDL3_SHARED" + INTERFACE_SDL3_SHARED "ON" + COMPATIBLE_INTERFACE_STRING "SDL_VERSION" + INTERFACE_SDL_VERSION "SDL3" + ) +endif() +set(SDL3_image_SDL3_image-shared_FOUND TRUE) + +set(SDL3_image_SDL3_image-static FALSE) + +unset(_sdl3_image_framework_path) +unset(_sdl3_image_framework_parent_path) + +if(SDL3_image_SDL3_image-shared_FOUND) + set(SDL3_image_SDL3_image_FOUND TRUE) +endif() + +function(_sdl_create_target_alias_compat NEW_TARGET TARGET) + if(CMAKE_VERSION VERSION_LESS "3.18") + # Aliasing local targets is not supported on CMake < 3.18, so make it global. + add_library(${NEW_TARGET} INTERFACE IMPORTED) + set_target_properties(${NEW_TARGET} PROPERTIES INTERFACE_LINK_LIBRARIES "${TARGET}") + else() + add_library(${NEW_TARGET} ALIAS ${TARGET}) + endif() +endfunction() + +# Make sure SDL3_image::SDL3_image always exists +if(NOT TARGET SDL3_image::SDL3_image) + if(TARGET SDL3_image::SDL3_image-shared) + _sdl_create_target_alias_compat(SDL3_image::SDL3_image SDL3_image::SDL3_image-shared) + endif() +endif() + +check_required_components(SDL3_image) diff --git a/Xcode/pkg-support/resources/CMake/sdl3_image-config-version.cmake b/Xcode/pkg-support/resources/CMake/SDL3_imageConfigVersion.cmake similarity index 100% rename from Xcode/pkg-support/resources/CMake/sdl3_image-config-version.cmake rename to Xcode/pkg-support/resources/CMake/SDL3_imageConfigVersion.cmake diff --git a/Xcode/pkg-support/resources/CMake/sdl3_image-config.cmake b/Xcode/pkg-support/resources/CMake/sdl3_image-config.cmake deleted file mode 100644 index 307fd695..00000000 --- a/Xcode/pkg-support/resources/CMake/sdl3_image-config.cmake +++ /dev/null @@ -1,61 +0,0 @@ -# SDL3_image CMake configuration file: -# This file is meant to be placed in Resources/CMake of a SDL3_image framework - -# INTERFACE_LINK_OPTIONS needs CMake 3.12 -cmake_minimum_required(VERSION 3.12) - -include(FeatureSummary) -set_package_properties(SDL3_image PROPERTIES - URL "https://www.libsdl.org/projects/SDL_image/" - DESCRIPTION "SDL_image is an image file loading library" -) - -set(SDL3_image_FOUND TRUE) - -set(SDLIMAGE_AVIF FALSE) -set(SDLIMAGE_BMP TRUE) -set(SDLIMAGE_GIF TRUE) -set(SDLIMAGE_JPG TRUE) -set(SDLIMAGE_JXL FALSE) -set(SDLIMAGE_LBM TRUE) -set(SDLIMAGE_PCX TRUE) -set(SDLIMAGE_PNG TRUE) -set(SDLIMAGE_PNM TRUE) -set(SDLIMAGE_QOI TRUE) -set(SDLIMAGE_SVG TRUE) -set(SDLIMAGE_TGA TRUE) -set(SDLIMAGE_TIF TRUE) -set(SDLIMAGE_XCF TRUE) -set(SDLIMAGE_XPM TRUE) -set(SDLIMAGE_XV TRUE) -set(SDLIMAGE_WEBP FALSE) - -set(SDLIMAGE_JPG_SAVE FALSE) -set(SDLIMAGE_PNG_SAVE FALSE) - -set(SDLIMAGE_VENDORED FALSE) - -set(SDLIMAGE_BACKEND_IMAGEIO FALSE) -set(SDLIMAGE_BACKEND_STB TRUE) -set(SDLIMAGE_BACKEND_WIC FALSE) - -string(REGEX REPLACE "SDL3_image\\.framework.*" "SDL3_image.framework" _sdl3image_framework_path "${CMAKE_CURRENT_LIST_DIR}") -string(REGEX REPLACE "SDL3_image\\.framework.*" "" _sdl3image_framework_parent_path "${CMAKE_CURRENT_LIST_DIR}") - -# All targets are created, even when some might not be requested though COMPONENTS. -# This is done for compatibility with CMake generated SDL3_image-target.cmake files. - -if(NOT TARGET SDL3_image::SDL3_image) - add_library(SDL3_image::SDL3_image INTERFACE IMPORTED) - set_target_properties(SDL3_image::SDL3_image - PROPERTIES - INTERFACE_COMPILE_OPTIONS "SHELL:-F ${_sdl3image_framework_parent_path}" - INTERFACE_INCLUDE_DIRECTORIES "${_sdl3image_framework_path}/Headers" - INTERFACE_LINK_OPTIONS "SHELL:-F ${_sdl3image_framework_parent_path};SHELL:-framework SDL3_image" - COMPATIBLE_INTERFACE_BOOL "SDL3_SHARED" - INTERFACE_SDL3_SHARED "ON" - ) -endif() - -unset(_sdl3image_framework_path) -unset(_sdl3image_framework_parent_path) diff --git a/Xcode/pkg-support/resources/share/cmake/SDL3_image/SDL3_imageConfig.cmake b/Xcode/pkg-support/resources/share/cmake/SDL3_image/SDL3_imageConfig.cmake new file mode 100644 index 00000000..612f1ee5 --- /dev/null +++ b/Xcode/pkg-support/resources/share/cmake/SDL3_image/SDL3_imageConfig.cmake @@ -0,0 +1,174 @@ +# SDL3 CMake configuration file: +# This file is meant to be placed in share/cmake/SDL3_image, next to SDL3_image.xcframework + +# INTERFACE_LINK_OPTIONS needs CMake 3.12 +cmake_minimum_required(VERSION 3.12) + +include(FeatureSummary) +set_package_properties(SDL3_image PROPERTIES + URL "https://www.libsdl.org/projects/SDL_image/" + DESCRIPTION "SDL_image is an image file loading library" +) + +# Copied from `configure_package_config_file` +macro(set_and_check _var _file) + set(${_var} "${_file}") + if(NOT EXISTS "${_file}") + message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !") + endif() +endmacro() + +# Copied from `configure_package_config_file` +macro(check_required_components _NAME) + foreach(comp ${${_NAME}_FIND_COMPONENTS}) + if(NOT ${_NAME}_${comp}_FOUND) + if(${_NAME}_FIND_REQUIRED_${comp}) + set(${_NAME}_FOUND FALSE) + endif() + endif() + endforeach() +endmacro() + +macro(_check_target_is_simulator) + set(src [===[ + #include + #if defined(TARGET_OS_SIMULATOR) && TARGET_OS_SIMULATOR + int target_is_simulator; + #endif + int main(int argc, char *argv[]) { return target_is_simulator; } + ]===]) + if(CMAKE_C_COMPILER) + include(CheckCSourceCompiles) + check_c_source_compiles("${src}" SDL_TARGET_IS_SIMULATOR) + elseif(CMAKE_CXX_COMPILER) + include(CheckCXXSourceCompiles) + check_cxx_source_compiles("${src}" SDL_TARGET_IS_SIMULATOR) + else() + enable_language(C) + include(CheckCSourceCompiles) + check_c_source_compiles("${src}" SDL_TARGET_IS_SIMULATOR) + endif() +endmacro() + +if(CMAKE_SYSTEM_NAME STREQUAL "iOS") + _check_target_is_simulator() + if(SDL_TARGET_IS_SIMULATOR) + set(_xcfw_target_subdir "ios-arm64_x86_64-simulator") + else() + set(_xcfw_target_subdir "ios-arm64") + endif() +elseif(CMAKE_SYSTEM_NAME STREQUAL "tvOS") + _check_target_is_simulator() + if(SDL_TARGET_IS_SIMULATOR) + set(_xcfw_target_subdir "tvos-arm64_x86_64-simulator") + else() + set(_xcfw_target_subdir "tvos-arm64") + endif() +elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set(_xcfw_target_subdir "macos-arm64_x86_64") +else() + message(WARNING "Unsupported Apple platform (${CMAKE_SYSTEM_NAME}) and broken SDL3_imageConfigVersion.cmake") + set(SDL3_image_FOUND FALSE) + return() +endif() + +# Compute the installation prefix relative to this file. +get_filename_component(_sdl3_image_xcframework_parent_path "${CMAKE_CURRENT_LIST_DIR}" REALPATH) # /share/cmake/SDL3/ +get_filename_component(_sdl3_image_xcframework_parent_path "${_sdl3_image_xcframework_parent_path}" REALPATH) # /share/cmake/SDL3/ +get_filename_component(_sdl3_image_xcframework_parent_path "${_sdl3_image_xcframework_parent_path}" PATH) # /share/cmake +get_filename_component(_sdl3_image_xcframework_parent_path "${_sdl3_image_xcframework_parent_path}" PATH) # /share +get_filename_component(_sdl3_image_xcframework_parent_path "${_sdl3_image_xcframework_parent_path}" PATH) # / +set_and_check(_sdl3_image_xcframework_path "${_sdl3_image_xcframework_parent_path}/SDL3_image.xcframework") # /SDL3_image.xcframework +set_and_check(_sdl3_image_framework_parent_path "${_sdl3_image_xcframework_path}/${_xcfw_target_subdir}") # /SDL3_image.xcframework/macos-arm64_x86_64 +set_and_check(_sdl3_image_framework_path "${_sdl3_image_framework_parent_path}/SDL3_image.framework") # /SDL3_image.xcframework/macos-arm64_x86_64/SDL3_image.framework + +set(SDL3_image_FOUND TRUE) + +set(SDLIMAGE_AVIF TRUE) +set(SDLIMAGE_BMP TRUE) +set(SDLIMAGE_GIF TRUE) +set(SDLIMAGE_JPG TRUE) +set(SDLIMAGE_JXL TRUE) +set(SDLIMAGE_LBM TRUE) +set(SDLIMAGE_PCX TRUE) +set(SDLIMAGE_PNG TRUE) +set(SDLIMAGE_PNM TRUE) +set(SDLIMAGE_QOI TRUE) +set(SDLIMAGE_SVG TRUE) +set(SDLIMAGE_TGA TRUE) +set(SDLIMAGE_TIF TRUE) +set(SDLIMAGE_XCF TRUE) +set(SDLIMAGE_XPM TRUE) +set(SDLIMAGE_XV TRUE) +set(SDLIMAGE_WEBP TRUE) + +set(SDLIMAGE_JPG_SAVE TRUE) +set(SDLIMAGE_PNG_SAVE TRUE) + +set(SDLIMAGE_VENDORED FALSE) + +set(SDLIMAGE_BACKEND_IMAGEIO TRUE) +set(SDLIMAGE_BACKEND_STB FALSE) +set(SDLIMAGE_BACKEND_WIC FALSE) + + +# All targets are created, even when some might not be requested though COMPONENTS. +# This is done for compatibility with CMake generated SDL3_image-target.cmake files. + +if(NOT TARGET SDL3_image::SDL3_image-shared) + add_library(SDL3_image::SDL3_image-shared SHARED IMPORTED) + # CMake does not automatically add RPATHS when using xcframeworks + # https://gitlab.kitware.com/cmake/cmake/-/issues/25998 + if(0) # if(CMAKE_VERSION GREATER_EQUAL "3.28") + set_target_properties(SDL3_image::SDL3_image-shared + PROPERTIES + FRAMEWORK "TRUE" + IMPORTED_LOCATION "${_sdl3_image_xcframework_path}" + ) + else() + set_target_properties(SDL3_image::SDL3_image-shared + PROPERTIES + FRAMEWORK "TRUE" + IMPORTED_LOCATION "${_sdl3_image_framework_path}/SDL3_image" + ) + endif() + set_target_properties(SDL3_image::SDL3_image-shared + PROPERTIES + COMPATIBLE_INTERFACE_BOOL "SDL3_SHARED" + INTERFACE_SDL3_SHARED "ON" + COMPATIBLE_INTERFACE_STRING "SDL_VERSION" + INTERFACE_SDL_VERSION "SDL3" + ) +endif() +set(SDL3_image_SDL3_image-shared_FOUND TRUE) + +set(SDL3_image_SDL3_image-static FALSE) + +unset(_sdl3_image_xcframework_parent_path) +unset(_sdl3_image_xcframework_path) +unset(_sdl3_image_framework_parent_path) +unset(_sdl3_image_framework_path) +unset(_sdl3_image_include_dirs) + +if(SDL3_image_SDL3_image-shared_FOUND) + set(SDL3_image_SDL3_image TRUE) +endif() + +function(_sdl_create_target_alias_compat NEW_TARGET TARGET) + if(CMAKE_VERSION VERSION_LESS "3.18") + # Aliasing local targets is not supported on CMake < 3.18, so make it global. + add_library(${NEW_TARGET} INTERFACE IMPORTED) + set_target_properties(${NEW_TARGET} PROPERTIES INTERFACE_LINK_LIBRARIES "${TARGET}") + else() + add_library(${NEW_TARGET} ALIAS ${TARGET}) + endif() +endfunction() + +# Make sure SDL3_image::SDL3_image always exists +if(NOT TARGET SDL3_image::SDL3_image) + if(TARGET SDL3_image::SDL3_image-shared) + _sdl_create_target_alias_compat(SDL3_image::SDL3_image SDL3_image::SDL3_image-shared) + endif() +endif() + +check_required_components(SDL3_image) diff --git a/Xcode/pkg-support/resources/share/cmake/SDL3_image/SDL3_imageConfigVersion.cmake b/Xcode/pkg-support/resources/share/cmake/SDL3_image/SDL3_imageConfigVersion.cmake new file mode 100644 index 00000000..4633a1bd --- /dev/null +++ b/Xcode/pkg-support/resources/share/cmake/SDL3_image/SDL3_imageConfigVersion.cmake @@ -0,0 +1,76 @@ +# based on the files generated by CMake's write_basic_package_version_file + +# SDL CMake version configuration file: +# This file is meant to be placed in share/cmake/SDL3_image, next to SDL3_image.xcframework + +cmake_minimum_required(VERSION 3.12) + +get_filename_component(_sdl3_image_xcframework_parent_path "${CMAKE_CURRENT_LIST_DIR}" REALPATH) # /share/cmake/SDL3_image/ +get_filename_component(_sdl3_image_xcframework_parent_path "${_sdl3_image_xcframework_parent_path}" REALPATH) # /share/cmake/SDL3_image/ +get_filename_component(_sdl3_image_xcframework_parent_path "${_sdl3_image_xcframework_parent_path}" PATH) # /share/cmake +get_filename_component(_sdl3_image_xcframework_parent_path "${_sdl3_image_xcframework_parent_path}" PATH) # /share +get_filename_component(_sdl3_image_xcframework_parent_path "${_sdl3_image_xcframework_parent_path}" PATH) # / +set(_sdl3_image_xcframework "${_sdl3_image_xcframework_parent_path}/SDL3_image.xcframework") # /SDL3_image.xcframework +set(_sdl3_image_framework "${_sdl3_image_xcframework}/macos-arm64_x86_64/SDL3_image.framework") # /SDL3_image.xcframework/macos-arm64_x86_64/SDL3_image.framework +set(_sdl3_image_version_h "${_sdl3_image_framework}/Headers/SDL_image.h") # /SDL3_image.xcframework/macos-arm64_x86_64/SDL3_image.framework/Headers/SDL_image.h + +if(NOT EXISTS "${_sdl3_image_version_h}") + message(AUTHOR_WARNING "Cannot not find ${_sdl3_image_framework}. This script is meant to be placed in share/cmake/SDL3, next to SDL3.xcframework") + return() +endif() + +file(READ "${_sdl3_image_version_h}" _sdl_version_h) + +unset(_sdl3_image_xcframework_parent_path) +unset(_sdl3_image_framework) +unset(_sdl3_image_xcframework) +unset(_sdl3_image_version_h) + +string(REGEX MATCH "#define[ \t]+SDL_IMAGE_MAJOR_VERSION[ \t]+([0-9]+)" _sdl_major_re "${_sdl_version_h}") +set(_sdl_major "${CMAKE_MATCH_1}") +string(REGEX MATCH "#define[ \t]+SDL_IMAGE_MINOR_VERSION[ \t]+([0-9]+)" _sdl_minor_re "${_sdl_version_h}") +set(_sdl_minor "${CMAKE_MATCH_1}") +string(REGEX MATCH "#define[ \t]+SDL_IMAGE_MICRO_VERSION[ \t]+([0-9]+)" _sdl_micro_re "${_sdl_version_h}") +set(_sdl_micro "${CMAKE_MATCH_1}") +if(_sdl_major_re AND _sdl_minor_re AND _sdl_micro_re) + set(PACKAGE_VERSION "${_sdl_major}.${_sdl_minor}.${_sdl_micro}") +else() + message(AUTHOR_WARNING "Could not extract version from SDL_image.h.") + return() +endif() + +unset(_sdl_major_re) +unset(_sdl_major) +unset(_sdl_minor_re) +unset(_sdl_minor) +unset(_sdl_micro_re) +unset(_sdl_micro) + +if(PACKAGE_FIND_VERSION_RANGE) + # Package version must be in the requested version range + if ((PACKAGE_FIND_VERSION_RANGE_MIN STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_MIN) + OR ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_GREATER PACKAGE_FIND_VERSION_MAX) + OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND PACKAGE_VERSION VERSION_GREATER_EQUAL PACKAGE_FIND_VERSION_MAX))) + set(PACKAGE_VERSION_COMPATIBLE FALSE) + else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + endif() +else() + if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) + set(PACKAGE_VERSION_COMPATIBLE FALSE) + else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) + set(PACKAGE_VERSION_EXACT TRUE) + endif() + endif() +endif() + +# The SDL3_image.xcframework only contains 64-bit archives +if(NOT "${CMAKE_SIZEOF_VOID_P}" EQUAL "8") + set(PACKAGE_VERSION_UNSUITABLE TRUE) +endif() + +if(NOT CMAKE_SYSTEM_NAME MATCHES "^(Darwin|iOS|tvOS)$") + set(PACKAGE_VERSION_UNSUITABLE TRUE) +endif() diff --git a/build-scripts/android-prefab.sh b/build-scripts/android-prefab.sh deleted file mode 100755 index a66bbd3f..00000000 --- a/build-scripts/android-prefab.sh +++ /dev/null @@ -1,353 +0,0 @@ -#!/bin/bash - -set -e - -if ! [ "x$ANDROID_NDK_HOME" != "x" -a -d "$ANDROID_NDK_HOME" ]; then - echo "ANDROID_NDK_HOME environment variable is not set" - exit 1 -fi - -if ! [ "x$ANDROID_HOME" != "x" -a -d "$ANDROID_HOME" ]; then - echo "ANDROID_HOME environment variable is not set" - exit 1 -fi - -if [ "x$ANDROID_API" = "x" ]; then - ANDROID_API="$(ls "$ANDROID_HOME/platforms" | grep -E "^android-[0-9]+$" | sed 's/android-//' | sort -n -r | head -1)" - if [ "x$ANDROID_API" = "x" ]; then - echo "No Android platform found in $ANDROID_HOME/platforms" - exit 1 - fi -else - if ! [ -d "$ANDROID_HOME/platforms/android-$ANDROID_API" ]; then - echo "Android api version $ANDROID_API is not available ($ANDROID_HOME/platforms/android-$ANDROID_API does not exist)" >2 - exit 1 - fi -fi - -android_platformdir="$ANDROID_HOME/platforms/android-$ANDROID_API" - -echo "Building for android api version $ANDROID_API" -echo "android_platformdir=$android_platformdir" - -scriptdir=$(cd -P -- "$(dirname -- "$0")" && printf '%s\n' "$(pwd -P)") -sdlimage_root=$(cd -P -- "$(dirname -- "$0")/.." && printf '%s\n' "$(pwd -P)") - -build_root="${sdlimage_root}/build-android-prefab" - -android_abis="armeabi-v7a arm64-v8a x86 x86_64" -android_api=19 -android_ndk=21 -android_stl="c++_shared" - -sdlimage_major=$(sed -ne 's/^#define SDL_IMAGE_MAJOR_VERSION *//p' "${sdlimage_root}/include/SDL3_image/SDL_image.h") -sdlimage_minor=$(sed -ne 's/^#define SDL_IMAGE_MINOR_VERSION *//p' "${sdlimage_root}/include/SDL3_image/SDL_image.h") -sdlimage_micro=$(sed -ne 's/^#define SDL_IMAGE_MICRO_VERSION *//p' "${sdlimage_root}/include/SDL3_image/SDL_image.h") -sdlimage_version="${sdlimage_major}.${sdlimage_minor}.${sdlimage_micro}" -echo "Building Android prefab package for SDL_image version $sdlimage_version" - -if test ! -d "${sdl_build_root}"; then - echo "sdl_build_root is not defined or is not a directory." - echo "Set this environment folder to the root of an android SDL${sdlimage_major} prefab build" - echo "This usually is SDL/build-android-prefab" - exit 1 -fi - -prefabhome="${build_root}/prefab-${sdlimage_version}" -rm -rf "$prefabhome" -mkdir -p "${prefabhome}" - -build_cmake_projects() { - for android_abi in $android_abis; do - - rm -rf "${build_root}/build_${android_abi}/prefix" - - for build_shared_libs in ON OFF; do - echo "Configuring CMake project for $android_abi (shared=${build_shared_libs})" - cmake -S "${sdlimage_root}" -B "${build_root}/build_${android_abi}/shared_${build_shared_libs}" \ - -DSDLIMAGE_DEPS_SHARED=ON \ - -DSDLIMAGE_VENDORED=ON \ - -DSDLIMAGE_BACKEND_STB=OFF \ - -DSDLIMAGE_AVIF=OFF \ - -DSDLIMAGE_BMP=ON \ - -DSDLIMAGE_GIF=ON \ - -DSDLIMAGE_JPG=ON \ - -DSDLIMAGE_JXL=OFF \ - -DSJPEG_ANDROID_NDK_PATH="${ANDROID_NDK_HOME}" \ - -DSDLIMAGE_LBM=ON \ - -DSDLIMAGE_PCX=ON \ - -DSDLIMAGE_PNG=ON \ - -DSDLIMAGE_PNM=ON \ - -DSDLIMAGE_QOI=ON \ - -DSDLIMAGE_SVG=ON \ - -DSDLIMAGE_TGA=ON \ - -DSDLIMAGE_TIF=ON \ - -DSDLIMAGE_WEBP=ON \ - -DSDLIMAGE_XCF=ON \ - -DSDLIMAGE_XPM=ON \ - -DSDLIMAGE_XV=ON \ - -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake" \ - -DSDL${sdlimage_major}_DIR="${sdl_build_root}/build_${android_abi}/prefix/lib/cmake/SDL${sdlimage_major}" \ - -DANDROID_PLATFORM=${android_platform} \ - -DANDROID_ABI=${android_abi} \ - -DBUILD_SHARED_LIBS=${build_shared_libs} \ - -DCMAKE_INSTALL_PREFIX="${build_root}/build_${android_abi}/prefix" \ - -DCMAKE_INSTALL_INCLUDEDIR=include \ - -DCMAKE_INSTALL_LIBDIR=lib \ - -DCMAKE_BUILD_TYPE=Release \ - -DSDL${sdlimage_major}IMAGE_SAMPLES=OFF \ - -DSDL${sdlimage_major}IMAGE_TESTS=OFF \ - -GNinja - - echo "Building CMake project for $android_abi (shared=${build_shared_libs})" - cmake --build "${build_root}/build_${android_abi}/shared_${build_shared_libs}" - - echo "Installing CMake project for $android_abi (shared=${build_shared_libs})" - cmake --install "${build_root}/build_${android_abi}/shared_${build_shared_libs}" - done - done -} - -pom_filename="SDL${sdlimage_major}_image-${sdlimage_version}.pom" -pom_filepath="${prefabhome}/${pom_filename}" -create_pom_xml() { - echo "Creating ${pom_filename}" - cat >"${pom_filepath}" < - 4.0.0 - org.libsdl.android - SDL${sdlimage_major}_image - ${sdlimage_version} - aar - SDL${sdlimage_major}_image - The AAR for SDL${sdlimage_major}_image - https://libsdl.org/ - - - zlib License - https://github.com/libsdl-org/SDL_image/blob/main/LICENSE.txt - repo - - - - - Sam Lantinga - slouken@libsdl.org - SDL - https://www.libsdl.org - - - - scm:git:https://github.com/libsdl-org/SDL_image - scm:git:ssh://github.com:libsdl-org/SDL_image.git - https://github.com/libsdl-org/SDL_image - - - - ossrh - https://s01.oss.sonatype.org/content/repositories/snapshots - - - ossrh - https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/ - - - -EOF -} - -create_aar_androidmanifest() { - echo "Creating AndroidManifest.xml" - cat >"${aar_root}/AndroidManifest.xml" < - - -EOF -} - -echo "Creating AAR root directory" -aar_root="${prefabhome}/SDL${sdlimage_major}_image-${sdlimage_version}" -mkdir -p "${aar_root}" - -aar_metainfdir_path=${aar_root}/META-INF -mkdir -p "${aar_metainfdir_path}" -cp "${sdlimage_root}/LICENSE.txt" "${aar_metainfdir_path}" - -prefabworkdir="${aar_root}/prefab" -mkdir -p "${prefabworkdir}" - -cat >"${prefabworkdir}/prefab.json" <"${sdl_moduleworkdir}/module.json" <"${abi_sdllibdir}/abi.json" <"${sdl_moduleworkdir}/module.json" <"${abi_sdllibdir}/abi.json" <"${sdl_moduleworkdir}/module.json" <"${abi_sdllibdir}/abi.json" <"${aar_metainfdir_path}/LICENSE.zlib.txt" - -create_shared_module external_libpng libpng16 ":external_zlib" -cp "${sdlimage_root}/external/libpng/LICENSE" "${aar_metainfdir_path}/LICENSE.libpng.txt" - -create_shared_module external_libjpeg libjpeg "" -cp "${sdlimage_root}/external/jpeg/README" "${aar_metainfdir_path}/LICENSE.libjpeg.txt" - -create_shared_module external_libtiff libtiff "" -cp "${sdlimage_root}/external/libtiff/COPYRIGHT" "${aar_metainfdir_path}/LICENSE.libtiff.txt" - -create_shared_module external_libwebp libwebp "" -cp "${sdlimage_root}/external/libwebp/COPYING" "${aar_metainfdir_path}/LICENSE.libwebp.txt" - -#create_shared_module libbrotlicommon libbrotlicommon "" -#create_shared_module libbrotlidec libbrotlidec ":libbrotlicommon" -#create_shared_module libbrotlienc libbrotlienc ":libbrotlicommon" -#cp "${sdlimage_root}/external/libjxl/third_party/brotli/LICENSE" "${aar_metainfdir_path}/LICENSE.brotli.txt" - -#create_shared_module external_libjxl libjxl ":brotlienc :brotlidec" -#cp "${sdlimage_root}/external/libjxl/LICENSE" "${aar_metainfdir_path}/LICENSE.libjxl.txt" - -pushd "${aar_root}" - aar_filename="SDL${sdlimage_major}_image-${sdlimage_version}.aar" - zip -r "${aar_filename}" AndroidManifest.xml prefab META-INF - zip -Tv "${aar_filename}" 2>/dev/null ; - mv "${aar_filename}" "${prefabhome}" -popd - -maven_filename="SDL${sdlimage_major}_image-${sdlimage_version}.zip" - -pushd "${prefabhome}" - zip_filename="SDL${sdlimage_major}_image-${sdlimage_version}.zip" - zip "${maven_filename}" "${aar_filename}" "${pom_filename}" 2>/dev/null; - zip -Tv "${zip_filename}" 2>/dev/null; -popd - -echo "Prefab zip is ready at ${prefabhome}/${aar_filename}" -echo "Maven archive is ready at ${prefabhome}/${zip_filename}" diff --git a/build-scripts/build-release.py b/build-scripts/build-release.py new file mode 100755 index 00000000..5ef2a348 --- /dev/null +++ b/build-scripts/build-release.py @@ -0,0 +1,1429 @@ +#!/usr/bin/env python + +""" +This script is shared between SDL2, SDL3, and all satellite libraries. +Don't specialize this script for doing project-specific modifications. +Rather, modify release-info.json. +""" + +import argparse +import collections +import dataclasses +from collections.abc import Callable +import contextlib +import datetime +import fnmatch +import glob +import io +import json +import logging +import multiprocessing +import os +from pathlib import Path +import platform +import re +import shlex +import shutil +import subprocess +import sys +import tarfile +import tempfile +import textwrap +import typing +import zipfile + + +logger = logging.getLogger(__name__) +GIT_HASH_FILENAME = ".git-hash" +REVISION_TXT = "REVISION.txt" + + +def safe_isotime_to_datetime(str_isotime: str) -> datetime.datetime: + try: + return datetime.datetime.fromisoformat(str_isotime) + except ValueError: + pass + logger.warning("Invalid iso time: %s", str_isotime) + if str_isotime[-6:-5] in ("+", "-"): + # Commits can have isotime with invalid timezone offset (e.g. "2021-07-04T20:01:40+32:00") + modified_str_isotime = str_isotime[:-6] + "+00:00" + try: + return datetime.datetime.fromisoformat(modified_str_isotime) + except ValueError: + pass + raise ValueError(f"Invalid isotime: {str_isotime}") + + +def arc_join(*parts: list[str]) -> str: + assert all(p[:1] != "/" and p[-1:] != "/" for p in parts), f"None of {parts} may start or end with '/'" + return "/".join(p for p in parts if p) + + +@dataclasses.dataclass(frozen=True) +class VsArchPlatformConfig: + arch: str + configuration: str + platform: str + + def extra_context(self): + return { + "ARCH": self.arch, + "CONFIGURATION": self.configuration, + "PLATFORM": self.platform, + } + + +@contextlib.contextmanager +def chdir(path): + original_cwd = os.getcwd() + try: + os.chdir(path) + yield + finally: + os.chdir(original_cwd) + + +class Executer: + def __init__(self, root: Path, dry: bool=False): + self.root = root + self.dry = dry + + def run(self, cmd, cwd=None, env=None): + logger.info("Executing args=%r", cmd) + sys.stdout.flush() + if not self.dry: + subprocess.check_call(cmd, cwd=cwd or self.root, env=env, text=True) + + def check_output(self, cmd, cwd=None, dry_out=None, env=None, text=True): + logger.info("Executing args=%r", cmd) + sys.stdout.flush() + if self.dry: + return dry_out + return subprocess.check_output(cmd, cwd=cwd or self.root, env=env, text=text) + + +class SectionPrinter: + @contextlib.contextmanager + def group(self, title: str): + print(f"{title}:") + yield + + +class GitHubSectionPrinter(SectionPrinter): + def __init__(self): + super().__init__() + self.in_group = False + + @contextlib.contextmanager + def group(self, title: str): + print(f"::group::{title}") + assert not self.in_group, "Can enter a group only once" + self.in_group = True + yield + self.in_group = False + print("::endgroup::") + + +class VisualStudio: + def __init__(self, executer: Executer, year: typing.Optional[str]=None): + self.executer = executer + self.vsdevcmd = self.find_vsdevcmd(year) + self.msbuild = self.find_msbuild() + + @property + def dry(self) -> bool: + return self.executer.dry + + VS_YEAR_TO_VERSION = { + "2022": 17, + "2019": 16, + "2017": 15, + "2015": 14, + "2013": 12, + } + + def find_vsdevcmd(self, year: typing.Optional[str]=None) -> typing.Optional[Path]: + vswhere_spec = ["-latest"] + if year is not None: + try: + version = self.VS_YEAR_TO_VERSION[year] + except KeyError: + logger.error("Invalid Visual Studio year") + return None + vswhere_spec.extend(["-version", f"[{version},{version+1})"]) + vswhere_cmd = ["vswhere"] + vswhere_spec + ["-property", "installationPath"] + vs_install_path = Path(self.executer.check_output(vswhere_cmd, dry_out="/tmp").strip()) + logger.info("VS install_path = %s", vs_install_path) + assert vs_install_path.is_dir(), "VS installation path does not exist" + vsdevcmd_path = vs_install_path / "Common7/Tools/vsdevcmd.bat" + logger.info("vsdevcmd path = %s", vsdevcmd_path) + if self.dry: + vsdevcmd_path.parent.mkdir(parents=True, exist_ok=True) + vsdevcmd_path.touch(exist_ok=True) + assert vsdevcmd_path.is_file(), "vsdevcmd.bat batch file does not exist" + return vsdevcmd_path + + def find_msbuild(self) -> typing.Optional[Path]: + vswhere_cmd = ["vswhere", "-latest", "-requires", "Microsoft.Component.MSBuild", "-find", r"MSBuild\**\Bin\MSBuild.exe"] + msbuild_path = Path(self.executer.check_output(vswhere_cmd, dry_out="/tmp/MSBuild.exe").strip()) + logger.info("MSBuild path = %s", msbuild_path) + if self.dry: + msbuild_path.parent.mkdir(parents=True, exist_ok=True) + msbuild_path.touch(exist_ok=True) + assert msbuild_path.is_file(), "MSBuild.exe does not exist" + return msbuild_path + + def build(self, arch_platform: VsArchPlatformConfig, projects: list[Path]): + assert projects, "Need at least one project to build" + + vsdev_cmd_str = f"\"{self.vsdevcmd}\" -arch={arch_platform.arch}" + msbuild_cmd_str = " && ".join([f"\"{self.msbuild}\" \"{project}\" /m /p:BuildInParallel=true /p:Platform={arch_platform.platform} /p:Configuration={arch_platform.configuration}" for project in projects]) + bat_contents = f"{vsdev_cmd_str} && {msbuild_cmd_str}\n" + bat_path = Path(tempfile.gettempdir()) / "cmd.bat" + with bat_path.open("w") as f: + f.write(bat_contents) + + logger.info("Running cmd.exe script (%s): %s", bat_path, bat_contents) + cmd = ["cmd.exe", "/D", "/E:ON", "/V:OFF", "/S", "/C", f"CALL {str(bat_path)}"] + self.executer.run(cmd) + + +class Archiver: + def __init__(self, zip_path: typing.Optional[Path]=None, tgz_path: typing.Optional[Path]=None, txz_path: typing.Optional[Path]=None): + self._zip_files = [] + self._tar_files = [] + self._added_files = set() + if zip_path: + self._zip_files.append(zipfile.ZipFile(zip_path, "w", compression=zipfile.ZIP_DEFLATED)) + if tgz_path: + self._tar_files.append(tarfile.open(tgz_path, "w:gz")) + if txz_path: + self._tar_files.append(tarfile.open(txz_path, "w:xz")) + + @property + def added_files(self) -> set[str]: + return self._added_files + + def add_file_data(self, arcpath: str, data: bytes, mode: int, time: datetime.datetime): + for zf in self._zip_files: + file_data_time = (time.year, time.month, time.day, time.hour, time.minute, time.second) + zip_info = zipfile.ZipInfo(filename=arcpath, date_time=file_data_time) + zip_info.external_attr = mode << 16 + zip_info.compress_type = zipfile.ZIP_DEFLATED + zf.writestr(zip_info, data=data) + for tf in self._tar_files: + tar_info = tarfile.TarInfo(arcpath) + tar_info.type = tarfile.REGTYPE + tar_info.mode = mode + tar_info.size = len(data) + tar_info.mtime = int(time.timestamp()) + tf.addfile(tar_info, fileobj=io.BytesIO(data)) + + self._added_files.add(arcpath) + + def add_symlink(self, arcpath: str, target: str, time: datetime.datetime, files_for_zip): + logger.debug("Adding symlink (target=%r) -> %s", target, arcpath) + for zf in self._zip_files: + file_data_time = (time.year, time.month, time.day, time.hour, time.minute, time.second) + for f in files_for_zip: + zip_info = zipfile.ZipInfo(filename=f["arcpath"], date_time=file_data_time) + zip_info.external_attr = f["mode"] << 16 + zip_info.compress_type = zipfile.ZIP_DEFLATED + zf.writestr(zip_info, data=f["data"]) + for tf in self._tar_files: + tar_info = tarfile.TarInfo(arcpath) + tar_info.type = tarfile.SYMTYPE + tar_info.mode = 0o777 + tar_info.mtime = int(time.timestamp()) + tar_info.linkname = target + tf.addfile(tar_info) + + self._added_files.update(f["arcpath"] for f in files_for_zip) + + def add_git_hash(self, arcdir: str, commit: str, time: datetime.datetime): + arcpath = arc_join(arcdir, GIT_HASH_FILENAME) + data = f"{commit}\n".encode() + self.add_file_data(arcpath=arcpath, data=data, mode=0o100644, time=time) + + def add_file_path(self, arcpath: str, path: Path): + assert path.is_file(), f"{path} should be a file" + logger.debug("Adding %s -> %s", path, arcpath) + for zf in self._zip_files: + zf.write(path, arcname=arcpath) + for tf in self._tar_files: + tf.add(path, arcname=arcpath) + + def add_file_directory(self, arcdirpath: str, dirpath: Path): + assert dirpath.is_dir() + if arcdirpath and arcdirpath[-1:] != "/": + arcdirpath += "/" + for f in dirpath.iterdir(): + if f.is_file(): + arcpath = f"{arcdirpath}{f.name}" + logger.debug("Adding %s to %s", f, arcpath) + self.add_file_path(arcpath=arcpath, path=f) + + def close(self): + # Archiver is intentionally made invalid after this function + del self._zip_files + self._zip_files = None + del self._tar_files + self._tar_files = None + + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + self.close() + + +class NodeInArchive: + def __init__(self, arcpath: str, path: typing.Optional[Path]=None, data: typing.Optional[bytes]=None, mode: typing.Optional[int]=None, symtarget: typing.Optional[str]=None, time: typing.Optional[datetime.datetime]=None, directory: bool=False): + self.arcpath = arcpath + self.path = path + self.data = data + self.mode = mode + self.symtarget = symtarget + self.time = time + self.directory = directory + + @classmethod + def from_fs(cls, arcpath: str, path: Path, mode: int=0o100644, time: typing.Optional[datetime.datetime]=None) -> "NodeInArchive": + if time is None: + time = datetime.datetime.fromtimestamp(os.stat(path).st_mtime) + return cls(arcpath=arcpath, path=path, mode=mode) + + @classmethod + def from_data(cls, arcpath: str, data: bytes, time: datetime.datetime) -> "NodeInArchive": + return cls(arcpath=arcpath, data=data, time=time, mode=0o100644) + + @classmethod + def from_text(cls, arcpath: str, text: str, time: datetime.datetime) -> "NodeInArchive": + return cls.from_data(arcpath=arcpath, data=text.encode(), time=time) + + @classmethod + def from_symlink(cls, arcpath: str, symtarget: str) -> "NodeInArchive": + return cls(arcpath=arcpath, symtarget=symtarget) + + @classmethod + def from_directory(cls, arcpath: str) -> "NodeInArchive": + return cls(arcpath=arcpath, directory=True) + + def __repr__(self) -> str: + return f"<{type(self).__name__}:arcpath={self.arcpath},path='{str(self.path)}',len(data)={len(self.data) if self.data else 'n/a'},directory={self.directory},symtarget={self.symtarget}>" + + +def configure_file(path: Path, context: dict[str, str]) -> bytes: + text = path.read_text() + return configure_text(text, context=context).encode() + + +def configure_text(text: str, context: dict[str, str]) -> str: + original_text = text + for txt, repl in context.items(): + text = text.replace(f"@<@{txt}@>@", repl) + success = all(thing not in text for thing in ("@<@", "@>@")) + if not success: + raise ValueError(f"Failed to configure {repr(original_text)}") + return text + + +class ArchiveFileTree: + def __init__(self): + self._tree: dict[str, NodeInArchive] = {} + + def add_file(self, file: NodeInArchive): + self._tree[file.arcpath] = file + + def get_latest_mod_time(self) -> datetime.datetime: + return max(item.time for item in self._tree.values() if item.time) + + def add_to_archiver(self, archive_base: str, archiver: Archiver): + remaining_symlinks = set() + added_files = dict() + + def calculate_symlink_target(s: NodeInArchive) -> str: + dest_dir = os.path.dirname(s.path) + if dest_dir: + dest_dir += "/" + target = dest_dir + s.symtarget + while True: + new_target, n = re.subn(r"([^/]+/+[.]{2}/)", "", target) + print(f"{target=} {new_target=}") + target = new_target + if not n: + break + return target + + # Add files in first pass + for arcpath, node in self._tree.items(): + if node.data is not None: + archiver.add_file_data(arcpath=arc_join(archive_base, arcpath), data=node.data, time=node.time, mode=node.mode) + added_files[node.path] = node + elif node.path is not None: + archiver.add_file_path(arcpath=arc_join(archive_base, arcpath), path=node.path) + added_files[node.path] = node + elif node.symtarget is not None: + remaining_symlinks.add(node) + elif node.directory: + pass + else: + raise ValueError(f"Invalid Archive Node: {repr(node)}") + + # Resolve symlinks in second pass: zipfile does not support symlinks, so add files to zip archive + while True: + if not remaining_symlinks: + break + symlinks_this_time = set() + extra_added_files = {} + for symlink in remaining_symlinks: + symlink_files_for_zip = {} + symlink_target_path = calculate_symlink_target(symlink) + if symlink_target_path in added_files: + symlink_files_for_zip[symlink.path] = added_files[symlink_target_path] + else: + symlink_target_path_slash = symlink_target_path + "/" + for added_file in added_files: + if added_file.startswith(symlink_target_path_slash): + path_in_symlink = symlink.path + "/" + added_file.removeprefix(symlink_target_path_slash) + symlink_files_for_zip[path_in_symlink] = added_files[added_file] + if symlink_files_for_zip: + symlinks_this_time.add(symlink) + extra_added_files.update(symlink_files_for_zip) + files_for_zip = [{"arcpath": f"{archive_base}/{sym_path}", "data": sym_info.data, "mode": sym_info.mode} for sym_path, sym_info in symlink_files_for_zip.items()] + archiver.add_symlink(arcpath=f"{archive_base}/{symlink.path}", target=symlink.symtarget, time=symlink.time, files_for_zip=files_for_zip) + # if not symlinks_this_time: + # logger.info("files added: %r", set(path for path in added_files.keys())) + assert symlinks_this_time, f"No targets found for symlinks: {remaining_symlinks}" + remaining_symlinks.difference_update(symlinks_this_time) + added_files.update(extra_added_files) + + def add_directory_tree(self, arc_dir: str, path: Path, time: datetime.datetime): + assert path.is_dir() + for files_dir, _, filenames in os.walk(path): + files_dir_path = Path(files_dir) + rel_files_path = files_dir_path.relative_to(path) + for filename in filenames: + self.add_file(NodeInArchive.from_fs(arcpath=arc_join(arc_dir, str(rel_files_path), filename), path=files_dir_path / filename, time=time)) + + def _add_files_recursively(self, arc_dir: str, paths: list[Path], time: datetime.datetime): + logger.debug(f"_add_files_recursively({arc_dir=} {paths=})") + for path in paths: + arcpath = arc_join(arc_dir, path.name) + if path.is_file(): + logger.debug("Adding %s as %s", path, arcpath) + self.add_file(NodeInArchive.from_fs(arcpath=arcpath, path=path, time=time)) + elif path.is_dir(): + self._add_files_recursively(arc_dir=arc_join(arc_dir, path.name), paths=list(path.iterdir()), time=time) + else: + raise ValueError(f"Unsupported file type to add recursively: {path}") + + def add_file_mapping(self, arc_dir: str, file_mapping: dict[str, list[str]], file_mapping_root: Path, context: dict[str, str], time: datetime.datetime): + for meta_rel_destdir, meta_file_globs in file_mapping.items(): + rel_destdir = configure_text(meta_rel_destdir, context=context) + assert "@" not in rel_destdir, f"archive destination should not contain an @ after configuration ({repr(meta_rel_destdir)}->{repr(rel_destdir)})" + for meta_file_glob in meta_file_globs: + file_glob = configure_text(meta_file_glob, context=context) + assert "@" not in rel_destdir, f"archive glob should not contain an @ after configuration ({repr(meta_file_glob)}->{repr(file_glob)})" + if ":" in file_glob: + original_path, new_filename = file_glob.rsplit(":", 1) + assert ":" not in original_path, f"Too many ':' in {repr(file_glob)}" + assert "/" not in new_filename, f"New filename cannot contain a '/' in {repr(file_glob)}" + path = file_mapping_root / original_path + arcpath = arc_join(arc_dir, rel_destdir, new_filename) + if path.suffix == ".in": + data = configure_file(path, context=context) + logger.debug("Adding processed %s -> %s", path, arcpath) + self.add_file(NodeInArchive.from_data(arcpath=arcpath, data=data, time=time)) + else: + logger.debug("Adding %s -> %s", path, arcpath) + self.add_file(NodeInArchive.from_fs(arcpath=arcpath, path=path, time=time)) + else: + relative_file_paths = glob.glob(file_glob, root_dir=file_mapping_root) + assert relative_file_paths, f"Glob '{file_glob}' does not match any file" + self._add_files_recursively(arc_dir=arc_join(arc_dir, rel_destdir), paths=[file_mapping_root / p for p in relative_file_paths], time=time) + + +class SourceCollector: + # TreeItem = collections.namedtuple("TreeItem", ("path", "mode", "data", "symtarget", "directory", "time")) + def __init__(self, root: Path, commit: str, filter: typing.Optional[Callable[[str], bool]], executer: Executer): + self.root = root + self.commit = commit + self.filter = filter + self.executer = executer + + def get_archive_file_tree(self) -> ArchiveFileTree: + git_archive_args = ["git", "archive", "--format=tar.gz", self.commit, "-o", "/dev/stdout"] + logger.info("Executing args=%r", git_archive_args) + contents_tgz = subprocess.check_output(git_archive_args, cwd=self.root, text=False) + tar_archive = tarfile.open(fileobj=io.BytesIO(contents_tgz), mode="r:gz") + filenames = tuple(m.name for m in tar_archive if (m.isfile() or m.issym())) + + file_times = self._get_file_times(paths=filenames) + git_contents = ArchiveFileTree() + for ti in tar_archive: + if self.filter and not self.filter(ti.name): + continue + data = None + symtarget = None + directory = False + file_time = None + if ti.isfile(): + contents_file = tar_archive.extractfile(ti.name) + data = contents_file.read() + file_time = file_times[ti.name] + elif ti.issym(): + symtarget = ti.linkname + file_time = file_times[ti.name] + elif ti.isdir(): + directory = True + else: + raise ValueError(f"{ti.name}: unknown type") + node = NodeInArchive(arcpath=ti.name, data=data, mode=ti.mode, symtarget=symtarget, time=file_time, directory=directory) + git_contents.add_file(node) + return git_contents + + def _get_file_times(self, paths: tuple[str, ...]) -> dict[str, datetime.datetime]: + dry_out = textwrap.dedent("""\ + time=2024-03-14T15:40:25-07:00 + + M\tCMakeLists.txt + """) + git_log_out = self.executer.check_output(["git", "log", "--name-status", '--pretty=time=%cI', self.commit], dry_out=dry_out, cwd=self.root).splitlines(keepends=False) + current_time = None + set_paths = set(paths) + path_times: dict[str, datetime.datetime] = {} + for line in git_log_out: + if not line: + continue + if line.startswith("time="): + current_time = safe_isotime_to_datetime(line.removeprefix("time=")) + continue + mod_type, file_paths = line.split(maxsplit=1) + assert current_time is not None + for file_path in file_paths.split("\t"): + if file_path in set_paths and file_path not in path_times: + path_times[file_path] = current_time + + # FIXME: find out why some files are not shown in "git log" + # assert set(path_times.keys()) == set_paths + if set(path_times.keys()) != set_paths: + found_times = set(path_times.keys()) + paths_without_times = set_paths.difference(found_times) + logger.warning("No times found for these paths: %s", paths_without_times) + max_time = max(time for time in path_times.values()) + for path in paths_without_times: + path_times[path] = max_time + + return path_times + + +class Releaser: + def __init__(self, release_info: dict, commit: str, revision: str, root: Path, dist_path: Path, section_printer: SectionPrinter, executer: Executer, cmake_generator: str, deps_path: Path, overwrite: bool, github: bool, fast: bool): + self.release_info = release_info + self.project = release_info["name"] + self.version = self.extract_sdl_version(root=root, release_info=release_info) + self.root = root + self.commit = commit + self.revision = revision + self.dist_path = dist_path + self.section_printer = section_printer + self.executer = executer + self.cmake_generator = cmake_generator + self.cpu_count = multiprocessing.cpu_count() + self.deps_path = deps_path + self.overwrite = overwrite + self.github = github + self.fast = fast + self.arc_time = datetime.datetime.now() + + self.artifacts: dict[str, Path] = {} + + def get_context(self, extra_context: typing.Optional[dict[str, str]]=None) -> dict[str, str]: + ctx = { + "PROJECT_NAME": self.project, + "PROJECT_VERSION": self.version, + "PROJECT_COMMIT": self.commit, + "PROJECT_REVISION": self.revision, + } + if extra_context: + ctx.update(extra_context) + return ctx + + @property + def dry(self) -> bool: + return self.executer.dry + + def prepare(self): + logger.debug("Creating dist folder") + self.dist_path.mkdir(parents=True, exist_ok=True) + + @classmethod + def _path_filter(cls, path: str) -> bool: + if ".gitmodules" in path: + return True + if path.startswith(".git"): + return False + return True + + @classmethod + def _external_repo_path_filter(cls, path: str) -> bool: + if not cls._path_filter(path): + return False + if path.startswith("test/") or path.startswith("tests/"): + return False + return True + + def create_source_archives(self) -> None: + source_collector = SourceCollector(root=self.root, commit=self.commit, executer=self.executer, filter=self._path_filter) + print(f"Collecting sources of {self.project}...") + archive_tree = source_collector.get_archive_file_tree() + latest_mod_time = archive_tree.get_latest_mod_time() + archive_tree.add_file(NodeInArchive.from_text(arcpath=REVISION_TXT, text=f"{self.revision}\n", time=latest_mod_time)) + archive_tree.add_file(NodeInArchive.from_text(arcpath=f"{GIT_HASH_FILENAME}", text=f"{self.commit}\n", time=latest_mod_time)) + archive_tree.add_file_mapping(arc_dir="", file_mapping=self.release_info["source"].get("files", {}), file_mapping_root=self.root, context=self.get_context(), time=latest_mod_time) + + archive_base = f"{self.project}-{self.version}" + zip_path = self.dist_path / f"{archive_base}.zip" + tgz_path = self.dist_path / f"{archive_base}.tar.gz" + txz_path = self.dist_path / f"{archive_base}.tar.xz" + + logger.info("Creating zip/tgz/txz source archives ...") + if self.dry: + zip_path.touch() + tgz_path.touch() + txz_path.touch() + else: + with Archiver(zip_path=zip_path, tgz_path=tgz_path, txz_path=txz_path) as archiver: + print(f"Adding source files of {self.project}...") + archive_tree.add_to_archiver(archive_base=archive_base, archiver=archiver) + + for extra_repo in self.release_info["source"].get("extra-repos", []): + extra_repo_root = self.root / extra_repo + assert (extra_repo_root / ".git").exists(), f"{extra_repo_root} must be a git repo" + extra_repo_commit = self.executer.check_output(["git", "rev-parse", "HEAD"], dry_out=f"gitsha-extra-repo-{extra_repo}", cwd=extra_repo_root).strip() + extra_repo_source_collector = SourceCollector(root=extra_repo_root, commit=extra_repo_commit, executer=self.executer, filter=self._external_repo_path_filter) + print(f"Collecting sources of {extra_repo} ...") + extra_repo_archive_tree = extra_repo_source_collector.get_archive_file_tree() + print(f"Adding source files of {extra_repo} ...") + extra_repo_archive_tree.add_to_archiver(archive_base=f"{archive_base}/{extra_repo}", archiver=archiver) + + for file in self.release_info["source"]["checks"]: + assert f"{archive_base}/{file}" in archiver.added_files, f"'{archive_base}/{file}' must exist" + + logger.info("... done") + + self.artifacts["src-zip"] = zip_path + self.artifacts["src-tar-gz"] = tgz_path + self.artifacts["src-tar-xz"] = txz_path + + if not self.dry: + with tgz_path.open("r+b") as f: + # Zero the embedded timestamp in the gzip'ed tarball + f.seek(4, 0) + f.write(b"\x00\x00\x00\x00") + + def create_dmg(self, configuration: str="Release") -> None: + dmg_in = self.root / self.release_info["dmg"]["path"] + xcode_project = self.root / self.release_info["dmg"]["project"] + assert xcode_project.is_dir(), f"{xcode_project} must be a directory" + assert (xcode_project / "project.pbxproj").is_file, f"{xcode_project} must contain project.pbxproj" + if not self.fast: + dmg_in.unlink(missing_ok=True) + build_xcconfig = self.release_info["dmg"].get("build-xcconfig") + if build_xcconfig: + shutil.copy(self.root / build_xcconfig, xcode_project.parent / "build.xcconfig") + + xcode_scheme = self.release_info["dmg"].get("scheme") + xcode_target = self.release_info["dmg"].get("target") + assert xcode_scheme or xcode_target, "dmg needs scheme or target" + assert not (xcode_scheme and xcode_target), "dmg cannot have both scheme and target set" + if xcode_scheme: + scheme_or_target = "-scheme" + target_like = xcode_scheme + else: + scheme_or_target = "-target" + target_like = xcode_target + self.executer.run(["xcodebuild", "ONLY_ACTIVE_ARCH=NO", "-project", xcode_project, scheme_or_target, target_like, "-configuration", configuration]) + if self.dry: + dmg_in.parent.mkdir(parents=True, exist_ok=True) + dmg_in.touch() + + assert dmg_in.is_file(), f"{self.project}.dmg was not created by xcodebuild" + + dmg_out = self.dist_path / f"{self.project}-{self.version}.dmg" + shutil.copy(dmg_in, dmg_out) + self.artifacts["dmg"] = dmg_out + + @property + def git_hash_data(self) -> bytes: + return f"{self.commit}\n".encode() + + def create_mingw_archives(self) -> None: + build_type = "Release" + build_parent_dir = self.root / "build-mingw" + ARCH_TO_GNU_ARCH = { + # "arm64": "aarch64", + "x86": "i686", + "x64": "x86_64", + } + ARCH_TO_TRIPLET = { + # "arm64": "aarch64-w64-mingw32", + "x86": "i686-w64-mingw32", + "x64": "x86_64-w64-mingw32", + } + + new_env = dict(os.environ) + + cmake_prefix_paths = [] + mingw_deps_path = self.deps_path / "mingw-deps" + + if "dependencies" in self.release_info["mingw"]: + shutil.rmtree(mingw_deps_path, ignore_errors=True) + mingw_deps_path.mkdir() + + for triplet in ARCH_TO_TRIPLET.values(): + (mingw_deps_path / triplet).mkdir() + + def extract_filter(member: tarfile.TarInfo, path: str, /): + if member.name.startswith("SDL"): + member.name = "/".join(Path(member.name).parts[1:]) + return member + for dep in self.release_info.get("dependencies", {}): + extract_path = mingw_deps_path / f"extract-{dep}" + extract_path.mkdir() + with chdir(extract_path): + tar_path = self.deps_path / glob.glob(self.release_info["mingw"]["dependencies"][dep]["artifact"], root_dir=self.deps_path)[0] + logger.info("Extracting %s to %s", tar_path, mingw_deps_path) + assert tar_path.suffix in (".gz", ".xz") + with tarfile.open(tar_path, mode=f"r:{tar_path.suffix.strip('.')}") as tarf: + tarf.extractall(filter=extract_filter) + for arch, triplet in ARCH_TO_TRIPLET.items(): + install_cmd = self.release_info["mingw"]["dependencies"][dep]["install-command"] + extra_configure_data = { + "ARCH": ARCH_TO_GNU_ARCH[arch], + "TRIPLET": triplet, + "PREFIX": str(mingw_deps_path / triplet), + } + install_cmd = configure_text(install_cmd, context=self.get_context(extra_configure_data)) + self.executer.run(shlex.split(install_cmd), cwd=str(extract_path)) + + dep_binpath = mingw_deps_path / triplet / "bin" + assert dep_binpath.is_dir(), f"{dep_binpath} for PATH should exist" + dep_pkgconfig = mingw_deps_path / triplet / "lib/pkgconfig" + assert dep_pkgconfig.is_dir(), f"{dep_pkgconfig} for PKG_CONFIG_PATH should exist" + + new_env["PATH"] = os.pathsep.join([str(dep_binpath), new_env["PATH"]]) + new_env["PKG_CONFIG_PATH"] = str(dep_pkgconfig) + cmake_prefix_paths.append(mingw_deps_path) + + new_env["CFLAGS"] = f"-O2 -ffile-prefix-map={self.root}=/src/{self.project}" + new_env["CXXFLAGS"] = f"-O2 -ffile-prefix-map={self.root}=/src/{self.project}" + + assert any(system in self.release_info["mingw"] for system in ("autotools", "cmake")) + assert not all(system in self.release_info["mingw"] for system in ("autotools", "cmake")) + + mingw_archs = set() + arc_root = f"{self.project}-{self.version}" + archive_file_tree = ArchiveFileTree() + + if "autotools" in self.release_info["mingw"]: + for arch in self.release_info["mingw"]["autotools"]["archs"]: + triplet = ARCH_TO_TRIPLET[arch] + new_env["CC"] = f"{triplet}-gcc" + new_env["CXX"] = f"{triplet}-g++" + new_env["RC"] = f"{triplet}-windres" + + assert arch not in mingw_archs + mingw_archs.add(arch) + + build_path = build_parent_dir / f"build-{triplet}" + install_path = build_parent_dir / f"install-{triplet}" + shutil.rmtree(install_path, ignore_errors=True) + build_path.mkdir(parents=True, exist_ok=True) + with self.section_printer.group(f"Configuring MinGW {triplet} (autotools)"): + extra_args = [arg.replace("@DEP_PREFIX@", str(mingw_deps_path / triplet)) for arg in self.release_info["mingw"]["autotools"]["args"]] + assert "@" not in " ".join(extra_args), f"@ should not be present in extra arguments ({extra_args})" + self.executer.run([ + self.root / "configure", + f"--prefix={install_path}", + f"--includedir={install_path}/include", + f"--libdir={install_path}/lib", + f"--bindir={install_path}/bin", + f"--host={triplet}", + f"--build=x86_64-none-linux-gnu", + ] + extra_args, cwd=build_path, env=new_env) + with self.section_printer.group(f"Build MinGW {triplet} (autotools)"): + self.executer.run(["make", f"-j{self.cpu_count}"], cwd=build_path, env=new_env) + with self.section_printer.group(f"Install MinGW {triplet} (autotools)"): + self.executer.run(["make", "install"], cwd=build_path, env=new_env) + archive_file_tree.add_directory_tree(arc_dir=arc_join(arc_root, triplet), path=install_path) + + if "cmake" in self.release_info["mingw"]: + assert self.release_info["mingw"]["cmake"]["shared-static"] in ("args", "both") + for arch in self.release_info["mingw"]["cmake"]["archs"]: + triplet = ARCH_TO_TRIPLET[arch] + new_env["CC"] = f"{triplet}-gcc" + new_env["CXX"] = f"{triplet}-g++" + new_env["RC"] = f"{triplet}-windres" + + assert arch not in mingw_archs + mingw_archs.add(arch) + + build_path = build_parent_dir / f"build-{triplet}" + install_path = build_parent_dir / f"install-{triplet}" + shutil.rmtree(install_path, ignore_errors=True) + build_path.mkdir(parents=True, exist_ok=True) + if self.release_info["mingw"]["cmake"]["shared-static"] == "args": + args_for_shared_static = ([], ) + elif self.release_info["mingw"]["cmake"]["shared-static"] == "both": + args_for_shared_static = (["-DBUILD_SHARED_LIBS=ON"], ["-DBUILD_SHARED_LIBS=OFF"]) + for arg_for_shared_static in args_for_shared_static: + with self.section_printer.group(f"Configuring MinGW {triplet} (CMake)"): + extra_args = [arg.replace("@DEP_PREFIX@", str(mingw_deps_path / triplet)) for arg in self.release_info["mingw"]["cmake"]["args"]] + assert "@" not in " ".join(extra_args), f"@ should not be present in extra arguments ({extra_args})" + self.executer.run([ + f"cmake", + f"-S", str(self.root), "-B", str(build_path), + f"-DCMAKE_BUILD_TYPE={build_type}", + f'''-DCMAKE_C_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''', + f'''-DCMAKE_CXX_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''', + f"-DCMAKE_PREFIX_PATH={mingw_deps_path / triplet}", + f"-DCMAKE_INSTALL_PREFIX={install_path}", + f"-DCMAKE_INSTALL_INCLUDEDIR=include", + f"-DCMAKE_INSTALL_LIBDIR=lib", + f"-DCMAKE_INSTALL_BINDIR=bin", + f"-DCMAKE_INSTALL_DATAROOTDIR=share", + f"-DCMAKE_TOOLCHAIN_FILE={self.root}/build-scripts/cmake-toolchain-mingw64-{ARCH_TO_GNU_ARCH[arch]}.cmake", + f"-G{self.cmake_generator}", + ] + extra_args + ([] if self.fast else ["--fresh"]) + arg_for_shared_static, cwd=build_path, env=new_env) + with self.section_printer.group(f"Build MinGW {triplet} (CMake)"): + self.executer.run(["cmake", "--build", str(build_path), "--verbose", "--config", build_type], cwd=build_path, env=new_env) + with self.section_printer.group(f"Install MinGW {triplet} (CMake)"): + self.executer.run(["cmake", "--install", str(build_path)], cwd=build_path, env=new_env) + archive_file_tree.add_directory_tree(arc_dir=arc_join(arc_root, triplet), path=install_path, time=self.arc_time) + + print("Recording extra files for MinGW development archive ...") + archive_file_tree.add_file_mapping(arc_dir=arc_root, file_mapping=self.release_info["mingw"].get("files", {}), file_mapping_root=self.root, context=self.get_context(), time=self.arc_time) + print("... done") + + print("Creating zip/tgz/txz development archives ...") + zip_path = self.dist_path / f"{self.project}-devel-{self.version}-mingw.zip" + tgz_path = self.dist_path / f"{self.project}-devel-{self.version}-mingw.tar.gz" + txz_path = self.dist_path / f"{self.project}-devel-{self.version}-mingw.tar.xz" + + with Archiver(zip_path=zip_path, tgz_path=tgz_path, txz_path=txz_path) as archiver: + archive_file_tree.add_to_archiver(archive_base="", archiver=archiver) + archiver.add_git_hash(arcdir=arc_root, commit=self.commit, time=self.arc_time) + print("... done") + + self.artifacts["mingw-devel-zip"] = zip_path + self.artifacts["mingw-devel-tar-gz"] = tgz_path + self.artifacts["mingw-devel-tar-xz"] = txz_path + + def _detect_android_api(self, android_home: str) -> typing.Optional[int]: + platform_dirs = list(Path(p) for p in glob.glob(f"{android_home}/platforms/android-*")) + re_platform = re.compile("android-([0-9]+)") + platform_versions = [] + for platform_dir in platform_dirs: + logger.debug("Found Android Platform SDK: %s", platform_dir) + if m:= re_platform.match(platform_dir.name): + platform_versions.append(int(m.group(1))) + platform_versions.sort() + logger.info("Available platform versions: %s", platform_versions) + platform_versions = list(filter(lambda v: v >= self._android_api_minimum, platform_versions)) + logger.info("Valid platform versions (>=%d): %s", self._android_api_minimum, platform_versions) + if not platform_versions: + return None + android_api = platform_versions[0] + logger.info("Selected API version %d", android_api) + return android_api + + def _get_prefab_json_text(self) -> str: + return textwrap.dedent(f"""\ + {{ + "schema_version": 2, + "name": "{self.project}", + "version": "{self.version}", + "dependencies": [] + }} + """) + + def _get_prefab_module_json_text(self, library_name: typing.Optional[str], export_libraries: list[str]) -> str: + for lib in export_libraries: + assert isinstance(lib, str), f"{lib} must be a string" + module_json_dict = { + "export_libraries": export_libraries, + } + if library_name: + module_json_dict["library_name"] = f"lib{library_name}" + return json.dumps(module_json_dict, indent=4) + + @property + def _android_api_minimum(self): + return self.release_info["android"]["api-minimum"] + + @property + def _android_api_target(self): + return self.release_info["android"]["api-target"] + + @property + def _android_ndk_minimum(self): + return self.release_info["android"]["ndk-minimum"] + + def _get_prefab_abi_json_text(self, abi: str, cpp: bool, shared: bool) -> str: + abi_json_dict = { + "abi": abi, + "api": self._android_api_minimum, + "ndk": self._android_ndk_minimum, + "stl": "c++_shared" if cpp else "none", + "static": not shared, + } + return json.dumps(abi_json_dict, indent=4) + + def _get_android_manifest_text(self) -> str: + return textwrap.dedent(f"""\ + + + + """) + + def create_android_archives(self, android_api: int, android_home: Path, android_ndk_home: Path) -> None: + cmake_toolchain_file = Path(android_ndk_home) / "build/cmake/android.toolchain.cmake" + if not cmake_toolchain_file.exists(): + logger.error("CMake toolchain file does not exist (%s)", cmake_toolchain_file) + raise SystemExit(1) + aar_path = self.dist_path / f"{self.project}-{self.version}.aar" + android_abis = self.release_info["android"]["abis"] + java_jars_added = False + module_data_added = False + android_deps_path = self.deps_path / "android-deps" + shutil.rmtree(android_deps_path, ignore_errors=True) + + for dep, depinfo in self.release_info["android"].get("dependencies", {}).items(): + android_aar = self.deps_path / glob.glob(depinfo["artifact"], root_dir=self.deps_path)[0] + with self.section_printer.group(f"Extracting Android dependency {dep} ({android_aar.name})"): + self.executer.run([sys.executable, str(android_aar), "-o", str(android_deps_path)]) + + for module_name, module_info in self.release_info["android"]["modules"].items(): + assert "type" in module_info and module_info["type"] in ("interface", "library"), f"module {module_name} must have a valid type" + + archive_file_tree = ArchiveFileTree() + + for android_abi in android_abis: + with self.section_printer.group(f"Building for Android {android_api} {android_abi}"): + build_dir = self.root / "build-android" / f"{android_abi}-build" + install_dir = self.root / "install-android" / f"{android_abi}-install" + shutil.rmtree(install_dir, ignore_errors=True) + assert not install_dir.is_dir(), f"{install_dir} should not exist prior to build" + build_type = "Release" + cmake_args = [ + "cmake", + "-S", str(self.root), + "-B", str(build_dir), + f'''-DCMAKE_C_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''', + f'''-DCMAKE_CXX_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''', + f"-DCMAKE_TOOLCHAIN_FILE={cmake_toolchain_file}", + f"-DCMAKE_PREFIX_PATH={str(android_deps_path)}", + f"-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=BOTH", + f"-DANDROID_HOME={android_home}", + f"-DANDROID_PLATFORM={android_api}", + f"-DANDROID_ABI={android_abi}", + "-DCMAKE_POSITION_INDEPENDENT_CODE=ON", + f"-DCMAKE_INSTALL_PREFIX={install_dir}", + "-DCMAKE_INSTALL_INCLUDEDIR=include ", + "-DCMAKE_INSTALL_LIBDIR=lib", + "-DCMAKE_INSTALL_DATAROOTDIR=share", + f"-DCMAKE_BUILD_TYPE={build_type}", + f"-G{self.cmake_generator}", + ] + self.release_info["android"]["cmake"]["args"] + ([] if self.fast else ["--fresh"]) + build_args = [ + "cmake", + "--build", str(build_dir), + "--verbose", + "--config", build_type, + ] + install_args = [ + "cmake", + "--install", str(build_dir), + "--config", build_type, + ] + self.executer.run(cmake_args) + self.executer.run(build_args) + self.executer.run(install_args) + + for module_name, module_info in self.release_info["android"]["modules"].items(): + arcdir_prefab_module = f"prefab/modules/{module_name}" + if module_info["type"] == "library": + library = install_dir / module_info["library"] + assert library.suffix in (".so", ".a") + assert library.is_file(), f"CMake should have built library '{library}' for module {module_name}" + arcdir_prefab_libs = f"{arcdir_prefab_module}/libs/android.{android_abi}" + archive_file_tree.add_file(NodeInArchive.from_fs(arcpath=f"{arcdir_prefab_libs}/{library.name}", path=library, time=self.arc_time)) + archive_file_tree.add_file(NodeInArchive.from_text(arcpath=f"{arcdir_prefab_libs}/abi.json", text=self._get_prefab_abi_json_text(abi=android_abi, cpp=False, shared=library.suffix == ".so"), time=self.arc_time)) + + if not module_data_added: + library_name = None + if module_info["type"] == "library": + library_name = Path(module_info["library"]).stem.removeprefix("lib") + export_libraries = module_info.get("export-libraries", []) + archive_file_tree.add_file(NodeInArchive.from_text(arcpath=arc_join(arcdir_prefab_module, "module.json"), text=self._get_prefab_module_json_text(library_name=library_name, export_libraries=export_libraries), time=self.arc_time)) + arcdir_prefab_include = f"prefab/modules/{module_name}/include" + if "includes" in module_info: + archive_file_tree.add_file_mapping(arc_dir=arcdir_prefab_include, file_mapping=module_info["includes"], file_mapping_root=install_dir, context=self.get_context(), time=self.arc_time) + else: + archive_file_tree.add_file(NodeInArchive.from_text(arcpath=arc_join(arcdir_prefab_include, ".keep"), text="\n", time=self.arc_time)) + module_data_added = True + + if not java_jars_added: + java_jars_added = True + if "jars" in self.release_info["android"]: + classes_jar_path = install_dir / configure_text(text=self.release_info["android"]["jars"]["classes"], context=self.get_context()) + sources_jar_path = install_dir / configure_text(text=self.release_info["android"]["jars"]["sources"], context=self.get_context()) + doc_jar_path = install_dir / configure_text(text=self.release_info["android"]["jars"]["doc"], context=self.get_context()) + assert classes_jar_path.is_file(), f"CMake should have compiled the java sources and archived them into a JAR ({classes_jar_path})" + assert sources_jar_path.is_file(), f"CMake should have archived the java sources into a JAR ({sources_jar_path})" + assert doc_jar_path.is_file(), f"CMake should have archived javadoc into a JAR ({doc_jar_path})" + + archive_file_tree.add_file(NodeInArchive.from_fs(arcpath="classes.jar", path=classes_jar_path, time=self.arc_time)) + archive_file_tree.add_file(NodeInArchive.from_fs(arcpath="classes-sources.jar", path=sources_jar_path, time=self.arc_time)) + archive_file_tree.add_file(NodeInArchive.from_fs(arcpath="classes-doc.jar", path=doc_jar_path, time=self.arc_time)) + + assert ("jars" in self.release_info["android"] and java_jars_added) or "jars" not in self.release_info["android"], "Must have archived java JAR archives" + + archive_file_tree.add_file_mapping(arc_dir="", file_mapping=self.release_info["android"].get("files", {}), file_mapping_root=self.root, context=self.get_context(), time=self.arc_time) + + archive_file_tree.add_file(NodeInArchive.from_text(arcpath="prefab/prefab.json", text=self._get_prefab_json_text(), time=self.arc_time)) + archive_file_tree.add_file(NodeInArchive.from_text(arcpath="AndroidManifest.xml", text=self._get_android_manifest_text(), time=self.arc_time)) + + with Archiver(zip_path=aar_path) as archiver: + archive_file_tree.add_to_archiver(archive_base="", archiver=archiver) + archiver.add_git_hash(arcdir="", commit=self.commit, time=self.arc_time) + self.artifacts[f"android-aar"] = aar_path + + def download_dependencies(self): + shutil.rmtree(self.deps_path, ignore_errors=True) + self.deps_path.mkdir(parents=True) + + if self.github: + with open(os.environ["GITHUB_OUTPUT"], "a") as f: + f.write(f"dep-path={self.deps_path.absolute()}\n") + + for dep, depinfo in self.release_info.get("dependencies", {}).items(): + startswith = depinfo["startswith"] + dep_repo = depinfo["repo"] + # FIXME: dropped "--exclude-pre-releases" + dep_string_data = self.executer.check_output(["gh", "-R", dep_repo, "release", "list", "--exclude-drafts", "--json", "name,createdAt,tagName", "--jq", f'[.[]|select(.name|startswith("{startswith}"))]|max_by(.createdAt)']).strip() + dep_data = json.loads(dep_string_data) + dep_tag = dep_data["tagName"] + dep_version = dep_data["name"] + logger.info("Download dependency %s version %s (tag=%s) ", dep, dep_version, dep_tag) + self.executer.run(["gh", "-R", dep_repo, "release", "download", dep_tag], cwd=self.deps_path) + if self.github: + with open(os.environ["GITHUB_OUTPUT"], "a") as f: + f.write(f"dep-{dep.lower()}-version={dep_version}\n") + + def verify_dependencies(self): + for dep, depinfo in self.release_info.get("dependencies", {}).items(): + if "mingw" in self.release_info: + mingw_matches = glob.glob(self.release_info["mingw"]["dependencies"][dep]["artifact"], root_dir=self.deps_path) + assert len(mingw_matches) == 1, f"Exactly one archive matches mingw {dep} dependency: {mingw_matches}" + if "dmg" in self.release_info: + dmg_matches = glob.glob(self.release_info["dmg"]["dependencies"][dep]["artifact"], root_dir=self.deps_path) + assert len(dmg_matches) == 1, f"Exactly one archive matches dmg {dep} dependency: {dmg_matches}" + if "msvc" in self.release_info: + msvc_matches = glob.glob(self.release_info["msvc"]["dependencies"][dep]["artifact"], root_dir=self.deps_path) + assert len(msvc_matches) == 1, f"Exactly one archive matches msvc {dep} dependency: {msvc_matches}" + if "android" in self.release_info: + android_matches = glob.glob(self.release_info["android"]["dependencies"][dep]["artifact"], root_dir=self.deps_path) + assert len(android_matches) == 1, f"Exactly one archive matches msvc {dep} dependency: {msvc_matches}" + + @staticmethod + def _arch_to_vs_platform(arch: str, configuration: str="Release") -> VsArchPlatformConfig: + ARCH_TO_VS_PLATFORM = { + "x86": VsArchPlatformConfig(arch="x86", platform="Win32", configuration=configuration), + "x64": VsArchPlatformConfig(arch="x64", platform="x64", configuration=configuration), + "arm64": VsArchPlatformConfig(arch="arm64", platform="ARM64", configuration=configuration), + } + return ARCH_TO_VS_PLATFORM[arch] + + def build_msvc(self): + with self.section_printer.group("Find Visual Studio"): + vs = VisualStudio(executer=self.executer) + for arch in self.release_info["msvc"].get("msbuild", {}).get("archs", []): + self._build_msvc_msbuild(arch_platform=self._arch_to_vs_platform(arch=arch), vs=vs) + if "cmake" in self.release_info["msvc"]: + deps_path = self.root / "msvc-deps" + shutil.rmtree(deps_path, ignore_errors=True) + dep_roots = [] + for dep, depinfo in self.release_info["msvc"].get("dependencies", {}).items(): + dep_extract_path = deps_path / f"extract-{dep}" + msvc_zip = self.deps_path / glob.glob(depinfo["artifact"], root_dir=self.deps_path)[0] + with zipfile.ZipFile(msvc_zip, "r") as zf: + zf.extractall(dep_extract_path) + contents_msvc_zip = glob.glob(str(dep_extract_path / "*")) + assert len(contents_msvc_zip) == 1, f"There must be exactly one root item in the root directory of {dep}" + dep_roots.append(contents_msvc_zip[0]) + + for arch in self.release_info["msvc"].get("cmake", {}).get("archs", []): + self._build_msvc_cmake(arch_platform=self._arch_to_vs_platform(arch=arch), dep_roots=dep_roots) + with self.section_printer.group("Create SDL VC development zip"): + self._build_msvc_devel() + + def _build_msvc_msbuild(self, arch_platform: VsArchPlatformConfig, vs: VisualStudio): + platform_context = self.get_context(arch_platform.extra_context()) + for dep, depinfo in self.release_info["msvc"].get("dependencies", {}).items(): + msvc_zip = self.deps_path / glob.glob(depinfo["artifact"], root_dir=self.deps_path)[0] + + src_globs = [configure_text(instr["src"], context=platform_context) for instr in depinfo["copy"]] + with zipfile.ZipFile(msvc_zip, "r") as zf: + for member in zf.namelist(): + member_path = "/".join(Path(member).parts[1:]) + for src_i, src_glob in enumerate(src_globs): + if fnmatch.fnmatch(member_path, src_glob): + dst = (self.root / configure_text(depinfo["copy"][src_i]["dst"], context=platform_context)).resolve() / Path(member_path).name + zip_data = zf.read(member) + if dst.exists(): + identical = False + if dst.is_file(): + orig_bytes = dst.read_bytes() + if orig_bytes == zip_data: + identical = True + if not identical: + logger.warning("Extracting dependency %s, will cause %s to be overwritten", dep, dst) + if not self.overwrite: + raise RuntimeError("Run with --overwrite to allow overwriting") + logger.debug("Extracting %s -> %s", member, dst) + + dst.parent.mkdir(exist_ok=True, parents=True) + dst.write_bytes(zip_data) + + prebuilt_paths = set(self.root / full_prebuilt_path for prebuilt_path in self.release_info["msvc"]["msbuild"].get("prebuilt", []) for full_prebuilt_path in glob.glob(configure_text(prebuilt_path, context=platform_context), root_dir=self.root)) + msbuild_paths = set(self.root / configure_text(f, context=platform_context) for file_mapping in (self.release_info["msvc"]["msbuild"]["files-lib"], self.release_info["msvc"]["msbuild"]["files-devel"]) for files_list in file_mapping.values() for f in files_list) + assert prebuilt_paths.issubset(msbuild_paths), f"msvc.msbuild.prebuilt must be a subset of (msvc.msbuild.files-lib, msvc.msbuild.files-devel)" + built_paths = msbuild_paths.difference(prebuilt_paths) + logger.info("MSbuild builds these files, to be included in the package: %s", built_paths) + if not self.fast: + for b in built_paths: + b.unlink(missing_ok=True) + + rel_projects: list[str] = self.release_info["msvc"]["msbuild"]["projects"] + projects = list(self.root / p for p in rel_projects) + + directory_build_props_src_relpath = self.release_info["msvc"]["msbuild"].get("directory-build-props") + for project in projects: + dir_b_props = project.parent / "Directory.Build.props" + dir_b_props.unlink(missing_ok = True) + if directory_build_props_src_relpath: + src = self.root / directory_build_props_src_relpath + logger.debug("Copying %s -> %s", src, dir_b_props) + shutil.copy(src=src, dst=dir_b_props) + + with self.section_printer.group(f"Build {arch_platform.arch} VS binary"): + vs.build(arch_platform=arch_platform, projects=projects) + + if self.dry: + for b in built_paths: + b.parent.mkdir(parents=True, exist_ok=True) + b.touch() + + for b in built_paths: + assert b.is_file(), f"{b} has not been created" + b.parent.mkdir(parents=True, exist_ok=True) + b.touch() + + zip_path = self.dist_path / f"{self.project}-{self.version}-win32-{arch_platform.arch}.zip" + zip_path.unlink(missing_ok=True) + + logger.info("Collecting files...") + archive_file_tree = ArchiveFileTree() + archive_file_tree.add_file_mapping(arc_dir="", file_mapping=self.release_info["msvc"]["msbuild"]["files-lib"], file_mapping_root=self.root, context=platform_context, time=self.arc_time) + archive_file_tree.add_file_mapping(arc_dir="", file_mapping=self.release_info["msvc"]["files-lib"], file_mapping_root=self.root, context=platform_context, time=self.arc_time) + + logger.info("Writing to %s", zip_path) + with Archiver(zip_path=zip_path) as archiver: + arc_root = f"" + archive_file_tree.add_to_archiver(archive_base=arc_root, archiver=archiver) + archiver.add_git_hash(arcdir=arc_root, commit=self.commit, time=self.arc_time) + self.artifacts[f"VC-{arch_platform.arch}"] = zip_path + + for p in built_paths: + assert p.is_file(), f"{p} should exist" + + def _arch_platform_to_build_path(self, arch_platform: VsArchPlatformConfig) -> Path: + return self.root / f"build-vs-{arch_platform.arch}" + + def _arch_platform_to_install_path(self, arch_platform: VsArchPlatformConfig) -> Path: + return self._arch_platform_to_build_path(arch_platform) / "prefix" + + def _build_msvc_cmake(self, arch_platform: VsArchPlatformConfig, dep_roots: list[Path]): + build_path = self._arch_platform_to_build_path(arch_platform) + install_path = self._arch_platform_to_install_path(arch_platform) + platform_context = self.get_context(extra_context=arch_platform.extra_context()) + + build_type = "Release" + + built_paths = set(install_path / configure_text(f, context=platform_context) for file_mapping in (self.release_info["msvc"]["cmake"]["files-lib"], self.release_info["msvc"]["cmake"]["files-devel"]) for files_list in file_mapping.values() for f in files_list) + logger.info("CMake builds these files, to be included in the package: %s", built_paths) + if not self.fast: + for b in built_paths: + b.unlink(missing_ok=True) + + shutil.rmtree(install_path, ignore_errors=True) + build_path.mkdir(parents=True, exist_ok=True) + with self.section_printer.group(f"Configure VC CMake project for {arch_platform.arch}"): + self.executer.run([ + "cmake", "-S", str(self.root), "-B", str(build_path), + "-A", arch_platform.platform, + "-DCMAKE_INSTALL_BINDIR=bin", + "-DCMAKE_INSTALL_DATAROOTDIR=share", + "-DCMAKE_INSTALL_INCLUDEDIR=include", + "-DCMAKE_INSTALL_LIBDIR=lib", + f"-DCMAKE_BUILD_TYPE={build_type}", + f"-DCMAKE_INSTALL_PREFIX={install_path}", + # MSVC debug information format flags are selected by an abstraction + "-DCMAKE_POLICY_DEFAULT_CMP0141=NEW", + # MSVC debug information format + "-DCMAKE_MSVC_DEBUG_INFORMATION_FORMAT=ProgramDatabase", + # Linker flags for executables + "-DCMAKE_EXE_LINKER_FLAGS=-INCREMENTAL:NO -DEBUG -OPT:REF -OPT:ICF", + # Linker flag for shared libraries + "-DCMAKE_SHARED_LINKER_FLAGS=-INCREMENTAL:NO -DEBUG -OPT:REF -OPT:ICF", + # MSVC runtime library flags are selected by an abstraction + "-DCMAKE_POLICY_DEFAULT_CMP0091=NEW", + # Use statically linked runtime (-MT) (ideally, should be "MultiThreaded$<$:Debug>") + "-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded", + f"-DCMAKE_PREFIX_PATH={';'.join(str(s) for s in dep_roots)}", + ] + self.release_info["msvc"]["cmake"]["args"] + ([] if self.fast else ["--fresh"])) + + with self.section_printer.group(f"Build VC CMake project for {arch_platform.arch}"): + self.executer.run(["cmake", "--build", str(build_path), "--verbose", "--config", build_type]) + with self.section_printer.group(f"Install VC CMake project for {arch_platform.arch}"): + self.executer.run(["cmake", "--install", str(build_path), "--config", build_type]) + + if self.dry: + for b in built_paths: + b.parent.mkdir(parents=True, exist_ok=True) + b.touch() + + zip_path = self.dist_path / f"{self.project}-{self.version}-win32-{arch_platform.arch}.zip" + zip_path.unlink(missing_ok=True) + + logger.info("Collecting files...") + archive_file_tree = ArchiveFileTree() + archive_file_tree.add_file_mapping(arc_dir="", file_mapping=self.release_info["msvc"]["cmake"]["files-lib"], file_mapping_root=install_path, context=platform_context, time=self.arc_time) + archive_file_tree.add_file_mapping(arc_dir="", file_mapping=self.release_info["msvc"]["files-lib"], file_mapping_root=self.root, context=self.get_context(), time=self.arc_time) + + logger.info("Creating %s", zip_path) + with Archiver(zip_path=zip_path) as archiver: + arc_root = f"" + archive_file_tree.add_to_archiver(archive_base=arc_root, archiver=archiver) + archiver.add_git_hash(arcdir=arc_root, commit=self.commit, time=self.arc_time) + + for p in built_paths: + assert p.is_file(), f"{p} should exist" + + def _build_msvc_devel(self) -> None: + zip_path = self.dist_path / f"{self.project}-devel-{self.version}-VC.zip" + arc_root = f"{self.project}-{self.version}" + + logger.info("Collecting files...") + archive_file_tree = ArchiveFileTree() + if "msbuild" in self.release_info["msvc"]: + for arch in self.release_info["msvc"]["msbuild"]["archs"]: + arch_platform = self._arch_to_vs_platform(arch=arch) + platform_context = self.get_context(arch_platform.extra_context()) + archive_file_tree.add_file_mapping(arc_dir=arc_root, file_mapping=self.release_info["msvc"]["msbuild"]["files-devel"], file_mapping_root=self.root, context=platform_context, time=self.arc_time) + if "cmake" in self.release_info["msvc"]: + for arch in self.release_info["msvc"]["cmake"]["archs"]: + arch_platform = self._arch_to_vs_platform(arch=arch) + platform_context = self.get_context(arch_platform.extra_context()) + archive_file_tree.add_file_mapping(arc_dir=arc_root, file_mapping=self.release_info["msvc"]["cmake"]["files-devel"], file_mapping_root=self._arch_platform_to_install_path(arch_platform), context=platform_context, time=self.arc_time) + archive_file_tree.add_file_mapping(arc_dir=arc_root, file_mapping=self.release_info["msvc"]["files-devel"], file_mapping_root=self.root, context=self.get_context(), time=self.arc_time) + + with Archiver(zip_path=zip_path) as archiver: + archive_file_tree.add_to_archiver(archive_base="", archiver=archiver) + archiver.add_git_hash(arcdir=arc_root, commit=self.commit, time=self.arc_time) + self.artifacts["VC-devel"] = zip_path + + @classmethod + def extract_sdl_version(cls, root: Path, release_info: dict) -> str: + with open(root / release_info["version"]["file"], "r") as f: + text = f.read() + major = next(re.finditer(release_info["version"]["re_major"], text, flags=re.M)).group(1) + minor = next(re.finditer(release_info["version"]["re_minor"], text, flags=re.M)).group(1) + micro = next(re.finditer(release_info["version"]["re_micro"], text, flags=re.M)).group(1) + return f"{major}.{minor}.{micro}" + + +def main(argv=None) -> int: + if sys.version_info < (3, 11): + logger.error("This script needs at least python 3.11") + return 1 + + parser = argparse.ArgumentParser(allow_abbrev=False, description="Create SDL release artifacts") + parser.add_argument("--root", metavar="DIR", type=Path, default=Path(__file__).absolute().parents[1], help="Root of project") + parser.add_argument("--release-info", metavar="JSON", dest="path_release_info", type=Path, default=Path(__file__).absolute().parent / "release-info.json", help="Path of release-info.json") + parser.add_argument("--dependency-folder", metavar="FOLDER", dest="deps_path", type=Path, default="deps", help="Directory containing pre-built archives of dependencies (will be removed when downloading archives)") + parser.add_argument("--out", "-o", metavar="DIR", dest="dist_path", type=Path, default="dist", help="Output directory") + parser.add_argument("--github", action="store_true", help="Script is running on a GitHub runner") + parser.add_argument("--commit", default="HEAD", help="Git commit/tag of which a release should be created") + parser.add_argument("--actions", choices=["download", "source", "android", "mingw", "msvc", "dmg"], required=True, nargs="+", dest="actions", help="What to do?") + parser.set_defaults(loglevel=logging.INFO) + parser.add_argument('--vs-year', dest="vs_year", help="Visual Studio year") + parser.add_argument('--android-api', type=int, dest="android_api", help="Android API version") + parser.add_argument('--android-home', dest="android_home", default=os.environ.get("ANDROID_HOME"), help="Android Home folder") + parser.add_argument('--android-ndk-home', dest="android_ndk_home", default=os.environ.get("ANDROID_NDK_HOME"), help="Android NDK Home folder") + parser.add_argument('--cmake-generator', dest="cmake_generator", default="Ninja", help="CMake Generator") + parser.add_argument('--debug', action='store_const', const=logging.DEBUG, dest="loglevel", help="Print script debug information") + parser.add_argument('--dry-run', action='store_true', dest="dry", help="Don't execute anything") + parser.add_argument('--force', action='store_true', dest="force", help="Ignore a non-clean git tree") + parser.add_argument('--overwrite', action='store_true', dest="overwrite", help="Allow potentially overwriting other projects") + parser.add_argument('--fast', action='store_true', dest="fast", help="Don't do a rebuild") + + args = parser.parse_args(argv) + logging.basicConfig(level=args.loglevel, format='[%(levelname)s] %(message)s') + args.deps_path = args.deps_path.absolute() + args.dist_path = args.dist_path.absolute() + args.root = args.root.absolute() + args.dist_path = args.dist_path.absolute() + if args.dry: + args.dist_path = args.dist_path / "dry" + + if args.github: + section_printer: SectionPrinter = GitHubSectionPrinter() + else: + section_printer = SectionPrinter() + + if args.github and "GITHUB_OUTPUT" not in os.environ: + os.environ["GITHUB_OUTPUT"] = "/tmp/github_output.txt" + + executer = Executer(root=args.root, dry=args.dry) + + root_git_hash_path = args.root / GIT_HASH_FILENAME + root_is_maybe_archive = root_git_hash_path.is_file() + if root_is_maybe_archive: + logger.warning("%s detected: Building from archive", GIT_HASH_FILENAME) + archive_commit = root_git_hash_path.read_text().strip() + if args.commit != archive_commit: + logger.warning("Commit argument is %s, but archive commit is %s. Using %s.", args.commit, archive_commit, archive_commit) + args.commit = archive_commit + revision = (args.root / REVISION_TXT).read_text().strip() + else: + args.commit = executer.check_output(["git", "rev-parse", args.commit], dry_out="e5812a9fd2cda317b503325a702ba3c1c37861d9").strip() + revision = executer.check_output(["git", "describe", "--always", "--tags", "--long", args.commit], dry_out="preview-3.1.3-96-g9512f2144").strip() + logger.info("Using commit %s", args.commit) + + try: + with args.path_release_info.open() as f: + release_info = json.load(f) + except FileNotFoundError: + logger.error(f"Could not find {args.path_release_info}") + + releaser = Releaser( + release_info=release_info, + commit=args.commit, + revision=revision, + root=args.root, + dist_path=args.dist_path, + executer=executer, + section_printer=section_printer, + cmake_generator=args.cmake_generator, + deps_path=args.deps_path, + overwrite=args.overwrite, + github=args.github, + fast=args.fast, + ) + + if root_is_maybe_archive: + logger.warning("Building from archive. Skipping clean git tree check.") + else: + porcelain_status = executer.check_output(["git", "status", "--ignored", "--porcelain"], dry_out="\n").strip() + if porcelain_status: + print(porcelain_status) + logger.warning("The tree is dirty! Do not publish any generated artifacts!") + if not args.force: + raise Exception("The git repo contains modified and/or non-committed files. Run with --force to ignore.") + + if args.fast: + logger.warning("Doing fast build! Do not publish generated artifacts!") + + with section_printer.group("Arguments"): + print(f"project = {releaser.project}") + print(f"version = {releaser.version}") + print(f"revision = {revision}") + print(f"commit = {args.commit}") + print(f"out = {args.dist_path}") + print(f"actions = {args.actions}") + print(f"dry = {args.dry}") + print(f"force = {args.force}") + print(f"overwrite = {args.overwrite}") + print(f"cmake_generator = {args.cmake_generator}") + + releaser.prepare() + + if "download" in args.actions: + releaser.download_dependencies() + + if set(args.actions).intersection({"msvc", "mingw", "android"}): + print("Verifying presence of dependencies (run 'download' action to download) ...") + releaser.verify_dependencies() + print("... done") + + if "source" in args.actions: + if root_is_maybe_archive: + raise Exception("Cannot build source archive from source archive") + with section_printer.group("Create source archives"): + releaser.create_source_archives() + + if "dmg" in args.actions: + if platform.system() != "Darwin" and not args.dry: + parser.error("framework artifact(s) can only be built on Darwin") + + releaser.create_dmg() + + if "msvc" in args.actions: + if platform.system() != "Windows" and not args.dry: + parser.error("msvc artifact(s) can only be built on Windows") + releaser.build_msvc() + + if "mingw" in args.actions: + releaser.create_mingw_archives() + + if "android" in args.actions: + if args.android_home is None or not Path(args.android_home).is_dir(): + parser.error("Invalid $ANDROID_HOME or --android-home: must be a directory containing the Android SDK") + if args.android_ndk_home is None or not Path(args.android_ndk_home).is_dir(): + parser.error("Invalid $ANDROID_NDK_HOME or --android_ndk_home: must be a directory containing the Android NDK") + if args.android_api is None: + with section_printer.group("Detect Android APIS"): + args.android_api = releaser._detect_android_api(android_home=args.android_home) + if args.android_api is None or not (Path(args.android_home) / f"platforms/android-{args.android_api}").is_dir(): + parser.error("Invalid --android-api, and/or could not be detected") + with section_printer.group("Android arguments"): + print(f"android_home = {args.android_home}") + print(f"android_ndk_home = {args.android_ndk_home}") + print(f"android_api = {args.android_api}") + releaser.create_android_archives( + android_api=args.android_api, + android_home=args.android_home, + android_ndk_home=args.android_ndk_home, + ) + with section_printer.group("Summary"): + print(f"artifacts = {releaser.artifacts}") + + if args.github: + with open(os.environ["GITHUB_OUTPUT"], "a") as f: + f.write(f"project={releaser.project}\n") + f.write(f"version={releaser.version}\n") + for k, v in releaser.artifacts.items(): + f.write(f"{k}={v.name}\n") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/build-scripts/cmake-toolchain-mingw64-i686.cmake b/build-scripts/cmake-toolchain-mingw64-i686.cmake new file mode 100644 index 00000000..8be7b3a8 --- /dev/null +++ b/build-scripts/cmake-toolchain-mingw64-i686.cmake @@ -0,0 +1,18 @@ +set(CMAKE_SYSTEM_NAME Windows) +set(CMAKE_SYSTEM_PROCESSOR x86) + +find_program(CMAKE_C_COMPILER NAMES i686-w64-mingw32-gcc) +find_program(CMAKE_CXX_COMPILER NAMES i686-w64-mingw32-g++) +find_program(CMAKE_RC_COMPILER NAMES i686-w64-mingw32-windres windres) + +if(NOT CMAKE_C_COMPILER) + message(FATAL_ERROR "Failed to find CMAKE_C_COMPILER.") +endif() + +if(NOT CMAKE_CXX_COMPILER) + message(FATAL_ERROR "Failed to find CMAKE_CXX_COMPILER.") +endif() + +if(NOT CMAKE_RC_COMPILER) + message(FATAL_ERROR "Failed to find CMAKE_RC_COMPILER.") +endif() diff --git a/build-scripts/cmake-toolchain-mingw64-x86_64.cmake b/build-scripts/cmake-toolchain-mingw64-x86_64.cmake new file mode 100644 index 00000000..8bf43669 --- /dev/null +++ b/build-scripts/cmake-toolchain-mingw64-x86_64.cmake @@ -0,0 +1,18 @@ +set(CMAKE_SYSTEM_NAME Windows) +set(CMAKE_SYSTEM_PROCESSOR x86_64) + +find_program(CMAKE_C_COMPILER NAMES x86_64-w64-mingw32-gcc) +find_program(CMAKE_CXX_COMPILER NAMES x86_64-w64-mingw32-g++) +find_program(CMAKE_RC_COMPILER NAMES x86_64-w64-mingw32-windres windres) + +if(NOT CMAKE_C_COMPILER) + message(FATAL_ERROR "Failed to find CMAKE_C_COMPILER.") +endif() + +if(NOT CMAKE_CXX_COMPILER) + message(FATAL_ERROR "Failed to find CMAKE_CXX_COMPILER.") +endif() + +if(NOT CMAKE_RC_COMPILER) + message(FATAL_ERROR "Failed to find CMAKE_RC_COMPILER.") +endif() diff --git a/build-scripts/create-release.py b/build-scripts/create-release.py new file mode 100755 index 00000000..2e1fd559 --- /dev/null +++ b/build-scripts/create-release.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python + +import argparse +from pathlib import Path +import json +import logging +import re +import subprocess + +ROOT = Path(__file__).resolve().parents[1] + + +def determine_project() -> str: + text = (ROOT / "build-scripts/release-info.json").read_text() + release_info = json.loads(text) + project_with_version = release_info["name"] + project, _ = re.subn("([^a-zA-Z_])", "", project_with_version) + return project + + +def main(): + project = determine_project() + default_remote = f"libsdl-org/{project}" + + current_commit = subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=ROOT, text=True).strip() + + parser = argparse.ArgumentParser(allow_abbrev=False) + parser.add_argument("--ref", required=True, help=f"Name of branch or tag containing release.yml") + parser.add_argument("--remote", "-R", default=default_remote, help=f"Remote repo (default={default_remote})") + parser.add_argument("--commit", default=current_commit, help=f"Commit (default={current_commit})") + args = parser.parse_args() + + + print(f"Running release.yml workflow:") + print(f" commit = {args.commit}") + print(f" remote = {args.remote}") + + subprocess.check_call(["gh", "-R", args.remote, "workflow", "run", "release.yml", "--ref", args.ref, "-f", f"commit={args.commit}"], cwd=ROOT) + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/build-scripts/pkg-support/android/INSTALL.md.in b/build-scripts/pkg-support/android/INSTALL.md.in new file mode 100644 index 00000000..136de4ed --- /dev/null +++ b/build-scripts/pkg-support/android/INSTALL.md.in @@ -0,0 +1,61 @@ +This Android archive allows use of @<@PROJECT_NAME@>@ in your Android project, without needing to copy any SDL source. +For integration with CMake/ndk-build, it uses [prefab](https://google.github.io/prefab/). + +Copy this archive (@<@PROJECT_NAME@>@-@<@PROJECT_VERSION@>@.aar) to a `app/libs` directory of your project. + +In `app/build.gradle` of your Android project, add: +``` +android { + /* ... */ + buildFeatures { + prefab true + } +} +dependencies { + implementation files('libs/@<@PROJECT_NAME@>@-@<@PROJECT_VERSION@>@.aar') + /* ... */ +} +``` + +If you're using CMake, add the following to your CMakeLists.txt: +``` +find_package(@<@PROJECT_NAME@>@ REQUIRED CONFIG) +target_link_libraries(yourgame PRIVATE @<@PROJECT_NAME@>@::@<@PROJECT_NAME@>@) +``` + +If you use ndk-build, add the following before `include $(BUILD_SHARED_LIBRARY)` to your `Android.mk`: +``` +LOCAL_SHARED_LIBARARIES := @<@PROJECT_NAME@>@ +``` +And add the following at the bottom: +``` +# https://google.github.io/prefab/build-systems.html + +# Add the prefab modules to the import path. +$(call import-add-path,/out) + +# Import @<@PROJECT_NAME@>@ so we can depend on it. +$(call import-module,prefab/@<@PROJECT_NAME@>@) +``` + +--- + +For advanced users: + +If you want to build a 3rd party library outside Gradle, +running the following command will extract the Android archive into a more common directory structure. +``` +python @<@PROJECT_NAME@>@-@PROJECT_VERSION@.aar -o android_prefix +``` +Add `--help` for a list of all available options. + + +Look at the example programs in ./test (of the source archive), and check out online documentation: + https://wiki.libsdl.org/SDL3/FrontPage + +Join the SDL discourse server if you want to join the community: + https://discourse.libsdl.org/ + + +That's it! +Sam Lantinga diff --git a/build-scripts/pkg-support/android/__main__.py.in b/build-scripts/pkg-support/android/__main__.py.in new file mode 100755 index 00000000..344cf719 --- /dev/null +++ b/build-scripts/pkg-support/android/__main__.py.in @@ -0,0 +1,104 @@ +#!/usr/bin/env python + +""" +Create a @<@PROJECT_NAME@>@ SDK prefix from an Android archive +This file is meant to be placed in a the root of an android .aar archive + +Example usage: +```sh +python @<@PROJECT_NAME@>@-@<@PROJECT_VERSION@>@.aar -o /usr/opt/android-sdks +cmake -S my-project \ + -DCMAKE_PREFIX_PATH=/usr/opt/android-sdks \ + -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake \ + -B build-arm64 -DANDROID_ABI=arm64-v8a \ + -DCMAKE_BUILD_TYPE=Releaase +cmake --build build-arm64 +``` +""" +import argparse +import io +import json +import os +import pathlib +import re +import stat +import zipfile + + +AAR_PATH = pathlib.Path(__file__).resolve().parent +ANDROID_ARCHS = { "armeabi-v7a", "arm64-v8a", "x86", "x86_64" } + + +def main(): + parser = argparse.ArgumentParser( + description="Convert a @<@PROJECT_NAME@>@ Android .aar archive into a SDK", + allow_abbrev=False, + ) + parser.add_argument("--version", action="version", version="@<@PROJECT_NAME@>@ @<@PROJECT_VERSION@>@") + parser.add_argument("-o", dest="output", type=pathlib.Path, required=True, help="Folder where to store the SDK") + args = parser.parse_args() + + print(f"Creating a @<@PROJECT_NAME@>@ SDK at {args.output}...") + + prefix = args.output + incdir = prefix / "include" + libdir = prefix / "lib" + + RE_LIB_MODULE_ARCH = re.compile(r"prefab/modules/(?P[A-Za-z0-9_-]+)/libs/android\.(?P[a-zA-Z0-9_-]+)/(?Plib[A-Za-z0-9_]+\.(?:so|a))") + RE_INC_MODULE_ARCH = re.compile(r"prefab/modules/(?P[A-Za-z0-9_-]+)/include/(?P
[a-zA-Z0-9_./-]+)") + RE_LICENSE = re.compile(r"(?:.*/)?(?P(?:license|copying)(?:\.md|\.txt)?)", flags=re.I) + RE_PROGUARD = re.compile(r"(?:.*/)?(?Pproguard.*\.(?:pro|txt))", flags=re.I) + RE_CMAKE = re.compile(r"(?:.*/)?(?P.*\.cmake)", flags=re.I) + + with zipfile.ZipFile(AAR_PATH) as zf: + project_description = json.loads(zf.read("description.json")) + project_name = project_description["name"] + project_version = project_description["version"] + licensedir = prefix / "share/licenses" / project_name + cmakedir = libdir / "cmake" / project_name + javadir = prefix / "share/java" / project_name + javadocdir = prefix / "share/javadoc" / project_name + + def read_zipfile_and_write(path: pathlib.Path, zippath: str): + data = zf.read(zippath) + path.parent.mkdir(parents=True, exist_ok=True) + path.write_bytes(data) + + for zip_info in zf.infolist(): + zippath = zip_info.filename + if m := RE_LIB_MODULE_ARCH.match(zippath): + lib_path = libdir / m["arch"] / m["filename"] + read_zipfile_and_write(lib_path, zippath) + if m["filename"].endswith(".so"): + os.chmod(lib_path, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH) + + elif m := RE_INC_MODULE_ARCH.match(zippath): + header_path = incdir / m["header"] + read_zipfile_and_write(header_path, zippath) + elif m:= RE_LICENSE.match(zippath): + license_path = licensedir / m["filename"] + read_zipfile_and_write(license_path, zippath) + elif m:= RE_PROGUARD.match(zippath): + proguard_path = javadir / m["filename"] + read_zipfile_and_write(proguard_path, zippath) + elif m:= RE_CMAKE.match(zippath): + cmake_path = cmakedir / m["filename"] + read_zipfile_and_write(cmake_path, zippath) + elif zippath == "classes.jar": + versioned_jar_path = javadir / f"{project_name}-{project_version}.jar" + unversioned_jar_path = javadir / f"{project_name}.jar" + read_zipfile_and_write(versioned_jar_path, zippath) + os.symlink(src=versioned_jar_path.name, dst=unversioned_jar_path) + elif zippath == "classes-sources.jar": + jarpath = javadir / f"{project_name}-{project_version}-sources.jar" + read_zipfile_and_write(jarpath, zippath) + elif zippath == "classes-doc.jar": + jarpath = javadocdir / f"{project_name}-{project_version}-javadoc.jar" + read_zipfile_and_write(jarpath, zippath) + + print("... done") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/build-scripts/pkg-support/android/cmake/SDL3_imageConfig.cmake b/build-scripts/pkg-support/android/cmake/SDL3_imageConfig.cmake new file mode 100644 index 00000000..3ae22f42 --- /dev/null +++ b/build-scripts/pkg-support/android/cmake/SDL3_imageConfig.cmake @@ -0,0 +1,128 @@ +# SDL CMake configuration file: +# This file is meant to be placed in lib/cmake/SDL3_image subfolder of a reconstructed Android SDL3_image SDK + +cmake_minimum_required(VERSION 3.0...3.5) + +include(FeatureSummary) +set_package_properties(SDL3_image PROPERTIES + URL "https://www.libsdl.org/projects/SDL_image/" + DESCRIPTION "SDL_image is an image file loading library" +) + +# Copied from `configure_package_config_file` +macro(set_and_check _var _file) + set(${_var} "${_file}") + if(NOT EXISTS "${_file}") + message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !") + endif() +endmacro() + +set(SDLIMAGE_AVIF FALSE) +set(SDLIMAGE_BMP TRUE) +set(SDLIMAGE_GIF TRUE) +set(SDLIMAGE_JPG TRUE) +set(SDLIMAGE_JXL FALSE) +set(SDLIMAGE_LBM TRUE) +set(SDLIMAGE_PCX TRUE) +set(SDLIMAGE_PNG TRUE) +set(SDLIMAGE_PNM TRUE) +set(SDLIMAGE_QOI TRUE) +set(SDLIMAGE_SVG TRUE) +set(SDLIMAGE_TGA TRUE) +set(SDLIMAGE_TIF FALSE) +set(SDLIMAGE_XCF FALSE) +set(SDLIMAGE_XPM TRUE) +set(SDLIMAGE_XV TRUE) +set(SDLIMAGE_WEBP FALSE) + +set(SDLIMAGE_JPG_SAVE FALSE) +set(SDLIMAGE_PNG_SAVE FALSE) + +set(SDLIMAGE_VENDORED FALSE) + +set(SDLIMAGE_BACKEND_IMAGEIO FALSE) +set(SDLIMAGE_BACKEND_STB TRUE) +set(SDLIMAGE_BACKEND_WIC FALSE) + +# Copied from `configure_package_config_file` +macro(check_required_components _NAME) + foreach(comp ${${_NAME}_FIND_COMPONENTS}) + if(NOT ${_NAME}_${comp}_FOUND) + if(${_NAME}_FIND_REQUIRED_${comp}) + set(${_NAME}_FOUND FALSE) + endif() + endif() + endforeach() +endmacro() + +set(SDL3_image_FOUND TRUE) + +if(SDL_CPU_X86) + set(_sdl_arch_subdir "x86") +elseif(SDL_CPU_X64) + set(_sdl_arch_subdir "x86_64") +elseif(SDL_CPU_ARM32) + set(_sdl_arch_subdir "armeabi-v7a") +elseif(SDL_CPU_ARM64) + set(_sdl_arch_subdir "arm64-v8a") +else() + set(SDL3_image_FOUND FALSE) + return() +endif() + +get_filename_component(_sdl3_prefix "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE) +get_filename_component(_sdl3_prefix "${_sdl3_prefix}/.." ABSOLUTE) +get_filename_component(_sdl3_prefix "${_sdl3_prefix}/.." ABSOLUTE) +set_and_check(_sdl3_prefix "${_sdl3_prefix}") +set_and_check(_sdl3_include_dirs "${_sdl3_prefix}/include") + +set_and_check(_sdl3_lib "${_sdl3_prefix}/lib/${_sdl_arch_subdir}/libSDL3_image.so") + +unset(_sdl_arch_subdir) +unset(_sdl3_prefix) + +# All targets are created, even when some might not be requested though COMPONENTS. +# This is done for compatibility with CMake generated SDL3_image-target.cmake files. + +if(EXISTS "${_sdl3_lib}") + if(NOT TARGET SDL3_image::SDL3_image-shared) + add_library(SDL3_image::SDL3_image-shared SHARED IMPORTED) + set_target_properties(SDL3_image::SDL3_image-shared + PROPERTIES + IMPORTED_LOCATION "${_sdl3_lib}" + COMPATIBLE_INTERFACE_BOOL "SDL3_SHARED" + INTERFACE_SDL3_SHARED "ON" + COMPATIBLE_INTERFACE_STRING "SDL_VERSION" + INTERFACE_SDL_VERSION "SDL3" + ) + endif() + set(SDL3_image_SDL3_image-shared_FOUND TRUE) +else() + set(SDL3_image_SDL3_image-shared_FOUND FALSE) +endif() +unset(_sdl3_lib) + +set(SDL3_image_SDL3_image-static_FOUND FALSE) + +if(SDL3_image_SDL3_image-shared_FOUND) + set(SDL3_image_SDL3_image_FOUND TRUE) +endif() + +function(_sdl_create_target_alias_compat NEW_TARGET TARGET) + if(CMAKE_VERSION VERSION_LESS "3.18") + # Aliasing local targets is not supported on CMake < 3.18, so make it global. + add_library(${NEW_TARGET} INTERFACE IMPORTED) + set_target_properties(${NEW_TARGET} PROPERTIES INTERFACE_LINK_LIBRARIES "${TARGET}") + else() + add_library(${NEW_TARGET} ALIAS ${TARGET}) + endif() +endfunction() + +# Make sure SDL3_image::SDL3_image always exists +if(NOT TARGET SDL3_image::SDL3_image) + if(TARGET SDL3_image::SDL3_image-shared) + _sdl_create_target_alias_compat(SDL3_image::SDL3_image SDL3_image::SDL3_image-shared) + endif() +endif() + +check_required_components(SDL3_image) diff --git a/build-scripts/pkg-support/android/cmake/SDL3_imageConfigVersion.cmake.in b/build-scripts/pkg-support/android/cmake/SDL3_imageConfigVersion.cmake.in new file mode 100644 index 00000000..0dae8ed6 --- /dev/null +++ b/build-scripts/pkg-support/android/cmake/SDL3_imageConfigVersion.cmake.in @@ -0,0 +1,33 @@ +# SDL_image CMake version configuration file: +# This file is meant to be placed in a lib/cmake/SDL3_image subfolder of a reconstructed Android SDL3_image SDK + +set(PACKAGE_VERSION "@<@PROJECT_VERSION@>@") + +if(PACKAGE_FIND_VERSION_RANGE) + # Package version must be in the requested version range + if ((PACKAGE_FIND_VERSION_RANGE_MIN STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_MIN) + OR ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_GREATER PACKAGE_FIND_VERSION_MAX) + OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND PACKAGE_VERSION VERSION_GREATER_EQUAL PACKAGE_FIND_VERSION_MAX))) + set(PACKAGE_VERSION_COMPATIBLE FALSE) + else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + endif() +else() + if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) + set(PACKAGE_VERSION_COMPATIBLE FALSE) + else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) + set(PACKAGE_VERSION_EXACT TRUE) + endif() + endif() +endif() + +include("${CMAKE_CURRENT_LIST_DIR}/sdlcpu.cmake") +SDL_DetectTargetCPUArchitectures(_detected_archs) + +# check that the installed version has a compatible architecture as the one which is currently searching: +if(NOT(SDL_CPU_X86 OR SDL_CPU_X64 OR SDL_CPU_ARM32 OR SDL_CPU_ARM64)) + set(PACKAGE_VERSION "${PACKAGE_VERSION} (X86,X64,ARM32,ARM64)") + set(PACKAGE_VERSION_UNSUITABLE TRUE) +endif() diff --git a/build-scripts/pkg-support/android/description.json.in b/build-scripts/pkg-support/android/description.json.in new file mode 100644 index 00000000..e75ef382 --- /dev/null +++ b/build-scripts/pkg-support/android/description.json.in @@ -0,0 +1,5 @@ +{ + "name": "@<@PROJECT_NAME@>@", + "version": "@<@PROJECT_VERSION@>@", + "git-hash": "@<@PROJECT_COMMIT@>@" +} diff --git a/build-scripts/pkg-support/mingw/Makefile b/build-scripts/pkg-support/mingw/Makefile new file mode 100644 index 00000000..5d1330c4 --- /dev/null +++ b/build-scripts/pkg-support/mingw/Makefile @@ -0,0 +1,39 @@ +# +# Makefile for installing the mingw32 version of the SDL_image library + +DESTDIR = /usr/local +ARCHITECTURES := i686-w64-mingw32 x86_64-w64-mingw32 + +default: + @echo "Run \"make install-i686\" to install 32-bit" + @echo "Run \"make install-x86_64\" to install 64-bit" + @echo "Run \"make install-all\" to install both" + @echo "Add DESTDIR=/custom/path to change the destination folder" + +install: + @if test -d $(ARCH) && test -d $(DESTDIR); then \ + (cd $(ARCH) && cp -rv bin include lib share $(DESTDIR)/); \ + else \ + echo "*** ERROR: $(ARCH) or $(DESTDIR) does not exist!"; \ + exit 1; \ + fi + +install-i686: + $(MAKE) install ARCH=i686-w64-mingw32 + +install-x86_64: + $(MAKE) install ARCH=x86_64-w64-mingw32 + +install-all: + @if test -d $(DESTDIR); then \ + mkdir -p $(DESTDIR)/cmake; \ + cp -rv cmake/* $(DESTDIR)/cmake; \ + for arch in $(ARCHITECTURES); do \ + $(MAKE) install ARCH=$$arch DESTDIR=$(DESTDIR)/$$arch; \ + done \ + else \ + echo "*** ERROR: $(DESTDIR) does not exist!"; \ + exit 1; \ + fi + +.PHONY: default install install-i686 install-x86_64 install-all diff --git a/mingw/pkg-support/cmake/sdl3_image-config.cmake b/build-scripts/pkg-support/mingw/cmake/SDL3_imageConfig.cmake similarity index 100% rename from mingw/pkg-support/cmake/sdl3_image-config.cmake rename to build-scripts/pkg-support/mingw/cmake/SDL3_imageConfig.cmake diff --git a/mingw/pkg-support/cmake/sdl3_image-config-version.cmake b/build-scripts/pkg-support/mingw/cmake/SDL3_imageConfigVersion.cmake similarity index 83% rename from mingw/pkg-support/cmake/sdl3_image-config-version.cmake rename to build-scripts/pkg-support/mingw/cmake/SDL3_imageConfigVersion.cmake index 51b02c28..584b45f5 100644 --- a/mingw/pkg-support/cmake/sdl3_image-config-version.cmake +++ b/build-scripts/pkg-support/mingw/cmake/SDL3_imageConfigVersion.cmake @@ -2,9 +2,9 @@ # This file is meant to be placed in a cmake subfolder of SDL3_image-devel-3.x.y-mingw if(CMAKE_SIZEOF_VOID_P EQUAL 4) - set(sdl3_image_config_path "${CMAKE_CURRENT_LIST_DIR}/../i686-w64-mingw32/lib/cmake/SDL3_image/sdl3_image-config-version.cmake") + set(sdl3_image_config_path "${CMAKE_CURRENT_LIST_DIR}/../i686-w64-mingw32/lib/cmake/SDL3_image/SDL3_imageConfigVersion.cmake") elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(sdl3_image_config_path "${CMAKE_CURRENT_LIST_DIR}/../x86_64-w64-mingw32/lib/cmake/SDL3_image/sdl3_image-config-version.cmake") + set(sdl3_image_config_path "${CMAKE_CURRENT_LIST_DIR}/../x86_64-w64-mingw32/lib/cmake/SDL3_image/SDL3_imageConfigVersion.cmake") else("${CMAKE_SIZEOF_VOID_P}" STREQUAL "") set(PACKAGE_VERSION_UNSUITABLE TRUE) return() diff --git a/build-scripts/pkg-support/msvc/cmake/SDL3_imageConfig.cmake.in b/build-scripts/pkg-support/msvc/cmake/SDL3_imageConfig.cmake.in new file mode 100644 index 00000000..70be4ac6 --- /dev/null +++ b/build-scripts/pkg-support/msvc/cmake/SDL3_imageConfig.cmake.in @@ -0,0 +1,115 @@ +# @<@PROJECT_NAME@>@ CMake configuration file: +# This file is meant to be placed in a cmake subfolder of @<@PROJECT_NAME@>@-devel-@<@PROJECT_VERSION@>@-VC.zip + +include(FeatureSummary) +set_package_properties(SDL3_image PROPERTIES + URL "https://www.libsdl.org/projects/SDL_image/" + DESCRIPTION "SDL_image is an image file loading library" +) + +cmake_minimum_required(VERSION 3.0...3.5) + +# Copied from `configure_package_config_file` +macro(check_required_components _NAME) + foreach(comp ${${_NAME}_FIND_COMPONENTS}) + if(NOT ${_NAME}_${comp}_FOUND) + if(${_NAME}_FIND_REQUIRED_${comp}) + set(${_NAME}_FOUND FALSE) + endif() + endif() + endforeach() +endmacro() + +set(SDL3_image_FOUND TRUE) + +set(SDLIMAGE_AVIF TRUE) +set(SDLIMAGE_BMP TRUE) +set(SDLIMAGE_GIF TRUE) +set(SDLIMAGE_JPG TRUE) +set(SDLIMAGE_JXL FALSE) +set(SDLIMAGE_LBM TRUE) +set(SDLIMAGE_PCX TRUE) +set(SDLIMAGE_PNG TRUE) +set(SDLIMAGE_PNM TRUE) +set(SDLIMAGE_QOI TRUE) +set(SDLIMAGE_SVG TRUE) +set(SDLIMAGE_TGA TRUE) +set(SDLIMAGE_TIF TRUE) +set(SDLIMAGE_XCF FALSE) +set(SDLIMAGE_XPM TRUE) +set(SDLIMAGE_XV TRUE) +set(SDLIMAGE_WEBP TRUE) + +set(SDLIMAGE_JPG_SAVE FALSE) +set(SDLIMAGE_PNG_SAVE FALSE) + +set(SDLIMAGE_VENDORED FALSE) + +set(SDLIMAGE_BACKEND_IMAGEIO FALSE) +set(SDLIMAGE_BACKEND_STB TRUE) +set(SDLIMAGE_BACKEND_WIC FALSE) + +if(SDL_CPU_X86) + set(_sdl_arch_subdir "x86") +elseif(SDL_CPU_X64 OR SDL_CPU_ARM64EC) + set(_sdl_arch_subdir "x64") +elseif(SDL_CPU_ARM64) + set(SDLIMAGE_AVIF FALSE) + set(SDLIMAGE_TIF FALSE) + set(SDLIMAGE_WEBP FALSE) + set(_sdl_arch_subdir "arm64") +else() + set(SDL3_image_FOUND FALSE) + return() +endif() + +set(_sdl3image_incdir "${CMAKE_CURRENT_LIST_DIR}/../include") +set(_sdl3image_library "${CMAKE_CURRENT_LIST_DIR}/../lib/${_sdl_arch_subdir}/SDL3_image.lib") +set(_sdl3image_dll "${CMAKE_CURRENT_LIST_DIR}/../lib/${_sdl_arch_subdir}/SDL3_image.dll") + +# All targets are created, even when some might not be requested though COMPONENTS. +# This is done for compatibility with CMake generated SDL3_image-target.cmake files. + +set(SDL3_image_SDL3_image-shared_FOUND TRUE) +if(NOT TARGET SDL3_image::SDL3_image-shared) + add_library(SDL3_image::SDL3_image-shared SHARED IMPORTED) + set_target_properties(SDL3_image::SDL3_image-shared + PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${_sdl3image_incdir}" + IMPORTED_IMPLIB "${_sdl3image_library}" + IMPORTED_LOCATION "${_sdl3image_dll}" + COMPATIBLE_INTERFACE_BOOL "SDL3_SHARED" + INTERFACE_SDL3_SHARED "ON" + ) +endif() + +unset(_sdl_arch_subdir) +unset(_sdl3image_incdir) +unset(_sdl3image_library) +unset(_sdl3image_dll) + +set(SDL3_image_SDL3_image-static_FOUND TRUE) + +set(SDL3_image_SDL3_image_FOUND FALSE) +if(SDL3_image_SDL3_image-hared_FOUND OR SDL3_image_SDL3_image-static_FOUND) + set(SDL3_image_SDL3_image_FOUND TRUE) +endif() + +function(_sdl_create_target_alias_compat NEW_TARGET TARGET) + if(CMAKE_VERSION VERSION_LESS "3.18") + # Aliasing local targets is not supported on CMake < 3.18, so make it global. + add_library(${NEW_TARGET} INTERFACE IMPORTED) + set_target_properties(${NEW_TARGET} PROPERTIES INTERFACE_LINK_LIBRARIES "${TARGET}") + else() + add_library(${NEW_TARGET} ALIAS ${TARGET}) + endif() +endfunction() + +# Make sure SDL3_image::SDL3_image always exists +if(NOT TARGET SDL3_image::SDL3_image) + if(TARGET SDL3_image::SDL3_image-shared) + _sdl_create_target_alias_compat(SDL3_image::SDL3_image SDL3_image::SDL3_image-shared) + endif() +endif() + +check_required_components(SDL3_image) diff --git a/build-scripts/pkg-support/msvc/cmake/SDL3_imageConfigVersion.cmake.in b/build-scripts/pkg-support/msvc/cmake/SDL3_imageConfigVersion.cmake.in new file mode 100644 index 00000000..ebbcf99a --- /dev/null +++ b/build-scripts/pkg-support/msvc/cmake/SDL3_imageConfigVersion.cmake.in @@ -0,0 +1,33 @@ +# @<@PROJECT_NAME@>@ CMake version configuration file: +# This file is meant to be placed in a cmake subfolder of @<@PROJECT_NAME@>@-devel-@<@PROJECT_VERSION@>@-VC.zip + +set(PACKAGE_VERSION "@<@PROJECT_VERSION@>@") + +if(PACKAGE_FIND_VERSION_RANGE) + # Package version must be in the requested version range + if ((PACKAGE_FIND_VERSION_RANGE_MIN STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_MIN) + OR ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_GREATER PACKAGE_FIND_VERSION_MAX) + OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND PACKAGE_VERSION VERSION_GREATER_EQUAL PACKAGE_FIND_VERSION_MAX))) + set(PACKAGE_VERSION_COMPATIBLE FALSE) + else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + endif() +else() + if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) + set(PACKAGE_VERSION_COMPATIBLE FALSE) + else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) + set(PACKAGE_VERSION_EXACT TRUE) + endif() + endif() +endif() + +include("${CMAKE_CURRENT_LIST_DIR}/sdlcpu.cmake") +SDL_DetectTargetCPUArchitectures(_detected_archs) + +# check that the installed version has a compatible architecture as the one which is currently searching: +if(NOT(SDL_CPU_X86 OR SDL_CPU_X64 OR SDL_CPU_ARM64 OR SDL_CPU_ARM64EC)) + set(PACKAGE_VERSION "${PACKAGE_VERSION} (X86,X64,ARM64)") + set(PACKAGE_VERSION_UNSUITABLE TRUE) +endif() diff --git a/build-scripts/release-info.json b/build-scripts/release-info.json new file mode 100644 index 00000000..01efd59b --- /dev/null +++ b/build-scripts/release-info.json @@ -0,0 +1,286 @@ +{ + "name": "SDL3_image", + "remote": "libsdl-org/SDL_image", + "dependencies": { + "SDL": { + "startswith": "3.", + "repo": "libsdl-org/SDL" + } + }, + "version": { + "file": "include/SDL3_image/SDL_image.h", + "re_major": "^#define SDL_IMAGE_MAJOR_VERSION\\s+([0-9]+)$", + "re_minor": "^#define SDL_IMAGE_MINOR_VERSION\\s+([0-9]+)$", + "re_micro": "^#define SDL_IMAGE_MICRO_VERSION\\s+([0-9]+)$" + }, + "source": { + "checks": [ + "src/IMG.c", + "include/SDL3_image/SDL_image.h", + "examples/showimage.c" + ] + }, + "dmg": { + "project": "Xcode/SDL_image.xcodeproj", + "path": "Xcode/build/SDL3_image.dmg", + "scheme": "SDL3_image.dmg", + "build-xcconfig": "Xcode/pkg-support/build.xcconfig", + "dependencies": { + "SDL": { + "artifact": "SDL3-*.dmg" + } + } + }, + "mingw": { + "cmake": { + "archs": ["x86", "x64"], + "args": [ + "-DSDLIMAGE_AVIF=OFF", + "-DSDLIMAGE_BMP=ON", + "-DSDLIMAGE_GIF=ON", + "-DSDLIMAGE_JPG=ON", + "-DSDLIMAGE_JXL=OFF", + "-DSDLIMAGE_LBM=ON", + "-DSDLIMAGE_PCX=ON", + "-DSDLIMAGE_PNG=ON", + "-DSDLIMAGE_PNM=ON", + "-DSDLIMAGE_QOI=ON", + "-DSDLIMAGE_SVG=ON", + "-DSDLIMAGE_TGA=ON", + "-DSDLIMAGE_TIF=OFF", + "-DSDLIMAGE_WEBP=OFF", + "-DSDLIMAGE_XCF=ON", + "-DSDLIMAGE_XPM=ON", + "-DSDLIMAGE_XV=ON", + "-DSDLIMAGE_SAMPLES=OFF", + "-DSDLIMAGE_TESTS=OFF", + "-DSDLIMAGE_VENDORED=OFF" + ], + "shared-static": "both" + }, + "files": { + "": [ + "CHANGES.txt", + "LICENSE.txt", + "README.txt", + "build-scripts/pkg-support/mingw/Makefile" + ], + "cmake": [ + "build-scripts/pkg-support/mingw/cmake/SDL3_imageConfig.cmake", + "build-scripts/pkg-support/mingw/cmake/SDL3_imageConfigVersion.cmake" + ] + }, + "dependencies": { + "SDL": { + "artifact": "SDL3-devel-*-mingw.tar.xz", + "install-command": "make install-@<@ARCH@>@ DESTDIR=@<@PREFIX@>@" + } + } + }, + "msvc": { + "msbuild": { + "archs": [ + "x86", + "x64" + ], + "projects": [ + "VisualC/SDL_image.vcxproj" + ], + "prebuilt": [ + "VisualC/external/optional/@<@ARCH@>@/*" + ], + "files-lib": { + "": [ + "VisualC/@<@PLATFORM@>@/@<@CONFIGURATION@>@/SDL3_image.dll" + ], + "optional": [ + "VisualC/external/optional/@<@ARCH@>@/libavif-16.dll", + "VisualC/external/optional/@<@ARCH@>@/libtiff-6.dll", + "VisualC/external/optional/@<@ARCH@>@/libwebp-7.dll", + "VisualC/external/optional/@<@ARCH@>@/libwebpdemux-2.dll", + "VisualC/external/optional/@<@ARCH@>@/LICENSE.avif.txt", + "VisualC/external/optional/@<@ARCH@>@/LICENSE.dav1d.txt", + "VisualC/external/optional/@<@ARCH@>@/LICENSE.tiff.txt", + "VisualC/external/optional/@<@ARCH@>@/LICENSE.webp.txt" + ] + }, + "files-devel": { + "lib/@<@ARCH@>@": [ + "VisualC/@<@PLATFORM@>@/@<@CONFIGURATION@>@/SDL3_image.dll", + "VisualC/@<@PLATFORM@>@/@<@CONFIGURATION@>@/SDL3_image.lib", + "VisualC/@<@PLATFORM@>@/@<@CONFIGURATION@>@/SDL3_image.pdb" + ], + "lib/@<@ARCH@>@/optional": [ + "VisualC/external/optional/@<@ARCH@>@/libavif-16.dll", + "VisualC/external/optional/@<@ARCH@>@/libtiff-6.dll", + "VisualC/external/optional/@<@ARCH@>@/libwebp-7.dll", + "VisualC/external/optional/@<@ARCH@>@/libwebpdemux-2.dll", + "VisualC/external/optional/@<@ARCH@>@/LICENSE.avif.txt", + "VisualC/external/optional/@<@ARCH@>@/LICENSE.dav1d.txt", + "VisualC/external/optional/@<@ARCH@>@/LICENSE.tiff.txt", + "VisualC/external/optional/@<@ARCH@>@/LICENSE.webp.txt" + ] + } + }, + "cmake": { + "archs": [ + "arm64" + ], + "args": [ + "-DBUILD_SHARED_LIBS=ON", + "-DSDLIMAGE_AVIF=ON", + "-DSDLIMAGE_BMP=ON", + "-DSDLIMAGE_GIF=ON", + "-DSDLIMAGE_JPG=ON", + "-DSDLIMAGE_JXL=OFF", + "-DSDLIMAGE_LBM=ON", + "-DSDLIMAGE_PCX=ON", + "-DSDLIMAGE_PNG=ON", + "-DSDLIMAGE_PNM=ON", + "-DSDLIMAGE_QOI=ON", + "-DSDLIMAGE_SVG=ON", + "-DSDLIMAGE_TGA=ON", + "-DSDLIMAGE_TIF=ON", + "-DSDLIMAGE_WEBP=ON", + "-DSDLIMAGE_XCF=ON", + "-DSDLIMAGE_XPM=ON", + "-DSDLIMAGE_XV=ON", + "-DSDLIMAGE_SAMPLES=OFF", + "-DSDLIMAGE_TESTS=OFF", + "-DSDLIMAGE_VENDORED=ON" + ], + "files-lib": { + "": [ + "bin/SDL3_image.dll" + ], + "optional": [ + "bin/libavif-16.dll", + "bin/dav1d.dll", + "bin/aom.dll", + "bin/tiff.dll", + "bin/libwebp.dll", + "bin/libwebpdemux.dll" + ] + }, + "files-devel": { + "lib/@<@ARCH@>@": [ + "bin/SDL3_image.dll", + "bin/SDL3_image.pdb", + "lib/SDL3_image.lib" + ], + "lib/@<@ARCH@>@/optional": [ + "bin/libavif-16.dll", + "bin/dav1d.dll", + "bin/aom.dll", + "bin/tiff.dll", + "bin/libwebp.dll", + "bin/libwebpdemux.dll" + ] + } + }, + "files-lib": { + "": [ + "README.txt" + ] + }, + "files-devel": { + "": [ + "CHANGES.txt", + "LICENSE.txt", + "README.txt" + ], + "cmake": [ + "build-scripts/pkg-support/msvc/cmake/SDL3_imageConfig.cmake.in:SDL3_imageConfig.cmake", + "build-scripts/pkg-support/msvc/cmake/SDL3_imageConfigVersion.cmake.in:SDL3_imageConfigVersion.cmake", + "cmake/sdlcpu.cmake" + ], + "include/SDL3_image": [ + "include/SDL3_image/SDL_image.h" + ] + }, + "dependencies": { + "SDL": { + "artifact": "SDL3-devel-*-VC.zip", + "copy": [ + { + "src": "lib/@<@ARCH@>@/SDL3.*", + "dst": "../SDL/VisualC/@<@PLATFORM@>@/@<@CONFIGURATION@>@" + }, + { + "src": "include/SDL3/*", + "dst": "../SDL/include/SDL3" + } + ] + } + } + }, + "android": { + "cmake": { + "args": [ + "-DBUILD_SHARED_LIBS=ON", + "-DSDLIMAGE_AVIF=OFF", + "-DSDLIMAGE_BMP=ON", + "-DSDLIMAGE_GIF=ON", + "-DSDLIMAGE_JPG=ON", + "-DSDLIMAGE_JXL=OFF", + "-DSDLIMAGE_LBM=ON", + "-DSDLIMAGE_PCX=ON", + "-DSDLIMAGE_PNG=ON", + "-DSDLIMAGE_PNM=ON", + "-DSDLIMAGE_QOI=ON", + "-DSDLIMAGE_SVG=ON", + "-DSDLIMAGE_TGA=ON", + "-DSDLIMAGE_TIF=OFF", + "-DSDLIMAGE_WEBP=OFF", + "-DSDLIMAGE_XCF=ON", + "-DSDLIMAGE_XPM=ON", + "-DSDLIMAGE_XV=ON", + "-DSDLIMAGE_SAMPLES=OFF", + "-DSDLIMAGE_TESTS=OFF", + "-DSDLIMAGE_VENDORED=ON" + ] + }, + "modules": { + "SDL3_image-shared": { + "type": "library", + "library": "lib/libSDL3_image.so", + "includes": { + "SDL3_image": ["include/SDL3_image/*.h"] + } + }, + "SDL3_image": { + "type": "interface", + "export-libraries": [":SDL3_image-shared"] + } + }, + "abis": [ + "armeabi-v7a", + "arm64-v8a", + "x86", + "x86_64" + ], + "api-minimum": 19, + "api-target": 29, + "ndk-minimum": 21, + "files": { + "": [ + "build-scripts/pkg-support/android/INSTALL.md.in:INSTALL.md", + "build-scripts/pkg-support/android/__main__.py.in:__main__.py", + "build-scripts/pkg-support/android/description.json.in:description.json" + ], + "META-INF": [ + "LICENSE.txt" + ], + "cmake": [ + "cmake/sdlcpu.cmake", + "build-scripts/pkg-support/android/cmake/SDL3_imageConfig.cmake", + "build-scripts/pkg-support/android/cmake/SDL3_imageConfigVersion.cmake.in:SDL3_imageConfigVersion.cmake" + ] + }, + "dependencies": { + "SDL": { + "artifact": "SDL3-*.aar" + } + } + } +} diff --git a/build-scripts/test-versioning.sh b/build-scripts/test-versioning.sh index bc0e1ba6..b9a4942d 100755 --- a/build-scripts/test-versioning.sh +++ b/build-scripts/test-versioning.sh @@ -138,13 +138,5 @@ else not_ok "project.pbxproj DYLIB_CURRENT_VERSION is inconsistent, expected $ref, got $dylib_cur" fi -sdl_req=$(sed -ne 's/\$sdl3_version = "\([0-9.]*\)"$/\1/p' .github/fetch_sdl_vc.ps1) - -if [ "$ref_sdl_req" = "$sdl_req" ]; then - ok ".github/fetch_sdl_vc.ps1 $sdl_req" -else - not_ok ".github/fetch_sdl_vc.ps1 sdl3_version=$sdl_req disagrees with CMakeLists.txt SDL_REQUIRED_VERSION=$ref_sdl_req" -fi - echo "1..$tests" exit "$failed" diff --git a/cmake/SDL3_imageConfig.cmake.in b/cmake/SDL3_imageConfig.cmake.in index a3862a4b..db72fd70 100644 --- a/cmake/SDL3_imageConfig.cmake.in +++ b/cmake/SDL3_imageConfig.cmake.in @@ -43,10 +43,13 @@ set(SDLIMAGE_BACKEND_WIC @SDLIMAGE_BACKEND_WIC@) set(SDLIMAGE_SDL3_REQUIRED_VERSION @SDL_REQUIRED_VERSION@) +set(SDL3_image_SDL3_image-shared_FOUND FALSE) if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL3_image-shared-targets.cmake") include("${CMAKE_CURRENT_LIST_DIR}/SDL3_image-shared-targets.cmake") + set(SDL3_image_SDL3_image-shared_FOUND TRUE) endif() +set(SDL3_image_SDL3_image-static_FOUND FALSE) if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL3_image-static-targets.cmake") if(SDLIMAGE_VENDORED) @@ -89,7 +92,7 @@ if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL3_image-static-targets.cmake") endif() endif() - if(SDLIMAGE_JPG AND NOT TARGET JPEG::JPEG AND NOT SDLIMAGE_JPG_SHARED) + if(SDLIMAGE_JPG AND NOT TARGET JPEG::JPEG AND NOT SDLIMAGE_JPG_SHARED AND NOT (SDLIMAGE_BACKEND_STB OR SDLIMAGE_BACKEND_WIC OR SDLIMAGE_BACKEND_IMAGEIO)) find_dependency(JPEG) endif() @@ -98,11 +101,11 @@ if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL3_image-static-targets.cmake") find_dependency(libjxl) endif() - if(SDLIMAGE_PNG AND NOT TARGET PNG::PNG AND NOT SDLIMAGE_PNG_SHARED) + if(SDLIMAGE_PNG AND NOT TARGET PNG::PNG AND NOT SDLIMAGE_PNG_SHARED AND NOT (SDLIMAGE_BACKEND_STB OR SDLIMAGE_BACKEND_WIC OR SDLIMAGE_BACKEND_IMAGEIO)) find_dependency(PNG) endif() - if(SDLIMAGE_TIF AND NOT TARGET TIFF::TIFF) + if(SDLIMAGE_TIF AND NOT TARGET TIFF::TIFF AND NOT (SDLIMAGE_BACKEND_IMAGEIO OR SDLIMAGE_BACKEND_WIC)) find_dependency(TIFF) endif() @@ -117,6 +120,7 @@ if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL3_image-static-targets.cmake") endif() include("${CMAKE_CURRENT_LIST_DIR}/SDL3_image-static-targets.cmake") + set(SDL3_image_SDL3_image-static_FOUND TRUE) endif() function(_sdl_create_target_alias_compat NEW_TARGET TARGET) @@ -133,7 +137,10 @@ endfunction() if(NOT TARGET SDL3_image::SDL3_image) if(TARGET SDL3_image::SDL3_image-shared) _sdl_create_target_alias_compat(SDL3_image::SDL3_image SDL3_image::SDL3_image-shared) - else() + elseif(TARGET SDL3_image::SDL3_image-static) _sdl_create_target_alias_compat(SDL3_image::SDL3_image SDL3_image::SDL3_image-static) endif() endif() + +@PACKAGE_INIT@ +check_required_components(SDL3_image) diff --git a/cmake/sdlcpu.cmake b/cmake/sdlcpu.cmake new file mode 100644 index 00000000..d63a57f9 --- /dev/null +++ b/cmake/sdlcpu.cmake @@ -0,0 +1,156 @@ +function(SDL_DetectTargetCPUArchitectures DETECTED_ARCHS) + + set(known_archs EMSCRIPTEN ARM32 ARM64 ARM64EC LOONGARCH64 POWERPC32 POWERPC64 X86 X64) + + if(APPLE AND CMAKE_OSX_ARCHITECTURES) + foreach(known_arch IN LISTS known_archs) + set(SDL_CPU_${known_arch} "0") + endforeach() + set(detected_archs) + foreach(osx_arch IN LISTS CMAKE_OSX_ARCHITECTURES) + if(osx_arch STREQUAL "x86_64") + set(SDL_CPU_X64 "1") + list(APPEND detected_archs "X64") + elseif(osx_arch STREQUAL "arm64") + set(SDL_CPU_ARM64 "1") + list(APPEND detected_archs "ARM64") + endif() + endforeach() + set("${DETECTED_ARCHS}" "${detected_archs}" PARENT_SCOPE) + return() + endif() + + set(detected_archs) + foreach(known_arch IN LISTS known_archs) + if(SDL_CPU_${known_arch}) + list(APPEND detected_archs "${known_arch}") + endif() + endforeach() + + if(detected_archs) + set("${DETECTED_ARCHS}" "${detected_archs}" PARENT_SCOPE) + return() + endif() + + set(arch_check_ARM32 "defined(__arm__) || defined(_M_ARM)") + set(arch_check_ARM64 "defined(__aarch64__) || defined(_M_ARM64)") + set(arch_check_ARM64EC "defined(_M_ARM64EC)") + set(arch_check_EMSCRIPTEN "defined(__EMSCRIPTEN__)") + set(arch_check_LOONGARCH64 "defined(__loongarch64)") + set(arch_check_POWERPC32 "(defined(__PPC__) || defined(__powerpc__)) && !defined(__powerpc64__)") + set(arch_check_POWERPC64 "defined(__PPC64__) || defined(__powerpc64__)") + set(arch_check_X86 "defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) ||defined( __i386) || defined(_M_IX86)") + set(arch_check_X64 "(defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)) && !defined(_M_ARM64EC)") + + set(src_vars "") + set(src_main "") + foreach(known_arch IN LISTS known_archs) + set(detected_${known_arch} "0") + + string(APPEND src_vars " +#if ${arch_check_${known_arch}} +#define ARCH_${known_arch} \"1\" +#else +#define ARCH_${known_arch} \"0\" +#endif +const char *arch_${known_arch} = \"INFO<${known_arch}=\" ARCH_${known_arch} \">\"; +") + string(APPEND src_main " + result += arch_${known_arch}[argc];") + endforeach() + + set(src_arch_detect "${src_vars} +int main(int argc, char *argv[]) { + (void)argv; + int result = 0; +${src_main} + return result; +}") + + if(CMAKE_C_COMPILER) + set(ext ".c") + elseif(CMAKE_CXX_COMPILER) + set(ext ".cpp") + else() + enable_language(C) + set(ext ".c") + endif() + set(path_src_arch_detect "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeTmp/SDL_detect_arch${ext}") + file(WRITE "${path_src_arch_detect}" "${src_arch_detect}") + set(path_dir_arch_detect "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeTmp/SDL_detect_arch") + set(path_bin_arch_detect "${path_dir_arch_detect}/bin") + + set(detected_archs) + + set(msg "Detecting Target CPU Architecture") + message(STATUS "${msg}") + + include(CMakePushCheckState) + + set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") + + cmake_push_check_state(RESET) + try_compile(SDL_CPU_CHECK_ALL + "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeTmp/SDL_detect_arch" + SOURCES "${path_src_arch_detect}" + COPY_FILE "${path_bin_arch_detect}" + ) + cmake_pop_check_state() + if(NOT SDL_CPU_CHECK_ALL) + message(STATUS "${msg} - ") + message(WARNING "Failed to compile source detecting the target CPU architecture") + else() + set(re "INFO<([A-Z0-9]+)=([01])>") + file(STRINGS "${path_bin_arch_detect}" infos REGEX "${re}") + + foreach(info_arch_01 IN LISTS infos) + string(REGEX MATCH "${re}" A "${info_arch_01}") + if(NOT "${CMAKE_MATCH_1}" IN_LIST known_archs) + message(WARNING "Unknown architecture: \"${CMAKE_MATCH_1}\"") + continue() + endif() + set(arch "${CMAKE_MATCH_1}") + set(arch_01 "${CMAKE_MATCH_2}") + set(detected_${arch} "${arch_01}") + endforeach() + + foreach(known_arch IN LISTS known_archs) + if(detected_${known_arch}) + list(APPEND detected_archs ${known_arch}) + endif() + endforeach() + endif() + + if(detected_archs) + foreach(known_arch IN LISTS known_archs) + set("SDL_CPU_${known_arch}" "${detected_${known_arch}}" CACHE BOOL "Detected architecture ${known_arch}") + endforeach() + message(STATUS "${msg} - ${detected_archs}") + else() + include(CheckCSourceCompiles) + cmake_push_check_state(RESET) + foreach(known_arch IN LISTS known_archs) + if(NOT detected_archs) + set(cache_variable "SDL_CPU_${known_arch}") + set(test_src " + int main(int argc, char *argv[]) { + #if ${arch_check_${known_arch}} + return 0; + #else + choke + #endif + } + ") + check_c_source_compiles("${test_src}" "${cache_variable}") + if(${cache_variable}) + set(SDL_CPU_${known_arch} "1" CACHE BOOL "Detected architecture ${known_arch}") + set(detected_archs ${known_arch}) + else() + set(SDL_CPU_${known_arch} "0" CACHE BOOL "Detected architecture ${known_arch}") + endif() + endif() + endforeach() + cmake_pop_check_state() + endif() + set("${DETECTED_ARCHS}" "${detected_archs}" PARENT_SCOPE) +endfunction() diff --git a/cmake/test/CMakeLists.txt b/cmake/test/CMakeLists.txt index a9dae6bf..61cad84c 100644 --- a/cmake/test/CMakeLists.txt +++ b/cmake/test/CMakeLists.txt @@ -16,6 +16,15 @@ add_feature_info("TEST_SHARED" TEST_SHARED "Test linking with shared library") option(TEST_STATIC "Test linking to static SDL3_image library" ON) add_feature_info("TEST_STATIC" TEST_STATIC "Test linking with static library") +if(ANDROID) + macro(add_executable NAME) + set(args ${ARGN}) + list(REMOVE_ITEM args WIN32) + add_library(${NAME} SHARED ${args}) + unset(args) + endmacro() +endif() + if(TEST_SHARED) find_package(SDL3 REQUIRED CONFIG COMPONENTS SDL3) find_package(SDL3_image REQUIRED CONFIG) diff --git a/external/dav1d b/external/dav1d index 58e3a991..aabfea0c 160000 --- a/external/dav1d +++ b/external/dav1d @@ -1 +1 @@ -Subproject commit 58e3a991928088a51020118149b2c8550fa0021d +Subproject commit aabfea0c42f9df86268fe1c578e8c9b50d28fcc9 diff --git a/external/download.sh b/external/download.sh index df63ee46..b78a4a50 100755 --- a/external/download.sh +++ b/external/download.sh @@ -2,6 +2,8 @@ set -e +ARGUMENTS="$*" + cd $(dirname "$0")/.. cat .gitmodules | \ while true; do @@ -12,5 +14,5 @@ while true; do url=$3 read line; set -- $line branch=$3 - git clone --filter=blob:none $url $path -b $branch --recursive + git clone --filter=blob:none $url $path -b $branch --recursive $ARGUMENTS done