Skip to content

chore: add explicit PUBLIC scope to macOS target_link_libraries #26

chore: add explicit PUBLIC scope to macOS target_link_libraries

chore: add explicit PUBLIC scope to macOS target_link_libraries #26

Workflow file for this run

name: Build and Release
on:
push:
tags:
- 'v*.*.*' # Official release (v1.0.0)
- 'v*.*.*-beta*' # Beta release (v1.0.0-beta.1)
- 'v*.*.*-alpha*' # Alpha release (v1.0.0-alpha.1)
- 'v*.*.*-rc*' # Release Candidate (v1.0.0-rc.1)
# Add manual trigger option for testing
workflow_dispatch:
inputs:
version:
description: 'Version number (e.g.: v1.0.0-test)'
required: true
default: 'v0.1.0-test'
create_release:
description: 'Whether to create GitHub Release'
type: boolean
default: false
jobs:
# Run comprehensive tests before building release packages
test:
name: Run Full Test Suite
runs-on: ${{ matrix.os }}
strategy:
fail-fast: true # Stop all jobs if any test fails
matrix:
include:
- os: windows-latest
name: Windows Tests
test_type: both
- os: ubuntu-latest
name: Linux Tests
test_type: both
- os: ubuntu-latest
name: Linux ARM64 Tests
test_type: functional
arch: arm64
- os: macos-latest
name: macOS Tests
test_type: both
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup cross-compilation for ARM64
if: matrix.arch == 'arm64'
shell: bash
run: |
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu qemu-user qemu-user-static
- name: Setup Visual Studio (Windows)
if: matrix.os == 'windows-latest'
uses: microsoft/setup-msbuild@v1.1
- name: Install Linux dependencies
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -y cmake build-essential gcc
if [ "${{ matrix.test_type }}" = "both" ]; then
sudo apt-get install -y libglfw3-dev
fi
- name: Run Tests
shell: bash
run: |
cd scripts
echo "=== Running ${{ matrix.name }} ==="
if [ "${{ matrix.arch }}" = "arm64" ]; then
# ARM64 cross-compilation tests
echo "Running ARM64 functional tests..."
./run_tests.sh --functional --exit-when-failed
elif [ "${{ matrix.test_type }}" = "both" ]; then
# Full test suite (functional + performance)
echo "Running full test suite..."
./run_tests.sh --functional --exit-when-failed
./run_tests.sh --performance --exit-when-failed
else
# Functional tests only
echo "Running functional tests..."
./run_tests.sh --functional --exit-when-failed
fi
echo "✅ ${{ matrix.name }} completed successfully!"
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results-${{ matrix.name }}-${{ github.run_id }}
path: |
build/**/test_results.xml
build/**/*_results.xml
retention-days: 7
if-no-files-found: ignore
build:
name: Build Release Packages
needs: test
strategy:
fail-fast: false
matrix:
include:
# Static library builds (updated naming)
- os: macos-latest
name: macOS Static
artifact_name: ccap-macos-universal-static
build_type: Release
shared: false
- os: windows-latest
name: Windows Static
artifact_name: ccap-msvc-x86_64-static
build_type: Release
shared: false
- os: ubuntu-latest
name: Linux Static
artifact_name: ccap-linux-x86_64-static
build_type: Release
shared: false
- os: ubuntu-latest
name: Linux ARM64 Static
artifact_name: ccap-linux-arm64-static
build_type: Release
arch: arm64
shared: false
# Shared library builds (updated naming)
- os: macos-latest
name: macOS Shared
artifact_name: ccap-macos-universal-shared
build_type: Release
shared: true
- os: windows-latest
name: Windows Shared
artifact_name: ccap-msvc-x86_64-shared
build_type: Release
shared: true
- os: ubuntu-latest
name: Linux Shared
artifact_name: ccap-linux-x86_64-shared
build_type: Release
shared: true
- os: ubuntu-latest
name: Linux ARM64 Shared
artifact_name: ccap-linux-arm64-shared
build_type: Release
arch: arm64
shared: true
runs-on: ${{ matrix.os }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup cross-compilation for ARM64
if: matrix.arch == 'arm64'
shell: bash
run: |
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
- name: Setup Visual Studio (Windows)
if: matrix.os == 'windows-latest'
uses: microsoft/setup-msbuild@v1.1
- name: Configure CMake
shell: bash
run: |
# Set shared library flag based on matrix configuration
SHARED_FLAG=""
if [ "${{ matrix.shared }}" = "true" ]; then
SHARED_FLAG="-DCCAP_BUILD_SHARED=ON"
else
SHARED_FLAG="-DCCAP_BUILD_SHARED=OFF"
fi
if [ "${{ matrix.os }}" = "windows-latest" ]; then
# Windows: Use multi-config generator (Visual Studio)
cmake -B build -G "Visual Studio 17 2022" -A x64 -DCCAP_BUILD_EXAMPLES=ON -DCCAP_BUILD_TESTS=OFF $SHARED_FLAG
elif [ "${{ matrix.os }}" = "ubuntu-latest" ]; then
# Linux: Use single-config generator
if [ "${{ matrix.arch }}" = "arm64" ]; then
# ARM64 cross-compilation
cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \
-DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc \
-DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ \
-DCMAKE_SYSTEM_NAME=Linux \
-DCMAKE_SYSTEM_PROCESSOR=aarch64 \
-DCCAP_BUILD_EXAMPLES=ON -DCCAP_BUILD_TESTS=OFF $SHARED_FLAG
else
# Regular Linux x86_64
cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCCAP_BUILD_EXAMPLES=ON -DCCAP_BUILD_TESTS=OFF $SHARED_FLAG
fi
else
# macOS: Use single-config generator with universal binary
cmake -B build -DCMAKE_OSX_ARCHITECTURES='arm64;x86_64' -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCCAP_BUILD_EXAMPLES=ON -DCCAP_BUILD_TESTS=OFF $SHARED_FLAG
fi
- name: Build project
shell: bash
run: |
if [ "${{ matrix.os }}" = "windows-latest" ]; then
# Windows: Build both Debug and Release versions
cmake --build build --config Debug --parallel
cmake --build build --config Release --parallel
else
# Other platforms: Build specified version
cmake --build build --config ${{ matrix.build_type }} --parallel
fi
- name: List build outputs (Windows Debug)
if: matrix.os == 'windows-latest'
shell: bash
run: |
echo "=== Debug build outputs ==="
find build/Debug -name "*.lib" -o -name "*.dll" -o -name "*.exe" | head -20
echo "=== Release build outputs ==="
find build/Release -name "*.lib" -o -name "*.dll" -o -name "*.exe" | head -20
- name: Prepare package directory
shell: bash
run: |
mkdir -p package/lib
mkdir -p package/include
mkdir -p package/examples
mkdir -p package/cmake
- name: Copy libraries (Windows)
if: matrix.os == 'windows-latest'
shell: bash
run: |
# Copy Debug version library files (ccapd.lib generated through DEBUG_POSTFIX "d")
cp build/Debug/ccapd.lib package/lib/ccapd.lib || echo "Debug static library not found"
# Copy Release version library files, keeping ccap.lib name
cp build/Release/ccap.lib package/lib/ccap.lib || echo "Release static library not found"
# Copy shared libraries (if shared build)
if [ "${{ matrix.shared }}" = "true" ]; then
cp build/Debug/ccapd.dll package/lib/ccapd.dll || echo "Debug shared library not found"
cp build/Release/ccap.dll package/lib/ccap.dll || echo "Release shared library not found"
# Also copy import libraries for DLLs
cp build/Debug/ccapd.lib package/lib/ccapd_import.lib || echo "Debug import library not found"
cp build/Release/ccap.lib package/lib/ccap_import.lib || echo "Release import library not found"
fi
# Copy example programs (both versions in examples directory)
mkdir -p package/examples/Debug
mkdir -p package/examples/Release
cp build/Debug/*.exe package/examples/Debug/ || echo "Debug examples not found"
cp build/Release/*.exe package/examples/Release/ || echo "Release examples not found"
- name: Copy libraries (macOS)
if: matrix.os == 'macos-latest'
shell: bash
run: |
if [ "${{ matrix.shared }}" = "true" ]; then
# Copy shared library
cp build/libccap.dylib package/lib/ || echo "Shared library not found"
else
# Copy static library
cp build/libccap.a package/lib/ || echo "Static library not found"
fi
# Copy example programs
find build -name "*-print_camera" -exec cp {} package/examples/ \; || echo "Examples not found"
find build -name "*-minimal_example" -exec cp {} package/examples/ \; || echo "Examples not found"
find build -name "*-capture_grab" -exec cp {} package/examples/ \; || echo "Examples not found"
find build -name "*-capture_callback" -exec cp {} package/examples/ \; || echo "Examples not found"
find build -name "*-example_with_glfw" -exec cp {} package/examples/ \; || echo "Examples not found"
- name: Copy libraries (Linux)
if: matrix.os == 'ubuntu-latest' && matrix.arch != 'arm64'
shell: bash
run: |
if [ "${{ matrix.shared }}" = "true" ]; then
# Copy shared library
cp build/libccap.so package/lib/ || echo "Shared library not found"
else
# Copy static library
cp build/libccap.a package/lib/ || echo "Static library not found"
fi
# Copy example programs
find build -name "0-print_camera" -exec cp {} package/examples/ \; || echo "Examples not found"
find build -name "1-minimal_example" -exec cp {} package/examples/ \; || echo "Examples not found"
find build -name "2-capture_grab" -exec cp {} package/examples/ \; || echo "Examples not found"
find build -name "3-capture_callback" -exec cp {} package/examples/ \; || echo "Examples not found"
find build -name "4-example_with_glfw" -exec cp {} package/examples/ \; || echo "Examples not found"
- name: Copy libraries (Linux ARM64)
if: matrix.os == 'ubuntu-latest' && matrix.arch == 'arm64'
shell: bash
run: |
if [ "${{ matrix.shared }}" = "true" ]; then
# Copy shared library
cp build/libccap.so package/lib/ || echo "Shared library not found"
else
# Copy static library
cp build/libccap.a package/lib/ || echo "Static library not found"
fi
# Copy example programs (ARM64 cross-compiled)
find build -name "0-print_camera" -exec cp {} package/examples/ \; || echo "Examples not found"
find build -name "1-minimal_example" -exec cp {} package/examples/ \; || echo "Examples not found"
find build -name "2-capture_grab" -exec cp {} package/examples/ \; || echo "Examples not found"
find build -name "3-capture_callback" -exec cp {} package/examples/ \; || echo "Examples not found"
find build -name "4-example_with_glfw" -exec cp {} package/examples/ \; || echo "Examples not found"
- name: Copy headers and other files
shell: bash
run: |
# Copy header files
cp -r include/* package/include/
# Copy CMake configuration files
cp build/ccap*.cmake package/cmake/ || echo "CMake config files not found"
cp build/ccap.pc package/ || echo "pkg-config file not found"
# Copy documentation
cp README.md package/ || echo "README not found"
cp README.zh-CN.md package/ || echo "Chinese README not found"
cp LICENSE package/ || echo "LICENSE not found"
cp BUILD_AND_INSTALL.md package/ || echo "Build instructions not found"
cp PACKAGE_USAGE.md package/ || echo "Package usage guide not found"
# Copy example source files
cp examples/desktop/*.cpp package/examples/ || echo "Example source files not found"
- name: Verify package contents (Windows)
if: matrix.os == 'windows-latest'
shell: bash
run: |
echo "=== Package contents ==="
find package -name "*.lib" -o -name "*.dll" -o -name "*.exe" | sort
echo "=== lib directory ==="
ls -la package/lib/ || echo "lib directory not found"
- name: Create archive
shell: bash
run: |
cd package
if [ "${{ matrix.os }}" = "windows-latest" ]; then
# Windows: Create ZIP file
7z a ../${{ matrix.artifact_name }}.zip ./*
else
# macOS and Linux: Create tar.gz file
tar -czf ../${{ matrix.artifact_name }}.tar.gz .
fi
cd ..
- name: Upload build artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact_name }}
path: ${{ matrix.artifact_name }}.*
retention-days: 5
release:
needs: [test, build]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download all artifacts
uses: actions/download-artifact@v4
- name: List downloaded files
shell: bash
run: |
echo "Downloaded artifacts:"
find . -name "ccap-*" -type f
- name: Determine release type
id: release_type
shell: bash
run: |
# Get version number (from tag or manual input)
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
TAG_NAME="${{ github.event.inputs.version }}"
echo "Manual trigger with version: $TAG_NAME"
else
TAG_NAME="${{ github.ref_name }}"
echo "Tag trigger with version: $TAG_NAME"
fi
echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT
if [[ "$TAG_NAME" =~ -beta ]]; then
echo "prerelease=true" >> $GITHUB_OUTPUT
echo "release_name=Beta Release $TAG_NAME" >> $GITHUB_OUTPUT
elif [[ "$TAG_NAME" =~ -alpha ]]; then
echo "prerelease=true" >> $GITHUB_OUTPUT
echo "release_name=Alpha Release $TAG_NAME" >> $GITHUB_OUTPUT
elif [[ "$TAG_NAME" =~ -rc ]]; then
echo "prerelease=true" >> $GITHUB_OUTPUT
echo "release_name=Release Candidate $TAG_NAME" >> $GITHUB_OUTPUT
elif [[ "$TAG_NAME" =~ -test ]]; then
echo "prerelease=true" >> $GITHUB_OUTPUT
echo "release_name=Test Build $TAG_NAME" >> $GITHUB_OUTPUT
else
echo "prerelease=false" >> $GITHUB_OUTPUT
echo "release_name=Release $TAG_NAME" >> $GITHUB_OUTPUT
fi
- name: Generate release notes
id: release_notes
shell: bash
run: |
cat > release_notes.md << 'EOF'
## 🚀 ccap ${{ steps.release_type.outputs.tag_name }}
### ✅ Quality Assurance
**All packages have passed comprehensive unit tests before release:**
- ✅ **Windows Tests**: Functional and performance tests on Windows platform
- ✅ **Linux x86_64 Tests**: Functional and performance tests on Linux
- ✅ **Linux ARM64 Tests**: Cross-compiled functional tests with QEMU validation
- ✅ **macOS Tests**: Functional and performance tests on macOS platform
> **Note**: This release was only created after ALL platform tests passed successfully. Any test failure would have prevented the release.
### 📦 Downloads
**Static Library Packages (for static linking):**
- **macOS** (Universal Binary - supports Intel & Apple Silicon): `ccap-macos-universal-static.tar.gz`
- **Windows** (MSVC x64 - includes Debug and Release versions): `ccap-msvc-x86_64-static.zip`
- **Linux x86_64** (compatible with most distributions): `ccap-linux-x86_64-static.tar.gz`
- **Linux ARM64** (compatible with Raspberry Pi, ARM servers, and other ARM64 boards): `ccap-linux-arm64-static.tar.gz`
**Shared Library Packages (for dynamic linking):**
- **macOS** (Universal Binary - supports Intel & Apple Silicon): `ccap-macos-universal-shared.tar.gz`
- **Windows** (MSVC x64 - includes Debug and Release versions): `ccap-msvc-x86_64-shared.zip`
- **Linux x86_64** (compatible with most distributions): `ccap-linux-x86_64-shared.tar.gz`
- **Linux ARM64** (compatible with Raspberry Pi, ARM servers, and other ARM64 boards): `ccap-linux-arm64-shared.tar.gz`
### 📁 Package Contents
**Static Library Packages:**
- **Library Files**: Static library files for linking
- Windows: `lib/ccap.lib` (Release version) and `lib/ccapd.lib` (Debug version)
- macOS: `lib/libccap.a` (Universal Binary)
- Linux x86_64: `lib/libccap.a` (x86_64)
- Linux ARM64: `lib/libccap.a` (ARM64)
**Shared Library Packages:**
- **Library Files**: Shared library files for runtime linking
- Windows: `lib/ccap.dll` + `lib/ccap_import.lib` (Release), `lib/ccapd.dll` + `lib/ccapd_import.lib` (Debug)
- macOS: `lib/libccap.dylib` (Universal Binary)
- Linux x86_64: `lib/libccap.so` (x86_64)
- Linux ARM64: `lib/libccap.so` (ARM64)
**All Packages Include:**
- **Header Files**: Complete C++ API header files
- **Example Programs**: 5 complete usage examples
- Windows: `examples/Release/` and `examples/Debug/` directories contain corresponding versions
- macOS: `examples/` directory contains executable files
- Linux x86_64: `examples/` directory contains executable files
- Linux ARM64: `examples/` directory contains executable files
- **Example Source Code**: Ready-to-compile example code
- **Documentation**: README and build instructions
- **CMake Configuration**: Easy integration with other CMake projects
### 🔧 Usage
**For Static Linking:**
1. Download the appropriate static library package
2. Extract to your project directory
3. Add the `include` directory to your compiler's include path
4. Link the corresponding library file:
- **Windows Debug**: Link `lib/ccapd.lib`
- **Windows Release**: Link `lib/ccap.lib`
- **macOS**: Link `lib/libccap.a`
- **Linux x86_64**: Link `lib/libccap.a`
- **Linux ARM64**: Link `lib/libccap.a`
5. Refer to example code in the `examples` directory
**For Shared Linking:**
1. Download the appropriate shared library package
2. Extract to your project directory
3. Add the `include` directory to your compiler's include path
4. Link and configure runtime libraries:
- **Windows Debug**: Link `lib/ccapd_import.lib`, ensure `lib/ccapd.dll` is in PATH or app directory
- **Windows Release**: Link `lib/ccap_import.lib`, ensure `lib/ccap.dll` is in PATH or app directory
- **macOS**: Link `lib/libccap.dylib`, ensure dylib is in DYLD_LIBRARY_PATH or install location
- **Linux x86_64**: Link `lib/libccap.so`, ensure so is in LD_LIBRARY_PATH or install location
- **Linux ARM64**: Link `lib/libccap.so`, ensure so is in LD_LIBRARY_PATH or install location
5. Refer to example code in the `examples` directory
### 📋 System Requirements
- **macOS**: 10.13 or higher
- **Windows**: Windows 10 or higher (requires Visual C++ Redistributable)
- **Linux**: Modern Linux distribution with kernel 2.6+ (supports V4L2)
---
For complete changelog, see the auto-generated content below.
EOF
- name: Create GitHub Release
# Only execute when triggered by tag or manual trigger with create_release enabled
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.create_release == 'true')
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.release_type.outputs.tag_name }}
name: ${{ steps.release_type.outputs.release_name }}
body_path: release_notes.md
files: |
*/ccap-*.zip
*/ccap-*.tar.gz
draft: false
prerelease: ${{ steps.release_type.outputs.prerelease }}
generate_release_notes: true
make_latest: ${{ steps.release_type.outputs.prerelease == 'false' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Summary
shell: bash
run: |
echo "## 🎉 Release Created Successfully!" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Release**: ${{ steps.release_type.outputs.release_name }}" >> $GITHUB_STEP_SUMMARY
echo "**Tag**: ${{ steps.release_type.outputs.tag_name }}" >> $GITHUB_STEP_SUMMARY
echo "**Prerelease**: ${{ steps.release_type.outputs.prerelease }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### ✅ Quality Assurance" >> $GITHUB_STEP_SUMMARY
echo "- ✅ **Windows Tests**: All functional and performance tests passed" >> $GITHUB_STEP_SUMMARY
echo "- ✅ **Linux x86_64 Tests**: All functional and performance tests passed" >> $GITHUB_STEP_SUMMARY
echo "- ✅ **Linux ARM64 Tests**: Cross-compilation and functional tests passed" >> $GITHUB_STEP_SUMMARY
echo "- ✅ **macOS Tests**: All functional and performance tests passed" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "> 🛡️ **This release was only created after ALL tests passed successfully!**" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 📦 Included Files:" >> $GITHUB_STEP_SUMMARY
echo "**Static Library Packages:**" >> $GITHUB_STEP_SUMMARY
echo "- ccap-macos-universal-static.tar.gz" >> $GITHUB_STEP_SUMMARY
echo "- ccap-msvc-x86_64-static.zip (includes Debug and Release versions)" >> $GITHUB_STEP_SUMMARY
echo "- ccap-linux-x86_64-static.tar.gz" >> $GITHUB_STEP_SUMMARY
echo "- ccap-linux-arm64-static.tar.gz" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Shared Library Packages:**" >> $GITHUB_STEP_SUMMARY
echo "- ccap-macos-universal-shared.tar.gz" >> $GITHUB_STEP_SUMMARY
echo "- ccap-msvc-x86_64-shared.zip (includes Debug and Release versions)" >> $GITHUB_STEP_SUMMARY
echo "- ccap-linux-x86_64-shared.tar.gz" >> $GITHUB_STEP_SUMMARY
echo "- ccap-linux-arm64-shared.tar.gz" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Release page: ${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ steps.release_type.outputs.tag_name }}" >> $GITHUB_STEP_SUMMARY