Skip to content

Build and Release XCFramework #11

Build and Release XCFramework

Build and Release XCFramework #11

name: Build and Release XCFramework
on:
push:
branches: [ main ]
tags:
- 'v*' # This will trigger the workflow on any tag starting with 'v'
pull_request:
branches: [ main ]
workflow_dispatch:
inputs:
release_version:
description: 'Release version (must start with "v", e.g., v0.1.6)'
required: false
default: ''
env:
OUTPUT_DIR: ${{ github.workspace }}/output
jobs:
build:
runs-on: macos-latest
strategy:
matrix:
config:
- { sdk: 'macosx', arch: 'arm64', platform: 'MacOSX' }
- { sdk: 'macosx', arch: 'x86_64', platform: 'MacOSX' }
- { sdk: 'iphoneos', arch: 'arm64', platform: 'iPhoneOS' }
- { sdk: 'iphonesimulator', arch: 'x86_64', platform: 'iPhoneSimulator' }
- { sdk: 'iphonesimulator', arch: 'arm64', platform: 'iPhoneSimulator' }
steps:
- uses: actions/checkout@v4
- name: Get Xcode version
id: xcode-version
run: echo "version=$(xcodebuild -version | grep Xcode | awk '{print $2}')" >> $GITHUB_OUTPUT
- name: Get macOS version
id: macos-version
run: echo "version=$(sw_vers -productVersion)" >> $GITHUB_OUTPUT
- name: Cache build results
uses: actions/cache@v4
id: cache
with:
path: ${{ env.OUTPUT_DIR }}
key: ${{ runner.os }}-build-${{ matrix.config.sdk }}-${{ matrix.config.arch }}-${{ hashFiles('**/*.c', '**/*.cpp', '**/*.h', '**/*.m', '**/*.mm', '.github/actions/*.sh') }}-${{ steps.xcode-version.outputs.version }}-${{ steps.macos-version.outputs.version }}

Check failure on line 48 in .github/workflows/build_xcframework.yml

View workflow run for this annotation

GitHub Actions / Build and Release XCFramework

Invalid workflow file

The workflow is not valid. .github/workflows/build_xcframework.yml (Line: 48, Col: 14): Unexpected symbol: ','. Located at position 62 within expression: hashFiles('**/*.c', '**/*.cpp', '**/*.h', '**/*.m', '**/*.mm', '.github/actions/*.sh')
- name: Set up Xcode
if: steps.cache.outputs.cache-hit != 'true'
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest-stable
- name: Install autotools
if: steps.cache.outputs.cache-hit != 'true'
run: brew install autoconf automake libtool
- name: Setup build environment
if: steps.cache.outputs.cache-hit != 'true'
run: |
aclocal && autoconf && automake --add-missing
mkdir -p "$OUTPUT_DIR"
- name: Build for ${{ matrix.config.sdk }} ${{ matrix.config.arch }}
if: steps.cache.outputs.cache-hit != 'true'
run: |
./.github/actions/build_library.sh ${{ matrix.config.sdk }} ${{ matrix.config.arch }} ${{ matrix.config.platform }}
- name: Upload build artifact
uses: actions/upload-artifact@v4
with:
name: build-${{ matrix.config.sdk }}-${{ matrix.config.arch }}
path: ${{ env.OUTPUT_DIR }}
retention-days: 1
create-xcframework:
needs: build
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Download all build artifacts
uses: actions/download-artifact@v4
with:
path: ${{ env.OUTPUT_DIR }}
- name: List downloaded artifacts
run: |
echo "Contents of OUTPUT_DIR:"
ls -R ${{ env.OUTPUT_DIR }}
- name: Create fat libraries using lipo
run: |
mkdir -p "${OUTPUT_DIR}/fat"
MACOS_ARCHS="arm64 x86_64"
IPHONEOS_ARCHS="arm64"
IPHONESIMULATOR_ARCHS="x86_64 arm64"
LIBRARIES="libopencore-amrnb libopencore-amrwb"
for lib in $LIBRARIES; do
# For macOS
lipo -create $(for arch in $MACOS_ARCHS; do echo "${OUTPUT_DIR}/build-macosx-${arch}/macosx-${arch}-MacOSX/lib/${lib}.a"; done) \
-output "${OUTPUT_DIR}/fat/${lib}-macos.a"
# For iOS device
cp "${OUTPUT_DIR}/build-iphoneos-arm64/iphoneos-arm64-iPhoneOS/lib/${lib}.a" "${OUTPUT_DIR}/fat/${lib}-iphoneos.a"
# For iOS simulator
lipo -create $(for arch in $IPHONESIMULATOR_ARCHS; do echo "${OUTPUT_DIR}/build-iphonesimulator-${arch}/iphonesimulator-${arch}-iPhoneSimulator/lib/${lib}.a"; done) \
-output "${OUTPUT_DIR}/fat/${lib}-iphonesimulator.a"
done
- name: Create XCFrameworks
run: |
mkdir -p "${OUTPUT_DIR}/Headers/"
LIBRARIES="opencore-amrnb opencore-amrwb"
PLATFORMS="macos iphoneos iphonesimulator"
for lib in $LIBRARIES; do
rm -rf ${OUTPUT_DIR}/Headers/*
rm -rf ${OUTPUT_DIR}/${lib}.xcframework
# Copy headers
case $lib in
opencore-amrnb)
cp -a amrnb/interf_dec.h amrnb/interf_enc.h ${OUTPUT_DIR}/Headers/
;;
opencore-amrwb)
cp -a amrwb/dec_if.h amrwb/if_rom.h ${OUTPUT_DIR}/Headers/
;;
esac
# Prepare xcodebuild command
cmd="xcodebuild -create-xcframework"
for platform in $PLATFORMS; do
cmd+=" -library ${OUTPUT_DIR}/fat/lib${lib}-${platform}.a"
cmd+=" -headers ${OUTPUT_DIR}/Headers"
done
cmd+=" -output ${OUTPUT_DIR}/${lib}.xcframework"
# Execute xcodebuild command
eval $cmd
done
- name: Zip XCFrameworks
run: |
cd ${{ env.OUTPUT_DIR }}
for framework in *.xcframework; do
zip -r "${framework%.xcframework}.xcframework.zip" "$framework"
done
ls -la
- name: Upload XCFrameworks
uses: actions/upload-artifact@v4
with:
name: XCFrameworks
path: ${{ env.OUTPUT_DIR }}/*.xcframework.zip
if-no-files-found: error
release:
needs: create-xcframework
runs-on: ubuntu-latest
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') || github.event_name == 'workflow_dispatch'
steps:
- name: Download XCFrameworks
uses: actions/download-artifact@v4
with:
name: XCFrameworks
- name: Determine Release Version
id: version
run: |
if [[ $GITHUB_REF == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/}
elif [[ "${{ github.event.inputs.release_version }}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
VERSION=${{ github.event.inputs.release_version }}
else
echo "Error: Invalid version format. Must start with 'v' followed by semantic versioning."
exit 1
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Create Release and Upload XCFrameworks
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.version.outputs.version }}
name: Release ${{ steps.version.outputs.version }}
draft: false
prerelease: false
generate_release_notes: true
fail_on_unmatched_files: true
files: |
*.xcframework.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Check Release
run: |
echo "Checking release ${{ steps.version.outputs.version }}"
release_info=$(curl -sS -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
https://api.github.com/repos/${{ github.repository }}/releases/tags/${{ steps.version.outputs.version }})
echo "Release info:"
echo "$release_info" | jq '.'
assets=$(echo "$release_info" | jq -r '.assets[].name')
echo "Release assets:"
echo "$assets"