Enhance compatibility for building on Linux #19
Workflow file for this run
This file contains hidden or 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 | |
| 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: | |
| build: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: macos-latest | |
| name: macOS | |
| artifact_name: ccap-macos-universal | |
| build_type: Release | |
| - os: windows-latest | |
| name: Windows | |
| artifact_name: ccap-msvc-x86_64 | |
| - os: ubuntu-latest | |
| name: Linux | |
| artifact_name: ccap-linux-x86_64 | |
| build_type: Release | |
| - os: ubuntu-latest | |
| name: Linux ARM64 | |
| artifact_name: ccap-linux-arm64 | |
| build_type: Release | |
| arch: arm64 | |
| 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: | | |
| 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 | |
| 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 | |
| else | |
| # Regular Linux x86_64 | |
| cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCCAP_BUILD_EXAMPLES=ON -DCCAP_BUILD_TESTS=OFF | |
| 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 | |
| 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 dynamic libraries (if exist) | |
| cp build/Debug/ccapd.dll package/lib/ccapd.dll || echo "Debug dynamic library not found" | |
| cp build/Release/ccap.dll package/lib/ccap.dll || echo "Release dynamic library not found" | |
| # 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: | | |
| # Copy static library | |
| cp build/libccap.a package/lib/ || echo "Static library not found" | |
| # Copy dynamic library (if exists) | |
| cp build/libccap.dylib package/lib/ || echo "Dynamic library not found" | |
| # 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: | | |
| # Copy static library | |
| cp build/libccap.a package/lib/ || echo "Static library not found" | |
| # Copy dynamic library (if exists) | |
| cp build/libccap.so package/lib/ || echo "Dynamic library not found" | |
| # 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: | | |
| # Copy static library | |
| cp build/libccap.a package/lib/ || echo "Static library not found" | |
| # Copy dynamic library (if exists) | |
| cp build/libccap.so package/lib/ || echo "Dynamic library not found" | |
| # 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: 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 }} | |
| ### 📦 Downloads | |
| **Supported Platforms:** | |
| - **macOS** (Universal Binary - supports Intel & Apple Silicon): `ccap-macos-universal.tar.gz` | |
| - **Windows** (MSVC x64 - includes Debug and Release versions): `ccap-msvc-x86_64.zip` | |
| - **Linux x86_64** (compatible with most distributions): `ccap-linux-x86_64.tar.gz` | |
| - **Linux ARM64** (compatible with Raspberry Pi, ARM servers, and other ARM64 boards): `ccap-linux-arm64.tar.gz` | |
| ### 📁 Package Contents | |
| - **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) | |
| - **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 | |
| 1. Download the appropriate platform 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 | |
| ### 📋 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**: ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY | |
| echo "**Prerelease**: ${{ steps.release_type.outputs.prerelease }}" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### 📦 Included Files:" >> $GITHUB_STEP_SUMMARY | |
| echo "- ccap-macos-universal.tar.gz" >> $GITHUB_STEP_SUMMARY | |
| echo "- ccap-msvc-x86_64.zip (includes Debug and Release versions)" >> $GITHUB_STEP_SUMMARY | |
| echo "- ccap-linux-x86_64.tar.gz" >> $GITHUB_STEP_SUMMARY | |
| echo "- ccap-linux-arm64.tar.gz" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "Release page: ${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY |