diff --git a/.github/actions/build-windows/action.yml b/.github/actions/build-windows/action.yml index 88c46534..39b6a7be 100644 --- a/.github/actions/build-windows/action.yml +++ b/.github/actions/build-windows/action.yml @@ -34,7 +34,7 @@ inputs: default: 'd3dcompiler_47 opengl32sw qt3d qtactiveqt qtbase qtconnectivity qtdeclarative qtgraphicaleffects qtimageformats qtlocation qtmultimedia qtquickcontrols qtquickcontrols2 qtremoteobjects qtscxml qtsensors qtsvg qttools qttranslations qtwebchannel qtwebsockets qtwebview qtwinextras qtxmlpatterns' windows_qt6_modules: required: false - default: 'debug_info qt3d qt5compat qtactiveqt qtcharts qtconnectivity qtdatavis3d qtgrpc qthttpserver qtimageformats qtlanguageserver qtlocation qtlottie qtmultimedia qtnetworkauth qtpdf qtpositioning qtquick3d qtquick3dphysics qtquickeffectmaker qtquicktimeline qtremoteobjects qtscxml qtsensors qtserialbus qtserialport qtshadertools qtspeech qtvirtualkeyboard qtwebchannel qtwebengine qtwebsockets qtwebview' + default: 'qtimageformats qtmultimedia qtpdf qtpositioning qtshadertools qtwebchannel qtwebengine' windows_qt6_archives: required: false default: 'd3dcompiler_47 opengl32sw qtbase qtdeclarative qtsvg qttools qttranslations' @@ -42,6 +42,12 @@ inputs: runs: using: "composite" steps: + - name: Disable Windows Defender Realtime Monitoring for Build Trees + shell: powershell + run: | + Set-MpPreference -DisableRealtimeMonitoring $true -ErrorAction SilentlyContinue + Add-MpPreference -ExclusionPath "${{ github.workspace }}", "C:\.sccache", "C:\Program Files\OpenUTVDeps", "C:\VulkanSDK" -ErrorAction SilentlyContinue + - name: Download and Install Prebuilt Dependencies shell: powershell env: @@ -191,7 +197,7 @@ runs: shell: powershell - name: Cache CMake for Windows - uses: actions/cache@v5 + uses: actions/cache@v6 id: windows-cmake-cache with: path: "C:/Program Files/CMake" @@ -202,10 +208,20 @@ runs: run: choco install cmake --version=${{ inputs.cmake-version }} --allow-downgrade --yes --no-progress shell: powershell - - name: Install build tools (Ninja, JOM, flex, bison, nasm, patch, pkg-config, Vulkan) + - name: Cache Vulkan SDK for Windows + uses: actions/cache@v6 + id: windows-vulkan-cache + with: + path: "C:/VulkanSDK" + key: ${{ runner.os }}-vulkan-sdk-1.4.350 + + - name: Install build tools (Ninja, flex, bison, nasm, patch, pkg-config, Vulkan) run: | choco feature enable -n allowEmptyChecksums - choco install ninja jom winflexbison3 nasm patch pkgconfiglite vulkan-sdk --yes --no-progress --allow-empty-checksums --ignore-checksums + choco install ninja winflexbison3 nasm patch pkgconfiglite --yes --no-progress --allow-empty-checksums --ignore-checksums + if ("${{ steps.windows-vulkan-cache.outputs.cache-hit }}" -ne "true") { + choco install vulkan-sdk --yes --no-progress --allow-empty-checksums --ignore-checksums + } "C:\ProgramData\chocolatey\bin" | Add-Content -Path $env:GITHUB_PATH $VulkanDir = Get-ChildItem -Path "C:\VulkanSDK" -ErrorAction SilentlyContinue | Sort-Object Name -Descending | Select-Object -First 1 if ($VulkanDir) { @@ -232,13 +248,12 @@ runs: shell: bash - name: Prepare Qt folder and 7-Zip + shell: powershell run: | - mkdir -p /c/qt - if [ -d "/c/Program Files/7-Zip" ]; then - echo "/c/Program Files/7-Zip" >> $GITHUB_PATH - echo "C:\Program Files\7-Zip" >> $GITHUB_PATH - fi - shell: bash + New-Item -ItemType Directory -Force -Path "C:\Qt" | Out-Null + if (Test-Path "C:\Program Files\7-Zip") { + "C:\Program Files\7-Zip" | Add-Content -Path $env:GITHUB_PATH + } - name: Install Qt ${{ inputs.qt-version }} uses: jurplel/install-qt-action@v4 @@ -294,22 +309,27 @@ runs: shell: powershell - name: Setup sccache - # Used for this run only (SCCACHE_GHA_ENABLED=false); not stored in Actions cache. - # For sccache to actually cache the Windows/MSVC build, CMake must use it as the compiler - # launcher, e.g. -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache - # in the Configure UTV step (and sccache must be on PATH when the build runs). - uses: mozilla-actions/sccache-action@v0.0.10 + uses: mozilla-actions/sccache-action@v0.0.11 with: version: "v0.15.0" - - name: Configure sccache for bash and powershell + - name: Configure sccache directory and cache run: | - # sccache is installed to cargo bin if (Test-Path "C:\Users\runneradmin\.cargo\bin") { "C:\Users\runneradmin\.cargo\bin" | Add-Content -Path $env:GITHUB_PATH } + "SCCACHE_DIR=C:\.sccache" | Add-Content -Path $env:GITHUB_ENV + "SCCACHE_CACHE_SIZE=5G" | Add-Content -Path $env:GITHUB_ENV shell: powershell + - name: Restore Sccache + uses: actions/cache/restore@v6 + with: + path: "C:/.sccache" + key: ${{ runner.os }}-sccache-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-sccache- + - name: Configure UTV run: | $PrefixPaths = "C:/Qt/${{ inputs.qt-version }}/msvc2022_64" @@ -447,6 +467,34 @@ runs: } shell: powershell + - name: Windows Defender Supply Chain Security Scan + shell: powershell + run: | + $installDir = Join-Path $env:GITHUB_WORKSPACE "_install" + if (Test-Path $installDir) { + Write-Host "Unexcluding staged application from Defender for security verification..." + Remove-MpPreference -ExclusionPath "${{ github.workspace }}" -ErrorAction SilentlyContinue + + $mpCmd = "C:\Program Files\Windows Defender\MpCmdRun.exe" + if (Test-Path $mpCmd) { + Write-Host "Scanning staged application with Windows Defender: $installDir" + & $mpCmd -Scan -ScanType 3 -File "$installDir" + if ($LASTEXITCODE -eq 2) { + Write-Error "Windows Defender detected malware or malicious threat in staged application!" + exit 1 + } elseif ($LASTEXITCODE -eq 0) { + Write-Host "Windows Defender scan clean. 0 threats detected." + } else { + Write-Warning "Windows Defender scan completed with exit code: $LASTEXITCODE" + } + } else { + Write-Host "Running PowerShell Start-MpScan on $installDir..." + Start-MpScan -ScanType CustomScan -ScanPath "$installDir" + } + } else { + Write-Warning "Directory _install not found for Defender scan." + } + - name: Sccache Statistics if: always() run: | @@ -455,3 +503,11 @@ runs: } shell: powershell + - name: Save Sccache + if: always() + uses: actions/cache/save@v6 + with: + path: "C:/.sccache" + key: ${{ runner.os }}-sccache-${{ github.sha }} + + diff --git a/.github/workflows/branch-build.yml b/.github/workflows/branch-build.yml index ddd53b1f..ff34993d 100644 --- a/.github/workflows/branch-build.yml +++ b/.github/workflows/branch-build.yml @@ -15,6 +15,7 @@ on: permissions: contents: read + actions: write env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" @@ -30,10 +31,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Setup Python - uses: actions/setup-python@v6 + uses: actions/setup-python@v7 with: python-version: '3.14' @@ -49,14 +50,14 @@ jobs: runs-on: macos-26 steps: - name: Check out repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: submodules: recursive fetch-depth: 0 - name: Check out proprietary vendor SDKs continue-on-error: true - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: repository: OpenUTV/openutv-vendor-sdks token: ${{ secrets.GH_TOKEN_DEPS_READ }} @@ -68,7 +69,7 @@ jobs: shell: bash - name: Restore Homebrew cache - uses: actions/cache/restore@v5 + uses: actions/cache/restore@v6 with: path: | ~/Library/Caches/Homebrew/downloads @@ -79,15 +80,19 @@ jobs: ${{ runner.os }}-brew- - name: Install Homebrew dependencies + env: + HOMEBREW_NO_AUTO_UPDATE: "0" run: | + brew update brew install --formula \ ninja readline sqlite3 xz zlib tcl-tk@8 python-tk autoconf automake libtool python@3.14 yasm clang-format black meson nasm pkg-config glew ccache doctest qt pyside \ ffmpeg openexr imath opencolorio libraw libtiff libpng libspng boost openimageio openjpeg webp yaml-cpp spdlog icu4c openjph jpeg-turbo + brew upgrade openexr imath opencolorio libraw libtiff boost openimageio spdlog openjph || true shell: bash - name: Save Homebrew cache if: always() - uses: actions/cache/save@v5 + uses: actions/cache/save@v6 with: path: | ~/Library/Caches/Homebrew/downloads @@ -95,7 +100,7 @@ jobs: key: ${{ runner.os }}-brew-${{ steps.date.outputs.date }}-${{ hashFiles('**/build.sh') }} - name: Restore CCache - uses: actions/cache/restore@v5 + uses: actions/cache/restore@v6 with: path: ~/.ccache key: ${{ runner.os }}-ccache-${{ github.sha }} @@ -112,27 +117,22 @@ jobs: - name: Save CCache if: always() - uses: actions/cache/save@v5 + uses: actions/cache/save@v6 with: path: ~/.ccache key: ${{ runner.os }}-ccache-${{ github.sha }} - - name: Package Ad-Hoc Signed App + - name: Sign Ad-Hoc App run: | python3 "${PWD}/src/build/sanitize_homebrew_links.py" "_build/stage/app/UTV.app" || true codesign --force --deep --sign - "_build/stage/app/UTV.app" - mkdir -p _dist - SHORT_SHA=$(git rev-parse --short=7 HEAD) - SAFE_BRANCH=$(echo "${{ github.ref_name }}" | tr '/' '-') - cd _build/stage/app - ditto -c -k --keepParent UTV.app "${GITHUB_WORKSPACE}/_dist/UTV-${SAFE_BRANCH}-${SHORT_SHA}-macOS-arm64.zip" shell: bash - name: Upload macOS Branch Artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: UTV-macOS-arm64 - path: _dist/*.zip + path: _build/stage/app/UTV.app retention-days: 5 build-windows: @@ -144,14 +144,14 @@ jobs: SCCACHE_GHA_ENABLED: "true" steps: - name: Check out repository code - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: submodules: recursive fetch-depth: 0 - name: Check out proprietary vendor SDKs continue-on-error: true - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: repository: OpenUTV/openutv-vendor-sdks token: ${{ secrets.GH_TOKEN_DEPS_READ }} @@ -162,21 +162,16 @@ jobs: with: version: 'dev' - - name: Package Windows Branch Archive + - name: Stage Windows Branch Directory shell: powershell run: | - $ShortSha = git rev-parse --short=7 HEAD - $SafeBranch = "${{ github.ref_name }}".Replace("/", "-") - $ZipName = "UTV-$SafeBranch-$ShortSha-windows-x64.zip" - New-Item -ItemType Directory -Force -Path "_dist" | Out-Null Rename-Item -Path "_install" -NewName "utv-windows-x64" - Compress-Archive -Path "utv-windows-x64" -DestinationPath "_dist\$ZipName" -CompressionLevel Optimal - name: Upload Windows Branch Artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: UTV-windows-x64 - path: _dist/*.zip + path: utv-windows-x64 retention-days: 5 build-linux: @@ -187,14 +182,14 @@ jobs: continue-on-error: true steps: - name: Check out repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: submodules: recursive fetch-depth: 0 - name: Check out proprietary vendor SDKs continue-on-error: true - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: repository: OpenUTV/openutv-vendor-sdks token: ${{ secrets.GH_TOKEN_DEPS_READ }} @@ -206,7 +201,7 @@ jobs: shell: bash - name: Restore Homebrew cache - uses: actions/cache/restore@v5 + uses: actions/cache/restore@v6 with: path: | ~/.cache/Homebrew/downloads @@ -216,25 +211,29 @@ jobs: ${{ runner.os }}-brew- - name: Install Homebrew dependencies + env: + HOMEBREW_NO_AUTO_UPDATE: "0" run: | eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" sudo apt-get update && sudo apt-get install -y build-essential patchelf mold tcsh libgl1-mesa-dev libglu1-mesa-dev libegl1-mesa-dev libosmesa6-dev libudev-dev libaio-dev libreadline-dev libx11-dev libxcursor-dev libxext-dev libxi-dev libxinerama-dev libxrandr-dev libxrender-dev libxcomposite-dev libxdamage-dev libxtst-dev libxxf86vm-dev libxkbcommon-dev libxkbcommon-x11-dev libffi-dev libasound2-dev libpulse-dev + brew update brew install --formula \ ninja pkg-config ccache glew doctest qt pyside \ ffmpeg openexr imath opencolorio libraw libtiff libpng libspng boost \ openimageio openjpeg webp yaml-cpp spdlog openjph jpeg-turbo + brew upgrade openexr imath opencolorio libraw libtiff boost openimageio spdlog openjph || true shell: bash - name: Save Homebrew cache if: always() - uses: actions/cache/save@v5 + uses: actions/cache/save@v6 with: path: | ~/.cache/Homebrew/downloads key: ${{ runner.os }}-brew-${{ steps.date.outputs.date }}-${{ hashFiles('**/build.sh') }} - name: Restore CCache - uses: actions/cache/restore@v5 + uses: actions/cache/restore@v6 with: path: ~/.ccache key: ${{ runner.os }}-ccache-${{ github.sha }} @@ -251,27 +250,16 @@ jobs: - name: Save CCache if: always() - uses: actions/cache/save@v5 + uses: actions/cache/save@v6 with: path: ~/.ccache key: ${{ runner.os }}-ccache-${{ github.sha }} - - name: Package Linux Branch Archive - if: success() - run: | - mkdir -p _dist - SHORT_SHA=$(git rev-parse --short=7 HEAD) - SAFE_BRANCH=$(echo "${{ github.ref_name }}" | tr '/' '-') - if [ -d "_build/stage/app" ]; then - tar -czf "_dist/UTV-${SAFE_BRANCH}-${SHORT_SHA}-linux-x64.tar.gz" -C _build/stage/app . - fi - shell: bash - - name: Upload Linux Branch Artifact if: success() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: UTV-linux-x64 - path: _dist/*.tar.gz + path: _build/stage/app retention-days: 5 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 807c9723..0f656eda 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -15,12 +15,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@v4 with: languages: python - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@v4 diff --git a/.github/workflows/dev-build.yml b/.github/workflows/dev-build.yml index 3b63c1f6..4e511189 100644 --- a/.github/workflows/dev-build.yml +++ b/.github/workflows/dev-build.yml @@ -14,6 +14,7 @@ on: permissions: contents: write + actions: write env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" @@ -29,10 +30,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Setup Python - uses: actions/setup-python@v6 + uses: actions/setup-python@v7 with: python-version: '3.14' @@ -52,7 +53,7 @@ jobs: short_sha: ${{ steps.ver.outputs.short_sha }} steps: - name: Check out repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: fetch-depth: 0 @@ -74,14 +75,14 @@ jobs: runs-on: macos-26 steps: - name: Check out repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: submodules: recursive fetch-depth: 0 - name: Check out proprietary vendor SDKs continue-on-error: true - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: repository: OpenUTV/openutv-vendor-sdks token: ${{ secrets.GH_TOKEN_DEPS_READ }} @@ -93,7 +94,7 @@ jobs: shell: bash - name: Restore Homebrew cache - uses: actions/cache/restore@v5 + uses: actions/cache/restore@v6 with: path: | ~/Library/Caches/Homebrew/downloads @@ -104,15 +105,19 @@ jobs: ${{ runner.os }}-brew- - name: Install Homebrew dependencies + env: + HOMEBREW_NO_AUTO_UPDATE: "0" run: | + brew update brew install --formula \ ninja readline sqlite3 xz zlib tcl-tk@8 python-tk autoconf automake libtool python@3.14 yasm clang-format black meson nasm pkg-config glew ccache doctest qt pyside \ ffmpeg openexr imath opencolorio libraw libtiff libpng libspng boost openimageio openjpeg webp yaml-cpp spdlog icu4c openjph jpeg-turbo + brew upgrade openexr imath opencolorio libraw libtiff boost openimageio spdlog openjph || true shell: bash - name: Save Homebrew cache if: always() - uses: actions/cache/save@v5 + uses: actions/cache/save@v6 with: path: | ~/Library/Caches/Homebrew/downloads @@ -120,7 +125,7 @@ jobs: key: ${{ runner.os }}-brew-${{ steps.date.outputs.date }}-${{ hashFiles('**/build.sh') }} - name: Restore CCache - uses: actions/cache/restore@v5 + uses: actions/cache/restore@v6 with: path: ~/.ccache key: ${{ runner.os }}-ccache-${{ github.sha }} @@ -137,7 +142,7 @@ jobs: - name: Save CCache if: always() - uses: actions/cache/save@v5 + uses: actions/cache/save@v6 with: path: ~/.ccache key: ${{ runner.os }}-ccache-${{ github.sha }} @@ -151,7 +156,7 @@ jobs: shell: bash - name: Upload Unsigned App Artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: utv-dev-unsigned-${{ needs.version.outputs.short_sha }} path: _build/stage/unsigned/UTV.app.tar.gz @@ -163,10 +168,10 @@ jobs: runs-on: macos-26 steps: - name: Check out repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Download Unsigned App Artifact - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: utv-dev-unsigned-${{ needs.version.outputs.short_sha }} path: _build/stage/unsigned @@ -256,7 +261,7 @@ jobs: shell: bash - name: Upload Signed macOS Dev Artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: UTV-dev-macOS-arm64 path: _build/stage/app/UTV-dev-macOS-arm64.zip @@ -281,14 +286,14 @@ jobs: SCCACHE_GHA_ENABLED: "true" steps: - name: Check out repository code - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: submodules: recursive fetch-depth: 0 - name: Check out proprietary vendor SDKs continue-on-error: true - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: repository: OpenUTV/openutv-vendor-sdks token: ${{ secrets.GH_TOKEN_DEPS_READ }} @@ -309,7 +314,7 @@ jobs: Compress-Archive -Path "utv-windows-x64" -DestinationPath "_dist\$ZipName" -CompressionLevel Optimal - name: Upload Windows Dev Artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: UTV-dev-windows-x64 path: _dist/UTV-dev-windows-x64.zip @@ -322,14 +327,14 @@ jobs: continue-on-error: true steps: - name: Check out repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: submodules: recursive fetch-depth: 0 - name: Check out proprietary vendor SDKs continue-on-error: true - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: repository: OpenUTV/openutv-vendor-sdks token: ${{ secrets.GH_TOKEN_DEPS_READ }} @@ -341,7 +346,7 @@ jobs: shell: bash - name: Restore Homebrew cache - uses: actions/cache/restore@v5 + uses: actions/cache/restore@v6 with: path: | ~/.cache/Homebrew/downloads @@ -351,25 +356,29 @@ jobs: ${{ runner.os }}-brew- - name: Install Homebrew dependencies + env: + HOMEBREW_NO_AUTO_UPDATE: "0" run: | eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" sudo apt-get update && sudo apt-get install -y build-essential patchelf mold tcsh libgl1-mesa-dev libglu1-mesa-dev libegl1-mesa-dev libosmesa6-dev libudev-dev libaio-dev libreadline-dev libx11-dev libxcursor-dev libxext-dev libxi-dev libxinerama-dev libxrandr-dev libxrender-dev libxcomposite-dev libxdamage-dev libxtst-dev libxxf86vm-dev libxkbcommon-dev libxkbcommon-x11-dev libffi-dev libasound2-dev libpulse-dev + brew update brew install --formula \ ninja pkg-config ccache glew doctest qt pyside \ ffmpeg openexr imath opencolorio libraw libtiff libpng libspng boost \ openimageio openjpeg webp yaml-cpp spdlog openjph jpeg-turbo + brew upgrade openexr imath opencolorio libraw libtiff boost openimageio spdlog openjph || true shell: bash - name: Save Homebrew cache if: always() - uses: actions/cache/save@v5 + uses: actions/cache/save@v6 with: path: | ~/.cache/Homebrew/downloads key: ${{ runner.os }}-brew-${{ steps.date.outputs.date }}-${{ hashFiles('**/build.sh') }} - name: Restore CCache - uses: actions/cache/restore@v5 + uses: actions/cache/restore@v6 with: path: ~/.ccache key: ${{ runner.os }}-ccache-${{ github.sha }} @@ -386,7 +395,7 @@ jobs: - name: Save CCache if: always() - uses: actions/cache/save@v5 + uses: actions/cache/save@v6 with: path: ~/.ccache key: ${{ runner.os }}-ccache-${{ github.sha }} @@ -402,7 +411,7 @@ jobs: - name: Upload Linux Dev Artifact if: success() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: UTV-dev-linux-x64 path: _dist/UTV-dev-linux-x64.tar.gz @@ -421,7 +430,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: fetch-depth: 0 @@ -430,21 +439,21 @@ jobs: - name: Download macOS Dev Artifact continue-on-error: true - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: UTV-dev-macOS-arm64 path: _dist - name: Download Windows Dev Artifact continue-on-error: true - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: UTV-dev-windows-x64 path: _dist - name: Download Linux Dev Artifact continue-on-error: true - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: UTV-dev-linux-x64 path: _dist diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index ac30f120..c82f96ab 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -42,12 +42,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: fetch-depth: 0 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v7 with: node-version: 20 @@ -63,10 +63,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Setup Python - uses: actions/setup-python@v6 + uses: actions/setup-python@v7 with: python-version: '3.14' @@ -84,7 +84,7 @@ jobs: continue-on-error: true steps: - name: Check out repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: submodules: recursive fetch-depth: 0 diff --git a/.github/workflows/publish-packages.yml b/.github/workflows/publish-packages.yml index 9c62cfcb..67040472 100644 --- a/.github/workflows/publish-packages.yml +++ b/.github/workflows/publish-packages.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Download Release Assets env: @@ -152,7 +152,7 @@ jobs: runs-on: windows-latest steps: - name: Check out repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Pack and Push to Chocolatey Community Repository shell: powershell diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ed1f4f43..2914e5fd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,6 +27,7 @@ on: permissions: contents: write pull-requests: read + actions: write env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" @@ -41,10 +42,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Setup Python - uses: actions/setup-python@v6 + uses: actions/setup-python@v7 with: python-version: '3.14' @@ -63,7 +64,7 @@ jobs: clean_version: ${{ steps.versioning.outputs.clean_version }} steps: - name: Check out repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: fetch-depth: 0 @@ -99,14 +100,14 @@ jobs: runs-on: macos-26 steps: - name: Check out repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: submodules: recursive fetch-depth: 0 - name: Check out proprietary vendor SDKs continue-on-error: true - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: repository: OpenUTV/openutv-vendor-sdks token: ${{ secrets.GH_TOKEN_DEPS_READ }} @@ -118,7 +119,7 @@ jobs: shell: bash - name: Restore Homebrew cache - uses: actions/cache/restore@v5 + uses: actions/cache/restore@v6 with: path: | ~/Library/Caches/Homebrew/downloads @@ -129,15 +130,19 @@ jobs: ${{ runner.os }}-brew- - name: Install Homebrew dependencies + env: + HOMEBREW_NO_AUTO_UPDATE: "0" run: | + brew update brew install --formula \ ninja readline sqlite3 xz zlib tcl-tk@8 python-tk autoconf automake libtool python@3.14 yasm clang-format black meson nasm pkg-config glew ccache doctest qt pyside \ ffmpeg openexr imath opencolorio libraw libtiff libpng libspng boost openimageio openjpeg webp yaml-cpp spdlog icu4c openjph jpeg-turbo + brew upgrade openexr imath opencolorio libraw libtiff boost openimageio spdlog openjph || true shell: bash - name: Save Homebrew cache if: always() - uses: actions/cache/save@v5 + uses: actions/cache/save@v6 with: path: | ~/Library/Caches/Homebrew/downloads @@ -145,7 +150,7 @@ jobs: key: ${{ runner.os }}-brew-${{ steps.date.outputs.date }}-${{ hashFiles('**/build.sh') }} - name: Restore CCache - uses: actions/cache/restore@v5 + uses: actions/cache/restore@v6 with: path: ~/.ccache key: ${{ runner.os }}-ccache-${{ github.sha }} @@ -162,7 +167,7 @@ jobs: - name: Save CCache if: always() - uses: actions/cache/save@v5 + uses: actions/cache/save@v6 with: path: ~/.ccache key: ${{ runner.os }}-ccache-${{ github.sha }} @@ -176,7 +181,7 @@ jobs: shell: bash - name: Upload Unsigned App Artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: utv-app-unsigned-${{ needs.version.outputs.version }} path: _build/stage/unsigned/UTV.app.tar.gz @@ -189,10 +194,10 @@ jobs: runs-on: macos-26 steps: - name: Check out repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Download Unsigned App Artifact - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: utv-app-unsigned-${{ needs.version.outputs.version }} path: _build/stage/unsigned @@ -355,7 +360,7 @@ jobs: shell: bash - name: Upload Signed Artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: UTV-${{ needs.version.outputs.version }}-macOS-arm64 path: _build/stage/app/UTV-${{ needs.version.outputs.version }}-macOS-arm64.zip @@ -381,14 +386,14 @@ jobs: SCCACHE_GHA_ENABLED: "true" steps: - name: Check out repository code - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: submodules: recursive fetch-depth: 0 - name: Check out proprietary vendor SDKs continue-on-error: true - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: repository: OpenUTV/openutv-vendor-sdks token: ${{ secrets.GH_TOKEN_DEPS_READ }} @@ -411,7 +416,7 @@ jobs: Write-Host "Created _dist\$ZipName successfully." - name: Upload Windows Artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: UTV-${{ needs.version.outputs.version }}-windows-x64 path: _dist/UTV-${{ needs.version.outputs.version }}-windows-x64.zip @@ -424,7 +429,7 @@ jobs: runs-on: windows-2022 steps: - name: Download Windows Artifact - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: UTV-${{ needs.version.outputs.version }}-windows-x64 path: _dist @@ -445,14 +450,14 @@ jobs: continue-on-error: true steps: - name: Check out repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: submodules: recursive fetch-depth: 0 - name: Check out proprietary vendor SDKs continue-on-error: true - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: repository: OpenUTV/openutv-vendor-sdks token: ${{ secrets.GH_TOKEN_DEPS_READ }} @@ -464,7 +469,7 @@ jobs: shell: bash - name: Restore Homebrew cache - uses: actions/cache/restore@v5 + uses: actions/cache/restore@v6 with: path: | ~/.cache/Homebrew/downloads @@ -474,25 +479,29 @@ jobs: ${{ runner.os }}-brew- - name: Install Homebrew dependencies + env: + HOMEBREW_NO_AUTO_UPDATE: "0" run: | eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" sudo apt-get update && sudo apt-get install -y build-essential patchelf mold tcsh libgl1-mesa-dev libglu1-mesa-dev libegl1-mesa-dev libosmesa6-dev libudev-dev libaio-dev libreadline-dev libx11-dev libxcursor-dev libxext-dev libxi-dev libxinerama-dev libxrandr-dev libxrender-dev libxcomposite-dev libxdamage-dev libxtst-dev libxxf86vm-dev libxkbcommon-dev libxkbcommon-x11-dev libffi-dev libasound2-dev libpulse-dev + brew update brew install --formula \ ninja pkg-config ccache glew doctest qt pyside \ ffmpeg openexr imath opencolorio libraw libtiff libpng libspng boost \ openimageio openjpeg webp yaml-cpp spdlog openjph jpeg-turbo + brew upgrade openexr imath opencolorio libraw libtiff boost openimageio spdlog openjph || true shell: bash - name: Save Homebrew cache if: always() - uses: actions/cache/save@v5 + uses: actions/cache/save@v6 with: path: | ~/.cache/Homebrew/downloads key: ${{ runner.os }}-brew-${{ steps.date.outputs.date }}-${{ hashFiles('**/build.sh') }} - name: Restore CCache - uses: actions/cache/restore@v5 + uses: actions/cache/restore@v6 with: path: ~/.ccache key: ${{ runner.os }}-ccache-${{ github.sha }} @@ -509,7 +518,7 @@ jobs: - name: Save CCache if: always() - uses: actions/cache/save@v5 + uses: actions/cache/save@v6 with: path: ~/.ccache key: ${{ runner.os }}-ccache-${{ github.sha }} @@ -525,7 +534,7 @@ jobs: - name: Upload Linux Artifact if: success() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: UTV-${{ needs.version.outputs.version }}-linux-x64 path: _dist/UTV-${{ needs.version.outputs.version }}-linux-x64.tar.gz @@ -545,7 +554,7 @@ jobs: dnf config-manager --set-enabled crb || true - name: Check out repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: submodules: recursive fetch-depth: 0 @@ -568,7 +577,7 @@ jobs: (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')) steps: - name: Check out repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: fetch-depth: 0 @@ -577,21 +586,21 @@ jobs: - name: Download macOS Artifact continue-on-error: true - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: UTV-${{ needs.version.outputs.version }}-macOS-arm64 path: _dist - name: Download Windows Artifact continue-on-error: true - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: UTV-${{ needs.version.outputs.version }}-windows-x64 path: _dist - name: Download Linux Artifact continue-on-error: true - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: UTV-${{ needs.version.outputs.version }}-linux-x64 path: _dist diff --git a/README.md b/README.md index f55cbd8d..1057d163 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,18 @@
+ + diff --git a/build.sh b/build.sh index 2b433d85..d0732c07 100755 --- a/build.sh +++ b/build.sh @@ -122,12 +122,13 @@ if [ "${INSTALL_DEPS}" -eq 1 ]; then libx11-dev libxcursor-dev libxext-dev libxi-dev libxinerama-dev \ libxrandr-dev libxrender-dev libxcomposite-dev libxdamage-dev libxtst-dev libxxf86vm-dev \ libxkbcommon-dev libxkbcommon-x11-dev libffi-dev \ - libasound2-dev libpulse-dev + libasound2-dev libpulse-dev libvulkan-dev fi brew install --formula \ ninja pkg-config ccache glew doctest qt pyside \ ffmpeg openexr imath opencolorio libraw libtiff libpng libspng boost \ - openimageio openjpeg webp yaml-cpp spdlog openjph jpeg-turbo + openimageio openjpeg webp yaml-cpp spdlog openjph jpeg-turbo \ + vulkan-headers vulkan-loader # RHEL / Rocky Setup elif command -v dnf >/dev/null 2>&1; then $SUDO dnf install -y epel-release dnf-plugins-core @@ -458,6 +459,12 @@ fi if [[ "$OSTYPE" == "darwin"* ]]; then echo "--- Sanitizing Homebrew Links ---" python3 "${PROJECT_ROOT}/src/build/sanitize_homebrew_links.py" "${BUILD_DIR}/stage" + if [ -d "${BUILD_DIR}/stage/app/UTV.app" ]; then + codesign --force --deep --sign - "${BUILD_DIR}/stage/app/UTV.app" 2>/dev/null || true + fi +elif [[ "$OSTYPE" == "linux"* ]]; then + echo "--- Sanitizing Dynamic Library Links ---" + python3 "${PROJECT_ROOT}/src/build/sanitize_homebrew_links.py" "${BUILD_DIR}/stage" fi if [ "${INSTALL}" -eq 1 ]; then @@ -467,6 +474,12 @@ if [ "${INSTALL}" -eq 1 ]; then if [[ "$OSTYPE" == "darwin"* ]]; then echo "--- Sanitizing Installed Homebrew Links ---" python3 "${PROJECT_ROOT}/src/build/sanitize_homebrew_links.py" "${INST_DIR}" + if [ -d "${INST_DIR}/UTV.app" ]; then + codesign --force --deep --sign - "${INST_DIR}/UTV.app" 2>/dev/null || true + fi + elif [[ "$OSTYPE" == "linux"* ]]; then + echo "--- Sanitizing Installed Dynamic Library Links ---" + python3 "${PROJECT_ROOT}/src/build/sanitize_homebrew_links.py" "${INST_DIR}" fi fi diff --git a/cmake/defaults/cxx_msvc_defaults.cmake b/cmake/defaults/cxx_msvc_defaults.cmake index 3d5b30e2..1d754a20 100644 --- a/cmake/defaults/cxx_msvc_defaults.cmake +++ b/cmake/defaults/cxx_msvc_defaults.cmake @@ -57,6 +57,8 @@ ADD_COMPILE_OPTIONS( -utf-8 -Zc:forScope -Zc:sizedDealloc- + -Zc:inline + -Gw -Z7 ) diff --git a/scripts/generate-changelog.sh b/scripts/generate-changelog.sh index bf4357ea..ad409032 100755 --- a/scripts/generate-changelog.sh +++ b/scripts/generate-changelog.sh @@ -32,21 +32,21 @@ format_section() { fi } -format_section "โจ Features" "feat(\([^)]+\))?:" -format_section "๐ Bug Fixes" "fix(\([^)]+\))?:" -format_section "โก Performance" "perf(\([^)]+\))?:" -format_section "โป๏ธ Refactoring" "refactor(\([^)]+\))?:" -format_section "๐จ Code Style" "style(\([^)]+\))?:" -format_section "๐๏ธ Build & Dependencies" "build(\([^)]+\))?:" -format_section "๐ง CI/CD" "ci(\([^)]+\))?:" -format_section "๐ Documentation" "docs(\([^)]+\))?:" -format_section "๐งช Tests" "test(\([^)]+\))?:" -format_section "๐ฆ Chores" "chore(\([^)]+\))?:" +format_section "Features" "feat(\([^)]+\))?:" +format_section "Bug Fixes" "fix(\([^)]+\))?:" +format_section "Performance Improvements" "perf(\([^)]+\))?:" +format_section "Refactoring" "refactor(\([^)]+\))?:" +format_section "Code Style" "style(\([^)]+\))?:" +format_section "Build & Dependencies" "build(\([^)]+\))?:" +format_section "CI/CD" "ci(\([^)]+\))?:" +format_section "Documentation" "docs(\([^)]+\))?:" +format_section "Tests" "test(\([^)]+\))?:" +format_section "Chores" "chore(\([^)]+\))?:" # Check for non-conventional or unclassified commits OTHER=$(git log --pretty=format:"* %s (%h)" "$RANGE" | grep -v -E "^\* (feat|fix|perf|refactor|style|build|ci|docs|test|chore)(\([^)]+\))?:" || true) if [ -n "$OTHER" ]; then - echo "### ๐ชต Other Changes" + echo "### Other Changes" echo "$OTHER" echo "" fi diff --git a/src/build/sanitize_homebrew_links.py b/src/build/sanitize_homebrew_links.py index 1f0ca816..6a1bae6c 100644 --- a/src/build/sanitize_homebrew_links.py +++ b/src/build/sanitize_homebrew_links.py @@ -1,7 +1,13 @@ #!/usr/bin/env python3 # -# Sanitize Homebrew Links for UTV -# Converts /opt/homebrew/Cellar/... links to /opt/homebrew/opt/... +# Sanitize Dynamic Library Links for UTV +# Ensures generic unversioned dynamic library links across packages: +# - macOS: Converts /opt/homebrew/Cellar/... links to /opt/homebrew/opt/... +# and versioned dylibs (e.g. libOpenEXR-3_4.33.dylib, libImath-3_2.30.dylib) +# to unversioned symlinks (e.g. libOpenEXR.dylib, libImath.dylib) via install_name_tool. +# - Linux: Converts versioned SONAMEs (e.g. libOpenEXR-3_4.so.33) to +# unversioned names (libOpenEXR.so) via patchelf if available. +# # Copyright (C) 2026 Makai Systems. All Rights Reserved. # @@ -11,14 +17,30 @@ import pathlib import re -BREW_PREFIX = os.environ.get("HOMEBREW_PREFIX", "/opt/homebrew" if os.uname().machine == "arm64" else "/usr/local") +DEFAULT_BREW_PREFIX = ( + "/opt/homebrew" + if (sys.platform == "darwin" and os.uname().machine == "arm64") + else ("/home/linuxbrew/.linuxbrew" if sys.platform.startswith("linux") else "/usr/local") +) +BREW_PREFIX = os.environ.get("HOMEBREW_PREFIX", DEFAULT_BREW_PREFIX) CELLAR_PATTERN = re.compile(rf"{re.escape(BREW_PREFIX)}/Cellar/([^/]+)/[^/]+/(.+)") +# System libraries that should never be renamed on Linux +LINUX_SYSTEM_LIBS = { + "libc.so", + "libm.so", + "libdl.so", + "libpthread.so", + "librt.so", + "libstdc++.so", + "libgcc_s.so", + "ld-linux", +} + -def get_dependencies(binary_path): +def get_dependencies_macho(binary_path): try: output = subprocess.check_output(["otool", "-L", binary_path], text=True) - # Skip first line (the binary itself) deps = [] for line in output.splitlines()[1:]: parts = line.strip().split() @@ -29,9 +51,8 @@ def get_dependencies(binary_path): return [] -def sanitize_binary(binary_path): - print(f"--- Sanitizing: {os.path.basename(binary_path)}") - deps = get_dependencies(binary_path) +def sanitize_macho_binary(binary_path): + deps = get_dependencies_macho(binary_path) changed = False for dep in deps: @@ -44,30 +65,89 @@ def sanitize_binary(binary_path): remaining_path = match.group(2) stable_path = f"{BREW_PREFIX}/opt/{pkg_name}/{remaining_path}" - # Verify stable path exists if os.path.exists(stable_path): - print(f" Mapping Cellar link: {current_dep} -> {stable_path}") + print(f" [{os.path.basename(binary_path)}] Mapping Cellar link: {current_dep} -> {stable_path}") try: subprocess.check_call(["install_name_tool", "-change", current_dep, stable_path, binary_path]) changed = True current_dep = stable_path except subprocess.CalledProcessError as e: - print(f" Error changing link: {e}") + print(f" [{os.path.basename(binary_path)}] Error changing Cellar link: {e}") else: - print(f" Warning: Stable path {stable_path} not found for {current_dep}") - - # 2. Map versioned OpenJPH dylib (e.g. libopenjph.0.31.dylib) to unversioned symlink (libopenjph.dylib) - # This ensures OpenUTV remains compatible across Homebrew OpenJPH minor version updates - if "openjph" in current_dep and re.search(r"libopenjph\.[0-9.]+\.dylib", current_dep): - unversioned_jph = f"{BREW_PREFIX}/opt/openjph/lib/libopenjph.dylib" - if os.path.exists(unversioned_jph): - print(f" Mapping OpenJPH versioned link: {current_dep} -> {unversioned_jph}") - try: - subprocess.check_call(["install_name_tool", "-change", current_dep, unversioned_jph, binary_path]) - changed = True - current_dep = unversioned_jph - except subprocess.CalledProcessError as e: - print(f" Error changing OpenJPH link: {e}") + # If stable path does not exist as-is, check if remaining_path has versioned dylib + base = os.path.basename(remaining_path) + generic_base = re.sub(r"(-[0-9_]+|\.[0-9]+).*\.dylib$", ".dylib", base) + alt_path = f"{BREW_PREFIX}/opt/{pkg_name}/lib/{generic_base}" + if os.path.exists(alt_path): + print(f" [{os.path.basename(binary_path)}] Mapping Cellar link: {current_dep} -> {alt_path}") + try: + subprocess.check_call(["install_name_tool", "-change", current_dep, alt_path, binary_path]) + changed = True + current_dep = alt_path + except subprocess.CalledProcessError as e: + print(f" [{os.path.basename(binary_path)}] Error changing Cellar link: {e}") + + # 2. Map versioned dylibs (e.g. libOpenEXR-3_4.33.dylib, libImath-3_2.30.dylib, libopenjph.0.31.dylib) + # to generic unversioned symlinks (e.g. libOpenEXR.dylib, libImath.dylib, libopenjph.dylib). + # This ensures OpenUTV remains compatible across package manager minor updates. + if current_dep.startswith(BREW_PREFIX) or "/opt/" in current_dep or "/Cellar/" in current_dep: + dir_name = os.path.dirname(current_dep) + base_name = os.path.basename(current_dep) + generic_name = re.sub(r"(-[0-9_]+|\.[0-9]+).*\.dylib$", ".dylib", base_name) + + if generic_name != base_name: + generic_path = os.path.join(dir_name, generic_name) + # If dir_name was inside a Cellar version folder, redirect to opt + if "/Cellar/" in generic_path: + generic_path = re.sub( + rf"{re.escape(BREW_PREFIX)}/Cellar/([^/]+)/[^/]+/", + rf"{BREW_PREFIX}/opt/\1/", + generic_path, + ) + + if os.path.exists(generic_path) or os.path.exists(os.path.dirname(generic_path)): + print( + f" [{os.path.basename(binary_path)}] Mapping to generic dylib link: {current_dep} -> {generic_path}" + ) + try: + subprocess.check_call(["install_name_tool", "-change", current_dep, generic_path, binary_path]) + changed = True + current_dep = generic_path + except subprocess.CalledProcessError as e: + print(f" [{os.path.basename(binary_path)}] Error changing generic link: {e}") + + return changed + + +def sanitize_elf_binary(binary_path): + if not hasattr(sanitize_elf_binary, "patchelf_available"): + sanitize_elf_binary.patchelf_available = ( + subprocess.call(["which", "patchelf"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) == 0 + ) + + if not sanitize_elf_binary.patchelf_available: + return False + + try: + output = subprocess.check_output(["patchelf", "--print-needed", binary_path], text=True) + needed_libs = [line.strip() for line in output.splitlines() if line.strip()] + except Exception: + return False + + changed = False + for lib in needed_libs: + # Skip glibc and system standard libraries + if any(sys_lib in lib for sys_lib in LINUX_SYSTEM_LIBS): + continue + + generic_lib = re.sub(r"(-[0-9_]+|\.so\.[0-9]+|\.[0-9]+).*", ".so", lib) + if generic_lib != lib and generic_lib.endswith(".so"): + print(f" [{os.path.basename(binary_path)}] Mapping needed ELF lib: {lib} -> {generic_lib}") + try: + subprocess.check_call(["patchelf", "--replace-needed", lib, generic_lib, binary_path]) + changed = True + except subprocess.CalledProcessError as e: + print(f" [{os.path.basename(binary_path)}] Error replacing needed library {lib}: {e}") return changed @@ -85,15 +165,26 @@ def main(): print(f"Scanning for binaries in: {search_path}") count = 0 - for root, _, files in os.walk(search_path): + for root, dirs, files in os.walk(search_path): + # Skip Python site-packages in app/lib to keep execution fast + if "site-packages" in root: + continue + for f in files: full_path = os.path.join(root, f) - # Basic check for Mach-O binaries + # Skip symlinks + if os.path.islink(full_path): + continue + + # Basic check for Mach-O or ELF binaries try: file_info = subprocess.check_output(["file", "-b", full_path], text=True) if "Mach-O" in file_info: - if sanitize_binary(full_path): + if sanitize_macho_binary(full_path): + count += 1 + elif "ELF" in file_info: + if sanitize_elf_binary(full_path): count += 1 except Exception: continue