Skip to content

Commit ffeb364

Browse files
feat: add cross-platform shim build system and diagnostics
- Add Makefile with zig cc cross-compilation for all platforms - Add GitHub Actions workflows for CI and shim builds - Improve shim loading with platform-specific search paths - Add Diagnose(), ShimStatus(), ShimBuildInstructions() functions - Add comprehensive shim tests - Update git-copy config with prompts/ exclusion and replace_history_with_current
1 parent cb4f049 commit ffeb364

File tree

10 files changed

+1565
-69
lines changed

10 files changed

+1565
-69
lines changed

.github/workflows/build-shim.yml

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
# Build ffshim for all supported platforms
2+
# This workflow builds the shim library on native runners for maximum compatibility
3+
name: Build Shim
4+
5+
on:
6+
push:
7+
branches: [master, main]
8+
paths:
9+
- 'shim/**'
10+
- '.github/workflows/build-shim.yml'
11+
pull_request:
12+
branches: [master, main]
13+
paths:
14+
- 'shim/**'
15+
- '.github/workflows/build-shim.yml'
16+
release:
17+
types: [created]
18+
workflow_dispatch:
19+
inputs:
20+
upload_artifacts:
21+
description: 'Upload artifacts even on non-release builds'
22+
required: false
23+
default: 'false'
24+
type: boolean
25+
26+
jobs:
27+
# Build on Linux (amd64 native, arm64 via cross-compilation)
28+
build-linux:
29+
runs-on: ubuntu-latest
30+
strategy:
31+
fail-fast: false
32+
matrix:
33+
arch: [amd64, arm64]
34+
steps:
35+
- uses: actions/checkout@v4
36+
37+
- name: Install FFmpeg development libraries (amd64)
38+
if: matrix.arch == 'amd64'
39+
run: |
40+
sudo apt-get update
41+
sudo apt-get install -y libavcodec-dev libavformat-dev libavutil-dev libavdevice-dev
42+
43+
- name: Install cross-compilation tools (arm64)
44+
if: matrix.arch == 'arm64'
45+
run: |
46+
sudo apt-get update
47+
sudo apt-get install -y gcc-aarch64-linux-gnu
48+
# Install arm64 FFmpeg dev libs
49+
sudo dpkg --add-architecture arm64
50+
# Add arm64 sources
51+
sudo sed -i 's/^deb /deb [arch=amd64] /' /etc/apt/sources.list
52+
echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports $(lsb_release -cs) main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list
53+
echo "deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports $(lsb_release -cs)-updates main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list
54+
sudo apt-get update || true
55+
sudo apt-get install -y libavcodec-dev:arm64 libavformat-dev:arm64 libavutil-dev:arm64 || true
56+
57+
- name: Build shim (amd64)
58+
if: matrix.arch == 'amd64'
59+
working-directory: shim
60+
run: |
61+
make native
62+
mkdir -p prebuilt/linux-amd64
63+
cp libffshim.so prebuilt/linux-amd64/
64+
65+
- name: Build shim (arm64)
66+
if: matrix.arch == 'arm64'
67+
working-directory: shim
68+
run: |
69+
# Try cross-compilation, fall back to stub if FFmpeg libs unavailable
70+
mkdir -p prebuilt/linux-arm64
71+
if aarch64-linux-gnu-gcc --version && pkg-config --exists libavutil 2>/dev/null; then
72+
aarch64-linux-gnu-gcc -shared -fPIC -Wall -Wextra -O2 \
73+
$(pkg-config --cflags libavutil libavcodec libavformat) \
74+
-o prebuilt/linux-arm64/libffshim.so ffshim.c \
75+
$(pkg-config --libs libavutil libavcodec libavformat) || \
76+
echo "Cross-compilation failed, arm64 shim will need to be built on native hardware"
77+
else
78+
echo "arm64 FFmpeg dev libs not available, skipping arm64 build"
79+
fi
80+
81+
- name: Upload artifact
82+
uses: actions/upload-artifact@v4
83+
with:
84+
name: shim-linux-${{ matrix.arch }}
85+
path: shim/prebuilt/linux-${{ matrix.arch }}/
86+
if-no-files-found: ignore
87+
88+
# Build on macOS (both amd64 and arm64 native)
89+
build-macos:
90+
strategy:
91+
fail-fast: false
92+
matrix:
93+
include:
94+
- runner: macos-13 # Intel
95+
arch: amd64
96+
- runner: macos-14 # Apple Silicon
97+
arch: arm64
98+
runs-on: ${{ matrix.runner }}
99+
steps:
100+
- uses: actions/checkout@v4
101+
102+
- name: Install FFmpeg
103+
run: brew install ffmpeg
104+
105+
- name: Build shim
106+
working-directory: shim
107+
run: |
108+
make native
109+
mkdir -p prebuilt/darwin-${{ matrix.arch }}
110+
cp libffshim.dylib prebuilt/darwin-${{ matrix.arch }}/
111+
112+
- name: Upload artifact
113+
uses: actions/upload-artifact@v4
114+
with:
115+
name: shim-darwin-${{ matrix.arch }}
116+
path: shim/prebuilt/darwin-${{ matrix.arch }}/
117+
118+
# Build on Windows
119+
build-windows:
120+
runs-on: windows-latest
121+
strategy:
122+
fail-fast: false
123+
matrix:
124+
arch: [amd64] # arm64 Windows runners are not commonly available
125+
steps:
126+
- uses: actions/checkout@v4
127+
128+
- name: Setup MSYS2
129+
uses: msys2/setup-msys2@v2
130+
with:
131+
msystem: MINGW64
132+
update: true
133+
install: >-
134+
mingw-w64-x86_64-gcc
135+
mingw-w64-x86_64-ffmpeg
136+
pkg-config
137+
138+
- name: Build shim
139+
shell: msys2 {0}
140+
working-directory: shim
141+
run: |
142+
make native
143+
mkdir -p prebuilt/windows-amd64
144+
cp ffshim.dll prebuilt/windows-amd64/
145+
146+
- name: Upload artifact
147+
uses: actions/upload-artifact@v4
148+
with:
149+
name: shim-windows-${{ matrix.arch }}
150+
path: shim/prebuilt/windows-${{ matrix.arch }}/
151+
152+
# Combine all artifacts into a single release asset
153+
package:
154+
needs: [build-linux, build-macos, build-windows]
155+
runs-on: ubuntu-latest
156+
if: github.event_name == 'release' || github.event.inputs.upload_artifacts == 'true'
157+
steps:
158+
- uses: actions/checkout@v4
159+
160+
- name: Download all artifacts
161+
uses: actions/download-artifact@v4
162+
with:
163+
path: artifacts
164+
165+
- name: Package shims
166+
run: |
167+
mkdir -p release/shim/prebuilt
168+
169+
# Copy all platform shims
170+
for dir in artifacts/shim-*/; do
171+
platform=$(basename "$dir" | sed 's/shim-//')
172+
if [ -d "$dir" ] && [ "$(ls -A "$dir")" ]; then
173+
mkdir -p "release/shim/prebuilt/$platform"
174+
cp -r "$dir"/* "release/shim/prebuilt/$platform/"
175+
fi
176+
done
177+
178+
# Create archive
179+
cd release
180+
tar -czvf ../ffshim-prebuilt.tar.gz shim/
181+
cd ..
182+
183+
# Create checksums
184+
sha256sum ffshim-prebuilt.tar.gz > ffshim-prebuilt.tar.gz.sha256
185+
186+
- name: Upload release asset
187+
if: github.event_name == 'release'
188+
uses: softprops/action-gh-release@v1
189+
with:
190+
files: |
191+
ffshim-prebuilt.tar.gz
192+
ffshim-prebuilt.tar.gz.sha256
193+
194+
- name: Upload package artifact
195+
uses: actions/upload-artifact@v4
196+
with:
197+
name: ffshim-prebuilt
198+
path: |
199+
ffshim-prebuilt.tar.gz
200+
ffshim-prebuilt.tar.gz.sha256

.github/workflows/ci.yml

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# Continuous Integration for ffgo
2+
name: CI
3+
4+
on:
5+
push:
6+
branches: [master, main]
7+
pull_request:
8+
branches: [master, main]
9+
10+
env:
11+
GO_VERSION: '1.23'
12+
13+
jobs:
14+
# Test without FFmpeg (should pass - tests mock/skip FFmpeg deps)
15+
test-no-ffmpeg:
16+
runs-on: ubuntu-latest
17+
steps:
18+
- uses: actions/checkout@v4
19+
20+
- name: Set up Go
21+
uses: actions/setup-go@v5
22+
with:
23+
go-version: ${{ env.GO_VERSION }}
24+
25+
- name: Run tests without FFmpeg
26+
run: go test -v -short ./...
27+
env:
28+
CGO_ENABLED: "0"
29+
30+
# Test with FFmpeg on multiple platforms
31+
test-with-ffmpeg:
32+
strategy:
33+
fail-fast: false
34+
matrix:
35+
include:
36+
- os: ubuntu-latest
37+
name: Linux amd64
38+
- os: macos-13
39+
name: macOS Intel
40+
- os: macos-14
41+
name: macOS ARM64
42+
# Windows tests are more complex due to FFmpeg setup
43+
# - os: windows-latest
44+
# name: Windows amd64
45+
46+
runs-on: ${{ matrix.os }}
47+
name: Test (${{ matrix.name }})
48+
steps:
49+
- uses: actions/checkout@v4
50+
51+
- name: Set up Go
52+
uses: actions/setup-go@v5
53+
with:
54+
go-version: ${{ env.GO_VERSION }}
55+
56+
- name: Install FFmpeg (Linux)
57+
if: runner.os == 'Linux'
58+
run: |
59+
sudo apt-get update
60+
sudo apt-get install -y ffmpeg libavcodec-dev libavformat-dev libavutil-dev \
61+
libswscale-dev libswresample-dev libavfilter-dev libavdevice-dev
62+
63+
- name: Install FFmpeg (macOS)
64+
if: runner.os == 'macOS'
65+
run: brew install ffmpeg
66+
67+
- name: Build shim
68+
working-directory: shim
69+
run: ./build.sh
70+
71+
- name: Set library path (Linux)
72+
if: runner.os == 'Linux'
73+
run: echo "LD_LIBRARY_PATH=${{ github.workspace }}/shim:$LD_LIBRARY_PATH" >> $GITHUB_ENV
74+
75+
- name: Set library path (macOS)
76+
if: runner.os == 'macOS'
77+
run: echo "DYLD_LIBRARY_PATH=${{ github.workspace }}/shim:$DYLD_LIBRARY_PATH" >> $GITHUB_ENV
78+
79+
- name: Run tests
80+
run: go test -v -race ./...
81+
env:
82+
CGO_ENABLED: "0"
83+
FFGO_SHIM_DIR: ${{ github.workspace }}/shim
84+
85+
- name: Run integration tests
86+
run: go test -v -run Integration ./...
87+
env:
88+
CGO_ENABLED: "0"
89+
FFGO_SHIM_DIR: ${{ github.workspace }}/shim
90+
91+
# Test graceful degradation without shim
92+
test-degraded-mode:
93+
runs-on: ubuntu-latest
94+
steps:
95+
- uses: actions/checkout@v4
96+
97+
- name: Set up Go
98+
uses: actions/setup-go@v5
99+
with:
100+
go-version: ${{ env.GO_VERSION }}
101+
102+
- name: Install FFmpeg (without building shim)
103+
run: |
104+
sudo apt-get update
105+
sudo apt-get install -y ffmpeg libavcodec-dev libavformat-dev libavutil-dev \
106+
libswscale-dev libswresample-dev libavfilter-dev
107+
108+
- name: Run tests (no shim - degraded mode)
109+
run: go test -v ./...
110+
env:
111+
CGO_ENABLED: "0"
112+
# Explicitly unset shim directory to test degraded mode
113+
FFGO_SHIM_DIR: ""
114+
115+
# Lint and vet
116+
lint:
117+
runs-on: ubuntu-latest
118+
steps:
119+
- uses: actions/checkout@v4
120+
121+
- name: Set up Go
122+
uses: actions/setup-go@v5
123+
with:
124+
go-version: ${{ env.GO_VERSION }}
125+
126+
- name: golangci-lint
127+
uses: golangci/golangci-lint-action@v4
128+
with:
129+
version: latest
130+
args: --timeout=5m
131+
132+
- name: go vet
133+
run: go vet ./...

0 commit comments

Comments
 (0)