Build and Release XCFramework #5
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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: Cache build results | |
uses: actions/cache@v4 | |
id: cache | |
with: | |
path: ${{ env.OUTPUT_DIR }}/build-${{ matrix.config.sdk }}-${{ matrix.config.arch }} | |
key: ${{ runner.os }}-build-${{ matrix.config.sdk }}-${{ matrix.config.arch }}-${{ hashFiles('**/*.c', '**/*.cpp', '**/*.h', '**/*.m', '**/*.mm') }} | |
- 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@v3 | |
- 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" | |
# For macOS | |
lipo -create \ | |
"${OUTPUT_DIR}/build-macosx-arm64/macosx-arm64-MacOSX/lib/libopencore-amrnb.a" \ | |
"${OUTPUT_DIR}/build-macosx-x86_64/macosx-x86_64-MacOSX/lib/libopencore-amrnb.a" \ | |
-output "${OUTPUT_DIR}/fat/libopencore-amrnb-macos.a" | |
lipo -create \ | |
"${OUTPUT_DIR}/build-macosx-arm64/macosx-arm64-MacOSX/lib/libopencore-amrwb.a" \ | |
"${OUTPUT_DIR}/build-macosx-x86_64/macosx-x86_64-MacOSX/lib/libopencore-amrwb.a" \ | |
-output "${OUTPUT_DIR}/fat/libopencore-amrwb-macos.a" | |
# For iOS device | |
cp "${OUTPUT_DIR}/build-iphoneos-arm64/iphoneos-arm64-iPhoneOS/lib/libopencore-amrnb.a" "${OUTPUT_DIR}/fat/libopencore-amrnb-iphoneos.a" | |
cp "${OUTPUT_DIR}/build-iphoneos-arm64/iphoneos-arm64-iPhoneOS/lib/libopencore-amrwb.a" "${OUTPUT_DIR}/fat/libopencore-amrwb-iphoneos.a" | |
# For iOS simulator | |
lipo -create \ | |
"${OUTPUT_DIR}/build-iphonesimulator-x86_64/iphonesimulator-x86_64-iPhoneSimulator/lib/libopencore-amrnb.a" \ | |
"${OUTPUT_DIR}/build-iphonesimulator-arm64/iphonesimulator-arm64-iPhoneSimulator/lib/libopencore-amrnb.a" \ | |
-output "${OUTPUT_DIR}/fat/libopencore-amrnb-iphonesimulator.a" | |
lipo -create \ | |
"${OUTPUT_DIR}/build-iphonesimulator-x86_64/iphonesimulator-x86_64-iPhoneSimulator/lib/libopencore-amrwb.a" \ | |
"${OUTPUT_DIR}/build-iphonesimulator-arm64/iphonesimulator-arm64-iPhoneSimulator/lib/libopencore-amrwb.a" \ | |
-output "${OUTPUT_DIR}/fat/libopencore-amrwb-iphonesimulator.a" | |
- name: Create XCFrameworks | |
run: | | |
mkdir -p "${OUTPUT_DIR}/Headers/" | |
# For opencore-amrnb | |
rm -rf ${OUTPUT_DIR}/Headers/* | |
rm -rf ${OUTPUT_DIR}/opencore-amrnb.xcframework | |
cp -a amrnb/{interf_dec,interf_enc}.h ${OUTPUT_DIR}/Headers/ | |
xcodebuild -create-xcframework \ | |
-library ${OUTPUT_DIR}/fat/libopencore-amrnb-macos.a -headers ${OUTPUT_DIR}/Headers \ | |
-library ${OUTPUT_DIR}/fat/libopencore-amrnb-iphoneos.a -headers ${OUTPUT_DIR}/Headers \ | |
-library ${OUTPUT_DIR}/fat/libopencore-amrnb-iphonesimulator.a -headers ${OUTPUT_DIR}/Headers \ | |
-output ${OUTPUT_DIR}/opencore-amrnb.xcframework | |
# For opencore-amrwb | |
rm -rf ${OUTPUT_DIR}/Headers/* | |
rm -rf ${OUTPUT_DIR}/opencore-amrwb.xcframework | |
cp -a amrwb/{dec_if,if_rom}.h ${OUTPUT_DIR}/Headers/ | |
xcodebuild -create-xcframework \ | |
-library ${OUTPUT_DIR}/fat/libopencore-amrwb-macos.a -headers ${OUTPUT_DIR}/Headers \ | |
-library ${OUTPUT_DIR}/fat/libopencore-amrwb-iphoneos.a -headers ${OUTPUT_DIR}/Headers \ | |
-library ${OUTPUT_DIR}/fat/libopencore-amrwb-iphonesimulator.a -headers ${OUTPUT_DIR}/Headers \ | |
-output ${OUTPUT_DIR}/opencore-amrwb.xcframework | |
- 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" |