diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..ec5d778 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,215 @@ +name: CI/CD Workflow +on: + push: + branches: + - main + pull_request: + branches: + - "*" +jobs: + test: + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + arch: [aarch64, x86_64] + runs-on: "${{ matrix.os }}" + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Cache dependencies + uses: actions/cache@v3 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: "${{ matrix.os }}-${{ matrix.arch }}-cargo-${{ hashFiles('**/Cargo.lock') }}" + + - name: Cache LLVM + id: cache-llvm + if: matrix.os == 'windows-latest' + uses: actions/cache@v3 + with: + path: | + C:\Program Files\LLVM + key: ${{ matrix.os }}-${{ matrix.arch }}-llvm-17.0.4 # Adjust version as needed + restore-keys: | + ${{ matrix.os }}-${{ matrix.arch }}-llvm-17.0.4 + + - name: Download and Install LLVM + if: steps.cache-llvm.outputs.cache-hit != 'true' && matrix.os == 'windows-latest' + run: | + $arch = if ($env:ARCH -eq 'x86_64') { "win64" } else { "woa64" } + $url = "https://github.com/llvm/llvm-project/releases/download/llvmorg-17.0.4/LLVM-17.0.4-$arch.exe" + echo "Downloading LLVM from $url" # Debugging line + $output = ".\llvm-installer.exe" + Invoke-WebRequest -Uri $url -OutFile $output + $process = Start-Process $output -ArgumentList "/S" -NoNewWindow -PassThru + $process.WaitForExit() + shell: powershell + env: + ARCH: ${{ matrix.arch }} + + - name: Set LIBCLANG_PATH + if: matrix.os == 'windows-latest' + run: | + echo "LIBCLANG_PATH=C:\Program Files\LLVM\bin" | Out-File -Append -FilePath $env:GITHUB_ENV -Encoding utf8 + # Debug: Print the LIBCLANG_PATH environment variable + echo "LIBCLANG_PATH: $env:LIBCLANG_PATH" + # Debug: Check if libclang.dll is present + Test-Path "C:\Program Files\LLVM\bin\libclang.dll" + shell: powershell + + - name: Run pre-build scripts and test + shell: bash + run: | + if [[ "${{ runner.os }}" == "Linux" ]]; then + # Execute Linux pre-build script + bash ./pre-build-linux.sh && cargo test + elif [[ "${{ runner.os }}" == "Windows" ]]; then + # Execute Windows pre-build script + powershell -File ./pre-build-win.ps1 --ci && cargo test + else + cargo test + fi + env: + # Build environment variables + GITHUB_ENV: ${{ github.workspace }}/.env + + build: + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + needs: test + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + arch: [aarch64, x86_64] + runs-on: "${{ matrix.os }}" + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Cache dependencies + uses: actions/cache@v3 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: "${{ matrix.os }}-${{ matrix.arch }}-cargo-${{ hashFiles('**/Cargo.lock') }}" + + - name: Cache LLVM + id: cache-llvm + if: matrix.os == 'windows-latest' + uses: actions/cache@v3 + with: + path: | + C:\Program Files\LLVM + key: ${{ matrix.os }}-${{ matrix.arch }}-llvm-17.0.4 # Adjust version as needed + restore-keys: | + ${{ matrix.os }}-${{ matrix.arch }}-llvm-17.0.4 + + - name: Download and Install LLVM + if: steps.cache-llvm.outputs.cache-hit != 'true' && matrix.os == 'windows-latest' + run: | + $arch = if ($env:ARCH -eq 'x86_64') { "win64" } else { "woa64" } + $url = "https://github.com/llvm/llvm-project/releases/download/llvmorg-17.0.4/LLVM-17.0.4-$arch.exe" + $output = ".\llvm-installer.exe" + Invoke-WebRequest -Uri $url -OutFile $output + $process = Start-Process $output -ArgumentList "/S" -NoNewWindow -PassThru + $process.WaitForExit() + shell: powershell + env: + ARCH: ${{ matrix.arch }} + + - name: Set LIBCLANG_PATH + if: matrix.os == 'windows-latest' + run: | + echo "LIBCLANG_PATH=C:\Program Files\LLVM\bin" | Out-File -Append -FilePath $env:GITHUB_ENV -Encoding utf8 + shell: powershell + + - name: Run pre-build scripts and build release + shell: bash + run: | + if [[ "${{ runner.os }}" == "Linux" ]]; then + # Execute Linux pre-build script + bash ./pre-build-linux.sh && cargo build --release + elif [[ "${{ runner.os }}" == "Windows" ]]; then + # Execute Windows pre-build script + powershell -File ./pre-build-win.ps1 --ci && cargo build --release + else + cargo build --release + fi + env: + # Build environment variables + GITHUB_ENV: ${{ github.workspace }}/.env + + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: "${{ matrix.os }}-${{ matrix.arch }}-binary" + path: target/release/smrec + release: + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + needs: build + runs-on: ubuntu-latest + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + arch: [aarch64, x86_64] + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Download artifact + uses: actions/download-artifact@v3 + with: + name: "${{ matrix.os }}-${{ matrix.arch }}-binary" + + - name: Get version from Cargo.toml + id: get_version + run: echo "::set-output name=version::$(grep '^version =' Cargo.toml | awk -F\" '{print $2}')" + + - name: Prepare asset + run: | + mkdir -p ./release + mv ./${{ matrix.os }}-${{ matrix.arch }}-binary ./release/smrec + cd release + zip -r ../smrec_${{ steps.get_version.outputs.version }}_${{ matrix.os }}_${{ matrix.arch }}.zip . + + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: v${{ steps.get_version.outputs.version }} + release_name: smrec v${{ steps.get_version.outputs.version }} - ${{ matrix.os }} ${{ matrix.arch }} + body: "Automatic changelog generation will be applied in the future. This is an auto generated release note." + draft: false + prerelease: false + + - name: Upload Release Asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./smrec_${{ steps.get_version.outputs.version }}_${{ matrix.os }}_${{ matrix.arch }}.zip + asset_name: smrec_${{ steps.get_version.outputs.version }}_${{ matrix.os }}_${{ matrix.arch }}.zip + asset_content_type: application/zip + + - name: Error Handling + if: failure() + run: echo "An error has occurred during the release process" + + publish: + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + needs: release + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Publish to Crates.io + uses: actions-rs/cargo@v1 + with: + command: publish + args: "--token ${{ secrets.CRATES_IO_TOKEN }}" diff --git a/README.md b/README.md index f8b870b..fe16d50 100644 --- a/README.md +++ b/README.md @@ -133,9 +133,9 @@ The configuration file can configure: ```toml [channel_names] -1 = "Kick" -2 = "Snare" -3 = "Hi-Hat" +1 = "Kick.wav" +2 = "Snare.wav" +3 = "Hi-Hat.wav" ``` - More to come.. diff --git a/pre-build-win.ps1 b/pre-build-win.ps1 index 565e85a..0dd44b4 100644 --- a/pre-build-win.ps1 +++ b/pre-build-win.ps1 @@ -1,8 +1,53 @@ +param ( + [switch]$ci +) + Write-Output "=============================================================================" Write-Output "Pre build script for cpal asio feature." -Write-Output "Make sure that you have sourced this script instead of directly executing it." +Write-Output "Make sure that you have sourced this script instead of directly executing it or if in CI environment, pass the --ci flag." Write-Output "=============================================================================" +function Write-Env { + <# + .SYNOPSIS + Sets an environment variable either in the current process or in the GITHUB_ENV file. + + .DESCRIPTION + This function sets an environment variable. If the --ci switch is specified when + running the script, it writes the environment variable to the GITHUB_ENV file + so it is available to subsequent steps in a GitHub Actions workflow. Otherwise, + it sets the environment variable in the current process. + + .PARAMETER name + The name of the environment variable to set. + + .PARAMETER value + The value to set the environment variable to. + + .EXAMPLE + Write-Env "MY_VARIABLE" "Some Value" + + This example sets the MY_VARIABLE environment variable to "Some Value" in the current process. + + .EXAMPLE + .\pre-build-win.ps1 --ci + Write-Env "MY_VARIABLE" "Some Value" + + This example, when run within the script with the --ci switch, writes the MY_VARIABLE + environment variable to the GITHUB_ENV file with a value of "Some Value". + #> + param ( + [string]$name, + [string]$value + ) + if ($ci) { + Write-Output "$name=$value" | Out-File -FilePath $env:GITHUB_ENV -Append + } + else { + [System.Environment]::SetEnvironmentVariable($name, $value, "Process") + } +} + function Invoke-VcVars { <# .SYNOPSIS @@ -18,23 +63,56 @@ function Invoke-VcVars { Write-Output "Determining system architecture..." $arch = if ([Environment]::Is64BitOperatingSystem) { switch -Wildcard ((Get-CimInstance -ClassName Win32_Processor).Description) { - "*ARM64*"{ "arm64" } - "*ARM*"{ "arm" } + "*ARM64*" { "arm64" } + "*ARM*" { "arm" } default { "amd64" } } - } else { + } + else { "x86" } Write-Output "Architecture detected as $arch." + # Define search paths based on architecture - $paths = if ($arch -eq 'amd64') { - @('C:\Program Files (x86)\Microsoft Visual Studio\', 'C:\Program Files\Microsoft Visual Studio\') - } else { - @('C:\Program Files\Microsoft Visual Studio\') + # Will be overridden if CI flag is set + $paths = @('C:\Program Files (x86)\Microsoft Visual Studio\', 'C:\Program Files\Microsoft Visual Studio\') + + # Find Visual Studio version number (only when CI flag is set) + # TODO: This can be more robust and improve.. but later.. + if ($ci) { + Write-Output "Searching for Visual Studio version number..." + $vsVersion = Get-ChildItem 'C:\Program Files (x86)\Microsoft Visual Studio\' -Directory | + Where-Object { $_.Name -match '\d{4}' } | + Select-Object -ExpandProperty Name -First 1 + + if (-not $vsVersion) { + $vsVersion = Get-ChildItem 'C:\Program Files\Microsoft Visual Studio\' -Directory | + Where-Object { $_.Name -match '\d{4}' } | + Select-Object -ExpandProperty Name -First 1 + } + + if ($vsVersion) { + Write-Output "Visual Studio version $vsVersion detected." + $paths = + @( + "C:\Program Files (x86)\Microsoft Visual Studio\$vsVersion\Community\VC\Auxiliary\Build\", + "C:\Program Files\Microsoft Visual Studio\$vsVersion\Community\VC\Auxiliary\Build\", + "C:\Program Files (x86)\Microsoft Visual Studio\$vsVersion\Professional\VC\Auxiliary\Build\", + "C:\Program Files\Microsoft Visual Studio\$vsVersion\Professional\VC\Auxiliary\Build\", + "C:\Program Files (x86)\Microsoft Visual Studio\$vsVersion\Enterprise\VC\Auxiliary\Build\", + "C:\Program Files\Microsoft Visual Studio\$vsVersion\Enterprise\VC\Auxiliary\Build\" + ) + + } + else { + Write-Output "Visual Studio version not detected. Proceeding with original search paths." + $paths = @('C:\Program Files (x86)\Microsoft Visual Studio\', 'C:\Program Files\Microsoft Visual Studio\') + } } + # Search for vcvarsall.bat and execute the first instance found with the appropriate architecture argument Write-Output "Searching for vcvarsall.bat..." foreach ($path in $paths) { @@ -46,7 +124,7 @@ function Invoke-VcVars { if ($line -match "^(.*?)=(.*)$") { $varName = $matches[1] $varValue = $matches[2] - [System.Environment]::SetEnvironmentVariable($varName, $varValue, "Process") + Write-Env $varName $varValue } } return @@ -86,25 +164,28 @@ if ($env:OS -match "Windows") { # Move the contents of the inner directory (like asiosdk_2.3.3_2019-06-14) to $asio_dir $innerDir = Get-ChildItem -Path $out_dir -Directory | Where-Object { $_.Name -match 'asio.*' } | Select-Object -First 1 Move-Item -Path "$($innerDir.FullName)\*" -Destination $asio_dir -Force - } else { + } + else { Write-Output "ASIO SDK already exists. Skipping download." } # Set the CPAL_ASIO_DIR environment variable Write-Output "Setting CPAL_ASIO_DIR environment variable..." - $env:CPAL_ASIO_DIR = $asio_dir + Write-Env "CPAL_ASIO_DIR" $asio_dir # Check if LIBCLANG_PATH is set if (-not $env:LIBCLANG_PATH) { Write-Error "Error: LIBCLANG_PATH is not set!" Write-Output "Please ensure LLVM is installed and set the LIBCLANG_PATH environment variable." exit 1 - } else { + } + else { Write-Output "LIBCLANG_PATH is set to $env:LIBCLANG_PATH." } # Run the vcvars function Invoke-VcVars -} else { +} +else { Write-Output "This setup script is intended for Windows only." } diff --git a/src/config.rs b/src/config.rs index bf07ca9..7fcf609 100644 --- a/src/config.rs +++ b/src/config.rs @@ -272,14 +272,14 @@ mod tests { fn deserialize_external_config() { let config: &str = r#" [channel_names] - 1 = "channel_1.wav" - 2 = "channel_2.wav" - 3 = "channel_3.wav" - 4 = "channel_4.wav" - 5 = "channel_5.wav" - 6 = "channel_6.wav" - 7 = "channel_7.wav" - 8 = "channel_8.wav" + 1 = "channel_1" + 2 = "channel_2" + 3 = "channel_3" + 4 = "channel_4" + 5 = "channel_5" + 6 = "channel_6" + 7 = "channel_7" + 8 = "channel_8" "#; let config: SmrecConfig = toml::from_str(config).unwrap();