From 15ec9ca0fb84af42750a43cbb1ef6600b854119d Mon Sep 17 00:00:00 2001 From: mlm-games <125530737+mlm-games@users.noreply.github.com> Date: Sun, 2 Nov 2025 22:05:10 +0530 Subject: [PATCH 1/3] Migrate from azure pipelines to gh actions (with android checks) --- .github/workflows/ci.yml | 241 +++++++++++++++++++++++++++++++++++ azure-pipelines-template.yml | 131 ------------------- azure-pipelines.yml | 43 ------- 3 files changed, 241 insertions(+), 174 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 azure-pipelines-template.yml delete mode 100644 azure-pipelines.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..0b85c27 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,241 @@ +name: CI + +on: + pull_request: + push: + branches: "**" + +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +env: + CARGO_TERM_COLOR: always + +jobs: + build-stable: + name: Build (stable) — ${{ matrix.name }} + runs-on: ${{ matrix.os }} + continue-on-error: ${{ matrix.allow_fail || false }} + strategy: + fail-fast: false + matrix: + include: + - { name: Linux (ALSA), os: ubuntu-latest, target: x86_64-unknown-linux-gnu, features: "", setup: linux-alsa } + - { name: Linux (JACK), os: ubuntu-latest, target: x86_64-unknown-linux-gnu, features: "jack", setup: linux-jack } + - { name: Linux (WASM), os: ubuntu-latest, target: wasm32-unknown-unknown, features: "", setup: wasm } + - { name: Windows (MSVC / WinMM), os: windows-latest, target: x86_64-pc-windows-msvc, features: "", setup: windows-msvc } + - { name: Windows (MSVC / WinRT), os: windows-latest, target: x86_64-pc-windows-msvc, features: "winrt", setup: windows-msvc } + - { name: Windows (GNU i686 / WinMM), os: windows-latest, target: i686-pc-windows-gnu, features: "", setup: windows-gnu } + - { name: Windows (GNU i686 / WinRT), os: windows-latest, target: i686-pc-windows-gnu, features: "winrt", setup: windows-gnu, allow_fail: true } + - { name: macOS (CoreMIDI), os: macos-latest, target: "", features: "", setup: macos } + - { name: macOS (JACK), os: macos-latest, target: "", features: "jack", setup: macos-jack, allow_fail: true } + - { name: iOS (Mac Catalyst aarch64-apple-ios-macabi), os: macos-latest, target: aarch64-apple-ios-macabi, features: "", setup: ios-macabi } + - { name: Linux (aarch64-unknown-linux-gnu), os: ubuntu-latest, target: aarch64-unknown-linux-gnu, features: "", setup: linux-aarch64 } + - { name: Windows (ARM64 MSVC), os: windows-latest, target: aarch64-pc-windows-msvc, features: "", setup: windows-msvc } + - { name: Android (aarch64/armv7/x86_64/i686; API 29), os: ubuntu-latest, target: "", features: "", setup: android } + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Rust cache + uses: Swatinem/rust-cache@v2 + with: + cache-all-crates: true + + - name: Setup Linux dependencies + if: runner.os == 'Linux' && matrix.setup != 'linux-aarch64' && matrix.setup != 'wasm' && matrix.setup != 'android' + run: | + sudo apt-get update && sudo apt-get install -y libasound2-dev pkg-config + if [[ "${{ matrix.setup }}" == "linux-jack" ]]; then + sudo apt-get install -y libjack-jackd2-dev + fi + + - name: Setup WASM + if: matrix.setup == 'wasm' + run: rustup target add wasm32-unknown-unknown + + - name: Install Chrome for WASM tests + if: matrix.setup == 'wasm' + uses: browser-actions/setup-chrome@v2 + with: + chrome-version: stable + install-dependencies: true + + - name: Install wasm-pack + if: matrix.setup == 'wasm' + run: curl -sSf https://rustwasm.github.io/wasm-pack/installer/init.sh | sh -s -- -f + + - name: Setup Linux aarch64 (cross-compile) + if: matrix.setup == 'linux-aarch64' + run: | + set -euxo pipefail + rustup target add aarch64-unknown-linux-gnu + + sudo dpkg --add-architecture arm64 + cat <<'EOF' | sudo tee /etc/apt/sources.list.d/ubuntu-arm64.sources + Types: deb + URIs: http://ports.ubuntu.com/ubuntu-ports + Suites: noble noble-updates noble-backports noble-security + Components: main restricted universe multiverse + Architectures: arm64 + EOF + sudo sed -Ei 's|^Types: deb|Types: deb\nArchitectures: amd64|' \ + /etc/apt/sources.list.d/ubuntu.sources + + sudo apt-get update + sudo apt-get install -y \ + gcc-aarch64-linux-gnu \ + libc6-dev-arm64-cross \ + pkg-config \ + libasound2-dev:arm64 \ + libjack-jackd2-dev:arm64 + + echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV + echo "PKG_CONFIG_ALLOW_CROSS=1" >> $GITHUB_ENV + echo "PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig" >> $GITHUB_ENV + + - name: Setup Windows MSVC toolchain + if: matrix.setup == 'windows-msvc' + run: | + rustup update stable + if [ -n "${{ matrix.target }}" ]; then rustup target add ${{ matrix.target }}; fi + shell: bash + + - name: Setup Windows GNU toolchain + if: matrix.setup == 'windows-gnu' + uses: msys2/setup-msys2@v2 + with: + install: >- + base-devel + mingw-w64-i686-toolchain + msystem: MINGW32 + update: true + + - name: Setup macOS JACK + if: matrix.setup == 'macos-jack' + run: | + brew install jack + echo "PKG_CONFIG_PATH=/opt/homebrew/lib/pkgconfig:/usr/local/lib/pkgconfig" >> $GITHUB_ENV + + - name: Start JACK (macOS) + if: matrix.setup == 'macos-jack' + run: | + jackd -d dummy >/tmp/jack.log 2>&1 & disown + sleep 2 + + - name: Setup iOS (Mac Catalyst) + if: matrix.setup == 'ios-macabi' + run: rustup target add aarch64-apple-ios-macabi + + - name: Setup Android NDK + if: matrix.setup == 'android' + uses: nttld/setup-ndk@v1 + with: + ndk-version: r26d + local-cache: true + + - name: Export ANDROID_NDK_HOME for cargo-ndk + if: matrix.setup == 'android' + run: echo "ANDROID_NDK_HOME=${ANDROID_NDK_HOME:-$NDK_HOME}" >> $GITHUB_ENV + + - name: Install cargo-ndk and Android targets + if: matrix.setup == 'android' + run: | + cargo install cargo-ndk --locked + rustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android i686-linux-android + + - name: Build (standard) + if: matrix.setup != 'windows-gnu' && matrix.setup != 'android' && matrix.setup != 'wasm' + run: | + if [ -n "${{ matrix.target }}" ]; then + cargo build --verbose --target ${{ matrix.target }} ${{ matrix.features && format('--features {0}', matrix.features) }} + else + cargo build --verbose ${{ matrix.features && format('--features {0}', matrix.features) }} + fi + shell: bash + + - name: Build (Windows GNU) + if: matrix.setup == 'windows-gnu' + shell: msys2 {0} + run: | + export PATH="$(cygpath -u "$USERPROFILE")/.cargo/bin:$PATH" + rustup update stable + rustup target add ${{ matrix.target }} + export CARGO_TARGET_I686_PC_WINDOWS_GNU_LINKER=i686-w64-mingw32-gcc + export CARGO_TARGET_I686_PC_WINDOWS_GNU_AR=i686-w64-mingw32-ar + cargo build --verbose --target ${{ matrix.target }} ${{ matrix.features && format('--features {0}', matrix.features) }} + + - name: Build (Android via cargo-ndk, API 29) + if: matrix.setup == 'android' + run: | + cargo ndk \ + --platform 29 \ + --target aarch64-linux-android \ + --target armv7-linux-androideabi \ + --target x86_64-linux-android \ + --target i686-linux-android \ + build --verbose + + - name: Build WASM + if: matrix.setup == 'wasm' + run: cargo build --verbose --target wasm32-unknown-unknown ${{ matrix.features && format('--features {0}', matrix.features) }} + + - name: Build WASM example (browser) + if: matrix.setup == 'wasm' && hashFiles('examples/browser/Cargo.toml') != '' + run: | + cd examples/browser + wasm-pack build --target=no-modules --dev + + - name: Test WASM + if: matrix.setup == 'wasm' + run: wasm-pack test --chrome --headless + + - name: Start JACK (Linux) + if: runner.os == 'Linux' && matrix.setup == 'linux-jack' + run: | + sudo apt-get update + sudo apt-get install -y jackd2 + jackd -d dummy >/tmp/jack.log 2>&1 & disown + sleep 2 + shell: bash + + - name: Test (Linux JACK) + if: runner.os == 'Linux' && matrix.setup == 'linux-jack' + run: cargo test --verbose ${{ matrix.features && format('--features {0}', matrix.features) }} + shell: bash + + - name: Test (Linux ALSA with gating) + if: runner.os == 'Linux' && matrix.setup == 'linux-alsa' + run: | + FEATURES='${{ matrix.features && format('--features {0}', matrix.features) }}' + if [ -e /dev/snd/seq ]; then + echo "ALSA sequencer present; running full tests" + cargo test --verbose ${FEATURES} + else + echo "ALSA sequencer not available; skipping end_to_end" + cargo test --verbose ${FEATURES} -- --skip end_to_end + fi + shell: bash + + - name: Test (non-Linux hosted targets) + if: > + runner.os != 'Linux' && + (matrix.target == '' || + matrix.target == 'x86_64-pc-windows-msvc' || + startsWith(matrix.name, 'macOS')) && + matrix.setup != 'windows-gnu' + run: cargo test --verbose ${{ matrix.features && format('--features {0}', matrix.features) }} + + - name: Test (Windows GNU) + if: matrix.setup == 'windows-gnu' + shell: msys2 {0} + run: | + export PATH="$(cygpath -u "$USERPROFILE")/.cargo/bin:$PATH" + export CARGO_TARGET_I686_PC_WINDOWS_GNU_LINKER=i686-w64-mingw32-gcc + export CARGO_TARGET_I686_PC_WINDOWS_GNU_AR=i686-w64-mingw32-ar + cargo test --verbose --target ${{ matrix.target }} ${{ matrix.features && format('--features {0}', matrix.features) }} diff --git a/azure-pipelines-template.yml b/azure-pipelines-template.yml deleted file mode 100644 index 90789c4..0000000 --- a/azure-pipelines-template.yml +++ /dev/null @@ -1,131 +0,0 @@ -jobs: -- job: ${{ parameters.name }} - pool: - vmImage: ${{ parameters.vmImage }} - strategy: - matrix: - stable: - rustup_toolchain: stable-${{ parameters.toolchain }} - rustup_target: ${{ parameters.target }} - features: "" - ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/master') }}: - beta: - rustup_toolchain: beta-${{ parameters.toolchain }} - rustup_target: ${{ parameters.target }} - features: "" - nightly: - rustup_toolchain: nightly-${{ parameters.toolchain }} - rustup_target: ${{ parameters.target }} - features: "" - ${{ if startsWith(parameters.name, 'Windows') }}: - stable-winrt: - rustup_toolchain: stable-${{ parameters.toolchain }} - rustup_target: ${{ parameters.target }} - features: "winrt" - ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/master') }}: - beta-winrt: - rustup_toolchain: beta-${{ parameters.toolchain }} - rustup_target: ${{ parameters.target }} - features: "winrt" - nightly-winrt: - rustup_toolchain: nightly-${{ parameters.toolchain }} - rustup_target: ${{ parameters.target }} - features: "winrt" - ${{ if and(not(startsWith(parameters.name, 'Windows')), not(endsWith(parameters.name, 'WASM')), not(startsWith(parameters.name, 'iOS'))) }}: - stable-jack: - rustup_toolchain: stable-${{ parameters.toolchain }} - rustup_target: ${{ parameters.target }} - features: "jack" - ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/master') }}: - beta-jack: - rustup_toolchain: beta-${{ parameters.toolchain }} - rustup_target: ${{ parameters.target }} - features: "jack" - nightly-jack: - rustup_toolchain: nightly-${{ parameters.toolchain }} - rustup_target: ${{ parameters.target }} - features: "jack" - steps: - - ${{ if not(startsWith(parameters.name, 'Windows')) }}: - # Install Rust (non-Windows) - - script: | - curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain $RUSTUP_TOOLCHAIN - export PATH="$HOME/.cargo/bin:$PATH" - echo "##vso[task.setvariable variable=PATH;]$PATH" - displayName: Install Rust - - ${{ if startsWith(parameters.name, 'Windows') }}: - # Install Rust (Windows) - - script: | - curl -sSf -o rustup-init.exe https://win.rustup.rs - rustup-init.exe -y --default-toolchain %RUSTUP_TOOLCHAIN% - set PATH=%PATH%;%USERPROFILE%\.cargo\bin - echo "##vso[task.setvariable variable=PATH;]%PATH%;%USERPROFILE%\.cargo\bin" - displayName: Install Rust (Windows) - - ${{ if and(startsWith(parameters.name, 'Linux'), not(endsWith(parameters.name, 'WASM')), not(endsWith(parameters.name, 'ARM'))) }}: - # Linux on x86_64 only - - script: | - sudo apt-get update && sudo apt-get install -y libasound2-dev libjack-jackd2-dev - displayName: Install ALSA and Jack dependencies - - ${{ if startsWith(parameters.name, 'macOS') }}: - # macOS only - - script: | - if [ "$FEATURES" = "jack" ]; then - curl -LOS https://github.com/jackaudio/jackaudio.github.com/releases/download/1.9.11/JackOSX.0.92_b3.zip && unzip JackOSX.0.92_b3.zip && sudo installer -pkg JackOSX.0.92_b3.pkg -target / - fi - displayName: Install Jack dependencies - # Install target (might be a no-op) - # Use bash for cross-platform env variable syntax - - bash: rustup target add "$RUSTUP_TARGET" - displayName: Add rustup target - - ${{ if endsWith(parameters.name, 'ARM') }}: - # Linux on ARM only - - script: | - grep "^deb http://azure.archive" /etc/apt/sources.list | sed 's/deb\ http:\/\/azure.archive.ubuntu.com\/ubuntu/deb\ [arch=arm64]\ http:\/\/ports.ubuntu.com\/ubuntu-ports/' > $HOME/arm-sources.list - sudo sed -i 's/deb\ /deb\ \[arch=amd64\]\ /' /etc/apt/sources.list - sudo sh -c "cat $HOME/arm-sources.list >> /etc/apt/sources.list" - rm $HOME/arm-sources.list - sudo dpkg --add-architecture arm64 - sudo apt-get update - sudo apt-get install -y libc6-arm64-cross libc6-dev-arm64-cross gcc-aarch64-linux-gnu - displayName: Set up ARM cross-compilation environment - - script: | - echo -e "[build]\ntarget = \"aarch64-unknown-linux-gnu\"\n[target.aarch64-unknown-linux-gnu]\nlinker = \"aarch64-linux-gnu-gcc\"\n[env]\nPKG_CONFIG_PATH=\"/usr/lib/aarch64-linux-gnu/pkgconfig\"\nPKG_CONFIG_ALLOW_CROSS=\"true\"">$HOME/.cargo/config - displayName: Add aarch64-unknown-linux-gnu target - - script: | - sudo apt-get install -y libasound2-dev:arm64 libjack-jackd2-dev:arm64 - displayName: Install ALSA and Jack dependencies - # All platforms - - script: | - rustc -Vv - cargo -V - displayName: Query installed versions - - ${{ if not(endsWith(parameters.name, 'WASM')) }}: - # Use bash for cross-platform env variable syntax - - bash: cargo build --verbose --target "$RUSTUP_TARGET" --features "$FEATURES" - displayName: Build - - bash: cargo build --target "$RUSTUP_TARGET" --features "$FEATURES" --example test_list_ports - displayName: Build example program - - ${{ if and(not(startsWith(parameters.name, 'Linux')), not(startsWith(parameters.name, 'iOS'))) }}: - # Tests cannot run on Linux (missing ALSA driver), or with Jack (Jack not running), or for cross-platform ARM build - - bash: | - if [[ "$FEATURES" != *"jack"* ]]; then - cargo test --verbose --target "$RUSTUP_TARGET" --features "$FEATURES" - fi - displayName: Run unit tests - - bash: | - if [[ "$FEATURES" != *"jack"* ]]; then - cargo run --target "$RUSTUP_TARGET" --features "$FEATURES" --example test_list_ports - fi - displayName: Run example program - - ${{ if endsWith(parameters.name, 'WASM') }}: - # WebAssembly - - script: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh -s -- -f - displayName: Install wasm-pack - #- bash: cargo build --verbose --target wasm32-unknown-unknown --features "$FEATURES" - # displayName: Build - - bash: | - cd examples/browser - wasm-pack build --target=no-modules --dev - displayName: Build WASM example program - - bash: wasm-pack test --chrome - displayName: Run WASM tests diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index 2eb84a8..0000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,43 +0,0 @@ -jobs: -- template: azure-pipelines-template.yml - parameters: - name: macOS - vmImage: macOS-latest - toolchain: x86_64-apple-darwin - target: x86_64-apple-darwin -- template: azure-pipelines-template.yml - parameters: - name: iOS - vmImage: macOS-latest # currently no ARM host available - toolchain: x86_64-apple-darwin - target: aarch64-apple-ios-macabi -- template: azure-pipelines-template.yml - parameters: - name: Linux - vmImage: ubuntu-latest - toolchain: x86_64-unknown-linux-gnu - target: x86_64-unknown-linux-gnu -- template: azure-pipelines-template.yml - parameters: - name: Windows - vmImage: windows-latest - toolchain: x86_64-pc-windows-msvc - target: x86_64-pc-windows-msvc -- template: azure-pipelines-template.yml - parameters: - name: Windows_GNU - vmImage: windows-latest - toolchain: i686-pc-windows-gnu - target: i686-pc-windows-gnu -- template: azure-pipelines-template.yml - parameters: - name: Linux_WASM - vmImage: ubuntu-latest - toolchain: x86_64-unknown-linux-gnu - target: wasm32-unknown-unknown -#- template: azure-pipelines-template.yml -# parameters: -# name: Linux_ARM -# vmImage: ubuntu-latest -# toolchain: x86_64-unknown-linux-gnu -# target: aarch64-unknown-linux-gnu \ No newline at end of file From bfecb691c708726be8b5a1f5eb9b8503356f8b74 Mon Sep 17 00:00:00 2001 From: mlm-games <125530737+mlm-games@users.noreply.github.com> Date: Fri, 17 Oct 2025 07:09:17 +0530 Subject: [PATCH 2/3] use c_char for better type conversion across platforms --- src/backend/jack/wrappers.rs | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/src/backend/jack/wrappers.rs b/src/backend/jack/wrappers.rs index 25d347c..55b56a4 100644 --- a/src/backend/jack/wrappers.rs +++ b/src/backend/jack/wrappers.rs @@ -2,6 +2,7 @@ use std::ffi::{CStr, CString}; use std::ops::Index; +use std::os::raw::c_char; use std::{ptr, slice, str}; use libc::{c_void, size_t}; @@ -66,25 +67,26 @@ impl Client { } pub fn get_midi_ports(&self, flags: PortFlags) -> PortInfos { - let ports_ptr = unsafe { + let raw: *mut *const c_char = unsafe { jack_get_ports( self.p, ptr::null_mut(), - JACK_DEFAULT_MIDI_TYPE.as_ptr() as *const _, + JACK_DEFAULT_MIDI_TYPE.as_ptr() as *const c_char, flags.bits() as _, ) }; - let slice = if ports_ptr.is_null() { + let slice: &[*const c_char] = if raw.is_null() { &[] } else { unsafe { - let count = (0isize..) - .find(|i| (*ports_ptr.offset(*i)).is_null()) - .unwrap() as usize; - slice::from_raw_parts(ports_ptr, count) + let mut n = 0usize; + while !(*raw.add(n)).is_null() { + n += 1; + } + slice::from_raw_parts(raw as *const *const c_char, n) } }; - PortInfos { p: slice } + PortInfos { raw, p: slice } } pub fn register_midi_port(&mut self, name: &str, flags: PortFlags) -> Result { @@ -146,16 +148,11 @@ impl Drop for Client { } } -#[cfg(not(any(target_arch = "aarch64", target_arch = "arm")))] -type PortInfo = i8; - -#[cfg(any(target_arch = "aarch64", target_arch = "arm"))] -type PortInfo = u8; - pub struct PortInfos<'a> { - p: &'a [*const PortInfo], + // Returned by jack_get_ports (NULL-terminated array), needs to be freed with jack_free + raw: *mut *const c_char, + p: &'a [*const c_char], } - unsafe impl<'a> Send for PortInfos<'a> {} impl<'a> PortInfos<'a> { @@ -164,7 +161,7 @@ impl<'a> PortInfos<'a> { } pub fn get_c_name(&self, index: usize) -> &CStr { - let ptr = self.p[index]; + let ptr: *const c_char = self.p[index]; unsafe { CStr::from_ptr(ptr) } } } @@ -182,8 +179,8 @@ impl<'a> Index for PortInfos<'a> { impl<'a> Drop for PortInfos<'a> { fn drop(&mut self) { - if self.p.len() > 0 { - unsafe { jack_free(self.p.as_ptr() as *mut _) } + if !self.raw.is_null() { + unsafe { jack_free(self.raw as *mut _) } } } } From d8b913ff1fa40885ba4c04f13d585283377690b7 Mon Sep 17 00:00:00 2001 From: Patrick Reisert Date: Sun, 2 Nov 2025 18:01:13 +0100 Subject: [PATCH 3/3] Disabled Android CI for now --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0b85c27..9d2d0ba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,7 +36,7 @@ jobs: - { name: iOS (Mac Catalyst aarch64-apple-ios-macabi), os: macos-latest, target: aarch64-apple-ios-macabi, features: "", setup: ios-macabi } - { name: Linux (aarch64-unknown-linux-gnu), os: ubuntu-latest, target: aarch64-unknown-linux-gnu, features: "", setup: linux-aarch64 } - { name: Windows (ARM64 MSVC), os: windows-latest, target: aarch64-pc-windows-msvc, features: "", setup: windows-msvc } - - { name: Android (aarch64/armv7/x86_64/i686; API 29), os: ubuntu-latest, target: "", features: "", setup: android } + #- { name: Android (aarch64/armv7/x86_64/i686; API 29), os: ubuntu-latest, target: "", features: "", setup: android } steps: - name: Checkout